def merge_tracks(tracks): merged_events = [] time_passed = 0 while True: result = get_next_events(tracks) for item in result: merged_events.append(item) if item.type == 'DeltaTime': time_passed += item.time if len(tracks) == 0: break midi_track = MidiTrack(0) midi_track.events = merged_events midi_track.length = time_passed for item in midi_track.events: item.track = midi_track if item.channel is not None: item.channel = 1 return [midi_track]
def merge_tracks(tracks): # longest = 0 # for track in tracks: # if len(track.events) > longest: # longest = len(track.events) merged_events = [] time_passed = 0 while True: result = get_next_events(tracks) for item in result: merged_events.append(item) if item.type == 'DeltaTime': time_passed += item.time if len(tracks) == 0: break midi_track = MidiTrack(0) midi_track.events = merged_events #TODO check effects of this #midi_track.length = time_passed for item in midi_track.events: item.track = midi_track if item.channel is not None: item.channel = 1 return [midi_track]
def quantized_to_midi(quantized_data): resulting_midi = MidiFile() resulting_midi.format = 0 resulting_midi.ticksPerQuarterNote = 400 track = MidiTrack(0) track.events.append(MidiEvent()) track.setChannel(1)
def write_starting_messages(track=MidiTrack(0)): no_time_spacing = DeltaTime(track, time=0) track.events.append(no_time_spacing) channel_prefix = MidiEvent(track=track, type='MIDI_CHANNEL_PREFIX') channel_prefix.data = b'\x00' track.events.append(channel_prefix) track.events.append(no_time_spacing) track_name = MidiEvent(track=track, type='SEQUENCE_TRACK_NAME') track_name.data = bytes("Quantized Midi", 'ascii') track.events.append(track_name) # track.events.append(no_time_spacing) # smtpe_offset = MidiEvent(track=track, type='SMTPE_OFFSET') # smtpe_offset.data = b'\x00\x00\x00\x00' # track.events.append(smtpe_offset) # # track.events.append(no_time_spacing) # tempo = MidiEvent(track=track, type='SET_TEMPO') # tempo.data = b'\x05\xe8\x19'#b'\x07\xA1\x20' # track.events.append(tempo) # track.events.append(no_time_spacing) # # time_signature = MidiEvent(track=track, type='TIME_SIGNATURE') # time_signature.data = b'\x04\x02\x18\x08' # track.events.append(time_signature) track.events.append(no_time_spacing) program_change = MidiEvent(track=track, type='PROGRAM_CHANGE') program_change.channel = 1 program_change.data = 1 track.events.append(program_change) # track.events.append(no_time_spacing) # # controller_change = MidiEvent(track=track, type='CONTROLLER_CHANGE') # controller_change.channel = 1 # controller_change.parameter1 = 64 # controller_change.parameter2 = 127 # track.events.append(controller_change) # track.events.append(no_time_spacing) return track
predict[0,:,:,0] # %% #---------------------------------------------------- MIDI Write file ----------------------------------# composed = MidiFile() composed.ticks_per_beat = 96 track = MidiTrack() track.append(Message('note_on', note=64, velocity=64, time=0)) track.append(Message('note_on', note=62, velocity=64, time=200)) track.append(Message('note_on', note=60, velocity=64, time=200)) track.append(Message('note_off', note=64, velocity=64, time=200)) track.append(Message('note_off', note=62, velocity=64, time=200)) track.append(Message('note_off', note=60, velocity=64, time=200)) composed.tracks.append(track) composed.save('composed.mid') # %%
def make_midi(quantized_data, ticks_per_sixteenth_note): result = MidiFile() result.format = 0 result.ticksPerQuarterNote = ticks_per_sixteenth_note * 4 track = write_starting_messages(MidiTrack(0)) beats_passed = 0 notes_to_end = [] leading_delta_time_written = False last_event_written_at_beat = 0 for beat in quantized_data: to_write_end = find_notes_to_remove(notes_to_end) last_event_written_at_beat += int(end_notes(to_write_end, track, ( beats_passed - last_event_written_at_beat) * ticks_per_sixteenth_note) / ticks_per_sixteenth_note) for note in beat: if note[1] > 0: time = (beats_passed - last_event_written_at_beat) * ticks_per_sixteenth_note spacing = DeltaTime(track=track, time=time) track.events.append(spacing) last_event_written_at_beat = beats_passed note_on = MidiEvent(track=track, type=ChannelVoiceMessages.NOTE_ON) note_on.velocity = 50 note_on.pitch = note[0] note_on.channel = 1 track.events.append(note_on) notes_to_end.append(note) beats_passed += 1 # toRemove = [] # # for note in notes_to_end: # if note[1] == 0: # time = (beats_passed - last_event_written_at_beat) * ticks_per_sixteenth_note # spacing = DeltaTime(track=track, time=time) # track.events.append(spacing) # # last_event_written_at_beat = beats_passed # # note_off = MidiEvent(track=track, type=ChannelVoiceMessages.NOTE_OFF) # note_off.pitch = note[0] # note_off.channel = 1 # note_off.parameter2 = 0 # toRemove.append(note) # # note[1] -= 1 # beats_passed += 1 # # for note in toRemove: # if note[1] <= 0: # notes_to_end.remove(note) # end_notes(notes_to_end, track, ticks_per_sixteenth_note * 2) end_notes(notes_to_end, track, ticks_per_sixteenth_note) end_track(track) result.tracks.append(track) return result
def write_midi(pitch_block, duration_block, outfile="out.mid", qpm_multiplier=1024, tempo_multiplier=1.0): # Assumes any element with from music21.midi import MidiTrack, MidiFile, MidiEvent, DeltaTime # duration, pitch, velocity qpm_mult = qpm_multiplier all_mt = [] for i in range(pitch_block.shape[0]): mt = MidiTrack(1) t = 0 t_last = 0 pitch_slice = pitch_block[i, :] duration_slice = duration_block[i, :] beat_slice = list((qpm_mult * duration_slice).astype("int32")) pitch_slice = list(pitch_slice.astype("int32")) for d, p in zip(beat_slice, pitch_slice): if (p == -1) or (d == -1): # bypass continue dt = DeltaTime(mt) dt.time = t - t_last mt.events.append(dt) me = MidiEvent(mt) me.type = "NOTE_ON" me.channel = 1 me.time = None me.pitch = p me.velocity = 90 mt.events.append(me) # add note off / velocity zero message dt = DeltaTime(mt) dt.time = d # add to track events mt.events.append(dt) me = MidiEvent(mt) me.type = "NOTE_ON" me.channel = 1 me.time = None me.pitch = p me.velocity = 0 mt.events.append(me) t_last = t + d t += d # add end of track dt = DeltaTime(mt) dt.time = 0 mt.events.append(dt) me = MidiEvent(mt) me.type = "END_OF_TRACK" me.channel = 1 me.data = '' mt.events.append(me) all_mt.append(mt) mf = MidiFile() mf.ticksPerQuarterNote = int(tempo_multiplier * qpm_mult) for mt in all_mt: mf.tracks.append(mt) mf.open(outfile, 'wb') mf.write() mf.close()
""" return int(round(seconds_from_start * ticks_per_second - offset_s)) # TODO rename to reflect it will update as it gets a sufficient amount of # messages for each update (at a note off for each on, etc) first_message_time_s = None curr_time_s = 0.0 # TODO TODO test case where a note actually starts (for example) a quarter note # past 1.1.1 in ableton (or anything > 1.1.1) last_ticks = 0 # TODO test w/ at least pitch bends, if i want to support that. # other cases with issues? note_num2start_data = dict() # TODO why was index required here? docs seem to indicate it's a kwarg.... midi_track = MidiTrack(0) # TODO TODO worth converting the stream to a score? if so, what fns to use? def process_msg(msg): """ Adds a new `music21.midi.Note` to `score` (`music21.stream.Score`) if it complete a note, otherwise just updates `curr_time_s`. Argument `msg` should be a `mido.Message` """ global first_message_time_s global last_ticks global curr_time_s if first_message_time_s is None: first_message_time_s = msg.time # This is assuming that the time is tracked by adding all the delta times