SimpleMIDIFile durations

I have some old midi files i recorded ages ago and I’m trying to extract all the basic data from them to turn them into Pbinds. Notes were a breeze, but when i try to fetch the duration values like so:

m = SimpleMIDIFile.read("/Users/L/aaa.mid");
m.p.trace(\dur).play;

i get values that do not really match the reality of the midi file, as i they were getting quantized. Is it because of the embedded tempo data in the .mid file? (the tempo is static, no fluctuations).
is there perhaps a better way of doing this than manually copying+pasting the values from the post window and then formatting them into arrays for a Pseq (which is what I’m doing)?

Thanks!

I have never used SimpleMIDIFile before but a quick test just now which yielded expected results. I did a 2 bar MIDI file in Ableton at 120 bpm. And got quarter notes to dur = 0.5 as expected, and also got non-quantized values for the notes I had move away from grid in Ableton.

So when you run the test above, do you only get quantized dur readings, even if the file has un-quantized notes?

i said quantized cause it was the only way i could make sense of it. it’s as if the durations i get are scaled up? so the relative space between note on events is right, but the tempo is not, if that makes sense?

When generating a MIDI file with Logic I get e.g. m.tempoMap = [ [ 0, 88.000023466673 ] ] for setting a tempo of 88 bpm in Logic, which is good. I am not sure how to apply the tempo information. I guess ideally you would want to play the pattern on a clock matching the tempo of original midifile or what?

as Thor said, we need to see the data to make sense of it. There is some rounding going on in MIDI files, as time data is stored as ticks. SimpleMIDIFile converts this to seconds if you make it play as a pattern. The number of ticks per quarter note is also specified in the file, different programs generate different resolutions (from the top of my head for example Sibelius generates a different resolution than Logic when exporting as SMF), and I suppose if the resolution is low the values could appear quantized. But to know if anything else is going on here we need to see the actual numbers I guess…

I think it is a different issue but @lionqueen correct me if I am wrong here.

If you have a MIDI file of say 88 BPM, how do you play it back on a clock equal to 88 BPM in SC, ie TempoClock(88/60), so that what was 16th notes and 8th notes in the original file shows up with dur values of 0.25 and 0.5 in the pattern?

In order to check whether or not the tempo being embedded in the MIDI file made a difference (which would make total sense) i tried the following: i exported the same bunch of MIDI note events from Reaper as MIDI files, one with and one without the tempo embedded. Then I loaded it into SimpleMIDIFile and traced the \dur as it played back each file.

with the tempo value embedded in the MIDI file i get:
0.2922075
0.8766225
0.6818175
0.77922
0.974025
0.584415
0.77922
0.8766225
0.6818175
1.753245
0.584415
1.55844
0.77922
1.55844
1.753245
0.584415
0.77922
0.77922
0.77922
0.8766225

without the tempo value embedded in the MIDI file i get:
0.375
1.125
0.875
1.0
1.25
0.75
1.0
1.125
0.875
2.25
0.75
2.0
1.0
2.0
2.25
0.75
1.0
1.0
1.0
1.125

Thanks

From those readings it looks like your original tempo was 77 bpm (0.375/0.2922075 * 60) and that the pattern is quantized to 32nds. So in that case, not embedding the tempo will default to 60 bpm = 1 bps and you get the correct durs in terms of fractions of a beat. What about exporting without embedding tempo and playing off a clock in the right tempo, in this case a TempoClock(0.375/0.2922075). Does that produce the correct timing?

i’m almost sure the original tempo was around 130 bpm, but i could be wrong.

i don’t normally specify or change any tempo values in SC, so i might be doing this wrong but would it be like this?

~bpm = TempoClock.tempo = 77 / 60;
m.p.trace(\dur).play(~bpm);

cause this gives me the same values no matter what number i put in the XX / 60 bit.

I think probably there are too many moving parts in this approach: dur will depend on both the MIDI file tempo and the TempoClock tempo.

It’s better IMO to dig into the help file and get the information directly out of the events.

To verify, I created a short 90bpm MIDI file, then:

m = SimpleMIDIFile.read("/home/dlm/Documents/REAPER Media/test.mid");

m.tempo
-> 89.999955000022  // ok

m.division
-> 960  // ok

~dursInFile = m.noteOnEvents.collect { |item| item[1] }.differentiate;
-> [0, 960, 960, 960, 960, 960, 960, 960]

~dursInFile / m.division  // 1 beat = 1 quarter note
-> [0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

I did create the file with quarter notes, so this result is correct.

Now if I get events out of m.p, it tells me that the note dur values are 0, 0.666667 etc. – because the clock is set to 60 bpm, and those quarter notes are at 90 bpm. So even in this simplest case, the pattern-based approach is confusing == probably best to not do it that way.

I also use Reaper. The dialog box says that the thing to be embedded is “tempo and time signature changes” – not just tempo generically.

It looks as though SC’s clock tempo is being changed to match the final tempo, resulting in similar duration ratios. But I don’t see where in the code that’s being done.

Long story short, get the rhythm values directly, rather than going through a more complex pattern mechanism.

hjh