def build_evt(self, evt_data): if len(evt_data) < 3: return None evt = None evt_type = evt_data[0] try: tick = int(evt_data[1]) data1 = int(evt_data[2]) data2=None if len(evt_data) > 3: data2 = int(evt_data[3]) except ValueError: return None if evt_type == "n": if data2 is not None: evt = midi.NoteOnEvent(tick=tick, channel=0, data=[data1, data2]) else: evt = midi.NoteOnEvent(tick=tick, channel=0, data=[data1]) if evt_type == "p": if data2 is not None: evt = midi.ProgramChangeEvent(tick=tick, channel=0, data=[data1 + 50, data2]) else: evt = midi.ProgramChangeEvent(tick=tick, channel=0, data=[data1]) if evt_type == "c": if data2 is not None: evt = midi.ControlChangeEvent(tick=tick, channel=0, data=[data1, data2]) else: evt = midi.ControlChangeEvent(tick=tick, channel=0, data=[data1]) print(evt) return evt
def handlePerf(type, value, duration, maxValue, track, tick): event2 = None if type == 0: # volume event1 = midi.ControlChangeEvent(tick=tick) event1.control = 7 # Main Volume #if maxValue > 0x7F: # event1.value = (value>>8)&0xFF # event2 = midi.ControlChangeEvent(tick=0) # event2.control = 39 # Volume LSB # event2.value = value&0xFF #else: # event1.value = value event1.value = (value*0x7F)/maxValue elif type == 1: # pitch event1 = midi.PitchWheelEvent(tick=tick) event1.pitch = (value*0x7FFF)/maxValue elif type == 3: # pan event1 = midi.ControlChangeEvent(tick=tick) event1.control = 10 # Pan #if maxValue > 0x7F: # event1.value = (value>>8)&0xFF # event2 = midi.ControlChangeEvent(tick=0) # event2.control = 42 # Pan LSB # event2.value = value&0xFF #else: # event1.value = value event1.value = (value*0x7F)/maxValue else: warn("Unknown perf type %d"%type) event1 = midi.TextMetaEvent(tick=tick, data=map(ord, "Perf %d (%d)"%(type, value))) track.append(event1) if event2 is not None: track.append(event2) if duration: if type == 0: # volume event = midi.ControlChangeEvent(tick=duration) event.control = 7 # Main Volume event.value = 0x7F elif type == 1: # pitch event = midi.PitchWheelEvent(tick=duration) event.pitch = 0x2000 elif type == 3: # pan event = midi.ControlChangeEvent(tick=duration) event.control = 10 # Pan event.value = 0x40 else: event = midi.TextMetaEvent(tick=duration, data=map(ord, "Perf %d (%d)"%(type, value))) return event
def list_to_midi(chunk_str_list, generated_dir, filename): pattern = midi.Pattern(resolution=480) track = midi.Track() pattern.append(track) for chunk in chunk_str_list: chunk_info = chunk.split("_") event_type = chunk_info[1] if event_type == "no": tick = int(chunk_info[0]) pitch = int(chunk_info[2]) velocity = int(chunk_info[3]) e = midi.NoteOnEvent(tick=tick, channel=0, velocity=velocity, pitch=pitch) track.append(e) elif event_type == "st": tick = int(chunk_info[0]) bpm = int(chunk_info[2]) mpqn = int(chunk_info[3]) ev = midi.SetTempoEvent(tick=tick, bpm=bpm, mpqn=mpqn) track.append(ev) elif event_type == "cc": control = int(chunk_info[3]) value = int(chunk_info[4]) e = midi.ControlChangeEvent(channel=0, control=control, value=value) track.append(e) end_event = midi.EndOfTrackEvent(tick=1) track.append(end_event) midi.write_midifile(generated_dir + filename + '.mid', pattern)
def setPos(self, pos): """ takes between 0 and 1 """ if self.slider_index is not None: event = midi.ControlChangeEvent(tick=0, control=self.slider_index + 1, value=int(pos * 127)) xtouch.writer.event_write(event, False, False, True)
def event_read(self): ev = S.event_input(self.client) if ev and (ev < 0): self._error(ev) if ev and ev.type in (S.SND_SEQ_EVENT_NOTEON, S.SND_SEQ_EVENT_NOTEOFF, S.SND_SEQ_EVENT_CONTROLLER): if ev.type == S.SND_SEQ_EVENT_NOTEON: mev = midi.NoteOnEvent() mev.channel = ev.data.note.channel mev.pitch = ev.data.note.note mev.velocity = ev.data.note.velocity elif ev.type == S.SND_SEQ_EVENT_NOTEOFF: mev = midi.NoteOffEvent() mev.channel = ev.data.note.channel mev.pitch = ev.data.note.note mev.velocity = ev.data.note.velocity elif ev.type == S.SND_SEQ_EVENT_CONTROLLER: mev = midi.ControlChangeEvent() mev.channel = ev.data.control.channel mev.control = ev.data.control.param mev.value = ev.data.control.value if ev.time.time.tv_nsec: # convert to ms mev.msdeay = \ (ev.time.time.tv_nsec / 1e6) + (ev.time.time.tv_sec * 1e3) else: mev.tick = ev.time.tick return mev else: return None
def write_music(song, speed=100): pattern = midi.Pattern() track = midi.Track() pattern.append(track) for i in range(len(song[0]) // 128): for note in range(128): if song[0][i * 128 + note] > .5: track.append(midi.NoteOnEvent(tick=0, velocity=100, pitch=note)) track.append(midi.ControlChangeEvent(tick=speed)) for note in range(128): track.append(midi.NoteOnEvent(tick=0, velocity=0, pitch=note)) midi.write_midifile("test.mid", pattern)
def handleBankProgram(which, selection, track, tick): if which == 7: # pitch print "Pitch", selection event = midi.ControlChangeEvent(tick=tick) event.control = 101 # RPN MSB event.value = 0 track.append(event) event = midi.ControlChangeEvent(tick=0) event.control = 100 # RPN LSB event.value = 0 track.append(event) event = midi.ControlChangeEvent(tick=0) event.control = 6 # Data entry MSB event.value = selection track.append(event) event = midi.ControlChangeEvent(tick=0) event.control = 38 # Data entry LSB event.value = 0 track.append(event) elif which == 0x20: # bank print "Bank", selection event = midi.ControlChangeEvent(tick=tick) event.control = 32 # Bank Select event.value = selection track.append(event) elif which == 0x21: # program print "Program", selection event = midi.ProgramChangeEvent(tick=tick, value=selection%128) track.append(event) else: warn("Unknown bank/program %x (%d)"%(which, selection)) event = midi.TextMetaEvent(tick=tick, data=map(ord, "Bank/Program %d (%d)"%(which, selection))) track.append(event)
def event_read(self): ev = S.event_input(self.client) if not ev: return None if ev < 0: self._error(ev) if ev.type == S.SND_SEQ_EVENT_NOTEON: mev = midi.NoteOnEvent() mev.channel = ev.data.note.channel mev.pitch = ev.data.note.note mev.velocity = ev.data.note.velocity elif ev.type == S.SND_SEQ_EVENT_NOTEOFF: mev = midi.NoteOffEvent() mev.channel = ev.data.note.channel mev.pitch = ev.data.note.note mev.velocity = ev.data.note.velocity ## add cc, prog, pb, aftertouch events elif ev.type == S.SND_SEQ_EVENT_CONTROLLER: mev = midi.ControlChangeEvent() mev.channel = ev.data.control.channel mev.control = ev.data.control.param mev.value = ev.data.control.value elif ev.type == S.SND_SEQ_EVENT_PGMCHANGE: mev = midi.ProgramChangeEvent() mev.channel = ev.data.control.channel mev.value = ev.data.control.value elif ev.type == S.SND_SEQ_EVENT_PITCHBEND: mev = midi.PitchWheelEvent() mev.channel = ev.data.control.channel mev.pitch = ev.data.control.value elif ev.type == S.SND_SEQ_EVENT_KEYPRESS: mev = midi.AfterTouchEvent() mev.channel = ev.data.control.channel mev.value = ev.data.control.value mev.pitch = ev.data.control.note elif ev.type == S.SND_SEQ_EVENT_CHANPRESS: mev = midi.ChannelAfterTouchEvent() mev.channel = ev.data.control.channel mev.value = ev.data.control.value else: return None if ev.time.time.tv_nsec: # convert to ms mev.msdeay = \ (ev.time.time.tv_nsec / 1e6) + (ev.time.time.tv_sec * 1e3) else: mev.tick = ev.time.tick return mev
event_type = chunk_info[1] if event_type == "no": tick = int(chunk_info[0]) pitch = int(chunk_info[2]) velocity = int(chunk_info[3]) e = midi.NoteOnEvent(tick=tick, channel=0, velocity=velocity, pitch=pitch) track.append(e) elif event_type == "st": tick = int(chunk_info[0]) bpm = int(chunk_info[2]) mpqn = int(chunk_info[3]) ev = midi.SetTempoEvent(tick=tick, bpm=bpm, mpqn=mpqn) track.append(ev) elif event_type == "cc": control = int(chunk_info[3]) value = int(chunk_info[4]) e = midi.ControlChangeEvent(channel=0, control=control, value=value) track.append(e) end_event = midi.EndOfTrackEvent(tick=1) track.append(end_event) midi.write_midifile(file, pattern)
def change_music_to_pattern(music): music.parse_track_msg() # music._init_main_trank() pattern = midi.Pattern() pattern.resolution = music.get_resolution() pattern.format = music.get_play_format() for track in reversed(music.track): t = midi.Track() for event in track: event_tick = int(event[0]) event_event = event[1] state_code = event_event["state_code"] if state_code == 255: if event_event["name"] == 'Set Tempo': eve = midi.SetTempoEvent(tick=event_tick, bpm=event_event["bpm"]) elif event_event["name"] == 'Trank Name': eve = midi.TrackNameEvent(tick=event_tick, text=event_event["text"]) elif event_event["name"] == 'Copyright Notice': eve = midi.CopyrightMetaEvent(tick=event_tick, text=event_event["text"]) elif event_event["name"] == 'SMPTE Offset': eve = midi.SmpteOffsetEvent(tick=event_tick, text=event_event["text"]) elif event_event["name"] == 'Time Signature': eve = midi.TimeSignatureEvent( tick=event_tick, numerator=event_event["numerator"], denominator=event_event["denominator"], metronome=event_event["metronome"], thirtyseconds=event_event["thirtyseconds"]) elif event_event["name"] == "End of Track": eve = midi.EndOfTrackEvent(tick=event_tick) else: continue elif 240 <= state_code <= 254: # 系统码 eve = midi.SysexEvent() elif 224 <= state_code <= 239: # 滑音 eve = midi.PitchWheelEvent(tick=event_tick, channel=event_event["channel"], pitch=event_event["pitch"]) elif 208 <= state_code <= 223: # After Touch eve = midi.AfterTouchEvent() elif 192 <= state_code <= 207: # 乐器转换 eve = midi.ProgramChangeEvent(tick=event_tick, channel=event_event["channel"], data=[event_event["program"]]) elif 176 <= state_code <= 191: # midi控制器 eve = midi.ControlChangeEvent( tick=event_tick, channel=event_event["channel"], data=[event_event["control"], event_event["value"]]) elif 160 <= state_code <= 175: continue elif 144 <= state_code <= 159: # note on eve = midi.NoteOnEvent(tick=event_tick, channel=event_event["channel"], velocity=event_event["velocity"], pitch=event_event["pitch"]) elif 128 <= state_code <= 143: # note off eve = midi.NoteOffEvent(tick=event_tick, channel=event_event["channel"], velocity=event_event["velocity"], pitch=event_event["pitch"]) elif state_code <= 127: continue t.append(eve) pattern.append(t) return pattern
def track_to_midi(track, resolution=120): midi_track = midi.Track() # deactivation_queue is an array with a value for each midi note pitch # negative numbers indicate the pitch is not active # positive numbers are the remaining ticks until cutoff deactivation_queue = np.zeros(128, dtype=np.int) - 1 ticks_to_measure = 0 for measure in track.measures: # TODO: Handle key and time signature to create midi events # TODO: The pad_rests method probably isn't going to let this handle overlapping beats/rests correctly. # Make sure the measure is filled so the next measure starts at the right time. measure.pad_rests() # Add an empty final beat to run the loop one last time to deactivate notes. measure.append_beat() for beat in measure.beats: ticks_to_beat = midi_length(beat.offset, resolution=resolution) if beat is measure.beats[0]: ticks_to_beat = ticks_to_beat + ticks_to_measure mask = (deactivation_queue >= 0) if mask.any(): ticks_to_off_event = deactivation_queue[mask].min() else: ticks_to_off_event = 999999999 # add note off events until time for the next beat while ticks_to_off_event <= ticks_to_beat: pitches_to_deactivate = np.where(deactivation_queue == ticks_to_off_event)[0] deactivation_queue[mask] -= ticks_to_off_event deactivation_queue[pitches_to_deactivate] -= 1 ticks_to_beat -= ticks_to_off_event for pitch in pitches_to_deactivate: off_event = midi.NoteOffEvent(tick=int(ticks_to_off_event), pitch=int(pitch)) midi_track.append(off_event) ticks_to_off_event = 0 mask = (deactivation_queue >= 0) if mask.any(): ticks_to_off_event = deactivation_queue[mask].min() else: ticks_to_off_event = 999999999 for note in beat.notes: if isinstance(note, music.Rest): ticks_to_measure = ticks_to_measure + midi_length(note.duration, resolution=resolution) continue midi_velocity = round(note.intensity * 127) midi_pitch = note.value note_on_event = midi.NoteOnEvent(tick=int(ticks_to_beat), velocity=midi_velocity, pitch=midi_pitch) midi_track.append(note_on_event) deactivation_queue[midi_pitch] = midi_length(note.duration, resolution=resolution) # note: doesn't handle ties yet ticks_to_beat = 0 ticks_to_measure = 0 for event in beat.events: if event.name == 'end_track': midi_event = midi.EndOfTrackEvent(tick=ticks_to_beat) else: midi_event = midi.ControlChangeEvent(tick=ticks_to_beat) # TODO: look into event specification midi_track.append(midi_event) ticks_to_beat = 0 ticks_to_measure = 0 # End the track if not isinstance(midi_track[-1], midi.EndOfTrackEvent): eot = midi.EndOfTrackEvent(tick=1) midi_track.append(eot) return midi_track
def writemidi( self, filedir="" ): # sort the events by absoluteticks # put all tempo, time signature data in track 0, as well as any instrument or track names # first grab the track name if self.texts[0][0].text != "": trackname = MIDI.TrackNameEvent(text=self.texts[0][0].text, tick=0) trackname.absoluteticks = 0 # for some reason, the data doesn't get through via the text above. trackname.data = [ ] i = 0 while i < len(self.texts[0][0].text): trackname.data.append( ord( self.texts[0][0].text[i] ) ) i+= 1 tracks = [[ trackname]] del trackname # so that when we reuse this variable later it doesn't change the above else: tracks = [[]] # put all tempo, time signature data in track 0 tracks[0] += self.texts[0][1:] + self.tempos+self.timesignatures+self.notes[0] # sort everything tracks[0].sort(key=operator.attrgetter('absoluteticks')) # then grab the instrument if self.channels[0] != 9 and self.instruments[0]: tracks[0].insert(0, MIDI.ProgramChangeEvent( value=self.instruments[0], channel=self.channels[0] ) ) for i in range(1,len(self.notes)): # sort each track separately # first grab the track name if self.texts[i][0].text != "": trackname = MIDI.TrackNameEvent(text=self.texts[i][0].text, tick=0) # for some reason, the data doesn't get through via the text above. trackname.data = [ ] trackname.absoluteticks = 0 j = 0 while j < len(self.texts[i][0].text): trackname.data.append( ord( self.texts[i][0].text[j] ) ) j += 1 tracks.append( [ trackname ] ) del trackname # so that when we reuse this variable later it doesn't change the above else: tracks.append( [] ) # then grab the instrument tracks[i] += self.texts[i][1:] + self.notes[i] tracks[i].sort(key=operator.attrgetter('absoluteticks')) if self.channels[i] != 9 and self.instruments[i]: tracks[i].insert(0, MIDI.ProgramChangeEvent( value=self.instruments[i], channel=self.channels[i] )) # now that everything is sorted globally, # make sure that the local ticks are correct. tickdivisor = config.EDITresolution for i in range(len(tracks)): tracks[i].insert(0, MIDI.ControlChangeEvent( tick=0, channel=self.channels[i], data=[7,127]) ) for track in tracks: previouseventabsoluteticks = 0 for event in track: try: thiseventabsoluteticks = int(event.absoluteticks) except AttributeError: thiseventabsoluteticks = 0 # number of ticks between previous event and the current event tickmeoff = thiseventabsoluteticks - previouseventabsoluteticks event.tick = tickmeoff # check to see how small we can get the resolution tickdivisor = gcd( tickdivisor, tickmeoff ) # set up the ticks for next event previouseventabsoluteticks = thiseventabsoluteticks if config.EDITresolution % tickdivisor: Error(" min RESOLUTION does not divide our EDITresolution. something is funky ") # prep the new pattern for creating newpattern = MIDI.Pattern( resolution=config.EDITresolution/tickdivisor ) for track in tracks: if tickdivisor > 1: for event in track: # divide up the relative ticks event.tick /= tickdivisor # keep absolute ticks in the EDITresolution if track[-1].name != "End of Track": # add an end of track if it isn't there track.append( MIDI.EndOfTrackEvent( tick=config.EDITresolution/tickdivisor ) ) newpattern.append( MIDI.Track(track) ) if filedir == "": MIDI.write_midifile(self.midifile, newpattern) else: MIDI.write_midifile(filedir, newpattern)
def revert(self, cut_silence=True): invertible_controllers = 64, 65, 66, 67, 68, 69 new_pattern = midi.Pattern(resolution=self.pattern.resolution, format=self.pattern.format) new_track_group = [] # Get the time value of the last event. times = [ j[0] for track in self.tracks for i in track.keys() for j in track[i] if len(j) != 0 ] if times: max_time = max(times) else: max_time = 0 for track_num, track in enumerate(self.tracks): notes_on = [] controllers = [] new_track = [] # Change order of various events. E.g: # delayevt1 -> noninvertevt1 -> delayevt2 -> noninvertevt2. will be # changed to: noninvertevt1 -> delayevt1 -> noninvertevt2 -> delayevt2 # so is easier to revert. self.delay_event(track, new_track, "track_name", max_time) self.delay_event(track, new_track, "tempo", max_time) self.delay_event(track, new_track, "time_signature", max_time) self.delay_event(track, new_track, "key_signature", max_time) self.delay_event(track, new_track, "marker", max_time) self.delay_event(track, new_track, "program_change", max_time) self.delay_event(track, new_track, "text_meta", max_time) # Doc: The Controller Event signals the change in a MIDI channels state. # Controller events might be in pairs or just alone. Check both cases. # This inverts appeareance order. E.g: # noninvertevt1start -> evt1 -> noninvertevt1end -> noninvertevt2start -> evt2 -> noninvertevt2end # changes to: noninvertevt1end -> evt1 -> noninvertevt1start -> noninvertevt2end -> evt2 -> noninvertevt2start. for i, evt in enumerate(track['control_change']): # First check if the controller is invertible (like pedals). if evt[1].data[0] in invertible_controllers: controller_found = False # A value in the range 0 - 63 is off, and 64 - 127 is on. if evt[1].data[1] >= 64 and evt[1].data[1] <= 127: controllers.append(evt) tmp = midi.ControlChangeEvent(tick=evt[1].tick, channel=evt[1].channel, data=[evt[1].data[0], 0]) new_track.append((evt[0], tmp)) else: for j, controller in enumerate(controllers): # Look for controller match. if controller[1].data[0] == evt[1].data[0]: new_track.append((evt[0], controller[1])) controllers.pop(j) controller_found = True break if not controller_found: print( "Warning: No matching controller found on invertible controller." ) tmp = midi.ControlChangeEvent( tick=evt[1].tick, channel=evt[1].channel, data=[evt[1].data[0], 127]) new_track.append((evt[0], tmp)) # If it's not invertible just append it changing the order. else: if i == len(track['control_change']) - 1: new_track.append((max_time, evt[1])) else: new_track.append( (track['control_change'][i + 1][0], evt[1])) if len(controllers) != 0: # The unmatched ones are probably at the end of the track. print("Warning: Track " + str(track_num) + ", " + str(len(controllers)) + " controller event/s unmatched.") for c in controllers: new_track.append((max_time, c)) # Revert notes (invert appearance order). for evt in track['note_on']: # Notes on. if evt[1].data[1] != 0: notes_on.append(evt) tmp = midi.NoteOnEvent(tick=evt[1].tick, channel=evt[1].channel, data=[evt[1].data[0], 0]) new_track.append((evt[0], tmp)) # Notes off. else: note_found = False for i, note in enumerate(notes_on): # Look for note match. if note[1].data[0] == evt[1].data[0]: new_track.append((evt[0], note[1])) notes_on.pop(i) note_found = True break if not note_found: print("Warning: No matching note found.") tmp = midi.NoteOnEvent(tick=evt[1].tick, channel=evt[1].channel, data=[evt[1].data[0], 100]) new_track.append((evt[0], tmp)) # The same as before. for evt in track['note_off']: note_found = False for i, note in enumerate(notes_on): # Look for note match. if note[1].data[0] == evt[1].data[0]: new_track.append((evt[0], note[1])) notes_on.pop(i) note_found = True break if not note_found: print("Warning: No matching note found.") tmp = midi.NoteOnEvent(tick=evt[1].tick, channel=evt[1].channel, data=[evt[1].data[0], 100]) new_track.append((evt[0], tmp)) if len(notes_on) != 0: print("Warning: Track " + str(track_num) + ", " + str(len(notes_on)) + " note/s unmatched.") # Lyrics won't be changed. for evt in track['lyric']: new_track.append(evt) # Sort and eliminate the empty time after the reversal. new_track.sort(key=lambda x: x[0], reverse=True) for i, evt in enumerate(new_track): t = max_time - evt[0] new_track[i] = (t, evt[1]) new_track_group.append(list(new_track)) # Find the time when the first note occurs and cut the silence between. if cut_silence: noteon_times = [ evt[0] for track in new_track_group for evt in track if isinstance(evt[1], midi.NoteOnEvent) ] if len(noteon_times) > 0: min_noteon = min(noteon_times) if min_noteon != 0: for i, track in enumerate(new_track_group): for j, evt in enumerate(track): t = evt[0] - min_noteon if t >= 0: new_track_group[i][j] = (t, evt[1]) self.open(read=new_track_group, open_file=False)
for j in range(len(r[i])): r[i][j] = int(r[i][j]) # print(r) # In[37]: pattern = midi.Pattern(format=1, resolution=480, tracks=[ midi.Track([ midi.TimeSignatureEvent(tick=0, data=[4, 2, 24, 8]), midi.KeySignatureEvent(tick=0, data=[0, 0]), midi.SetTempoEvent(tick=0, data=[7, 161, 32]), midi.ControlChangeEvent(tick=0, channel=0, data=[121, 0]), midi.ProgramChangeEvent(tick=0, channel=0, data=[0]), midi.ControlChangeEvent(tick=0, channel=0, data=[7, 100]), midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64]), midi.ControlChangeEvent(tick=0, channel=0, data=[91, 0]), midi.ControlChangeEvent(tick=0, channel=0,
def drum_matrix_to_midi(drum_matrix,tatums_per_beat,output_filename,midi_ref_file,notes=None): ''' write a drum pattern matrix to a midi file input: drum_matrix - drum onsets to be converted to midi [one drum per row, one tatum per column] tatums_per_beat - number of subdivisions per beat output_filename - file to write midi output to midi_ref_file - midi file to steal header info (tempo, etc.) from notes - (optional) the midi notes to write each drum column to ''' if notes is None: notes = [36, 38, 42, 46, 51] parsed_midi = midi.read_midifile(midi_ref_file) #gets a list of events parsed_midi.make_ticks_abs() #turns the ticks into absolute ms times events = parsed_midi[0] resolution = parsed_midi.resolution print 'resolution:', resolution tempo = 0 for e in events: if e.name == 'Set Tempo': tempo = e.get_bpm() print 'detected tempo:',tempo break if tempo is 0: print 'did not detect tempo' tatum = resolution/tatums_per_beat # ignore small amplitude onsets thresh = 0.05 * drum_matrix.max() onset_locs = np.where(drum_matrix > thresh) # convert tatums to ticks num_tatums = drum_matrix.shape[1] ticks = np.arange(num_tatums) * tatum # create note on/off events events = [] for i in xrange(len(onset_locs[0])): note = notes[onset_locs[0][i]] tick = ticks[onset_locs[1][i]] vel = int(max(0,min(127, 127 * drum_matrix[onset_locs[0][i],onset_locs[1][i]]))) on = midi.NoteOnEvent() on.channel = 9 on.set_pitch(note) on.set_velocity(vel) on.tick = tick events += [on] off = midi.NoteOffEvent() off.channel = 9 off.set_pitch(note) off.set_velocity(64) off.tick = tick + 60 events += [off] # create hihat footcontrol events # (for now just set all to max [closed hihat]) for t in ticks: val = 127 # all the way down control = midi.ControlChangeEvent() control.channel = 9 control.set_control(4) control.set_value(val) control.tick = t events += [control] # sort events in tick order inds = np.argsort([e.tick for e in events]) # reuse midi headers new_track = midi.Track(parsed_midi[0]) for e in parsed_midi[0]: if e.name == 'Note Off' or e.name == 'Note On' or e.name == 'Control Change': new_track.remove(e) if e.name == 'End of Track': end_of_track = e new_track.remove(e) # set end of track to time of last event + one beat end_of_track.tick = ticks[-1] + resolution for i in inds: new_track += [events[i]] new_track += [end_of_track] parsed_midi[0] = new_track parsed_midi[0].make_ticks_rel() midi.write_midifile(output_filename,parsed_midi) return parsed_midi
def csv_to_midi(self, fpath): track = midi.Track() track.append(midi.SequencerSpecificEvent(tick=0, data=[5, 15, 9, 70, 200])) track.append(midi.SequencerSpecificEvent(tick=0, data=[5, 15, 6, 71, 101, 110, 101, 114, 97, 108, 32, 77, 73, 68, 73])) track.append(midi.TrackNameEvent(tick=0, text='Acoustic Grand Piano High', data=[65, 99, 111, 117, 115, 116, 105, 99, 32, 71, 114, 97, 110, 100, 32, 80, 105, 97, 110, 111, 32, 72, 105, 103, 104])) track.append(midi.ProgramChangeEvent(tick=0, channel=0, data=[0])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[7, 127])) track.append(midi.ControlChangeEvent(tick=3, channel=0, data=[100, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[101, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[100, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[101, 64])) track.append(midi.ControlChangeEvent(tick=1, channel=0, data=[6, 12])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[6, 12])) track.append(midi.ControlChangeEvent(tick=1, channel=0, data=[38, 0])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[38, 0])) track.append(midi.NoteOnEvent(tick=5, channel=0, data=[67, 69])) df = pd.read_csv(fpath, index_col=0, names=["Tick", "Data1", "Data2","Evt_Type"], header=0) nrows = len(df.iloc[:, 0]) for i in range(nrows): if df.Evt_Type[i] == "p": evt = midi.events.ProgramChangeEvent(tick=int(df.Tick[i]), data=[int(df.Data1[i]) + 50, int(df.Data2[i])]) track.append(evt) if df.Evt_Type[i] == "c": evt = midi.events.ControlChangeEvent(tick=int(df.Tick[i]), data=[int(df.Data1[i]), int(df.Data2[i])]) track.append(evt) if df.Evt_Type[i] == "n": evt = midi.events.NoteOnEvent(tick=int(df.Tick[i]), data=[int(df.Data1[i]), int(df.Data2[i])]) track.append(evt) track.append(midi.events.EndOfTrackEvent()) for t in track: print(t) self.tracks_to_mid([track], "output_test.mid")
import midi MARY_MIDI = midi.Pattern( tracks=[[ midi.TimeSignatureEvent(tick=0, data=[4, 2, 24, 8]), midi.KeySignatureEvent(tick=0, data=[0, 0]), midi.EndOfTrackEvent(tick=1, data=[]) ], [ midi.ControlChangeEvent(tick=0, channel=0, data=[91, 58]), midi.ControlChangeEvent(tick=0, channel=0, data=[10, 69]), midi.ControlChangeEvent(tick=0, channel=0, data=[0, 0]), midi.ControlChangeEvent(tick=0, channel=0, data=[32, 0]), midi.ProgramChangeEvent(tick=0, channel=0, data=[24]), midi.NoteOnEvent(tick=0, channel=0, data=[64, 72]), midi.NoteOnEvent(tick=0, channel=0, data=[55, 70]), midi.NoteOnEvent(tick=231, channel=0, data=[64, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[62, 72]), midi.NoteOnEvent(tick=231, channel=0, data=[62, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[60, 71]), midi.NoteOnEvent(tick=231, channel=0, data=[60, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[62, 79]), midi.NoteOnEvent(tick=206, channel=0, data=[55, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[62, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[64, 85]), midi.NoteOnEvent(tick=0, channel=0, data=[55, 79]), midi.NoteOnEvent(tick=231, channel=0, data=[64, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[64, 78]), midi.NoteOnEvent(tick=231, channel=0, data=[64, 0]), midi.NoteOnEvent(tick=25, channel=0, data=[64, 74]), midi.NoteOnEvent(tick=462, channel=0, data=[55, 0]),
def instrument_num(instrument): """Given a GUS patch name, get the MIDI instrument number. For percussion instruments, the instrument number is offset by 128. """ for key, name in GUS_INSTR_PATCHES.items(): if name == instrument: return key raise Exception("Unknown instrument %s" % instrument) pattern = midi.Pattern(resolution=48) track = midi.Track() track.append(midi.ControlChangeEvent(tick=0, channel=9, data=[7, 92])) time = 500 for group in SIMILAR_GROUPS: # Don't bother with special effects. # if group[0] == 'blank': # continue print("Group: ") empty = True for instrument in group: inum = instrument_num(instrument) # For normal instruments, play a couple of different notes. # For percussion instruments, play a couple of note on # the percussion channel.
def finish(self, filename): # "All Notes End" event self.track.append(midi.ControlChangeEvent(tick=0, control=123)) self.track.append(midi.EndOfTrackEvent(tick=1)) midi.write_midifile(filename, self.pattern)
def writemidi(self, filedir=""): # sorteer de events van abs ticks # gooit alle tracks en time signatures in track [0] # pak de track naam if self.texts[0][0].text != "": trackname = MIDI.TrackNameEvent(text=self.texts[0][0].text, tick=0) trackname.absoluteticks = 0 # dunno werkt niet voor een of andere reden trackname.data = [] i = 0 while i < len(self.texts[0][0].text): trackname.data.append(ord(self.texts[0][0].text[i])) i += 1 tracks = [[trackname]] del trackname # verwijderd de naam als de hierboven genoteerde naam opnieuw wordt gebruikt else: tracks = [[]] # gooi alles in track [0] tracks[0] += self.texts[0][ 1:] + self.tempos + self.timesignatures + self.notes[0] # sorteer alles tracks[0].sort(key=operator.attrgetter('absoluteticks')) # pakt de instrument if self.channels[0] != 9 and self.instruments[0]: tracks[0].insert( 0, MIDI.ProgramChangeEvent(value=self.instruments[0], channel=self.channels[0])) for i in range(1, len(self.notes)): # sorteer de tracks # pak de track naam if self.texts[i][0].text != "": trackname = MIDI.TrackNameEvent(text=self.texts[i][0].text, tick=0) # dunno dit werkt niet voor een of andere reden trackname.data = [] trackname.absoluteticks = 0 j = 0 while j < len(self.texts[i][0].text): trackname.data.append(ord(self.texts[i][0].text[j])) j += 1 tracks.append([trackname]) del trackname # verwijderd de naam als de hierboven genoteerde naam opnieuw wordt gebruikt else: tracks.append([]) # pak de instrument tracks[i] += self.texts[i][1:] + self.notes[i] tracks[i].sort(key=operator.attrgetter('absoluteticks')) if self.channels[i] != 9 and self.instruments[i]: tracks[i].insert( 0, MIDI.ProgramChangeEvent(value=self.instruments[i], channel=self.channels[i])) # kijk of de lokale ticks goed zijn tickdivisor = config.EDITresolution for i in range(len(tracks)): tracks[i].insert( 0, MIDI.ControlChangeEvent(tick=0, channel=self.channels[i], data=[7, 127])) for track in tracks: previouseventabsoluteticks = 0 for event in track: try: thiseventabsoluteticks = int(event.absoluteticks) except AttributeError: thiseventabsoluteticks = 0 # aantal ticks in vergelijking tot voorgaande ticks en current ticks tickmeoff = thiseventabsoluteticks - previouseventabsoluteticks event.tick = tickmeoff # om te kijken hoe klein de resolutie is tickdivisor = gcd(tickdivisor, tickmeoff) # set de ticks voor de volgende event(midi) previouseventabsoluteticks = thiseventabsoluteticks if config.EDITresolution % tickdivisor: Error( " min RESOLUTON kan niet gedeeld worden door EDITresolution. er is iets gaande " ) newpattern = MIDI.Pattern(resolution=config.EDITresolution / tickdivisor) for track in tracks: if tickdivisor > 1: for event in track: # deel de relatieve ticks event.tick /= tickdivisor # laat abs ticks in de edit resolution if track[-1].name != "End of Track": # voeg het einde van een track hier als het er niet is track.append( MIDI.EndOfTrackEvent(tick=config.EDITresolution / tickdivisor)) newpattern.append(MIDI.Track(track)) if filedir == "": MIDI.write_midifile(self.midifile, newpattern) else: MIDI.write_midifile(filedir, newpattern)
def notes_only_csv_to_mid(self, fpath): track = midi.Track() track.append(midi.SequencerSpecificEvent(tick=0, data=[5, 15, 9, 70, 200])) track.append(midi.SequencerSpecificEvent(tick=0, data=[5, 15, 6, 71, 101, 110, 101, 114, 97, 108, 32, 77, 73, 68, 73])) track.append(midi.TrackNameEvent(tick=0, text='Acoustic Grand Piano High', data=[65, 99, 111, 117, 115, 116, 105, 99, 32, 71, 114, 97, 110, 100, 32, 80, 105, 97, 110, 111, 32, 72, 105, 103, 104])) track.append(midi.ProgramChangeEvent(tick=0, channel=0, data=[0])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[10, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[7, 127])) track.append(midi.ControlChangeEvent(tick=3, channel=0, data=[100, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[101, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[100, 64])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[101, 64])) track.append(midi.ControlChangeEvent(tick=1, channel=0, data=[6, 12])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[6, 12])) track.append(midi.ControlChangeEvent(tick=1, channel=0, data=[38, 0])) track.append(midi.ControlChangeEvent(tick=0, channel=0, data=[38, 0])) track.append(midi.NoteOnEvent(tick=5, channel=0, data=[67, 69])) df = pd.read_csv(fpath, index_col=0, names=["Tick", "Data1", "Data2","Evt_Type"], header=0) nrows = len(df.iloc[:, 0]) oor = False for i in range(nrows): tick = int(abs(df.iloc[i, 0])) d1 = int(abs(df.iloc[i, 1])) d2 = int(abs(df.iloc[i, 2])) if tick > 256 or tick < 0 or d1 > 256 or d1 < 0 or d2 > 256 or d2 < 0: print("Note in position {} out of range".format(str(i))) break evt = midi.events.NoteOnEvent(tick=tick, data=[d1, d2]) track.append(evt) track.append(midi.events.EndOfTrackEvent()) for t in track: print(t) self.tracks_to_mid([track], "output_test.mid")