Example #1
0
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)
Example #3
0
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
Example #4
0
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)
Example #5
0
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)