Thanks! This is all timely information since I have been working on
rewriting Midi file output in BP Console over the past two weeks. I've
ended up making many more changes than were strictly necessary. Some
will hopefully make the code more portable. Some involve just
refactoring duplicated code into separate functions, etc. There are
also two functions that I decided to rewrite from scratch because the
previous code appeared to have been copied from that MIDI file
specification document that you sent me, Bernard.
Unfortunately, I haven't finished this task yet because of various other
things that have come up.
Comments below...
On 8/13/20, 5:20 AM, Bernard Bel wrote:
> More on this topic:
>
> I was wrong regarding "division": in this MIDI file, division = 1000 is
> the correct value, provided that we keep the information contained in
> the first track, namely "TimeSig" and "Tempo".
Yes, I have noticed that BP2 always writes a division of 1000,
presumably for millisecond accuracy?
> The content of the MIDI file is attached in MF2T text format to make
> things clear.
>
> The original content was incorrect and MIDIjs refused to play it. It
> became correct after adding these metadata:
>
> 0 Meta TrkName "imported_1"
> ...
> 0 Meta TrkName "imported_2"
> ...
> 171250 Meta TrkEnd
>
> Therefore, tracks require (arbitrary) names and a "Meta TrkEnd" should
> be placed just before each "TrkEnd" instruction. At least, these are
> requirements for MIDIclass.php to produce a MIDI file accepted by MIDIjs.
The specification that you sent does not say that the Meta TrkName
events are required. It just says "Sequence Number and
Sequence/Track Name events, if present, must appear at time 0."
However, it should be easy to add them for compatibility if desired.
The "Meta TrkEnd" is required and BP2.9.8 should write it. But the
TrkEnd for the final track appears not to be written until the file is
closed. Therefore, I suspect that you may have copied the Midi file
before BP2 closed it. This is related to the problem reported by Rob
Moore. Perhaps it would be better to finish writing the file and close
it at the end of performance unless BP is in a mode where producing
multiple items is expected? Alternatively, the file could always be
closed at the end of performance and reopened and extended if necessary.
> When trying to import it to a sound-object prototype I got an error in
> MIDIclass.php indicating that the last event (a NoteOff) had been lost.
> The file was imported anyway but the last event was missing. We do get
> the last NoteOn timed 171250 ms but we miss its NoteOff around 180000 ms.
This is probably related to the same problem above. The last normal
Midi event also does not get written until the file is closed.
There are other related problems that I have discovered too. If
"Non-stop improvise" is on with the option to write each item to a new
MIDI file after it is performed then the track duration is equal to the
total elapsed time of the performance _including_ the time it takes the
user to enter a file name and click "Save"! It also appears that that
BP2 may be writing "0" for the time of the "Meta TrkEnd" event when it
should correspond to the track duration.
If it sounds like the second issue contradicts the first, I think it
because BP2 writes a lot of volume controller events at the end of each
track to "fade out" the performance and that lengthens the track if it
doesn't occur immediately. Is there a good reason for this fade out? I
can imagine it being confusing if the MIDI file is played back on a
synth and then the user tries to play notes on that synth outside of BP2
and hears no sound as a result.
> In addition, the "division" found by MIDIclass is "1000" yielding a
> faster playback. It should be set to "480" for a reason I still don't
> understand…
If I am remembering correctly, I think 480 is a common division of the
quarter note for MIDI sequencers. I always thought it strange too, but
if you factor 480 you get 2*2*2*2*2*3*5 which is a clue, I think. This
division allows quarter notes to be accurately subdivided into 128th
notes or any triplet or quintuplet division of the power-of-2 note
durations. So, 480 divisions could be more accurate for some music than
the 1000 divisions BP2 is using.
> Problems are identical when exporting type 0 and type 1 files. We should
> avoid type 0 anyway, even though BP always produces single-track files.
What is the reason for avoiding type 0?
> This trace might be helpful for the design of MIDIfile export on the
> console…
Yes, thank you for delving into these issues! I'll keep all of this in
mind as I work on the code.
Anthony
|