Problem with MIDI score not being exact

• Dec 15, 2022 - 16:27

I'm doing some computational analysis of rhythm, and I had to generate a Audio + MIDI rendition of Steve Reich's "Piano Phase" (I used Pd for that). Further down in my project I have to compare my computational analysis to the precise moment in the score. The problem is I can't get a faithful/exact (to the MIDI file), due to some problems in the durations of notes, that should be composed of a sequence of twelve 16th-notes on loop. I generated a small MIDI file to be easier to understand (please do not mind the silence it has in the beginning of the file "time=678"). These are the MIDI messages on the generated file:

Track 0: seq-track
MetaMessage('track_name', name='seq-track\x00', time=0)
note_on channel=0 note=64 velocity=100 time=678
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
note_on channel=0 note=74 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=64 velocity=100 time=4
note_on channel=0 note=64 velocity=0 time=48
note_on channel=0 note=73 velocity=100 time=4
note_on channel=0 note=73 velocity=0 time=48
note_on channel=0 note=71 velocity=100 time=4
note_on channel=0 note=71 velocity=0 time=48
note_on channel=0 note=66 velocity=100 time=4
note_on channel=0 note=66 velocity=0 time=48
note_on channel=0 note=74 velocity=100 time=4
MetaMessage('end_of_track', time=0)

As you can see, the duration of each note should be the same, but when I try to open it in MuseScore I get a score very different from my expectation, namely because the notes don't have the same duration. I attach the best 3 (of many) attempts to get a good rendition:
pic

The rendition would be (ideally) similar to the original rendition on Reich's stave:
pic

Can anyone help me?

Attachment Size
reich_original.png 124.42 KB
MuseScore_reichattempt.png 115.6 KB

Comments

In reply to by asp2022

While each event is nicely 48 ticks long and leaves a 4 tick gap with the next one, this totals to 52 ticks for a 16th and thus 208 ticks for a quarter note, but it also states in its header to use 192 ticks for a quarter note.

It is lacking tempo and time signature events on its track, and as such the standard says 4/4 and q = 120 must be assumed.
As such your durations don't end up on clean duration borders at all (Grid at 1/8th notes):
staff-1-grid.png

Try starting from the attached instead, where all I've done is to set the header to claim 208 ticks per quarter. This seems the easier fix than re-quantifying all events.

Attachment Size
stave1-208qTicks.mid 321 bytes

In reply to by jeetee

First of all, thank you so much for your help.
So the problem is in the header. How do you edit the header? (in something similar to HexEdit ou is there something more friendly for MIDI?)

I opened your midi file, and yes, it has the expected output, but unfortunately I can't depart from it.
Let me explain briefly what I'm trying to do, and see if you can point me in the right direction:
- I'm processing Reich's Piano Phase (please skip this part if you know the piece). It's composed of a) a sequence of 12 notes that should be played in loop at approximately 72 dotted quarter-note per minute; and b) an identical sequence loop that will start in sync with the first one and slowly accelerate thus dephasing from it. This is summarized in the original score, where it shows that (excluding the 1st measure) both voices start in sync (as in 2) and after a while (depending on the accelerando) they will be as in measures 3, 4, and so on.
pic
- I'm simulating this in PureData (except for measure 1, where only one sequence is being played), where I generate both MIDI tracks procedurally: track 1 corresponding to a) generating a 16th-note every 138 ms (which gives roughly the 96quarter-note-per-minute); and track 2 corresponding to b) generating a 16th-note every 137 ms (which gives roughly the 97quarter-note-per-minute).
- I don't give explicitly any indication of tempo or any header information for the MIDI file, that's with the Pd object, and it seems that the issue lies here! In fact, Reich explicitly avoids measure-related metric information, because he wants the musicians to avoid all musical accents. Nevertheless, we could assume a 6/8 measure by looking at the original score.
- Finally, I generate 2 audio tracks, mix them, and then I perform some onset detection analysis on this resulting waveform. My goal is to be able to show the full analysis (in a report) of the 6/7mins long and be able to focus on specific areas and show the corresponding "stage" (like in reich's score measure 2,3,4,...). Ideally, it would be as similar as possible to the original (although not necessarily with the 2 voices on each stave - some 16th-note are upwards and others are downwards).

So, in summary, I hope that by changing the header information in the complete MIDI files, I can accomplish that, do you think that'll be the case?

Thanks in advance.

Attachment Size
reichfullscore.png 637.32 KB

In reply to by asp2022

If your end goal is to reproduce that score visually, then I wouldn't bother with the MIDI import at all and just notate it out.
If you want a score that does this minimal time-shifting, then you're probably going past the limit of what standard notation can convey.

As for editing the header information I indeed used a hex editor.

In reply to by jeetee

I aim to show the right score on top of the real computational analysis. And as the latter is done on the real audio (done in Pd), I'd have to look into the score to understand musically what is happening at some particular time, e.g. at 15 seconds. (I cannot do it by ear, ie notate through what I'm listening to from the audio file).
Something like this (this is just a rough draft by hand to give you a better idea).
pic
But probably this is too much for any notation software.

Attachment Size
example.png 111.47 KB

Do you still have an unanswered question? Please log in first to post your question.