def tuple_events_to_midi(events, save_path, tick_resolution=utils.DEFAULT_RESOLUTION): midi = miditoolkit.midi.parser.MidiFile() # Notes notes = [] tempo_changes = [] prev_tempo = None for e in events: # velocity = e.Velocity * 4 velocity = int(utils.DEFAULT_VELOCITY_BINS[e.Velocity]) pitch = e.Pitch ticks_per_bar = tick_resolution * 4 st = int( int(e.Bar) * ticks_per_bar + (Fraction(e.Position) * ticks_per_bar)) # et = st + e.Duration * 60 et = st + int(utils.DEFAULT_DURATION_BINS[e.Duration]) notes.append(miditoolkit.Note(velocity, pitch, st, et)) if e.Tempo != prev_tempo: prev_tempo = e.Tempo tempo_changes.append( miditoolkit.midi.containers.TempoChange(e.Tempo, st)) midi.ticks_per_beat = tick_resolution # write instrument inst = miditoolkit.midi.containers.Instrument(0, is_drum=False) inst.notes = notes midi.instruments.append(inst) # temp_tempos.append(miditoolkit.midi.containers.TempoChange(bpm, st)) # midi.tempo_changes = temp_tempos # Tempo changes midi.tempo_changes = tempo_changes midi.dump(save_path)
def write_midi(words, word2event, output_path, prompt_path=None): events = word_to_event(words, word2event) # get downbeat and note (no time) temp_notes = [] temp_chords = [] temp_tempos = [] for i in range(len(events)-3): if events[i].name == 'Bar' and i > 0: temp_notes.append('Bar') temp_chords.append('Bar') temp_tempos.append('Bar') elif events[i].name == 'Position' and \ events[i+1].name == 'Note Velocity' and \ events[i+2].name == 'Note On' and \ events[i+3].name == 'Note Duration': # start time and end time from position position = int(events[i].value.split('/')[0]) - 1 # velocity index = int(events[i+1].value) velocity = int(DEFAULT_VELOCITY_BINS[index]) # pitch pitch = int(events[i+2].value) # duration index = int(events[i+3].value) duration = DEFAULT_DURATION_BINS[index] # adding temp_notes.append([position, velocity, pitch, duration]) elif events[i].name == 'Position' and events[i+1].name == 'Chord': position = int(events[i].value.split('/')[0]) - 1 temp_chords.append([position, events[i+1].value]) elif events[i].name == 'Position' and \ events[i+1].name == 'Tempo Class' and \ events[i+2].name == 'Tempo Value': position = int(events[i].value.split('/')[0]) - 1 if events[i+1].value == 'slow': tempo = DEFAULT_TEMPO_INTERVALS[0].start + int(events[i+2].value) elif events[i+1].value == 'mid': tempo = DEFAULT_TEMPO_INTERVALS[1].start + int(events[i+2].value) elif events[i+1].value == 'fast': tempo = DEFAULT_TEMPO_INTERVALS[2].start + int(events[i+2].value) temp_tempos.append([position, tempo]) # get specific time for notes ticks_per_beat = DEFAULT_RESOLUTION ticks_per_bar = DEFAULT_RESOLUTION * 4 # assume 4/4 notes = [] current_bar = 0 for note in temp_notes: if note == 'Bar': current_bar += 1 else: position, velocity, pitch, duration = note # position (start time) current_bar_st = current_bar * ticks_per_bar current_bar_et = (current_bar + 1) * ticks_per_bar flags = np.linspace(current_bar_st, current_bar_et, DEFAULT_FRACTION, endpoint=False, dtype=int) st = flags[position] # duration (end time) et = st + duration notes.append(miditoolkit.Note(velocity, pitch, st, et)) # get specific time for chords if len(temp_chords) > 0: chords = [] current_bar = 0 for chord in temp_chords: if chord == 'Bar': current_bar += 1 else: position, value = chord # position (start time) current_bar_st = current_bar * ticks_per_bar current_bar_et = (current_bar + 1) * ticks_per_bar flags = np.linspace(current_bar_st, current_bar_et, DEFAULT_FRACTION, endpoint=False, dtype=int) st = flags[position] chords.append([st, value]) # get specific time for tempos tempos = [] current_bar = 0 for tempo in temp_tempos: if tempo == 'Bar': current_bar += 1 else: position, value = tempo # position (start time) current_bar_st = current_bar * ticks_per_bar current_bar_et = (current_bar + 1) * ticks_per_bar flags = np.linspace(current_bar_st, current_bar_et, DEFAULT_FRACTION, endpoint=False, dtype=int) st = flags[position] tempos.append([int(st), value]) # write if prompt_path: midi = miditoolkit.midi.parser.MidiFile(prompt_path) # last_time = DEFAULT_RESOLUTION * 4 * 4 # note shift for note in notes: note.start += last_time note.end += last_time midi.instruments[0].notes.extend(notes) # tempo changes temp_tempos = [] for tempo in midi.tempo_changes: if tempo.time < DEFAULT_RESOLUTION*4*4: temp_tempos.append(tempo) else: break for st, bpm in tempos: st += last_time temp_tempos.append(miditoolkit.midi.containers.TempoChange(bpm, st)) midi.tempo_changes = temp_tempos # write chord into marker if len(temp_chords) > 0: for c in chords: midi.markers.append( miditoolkit.midi.containers.Marker(text=c[1], time=c[0]+last_time)) else: midi = miditoolkit.midi.parser.MidiFile() midi.ticks_per_beat = DEFAULT_RESOLUTION # write instrument inst = miditoolkit.midi.containers.Instrument(0, is_drum=False) inst.notes = notes midi.instruments.append(inst) # write tempo tempo_changes = [] for st, bpm in tempos: tempo_changes.append(miditoolkit.midi.containers.TempoChange(bpm, st)) midi.tempo_changes = tempo_changes # write chord into marker if len(temp_chords) > 0: for c in chords: midi.markers.append( miditoolkit.midi.containers.Marker(text=c[1], time=c[0])) # write midi.dump(output_path)
def event_to_midi(events, output_midi_path=None, is_full_event=False, return_tempos=False, enforce_tempo=False, enforce_tempo_evs=None): events = [ ConversionEvent(ev, is_full_event=is_full_event) for ev in events ] # print (events[:20]) assert events[0].name == 'Bar' temp_notes = [] temp_tempos = [] temp_chords = [] cur_bar = 0 cur_position = 0 for i in range(len(events)): if events[i].name == 'Bar': if i > 0: cur_bar += 1 elif events[i].name == 'Beat': cur_position = int(events[i].value) assert cur_position >= 0 and cur_position < DEFAULT_FRACTION elif events[i].name == 'Tempo': temp_tempos.append( TempoEvent(int(events[i].value), cur_bar, cur_position)) elif 'Note_Pitch' in events[i].name and \ (i+1) < len(events) and 'Note_Velocity' in events[i+1].name and \ (i+2) < len(events) and 'Note_Duration' in events[i+2].name: # check if the 3 events are of the same instrument temp_notes.append( NoteEvent(pitch=int(events[i].value), bar=cur_bar, position=cur_position, duration=int(events[i + 2].value), velocity=int(events[i + 1].value))) elif 'Chord' in events[i].name: temp_chords.append( ChordEvent(events[i].value, cur_bar, cur_position)) elif events[i].name in ['EOS', 'PAD']: continue print('# tempo changes:', len(temp_tempos), '| # notes:', len(temp_notes)) midi_obj = miditoolkit.midi.parser.MidiFile() midi_obj.instruments = [ miditoolkit.Instrument(program=0, is_drum=False, name='Piano') ] for n in temp_notes: midi_obj.instruments[0].notes.append( miditoolkit.Note(int(n.velocity), n.pitch, int(n.start_tick), int(n.start_tick + n.duration))) if enforce_tempo is False: for t in temp_tempos: midi_obj.tempo_changes.append( miditoolkit.TempoChange(t.tempo, int(t.start_tick))) else: if enforce_tempo_evs is None: enforce_tempo_evs = temp_tempos[1] for t in enforce_tempo_evs: midi_obj.tempo_changes.append( miditoolkit.TempoChange(t.tempo, int(t.start_tick))) for c in temp_chords: midi_obj.markers.append( miditoolkit.Marker('Chord-{}'.format(c.chord_val), int(c.start_tick))) for b in range(cur_bar): midi_obj.markers.append( miditoolkit.Marker('Bar-{}'.format(b + 1), int(DEFAULT_BAR_RESOL * b))) if output_midi_path is not None: midi_obj.dump(output_midi_path) if not return_tempos: return midi_obj else: return midi_obj, temp_tempos
def write_midi(words, word2event, output_path, prompt_path=None): events = word_to_event(words, word2event) # get downbeat and note (no time) temp_notes = [] temp_chords = [] last_meter = 0 for i in range(len(events) - 3): if events[i].name == 'Bar': if 'Bar' in temp_notes: last_bar_index = max(loc for loc, val in enumerate(temp_notes) if val == 'Bar') temp_notes[last_bar_index + 1] = last_meter temp_notes.append('Bar') temp_notes.append(last_meter) elif events[i].name == 'Position Bar' and \ events[i+1].name == 'Position Quarter' and \ events[i+2].name == 'Note On' and \ events[i+3].name == 'Note Duration' and \ events[i+4].name == 'Note Voice': # start time and end time from position last_meter = int(events[i].value) position_in_bar = int(events[i].value) - 1 position_in_quarter = int(events[i + 1].value.split('/')[0]) - 1 position = position_in_bar + position_in_quarter * MIN_DURATION # pitch pitch = int(events[i + 2].value) # duration duration = int(events[i + 3].value) duration = duration * MIN_DURATION #voice voice = int(events[i + 4].value) # adding temp_notes.append([position, pitch, duration, voice]) # get specific time for notes notes = [[] for i in range(0, MAX_VOICE)] current_bar = -1 meter = 0 # find max meter for note in temp_notes: if note != 'Bar' and type(note) is not list and meter < int(note): meter = int(note) time_to_current_bar = -meter for note in temp_notes: if note == 'Bar': current_bar += 1 time_to_current_bar += meter elif type(note) is list: position, pitch, duration, voice = note absolute_position_st = (time_to_current_bar + position) * DEFAULT_RESOLUTION absolute_position_et = (time_to_current_bar + position + duration) * DEFAULT_RESOLUTION notes[voice].append( miditoolkit.Note(100, pitch, int(absolute_position_st), int(absolute_position_et))) # write if prompt_path: # TODO midi = miditoolkit.midi.parser.MidiFile(prompt_path) # last_time = DEFAULT_RESOLUTION * 4 * 4 # note shift for note in notes: note.start += last_time note.end += last_time midi.instruments[0].notes.extend(notes) # tempo changes temp_tempos = [] for tempo in midi.tempo_changes: if tempo.time < DEFAULT_RESOLUTION * 4 * 4: temp_tempos.append(tempo) else: break for st, bpm in tempos: st += last_time temp_tempos.append(miditoolkit.midi.containers.TempoChange( bpm, st)) midi.tempo_changes = temp_tempos # write chord into marker if len(temp_chords) > 0: for c in chords: midi.markers.append( miditoolkit.midi.containers.Marker(text=c[1], time=c[0] + last_time)) else: midi = miditoolkit.midi.parser.MidiFile() midi.ticks_per_beat = DEFAULT_RESOLUTION # write instrument for inst_num in range(0, MAX_VOICE): inst = miditoolkit.midi.containers.Instrument(0, is_drum=False) inst.notes = notes[inst_num] midi.instruments.append(inst) # write tempo tempo_changes = [] tempo_changes.append(miditoolkit.midi.containers.TempoChange(100, 0)) midi.tempo_changes = tempo_changes # write meter meter_changes = [] meter_changes.append( miditoolkit.midi.containers.TimeSignature(time=0, numerator=meter, denominator=4)) midi.time_signature_changes = meter_changes # write midi.dump(output_path)
def write_midi(words, word2event, output_path, prompt_path=None): events = word_to_event(words, word2event) # get downbeat and note (no time) temp_notes = [] temp_chords = [] temp_tempos = [] last_meter = 0 for i in range(len(events) - 3): if events[i].name == 'Bar': if 'Bar' in temp_notes: last_bar_index = max(loc for loc, val in enumerate(temp_notes) if val == 'Bar') temp_notes[last_bar_index + 1] = last_meter temp_notes.append('Bar') temp_notes.append(last_meter) # temp_chords.append('Bar') if 'Bar' in temp_tempos: last_bar_index = max(loc for loc, val in enumerate(temp_tempos) if val == 'Bar') temp_tempos[last_bar_index + 1] = last_meter temp_tempos.append('Bar') temp_tempos.append(last_meter) elif events[i].name == 'Position Bar' and \ events[i+1].name == 'Position Quarter' and \ events[i+2].name == 'Note Velocity' and \ events[i+3].name == 'Note On' and \ events[i+4].name == 'Note Duration': # start time and end time from position last_meter = int(events[i].value) position_in_bar = int(events[i].value) - 1 position_in_quarter = int(events[i + 1].value.split('/')[0]) - 1 position = position_in_bar + position_in_quarter * MIN_DURATION # velocity velocity = int(events[i + 2].value) # pitch pitch = int(events[i + 3].value) # duration duration = int(events[i + 4].value) duration = duration * MIN_DURATION # adding temp_notes.append([position, velocity, pitch, duration]) # elif events[i].name == 'Position' and events[i+1].name == 'Chord': # position = int(events[i].value.split('/')[0]) - 1 # temp_chords.append([position, events[i+1].value]) elif events[i].name == 'Position Bar' and \ events[i+1].name == 'Position Quarter' and \ events[i+2].name == 'Tempo Class' and \ events[i+3].name == 'Tempo Value': last_meter = int(events[i].value) position_in_bar = int(events[i].value) - 1 position_in_quarter = int(events[i + 1].value.split('/')[0]) - 1 position = position_in_bar + position_in_quarter * MIN_DURATION if events[i + 2].value == 'slow': tempo = DEFAULT_TEMPO_INTERVALS[0].start + int( events[i + 3].value) * 5 elif events[i + 2].value == 'mid': tempo = DEFAULT_TEMPO_INTERVALS[1].start + int( events[i + 3].value) * 5 elif events[i + 2].value == 'fast': tempo = DEFAULT_TEMPO_INTERVALS[2].start + int( events[i + 3].value) * 5 temp_tempos.append([position, tempo]) # get specific time for notes notes = [] current_bar = -1 time_to_current_bar = 0 current_meter = 0 for note in temp_notes: if note == 'Bar': current_bar += 1 time_to_current_bar += current_meter elif type(note) is not list: current_meter = int(note) else: position, velocity, pitch, duration = note absolute_position_st = (time_to_current_bar + position) * DEFAULT_RESOLUTION absolute_position_et = (time_to_current_bar + position + duration) * DEFAULT_RESOLUTION notes.append( miditoolkit.Note(velocity, pitch, int(absolute_position_st), int(absolute_position_et))) # get specific time for chords # if len(temp_chords) > 0: # chords = [] # current_bar = 0 # for chord in temp_chords: # if chord == 'Bar': # current_bar += 1 # else: # position, value = chord # # position (start time) # current_bar_st = current_bar * ticks_per_bar # current_bar_et = (current_bar + 1) * ticks_per_bar # flags = np.linspace(current_bar_st, current_bar_et, DEFAULT_FRACTION, endpoint=False, dtype=int) # st = flags[position] # chords.append([st, value]) # get specific time for tempos tempos = [] meter = [] # teraz zaczyna sie od 'Bar_None' current_bar = -1 time_to_current_bar = 0 current_meter = 0 for tempo in temp_tempos: if tempo == 'Bar': current_bar += 1 time_to_current_bar += current_meter elif type(tempo) is not list: current_meter = int(tempo) if len(meter) == 0 or meter[-1][1] != current_meter: meter.append([ int(time_to_current_bar * DEFAULT_RESOLUTION), current_meter ]) else: position, value = tempo absolute_position_st = (time_to_current_bar + position) * DEFAULT_RESOLUTION tempos.append([int(absolute_position_st), int(value)]) # write if prompt_path: # TODO midi = miditoolkit.midi.parser.MidiFile(prompt_path) # last_time = DEFAULT_RESOLUTION * 4 * 4 # note shift for note in notes: note.start += last_time note.end += last_time midi.instruments[0].notes.extend(notes) # tempo changes temp_tempos = [] for tempo in midi.tempo_changes: if tempo.time < DEFAULT_RESOLUTION * 4 * 4: temp_tempos.append(tempo) else: break for st, bpm in tempos: st += last_time temp_tempos.append(miditoolkit.midi.containers.TempoChange( bpm, st)) midi.tempo_changes = temp_tempos # write chord into marker if len(temp_chords) > 0: for c in chords: midi.markers.append( miditoolkit.midi.containers.Marker(text=c[1], time=c[0] + last_time)) else: midi = miditoolkit.midi.parser.MidiFile() midi.ticks_per_beat = DEFAULT_RESOLUTION # write instrument inst = miditoolkit.midi.containers.Instrument(0, is_drum=False) inst.notes = notes midi.instruments.append(inst) # write tempo tempo_changes = [] for st, bpm in tempos: tempo_changes.append( miditoolkit.midi.containers.TempoChange(bpm, st)) midi.tempo_changes = tempo_changes # write meter meter_changes = [] for st, new_meter in meter: meter_changes.append( miditoolkit.midi.containers.TimeSignature(time=st, numerator=new_meter, denominator=4)) midi.time_signature_changes = meter_changes # write chord into marker # if len(temp_chords) > 0: # for c in chords: # midi.markers.append( # miditoolkit.midi.containers.Marker(text=c[1], time=c[0])) # write midi.dump(output_path)