wazenmai / MIDI-BERT

This is the official repository for the paper, MidiBERT-Piano: Large-scale Pre-training for Symbolic Music Understanding.
MIT License
176 stars 22 forks source link

How to convert the CP-Word of this project into MIDI ? #13

Closed li-car-fei closed 9 months ago

li-car-fei commented 1 year ago

I try to write a function for it, but I do not know is it right :

def write_midi(words, path_outfile, word2event):
    class_keys = word2event.keys()
    midi_obj = miditoolkit.midi.parser.MidiFile()

    # global tempo
    midi_obj.tempo_changes.append(TempoChange(tempo=119, time=0))

    bar_cnt = 0

    all_notes = []

    for i in range(len(words)):
        vals = []
        for kidx, key in enumerate(class_keys):
            vals.append(word2event[key][words[i][kidx]])
        # print(vals)

        if vals[0].split(' ')[-1] == 'New':
            bar_cnt += 1
        if (vals[0].split(' ')[-1] == 'New') or (vals[0].split(' ')[-1] == 'Continue'):
            position_ = vals[1].split(' ')[-1]
            if position_ != "<PAD>" and position_ != "<MASK>":
                position = int(position_.split('/')[0]) - 1
            else:
                continue

            duration_ = vals[3].split(' ')[-1]
            if duration_ != "<PAD>" and duration_ != "<MASK>":
                duration = int(duration_) * 60
                if duration == 0:
                    duration = 60
            else:
                continue

            pitch_ = vals[2].split(' ')[-1]
            if pitch_ != "<PAD>" and pitch_ != "<MASK>":
                pitch = int(pitch_)
            else:
                continue

            st = bar_cnt * BAR_RESOL + position * TICK_RESOL

            et = st + duration
            all_notes.append(miditoolkit.Note(velocity=60 pitch=pitch, start=st, end=et))

    # save midi
    piano_track = Instrument(0, is_drum=False, name='piano')
    piano_track.notes = all_notes
    midi_obj.instruments = [piano_track]
    midi_obj.dump(path_outfile)

the velocity is set to default 60

sophia1488 commented 1 year ago

Hi sorry for the late reply. Are you using version 1 (midi-score) or version 2 (midi-performance)? For version 1, please refer to this code. It extracts melody MIDI given original MIDI, and you can adjust it to suit your needs. If it's version 2, I have not pushed the code yet, and I'll try to update it this week.

I didn't run your code above, but it looks fine. If you can preprocess your generated midi to the same CP, then it should be alright!

li-car-fei commented 1 year ago

Is the duration value multiplied by 60 and then output? In this case, the maximum duration will reach 3600, is it too long?