For my project, I have taken midi files, and with the midi2dat function of SoundForge converted them to a matrix with 88 columns, 88 being the number of possible notes. The values in the columns are either 0 or the velocity of the note played. The sampling rate is 20Hz, meaning that the time interval between 2 rows is 50 milliseconds. After doing some modifications etc, I want to have a way to convert the pianoroll back into a MIDI file that I can listen at. What is the most efficient method to do so? Also, in terms of the Metainformation such as tempo etc, I would just copy the one from my initial midi file prior to the modifications made.
I tried following idea but the output mid file isn't even playable even if I put normal time.
import mido
import numpy as np
midi_file = mido.MidiFile(type=0)
pianoroll = np.genfromtxt('dataset/1.csv', delimiter=' ', dtype=int)
print(pianoroll)
track = mido.MidiTrack()
midi_file.tracks.append(track)
for i in range(pianoroll.shape[0]):
for j in range(pianoroll.shape[1]):
if pianoroll[i,j] > 0:
note_on = mido.Message('note_on', note=j, velocity=int(pianoroll[i,j]), time=int(???/20))
track.append(note_on)
# Change maybe to a note on event looking at prior column and checking if nonzero entry etc
if j < pianoroll.shape[1] - 1 and pianoroll[i,j+1] == 0:
note_off = mido.Message('note_off', note=j, velocity=0, time=int(??/20))
track.append(note_off)
midi_file.save('output.mid')
One issue with your code is that the time attribute of the note_on and note_off messages is not being set correctly. The time attribute represents the delta time in ticks since the last message, not the absolute time in seconds. You can calculate the delta time by keeping track of the time of the last message and subtracting it from the current time.
Here’s an example that shows how to convert a piano roll representation back into a MIDI file: