MIDI notes timing issue


I am currently developing a MIDI VST/AU plugin, I’m quite a newbie with Juce and I need a little advice.

I am having a MIDI timing problem with my plugin and I don’t understand where it is coming from. The position and length of the MIDI notes generated at the output of my plugin are not exactly what I expected.

As input, I inject cadenced and quantized notes to the sixteenth note, and of a duration equal to exactly sixteenth note. My plugin modifies the velocities of the incoming notes by applying a ratio and an offset to them. On output, the velocities are OK but the position and length of my MIDI notes are not always exactly what I expected. The problem seems to be with the host’s sample rate because in Ableton Live the micro time offsets only appear at 44100 Hz. When I work at 48000 Hz or other frequencies, everything seems to be fine.

To understand where the problem comes from, I created a very simple MIDI plugin which simply extracts the MIDI messages present in the MIDI buffer passed by the host in processBlock (), copies them into a new empty MIDI buffer and then swaps the two buffers at the end of processBlock (). I do see a concern about the position and length of my notes even with this very simple plugin, although the code does not do anything exceptional.

Has anyone seen the same problem with Juce ? Here is my processBlock() code :

void PluginProcessor::processBlock (juce::AudioBuffer<float>& audioBuffer, juce::MidiBuffer& midiBuffer)
	juce::MidiBuffer processedBuffer;

	for (const auto metadata : midiBuffer)
		auto midiMessage = metadata.getMessage();
		const auto samplePosition = metadata.samplePosition;
		processedBuffer.addEvent (midiMessage, samplePosition);

	midiBuffer.swapWith (processedBuffer);

Here are some screenshots of what I get in Ableton Live while testing this simple plugin :

Thank you in advance for your help. :slight_smile:


macOS Catalina 10.15.7
Juce 6.0.8
Xcode 12.4
Ableton Live Suite 11.0.2

I think that you are missing that even the simplest plugin introduces latency (the MIDI output is written in the next buffer). If the buffer size stays the same, the latency is lower with 48kHz.

1 Like

Hi Qfactor,
I thank you for your message and for these avenues of reflection.
I am quite aware of the phenomena related to audio latency but I do not think this is a problem here. Indeed, what I describe in my post looks more like jitter because the position and length of the notes vary differently from note to note, even though it is extremely thin. And in the sequence of notes processed by my plugin, some notes have positions and lengths that meet expectations.
As you rightly point out, any plugin induces some latency but here it should rather have the effect of shifting the position of all the notes, with a constant shift and without modifying their length, which is not the case. In addition, the latency is normally automatically compensated in Ableton Live and therefore should not interact in this scenario. To verify this, I carried out the same experiment with Live’s “Velocity” MIDI device and the notes generated at the output of the device are perfectly in line with expectations, whatever the sampling frequency used.
Going back to my test VST plugin, I extract the position of the incoming MIDI notes from the buffer provided by the host with this line of code:
const auto samplePosition = metadata.samplePosition;
I use these time positions without modifying them to create my notes in the new processedBuffer buffer. So the notes generated by the plugin should be perfectly superimposable on the input notes, right?
It is mainly for this reason that I do not understand why the position and length of my notes vary a bit when exiting the plugin, there is no apparent reason for this to happen. Could it be due to Juce?

Try in another DAW just in case

Hi Olivier,
I also do my tests in Bitwig Studio, mainly because the User VST folder is automatically updated every time I rebuild my plugin, very handy ! :wink: I also have some little variations, mainly on the length of the output notes. So I guess the answer is rather to be found at Juce side !

Could this simply be a limitation of the sample rate vs. timing resolution? Are your lengths off by more than 1 sample? Because if you calculate the length of a 1/16 note in samples, it might come out as 2756.25 for 44.1 kHz whereas for 48 kHz, it would be an even 3000. So now the 2756.25 gets rounded down to 2756, making your not a quarter sample shorter.

If we’re really talking about these rounding differences (off by 1 sample), then is it even worth worrying about?