in this section:
void timerCallback() override
{
auto currentTime = juce::Time::getMillisecondCounterHiRes() * 0.001 - startTime;
auto currentSampleNumber = (int) (currentTime * sampleRate); // [4]
for (const auto metadata : midiBuffer) // [5]
{
if (metadata.samplePosition > currentSampleNumber) // [6]
break;
auto message = metadata.getMessage();
message.setTimeStamp (metadata.samplePosition / sampleRate); // [7]
addMessageToList (message);
}
midiBuffer.clear (previousSampleNumber, currentSampleNumber - previousSampleNumber); // [8]
previousSampleNumber = currentSampleNumber; // [9]
}
in a case where metadata.samplePosition == currentSampleNumber
the midi message will be sent twice. this can be fixed by either changing:
if (metadata.samplePosition >= currentSampleNumber)
or
midiBuffer.clear (previousSampleNumber, (currentSampleNumber - previousSampleNumber) + 1); // [8]