I’m pretty new at Matlab so would need a baby-steps explanation.
I have some MIDI data which looks a bit like this:
time on/off note
10 1 61
90 0 61
90 1 72
92 1 87
100 0 72
What I want to do is expand or ‘fill-in’ the gaps so that I have a row for every single moment in time, and I have columns which show which notes are on (there is often more than one note at the same time).
the ultimate goal is to do some calculations about the overall relationship between notes on (the harmonic dissonance) at a given time.
So I was thinking that maybe I needed a new column for every single possible note (there are 127), and then a 1 or 0 for every time. Or maybe I can just have a matrix which just tells me which notes are on (so the number of columns varies).
I wrote my own pseudo-code, but have no idea how to implement it. I suspect there is a simple function that can do this. Here is my pseudo-code:
start with 0, at time 0 in a new ‘notes-on matrix’
for numbers: 0 to n
if the number matches a number in the time column, go to the on/off column for that row.
if 1 in on/off column then copy number in notes column to ‘notes-on matrix’ for corresponding row
if 0 then don’t copy/do nothing.
if number doesn’t match number in time column
copy the previous row (which can be blank if there were no notes on).
for each row in the new ‘notes-on matrix’, arrange numbers low to high in different columns.
So can anyone tell me what to do?? I’m banging my head against a brick wall here!
Here’s a solution that will work even if the list is in a completely random order. It is based on the following idea: The cumulative sum of the vector
[0 1 0 0 -1 0 0]is[0 1 1 1 0 0 0]. This corresponds to “on” in time 2, and “off” in time 5. Now all we need to do is populate an array with1and-1, and run CUMSUM to transform it into an array that has, in each column, ones whenever the sound ison.I assume that there are 128 notes (0-127), and that you want to have one time step of silence (if all notes eventually end) at the very end. Note that Matlab starts counting at 1, so time 0 corresponds to row #1.
The previous solution, for completeness: