def pianoroll_to_midi(y, pianoroll): """ Parameters ---------- y : 1D numpy array. Audio signal (used to estimate BPM) pianoroll : list A pianoroll list as estimated by states_to_pianoroll(). Returns ------- None. """ bpm = librosa.beat.tempo(y)[0] print(bpm) quarter_note = 60 / bpm ticks_per_quarter = 1024 onsets = np.array([p[0] for p in pianoroll]) offsets = np.array([p[1] for p in pianoroll]) onsets = onsets / quarter_note offsets = offsets / quarter_note durations = offsets - onsets MyMIDI = midiutil.MIDIFile(1) MyMIDI.addTempo(0, 0, bpm) for i in range(len(onsets)): MyMIDI.addNote(0, 0, int(pianoroll[i][2]), onsets[i], durations[i], 100) return MyMIDI
def writeToFile(self, file_name: str): """Writes the tracks in a MIDIFile and saves it. \n input : -file_name : string, name of the generated MIDI file (with .mdi extension). Can be a path as well. """ file = mu.MIDIFile(self.num_tracks) for track_id, track in enumerate(self.track_list): time = track.start_time for staff in track.staff_list: file.addTempo(track_id, time, staff.tempo) numerator, denominator, clocks_amount = self.__get_time_signature_values( staff.time_signature) file.addTimeSignature(track_id, time, numerator, int(math.log(denominator, 2)), clocks_amount) for measure in staff.measure_list: for note in measure.note_list: if note.name != NoteEnum.REST: file.addNote(track_id, 0, self.__pitch_convert(note), time, note.duration, 127) time += note.duration with open(file_name, "wb") as output_file: file.writeFile(output_file) output_file.close()
def time_series_to_midi(time_series, output_filepath): """ Generates midi file from time series representation of the song Args: time_series (pandas.DataFrame): time series representation of the song in MAPS database (Onset, Offset, MidiPitch) output_filepath (str): path to desired midi file Returns: None """ output_midi = midiutil.MIDIFile(1) output_midi.addTrackName(0, 0, "Test track") output_midi.addTempo(0, 0, 120) for index, row in tqdm.tqdm(time_series.iterrows()): output_midi.addNote( 0, 0, int(row["MidiPitch"]), float(row["OnsetTime"]), float(row["OffsetTime"] - row["OnsetTime"]), 100 ) with open(output_filepath, "wb") as binfile: output_midi.writeFile(binfile)
def compose_midi(in_data, notes, max_gen): track = 0 channel = 0 time = 0 # in beats tempo = 60 # beats per minute # volume = 100 # from 0-127 program = 0 # Midi instrument midi_file = midiutil.MIDIFile(1, deinterleave=False, adjust_origin=False) midi_file.addTempo(track, time, tempo) # midi_file.addProgramChange(track, channel, time, program) duration = 1.0 i = 1 while i < len(in_data): time = float(in_data[i][0]) print time if time >= 0: column = 1 while column < len(in_data[i]): note = notes[in_data[0][column]] volume = int(127 * int(in_data[i][column]) / int(max_gen[in_data[0][column]])) midi_file.addNote(track, channel, note, time, duration, volume) column += 1 i += 1 save_midi(midi_file)
def generate_file(self, filename): ofile = midiutil.MIDIFile(1) ofile.addTrackName(0, 0, "Track") ofile.addTempo(0, 0, 300) self.populate(ofile, 80) binf = open(filename, 'wb') ofile.writeFile(binf) binf.close()
def __new_song(): global midi_file, __MIDI_BUILDER, __POSITION, __CURRENT_OCTAVE __MIDI_BUILDER = midiutil.MIDIFile(numTracks=1, file_format=1) __MIDI_BUILDER.addTempo(0, 0, 120) __MIDI_BUILDER.addProgramChange(0, 0, 0, 80) __POSITION = 0 __CURRENT_OCTAVE = 5 __CURRENT_NOTE_LEN = 1
def writeMidi(self, notes): """ Writes notes to a MIDI file. Args: notes: The notes to write to MIDI. """ track = 0 channel = 0 time = 0 # # Guess the tempo of the piece based on the most common note duration # noteDurations = {} # for note in notes[0]: # if note.midi > 0: # if note.duration in noteDurations: # noteDurations[note.duration] += 1 # else: # noteDurations[note.duration] = 1 # best = None # for duration, count in noteDurations.items(): # if not best or best[1] < count: # best = (duration, count) # elif best[1] == count and duration > best[0]: # best = (duration, count) # bestDuration = best[0] # if bestDuration > 0: # bestTempo = int(60 / (bestDuration / self.sampleRate)) # # Correct tempos that are abnormally slow/fast. # while bestTempo > 200: # bestTempo = bestTempo >> 1 # if bestTempo > 0: # while bestTempo < 40: # bestTempo = bestTempo << 1 # else: # bestTempo = 120 # tempo = bestTempo # print("Tempo:", tempo) tempo = 100 samplesPerBeat = self.sampleRate / (tempo / 60) midiFile = midi.MIDIFile(1) midiFile.addTempo(track, time, tempo) started = False for note in notes[0]: if note.midi > 0: midiFile.addNote(track, channel, note.midi, time / samplesPerBeat, note.duration / samplesPerBeat, int(127 * note.volume)) started = True # Ignore silence at the beginning of the note sequence. if started: time += note.duration with open("output.mid", "wb") as output_file: midiFile.writeFile(output_file)
def compose_midi(in_data, notes, max_gen): track = 0 channel = 0 time = 0 # in beats tempo = 60 # beats per minute # volume = 100 # from 0-127 program = 0 # Midi instrument midi_file = midiutil.MIDIFile(3, deinterleave=False, adjust_origin=False) midi_file.addTrackName(0, 0, "Piano-Embalses") midi_file.addTrackName(1, 0, "Sample-Ralco") midi_file.addTrackName(2, 0, "Bass-BocaminaII") midi_file.addTempo(track, time, tempo) # midi_file.addProgramChange(track, channel, time, program) duration = 1.0 i = 1 while i < len(in_data): time = float(in_data[i][1]) - 1.0 # print time if time >= 0: column = 2 while column < len(in_data[i]): # if column is ralco do notes to trigger mapuche samples if in_data[0][column] == "Ralco": note = note_assign(float(in_data[i][column]), "Ralco", 0, c_maj, 4, in_data) # print note volume = 100 midi_file.addNote(track + 1, channel, note, time, duration, volume) # print "Ralco!" # elseif column is bocamina create bass elif in_data[0][column] == "Bocamina_II": note = note_assign(float(in_data[i][column]), "Bocamina_II", -2, c_maj, 10, in_data) # print note volume = 100 midi_file.addNote(track + 2, channel, note, time, duration, volume) # print "Bocamina!" # else do chords else: note = notes[in_data[0][column]] volume = int(127 * int(in_data[i][column]) / int(max_gen[in_data[0][column]])) midi_file.addNote(track, channel, note, time, duration, volume) column += 1 i += 1 save_midi(midi_file)
def make_midi(song, filename): my_midi = midiutil.MIDIFile(1) track = 0 channel = 0 volume = 100 song = np.pad(song, [(0, 0), (39, 39)]) print(song.shape) notes = get_note_properties(song) for pitch, start_time, duration in notes: my_midi.addNote(track, channel, pitch, start_time, duration, volume) my_midi.writeFile(open(filename, "wb"))
def compose_midi(text): track = 0 channel = 0 time = 0 # in beats tempo = 120 # beats per minute volume = 100 # from 0-127 midi_file = midiutil.MIDIFile(1, adjust_origin=True) midi_file.addTempo(track, time, tempo) for item in text.split(): note = ''.join(list(item)[:2]) note = int(note) duration = ''.join(list(item)[2:]) duration = float(duration) midi_file.addNote(track, channel, note, time, duration, volume) time = time + duration return midi_file
def midi_test(): test_midi = mu.MIDIFile() test_midi.addTempo(0, 0, 182) major_offset = [0, 2, 4, 5, 7, 9, 11] minor_offset = [0, 2, 3, 5, 7, 8, 10] notes = [] for i, note in enumerate(range(8)): noteval = 60 + choice(minor_offset) test_midi.addNote(0, 0, noteval, i, 0.85, 96) notes.append(noteval) print(notes) with open("test_midi.mid", "wb") as file: test_midi.writeFile(file)
def compose_midi(sightings, duration_stats): track = 0 channel = 0 time = 0 # in beats tempo = 160 # beats per minute volume = 100 # from 0-127 program = 0 # Midi instrument duration = 8 transpose = 0 lh_step_recover = 12 lh_max_vel_mu = 40 lh_vel_sig = 8 midi_file = midiutil.MIDIFile(1, adjust_origin=False) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) midi_file.addProgramChange(track, channel + 1, time, 52) steps_since_rh = 99 for sighting in sightings: note = get_note(sighting["shape"]) if check_for_voice(sighting["desc"]) == True: dm = duration_stats["mean"] magnitude = bisect.bisect([dm / 2, dm, dm + dm / 2], sighting["num"]) for mag in range(magnitude + 1): mag = mag + 1 gracenote_offset_time = random.gauss((1 / 8), (1 / 8)) * mag midi_file.addNote(track, channel, note + transpose + (12 * mag), time + gracenote_offset_time, duration, int(random.gauss(60, 2))) steps_since_rh = 0 pass else: vel_mu = ((lh_max_vel_mu / lh_step_recover) * (steps_since_rh) ) if steps_since_rh < lh_step_recover else lh_max_vel_mu vel = max(int(random.gauss(vel_mu, lh_vel_sig)), 0) midi_file.addNote(track, channel, note - 12 + transpose, time, duration, vel) steps_since_rh += 1 time = time + 0.25 save_midi(midi_file)
def compose_midi(x): track = 0 channel = 0 time = 0 # in beats tempo = 60 # beats per minute volume = 0 # from 0-127 program = 0 # Midi instrument duration = 1 midi_file = midiutil.MIDIFile(1, adjust_origin=False) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) midi_file.addProgramChange(track, channel + 1, time, 65) for item in range(len(x)): volume = get_volume(x[item][3]) note = get_note(int(x[item][2])) midi_file.addNote(track, channel, note, time, duration, volume) time = time + duration #execute funtion to save midi save_midi(midi_file)
def compose_midi(text): track = 0 channel = 0 time = 0 # in beats tempo = 120 # beats per minute volume = 100 # from 0-127 midi_file = midiutil.MIDIFile(1, adjust_origin=True) midi_file.addTempo(track, time, tempo) for item in text.split(): print(list(item)) note = ''.join(list(item)[:2]) note = int(note) # If your encoding has a duration, you can add that here. Otherwise, default is 1.0, or a quarter note duration = 1.0 midi_file.addNote(track, channel, note, time, duration, volume) time = time + duration return midi_file
def convert_file(json_path, dest): with open(json_path) as f: data = json.load(f) mid = midiutil.MIDIFile(1) mid.addTempo(0, 0, 60) for notes in data['notes']: if 'sounds' not in notes: continue if '_time' not in notes: time = 0 else: time = notes['_time'] for note in notes['sounds']: if 'd' not in note: continue if note['d'] == 0 or note['v'] == 0: continue mid.addNote(0, 0, note['p'], time, note['d'], note['v']) with open(dest, 'wb') as output_file: mid.writeFile(output_file)
def compose_midi(all_sightings, duration_stats): track = 0 channel = 0 time = 0 # in beats tempo = 160 # beats per minute volume = 100 # from 0-127 program = 0 # Midi instrument midi_file = midiutil.MIDIFile(1, adjust_origin=False) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) midi_file.addProgramChange(track, channel + 1, time, 52) for row in all_sightings: duration = 1 #duration = get_duration(round(float(row[5])), duration_stats) # duration is in beats note = get_note(row[4]) # if check_for_voice(row[7]) == True: # midi_file.addNote(track, channel+1, note, time, 2, volume) midi_file.addNote(track, channel, note, time, duration, volume) time = time + duration save_midi(midi_file)
def compose_midi(tagged_text): track = 0 channel = 0 time = 0 # in beats duration = 1 # in beats tempo = 120 # beats per minute volume = 100 # from 0-127 midi_file = midiutil.MIDIFile(1, adjust_origin=True) midi_file.addTempo(track, time, tempo) for tag in tagged_text: #print tag note = 0 if 'NN' in tag[1]: note = 52 elif 'VB' in tag[1]: note = 55 else: note = 48 midi_file.addNote(track, channel, note, time, duration, volume) time = time + 1 return midi_file
def compose_midi(rides, duration_stats, station_stats): track = 0 channel = 0 time = 0 # in beats tempo = 200 # beats per minute volume = 100 # from 0-127 program = 0 # Midi instrument midi_file = midiutil.MIDIFile(1, deinterleave=False, adjust_origin=False) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) midi_file.addProgramChange(track, channel+1, time, 112) for ride in rides: time = parse_date(ride.start_time)[3] if time >= 0: duration = get_duration(ride.tripduration, duration_stats) # duration is in beats note = get_note(ride.to_station_name, station_stats) midi_file.addNote(track, channel, note, time, duration, volume) if ride.usertype == "Customer": midi_file.addNote(track, channel+1, note, time, 2, volume) else: midi_file.addNote(track, channel, note, time, duration, volume) save_midi(midi_file)
def compose_midi(song): # setup midifile track = 0 channel = 0 time = 0 # in beats tempo = 120 # beats per minute volume = 100 # from 0-127 midi_file = midiutil.MIDIFile(1, adjust_origin=True) midi_file.addTempo(track, time, tempo) # compose notes from coded text notes = song.split(" ") for each_note in notes: pitch = int(each_note.split("_")[0]) if pitch > 255: pitch = int(pitch / 100) duration = float(tempo) * float(each_note.split("_")[1]) / 60000 # duration = 1 if duration != 0.0: midi_file.addNote(track, channel, pitch, time, duration, volume) time = time + duration print("note:", pitch, "time:", duration) return midi_file
def compose_midi(all_sightings, duration_stats): counter = 0 track = 0 channel = 0 time = 0 # in beats tempo = 200 # beats per minute volume = 100 # from 0-127 program = 0 # Midi instrument midi_file = midiutil.MIDIFile(1, deinterleave=False, adjust_origin=True) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) midi_file.addProgramChange(track, channel+1, time, 52) for row in all_sightings: time = parse_date(row[0])[2] if time >= 0: duration = get_duration(round(float(row[5])), duration_stats) # duration is in beats note = get_note(row[4]) if check_for_voice(row[7]) == True: midi_file.addNote(track, channel+1, note, time, 2, volume) else: midi_file.addNote(track, channel, note, time, duration, volume) midi_file.addNote(track, channel, note, time, duration, volume) save_midi(midi_file)
def fix(fileName, outName): outFile = midiutil.MIDIFile() notes = getNotes(mido.MidiFile(fileName)) notes = mergeSameNotes(notes) notes = fixAdjacentNotes(notes) notes = mergeSameNotes(notes) for note in notes: if note.duration > 0.1 and 40 < note.pitch < 90: outFile.addNote(0, 0, pitch=note.pitch, duration=2 * note.duration, time=2 * note.start, volume=127) try: os.remove(outName) except: pass with open(outName, 'wb') as f: outFile.writeFile(f)
def compose_midi(data_input): track = 0 channel = 0 time = 0 # in beats tempo = 60 # beats per minute volume = 100 # from 0-127 program = 0 # Midi instrument duration = 2 #duration = get_duration(all_data) midi_file = midiutil.MIDIFile(1, adjust_origin=False) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) midi_file.addProgramChange(track, channel + 1, time, 52) for item in range(len(data_input)): volume = get_volume(data_input[item][3]) note = get_note(int(data_input[item][2])) duration = len(data_input) * 2 - item * 2 track = item midi_file.addNote(track, channel, note, time, duration, volume) time = time + item * 2 # function executes save_midi(midi_file)
def compose_midi_from_sequences(pitch_seq, onset_seq, tempo_seq, dur_seq): # initial midi file setting track = 0 channel = 0 time = 0 # in beats tempo = miditemp_list2bpm_list(tempo_seq)[0] # beats per minute volume = 100 # from 0-127 midi_file = midiutil.MIDIFile(1, adjust_origin=True) midi_file.addTempo(track, time, tempo) # add notes to midifile for i in range(len(pitch_seq)): pitch = int(pitch_seq[i]) time = onset_seq[ i] / 24 # the time at which the note sounds, correspond to the onset (idyom uses basic time units, quarter note =24) duration = dur_seq[i] / 24 # midiutil: 1 beat (quarter note) = 1 midi_file.addNote(track=track, channel=channel, pitch=pitch, time=time, duration=duration, volume=volume) return midi_file
def write_midi_file(filename, midi_tracks, program, duration, tempo, volume): print "...Writing MIDI file" MyMIDI = midiutil.MIDIFile(len(midi_tracks)) time = 0 channel = 1 for i in range(len(midi_tracks)): if (program[i] == 128): channel = 10 program[i] = 0 MyMIDI.addTempo(track=i + 1, time=time, tempo=tempo) MyMIDI.addProgramChange(track=i + 1, channel=channel - 1, time=time, program=program[i]) d = duration[i] v = volume[i] for j, midi_note in enumerate(midi_tracks[i]): for k in range(len(midi_note)): MyMIDI.addNote(i, channel - 1, midi_note[k], time, d[j], v[j]) time = sum(d[:j + 1]) time = 0 with open(filename[:-4] + ".mid", "wb") as output_file: MyMIDI.writeFile(output_file)
def make_midi(self, onsets, midi, file_name, timestep): track = 0 channel = 0 bpm = 120 def time_to_beat(time): return time / 60 * bpm onset_indices = (onsets / timestep).astype(np.int32) print("onset indices ", onset_indices) if len(onset_indices) > 0 and np.count_nonzero(midi) > 0: # make midi file template (bpm is just random at 120) myMidi = midiutil.MIDIFile(1) myMidi.addTempo(track, 0, bpm) myMidi.addTimeSignature(0, 0, 4, 2, 24) pitch_segments = [] for i in range(len(onset_indices)): # find end of the note: # either when the frequency next goes to 0, or when the next onset is next_onset = len(midi) - 1 next_0_index = len(midi) - 1 if i < len(onset_indices) - 1: # not the last one next_onset = onset_indices[i + 1] for j in range(onset_indices[i] + 1, len(midi)): if midi[j] == 0: next_0_index = j break #rint("onset_indices[i] ", onset_indices[i]) #print("next onset ", next_onset) #print("next_0_index ", next_0_index) # pitches within this "midi note" (for pitch bends) if onset_indices[i] == len(midi) - 1: segment = [midi[onset_indices[i]]] else: segment = midi[ onset_indices[i]:min(next_onset, next_0_index)] # average integer midi to use as center point for pitch bends average_midi = int(np.round(np.mean(segment))) # timing calculations start_beat = time_to_beat(onset_indices[i] * timestep) duration_beat = time_to_beat(len(segment) * timestep) myMidi.addNote(track, channel, average_midi, start_beat, duration_beat, 50) #print("original midi ", midi[onset_indices[i]:onset_indices[i]+len(segment)]) # do a pitch bend for every sample according to tuned_midi curve mean_filtered_midi = self.moving_average( midi[onset_indices[i]:onset_indices[i] + len(segment)]) #print("filtered ", mean_filtered_midi) for j in np.arange(len(segment)): beat = start_beat + time_to_beat(j * timestep) index = j + onset_indices[i] # myMidi.addPitchWheelEvent(track, channel, beat, # min(8192, max(-8192, int(8192 * (midi[index] - average_midi) / 2)))) myMidi.addPitchWheelEvent( track, channel, beat, min( 8192, max( -8192, int(8192 * (mean_filtered_midi[j] - average_midi) / 2)))) # write midi file with open(file_name + ".mid", "wb") as output_file: myMidi.writeFile(output_file)
filename = sys.argv[1] source = open(filename,'rb') if len(sys.argv)<3: # individual file data = source.read() musi = delv.sound.Music(data) else: # archive resource = delv.archive.Scenario(source).get(int(sys.argv[2],16)) if not resource: print("No resource", sys.argv[2], "found in that archive.", file=sys.stderr) sys.exit(-1) musi = delv.sound.Music(resource.get_data()) # Setup midi file midi = midiutil.MIDIFile(len(list(musi.instruments)), file_format=1) # tracks equal to number of original parts; format=1 adds tempo track at 0 # May need to add an empty track if error occurs (like with 9005, Danger track), probably an error with the lib but unimportant # Tempo tempo_track = 0 # Tempo track always added as extra track at 0 in this format; bug in midiutil fixed as of v1.2.1 , tempo track correct with no other directives midi.addTempo(tempo_track, 0, 120) # QT prefers 60 bpm, but SMF default is 120, which has much better support on most synths # Channels parts = list(musi.channels) # parts are 0-indexed, but with tempo track, must add offset time = 0 for part in parts: # Setting instrument programs midi.addProgramChange(part,musi.channels[part]-1,time,program=(musi.instruments[part]-1)%127) # mod 127 used to ensure valid program nums (doesn't matter when channel 10 anyways) # Notes, Extended Notes, and Rests for com in musi.qtma_commands: if com[0] == 'rest':
# -*- coding: utf-8 -*- import midiutil as mu import pandas import numpy as np melody = pandas.read_csv("melody.csv") array = melody.to_numpy() note = array[:, 2] note = note.astype(int) dur = array[:, 3] track = 0 channel = 0 time = 0 tempo = 90 duration = 1 volume = 100 testvar = [(note[i], dur[i]) for i in range(0, len(note))] MyMIDI = mu.MIDIFile(1) MyMIDI.addTempo(track, time, tempo) for pitch, y in testvar: MyMIDI.addNote(track, channel, pitch, time, y, volume) time = time + y with open("melody.mid", "wb") as output_file: MyMIDI.writeFile(output_file)
def __init__(self, name, track=0, channel=0, numTracks=1): self.midi_file = util.MIDIFile(numTracks, adjust_origin=False) self.name = name self.current_track = track self.channel = channel self.time = 0
import midi_constants as mc import midi_tools as mt import midiutil as midi import sound #degrees = [60, 62, 64, 65, 67, 69, 71, 72] # MIDI note number #degrees = [note for note in [mc.c[3]+i for i in [0,2,4,5,7,9,11,12]]] degrees = mc.c track = 0 channel = 0 time = 0 # In beats duration = 1.5 # In beats tempo = 400 # In BPM volume = 63 # 0-127, as per the MIDI standard MyMIDI = midi.MIDIFile(1, adjust_origin=False) # One track, defaults to format 1 (tempo track automatically created) MyMIDI.addTempo(track,time,tempo) MyMIDI.addProgramChange(track, channel, time, mc.Acoustic_Grand_Piano) for pitch in degrees: MyMIDI.addNote(track, channel, pitch, time, duration, volume) time = time + 1 #MyMIDI.addProgramChange(track, channel, time, mc.Marimba) for pitch in degrees: MyMIDI.addNote(track, channel, pitch, time, duration, volume) time = time + 1
def compose_midi(stats): beats_1 = [2, 1, 0.5, 0.25] beats_2 = [0.5, 1, 2, 4] C_minor_scale_1 = [60, 62, 63, 65, 67, 68, 70] C_major_scale = [72, 74, 76, 77, 79, 81, 83] C_arpeggio_scale = [72, 76, 79, 84] minor_scale = [36, 38, 39, 41, 43, 44, 47] volumes_1 = [50, 70, 90, 110] volumes_2 = [80, 95, 110, 125] measure = 4 #4 beats represents 1 day track = 0 channel = 0 time = 0 tempo = 200 # beats per minute program = 0 # instrument: piano midi_file = midiutil.MIDIFile(1, deinterleave=False, adjust_origin=False) midi_file.addTempo(track, time, tempo) midi_file.addProgramChange(track, channel, time, program) maxs = stats.max(axis=0) for row in stats: #cases cases = row[0] cases_quartile = math.ceil(cases / maxs[0] * 4) - 1 if cases <= 0: rand_volume = 30 + int(random.gauss((0), (10))) rand = random.randint(0, 3) note2 = C_major_scale[random.randint(0, 6)] midi_file.addNote(track, channel, C_arpeggio_scale[rand], time, 2, rand_volume) midi_file.addNote(track, channel, note2, time + measure / 2, 2, rand_volume) else: offset = 0 while offset < 4: length = beats_1[cases_quartile] note = C_minor_scale_1[int(cases + 1 + offset * measure) % 7] midi_file.addNote(track, channel, note, time + offset, length, volumes_1[cases_quartile]) offset += length # deaths val = row[1] quartile = math.ceil(val / maxs[1] * measure) - 1 note = minor_scale[val % 7] note2 = minor_scale[(val + 2) % 7] offset = 0 for i in range(0, quartile + 1): midi_file.addNote(track, channel, note, time + offset, beats_2[quartile], volumes_2[quartile]) midi_file.addNote(track, channel, note2, time + offset, beats_2[quartile], volumes_2[quartile]) offset += beats_2[quartile] * 4 time += measure save_midi(midi_file)