First note not playing


(I think this has discussed earlier but since I just upgraded to Tracktion Engine 2.0 I thought it might be justified to bring it up again.)

When starting playback (using transport.playSectionAndReset), often the first MIDI note is not played. It is probably some kind of race/timing issue since sometimes (in a seemingly random fashion) the note is played as expected.

Playing from an earlier position, such as a few milliseconds earlier, does not help in general, although backing up far enough (say 100 ms) works around the problem.

I noticed this thread:

but I don’t think this is the same problem. I tried logging incoming messages in the synth and the NoteOn of the first note never arrives (however the NoteOff arrives).

Any suggestions?

Does it happen if you just use the standard “play” function?

Yes. In order to get the same behavior, I tried now to first set the transport and then calling play:

transport.position = startTime;;

I also tried to insert a Thread:sleep(200) between setting the position and calling play but that had no effect.

Can you replicate this in any of the demos? I can’t say we’ve seen this in Waveform so I’d need a reproducible case before I look in to it.

Allright, I’ll try!

Are the demos supposed to work with TE 2.0? I get some compilation errors

Unknown type name 'Engine'; did you mean 'tracktion::Engine'?
No template named 'DemoTypeBase'

I also had to change to C++17 (default still seems to be C++14)

How are you building them?
You need to use cmake now. They should all work if you cd in to the examples/DemoRunner dir and then cmake -B build etc.

Oh, are you trying to build the demo header files individually? They’re all part of the same DemoRunner now (expect the Engine In Plugin example).

Ok, thanks, I built the DemoRunner using CMake and added a new example, attached below.

The code may look a bit weird since I tried to use the same chain as I use in my application (in particular loading the MIDI clip via a base64-encoded MIDI file).

Setup by loading the demo, press the “Create MIDI Clip” button and add a 4OSC synth to the track. Now, pressing the “Move to first note” button followed by “Play” reproduces the problem: the first note is sometimes played, sometimes not.

MidiPlaybackDemo.h (12.6 KB)

Ok, I think I’ve figured out what’s happening here and it’s multi-faceted.

Firstly, it’s to do with the 'createMessagesForTime` function which gets called when there is a break in playback continuity (e.g. when you press play). Here is the output of that function:

	Controller Volume (coarse): 100 Channel 1 - 0
	Controller Pan position (coarse): 64 Channel 1 - 0
	Controller Volume (fine): 42 Channel 1 - 0
	Controller Pan position (fine): 0 Channel 1 - 0
	Controller Bank Select: 0 Channel 1 - 2.74656
	Controller Bank Select (fine): 0 Channel 1 - 2.74656
	Program change 53 Channel 1 - 2.74656
	Note on A#1 Velocity 100 Channel 1 - 0.0001

As you can see, all the CC messages are created and then the note-on message which if the first in the sequence. I imagine what is happening is that somewhere the buffer is getting iterated and once the timestamp is beyond the sample range for the buffer, the iteration stops, dropping the note-on at the end.

I could partially fix this by sorting the events so the note-on appears near the start, within the allowed time range… but I think the real fix is to create all the messages at the same time. I’ve added this now on the develop branch, can you check it out and see if it fixes your issues please?

This should also fix an issue where bank select and program change messages could be missed.

Thanks! I’m not sure I completely follow… but…

I could partially fix this by sorting the events so the note-on appears near the start, within the allowed time range…

Wouldn’t changing the event order affect how the first note sound?

Anyway, I’ll test your fix now!

Yes, I didn’t have to go down that route in the end though so the CC messages should come before the note-on still.

I tested now and so far it seems to work!

A side effect seems to be that if playback is started in the middle of a long note, that note is played as if it had its onset at the starting position. I don’t know if this is intentional but it feels a bit weird, at least for piano and other instruments with much attack.

I don’t see how it could work any other way though?
There’s no way in MIDI to say “start this note but not with a note-on message”.

It’s the only way to start long notes if you start them in the middle of the note. Otherwise they wouldn’t sound until the start of the note is played which would be a bit weird?

Otherwise they wouldn’t sound until the start of the note is played which would be a bit weird?

Isn’t that how it’s always worked before? I don’t know which way is better or worse but it is a change in behavior which in itself may be surprising.

No, pretty sure it worked the way I’ve described always. That’s how most other DAWs work as well isn’t it?

Hmm… you may be right… so would that mean that the reason that I thought otherwise is due to this bug always hitting me in the past??

A strange thing is that if I open the DemoRunner I built just before your fix, the MidiRecordingDemo has the behaviour you describe: starting in the middle of a note plays that note back. But my MidiPlaybackDemo does NOT do that! (I tried this by positioning the playhead with the mouse and then starting playback).

I thought it could have something to do with play vs playSectionAndReset but both examples start playback in the same way (using EngineHelpers::togglePlay which calls play).

Perhaps this is not so important and worth the time to dig into but I do find it strange that they behave differently!

I think it’s just that the MIDI sequences you were using had lots of CC messages in them which messed up the order to give you the bug described. Simpler sequences would have started in the middle of the note I believe.

Allright, that makes sense.

Again, many thanks for fixing this, those dropped notes had been bugging me for a long time!

Thanks for making a test case I could reproduce with!
It was indeed a tricky thing to track down, it took me all morning to understand what was going on.

Would you mind if I used that MIDI in a unit test in the repo?