Best Practice: Capture MIDI event timing from Host

I’ve been reading all of the tutorials and perusing the example code provided in the Projucer and have seen no clear example of how best to capture the host’s transport information. I did considerable searching through this forum and found enough hints from other posts to put together a code example that seems to work for me, that I thought might be helpful for other people trying to build a (MIDI) plug-in for a VST host.

I’ll post my code example below. I would appreciate any knowledgeable folks to confirm I’m on the right track with this, or suggest a better approach if mine is flawed in some way. Thanks in advance!

void VstplugInAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
	ScopedNoDenormals noDenormals;
	auto totalNumInputChannels  = getTotalNumInputChannels();
	auto totalNumOutputChannels = getTotalNumOutputChannels();

	buffer.clear();

	AudioPlayHead::CurrentPositionInfo hostInfo;
	this->getPlayHead()->getCurrentPosition(hostInfo);
	auto blockStartTime = hostInfo.timeInSamples;

	MidiMessage m;
	int offset;

	for (MidiBuffer::Iterator i(midiMessages); i.getNextEvent(m, offset);)
	{
		if (m.isNoteOn())
		{
			this->lastNoteNumber = m.getNoteNumber();
			this->lastNoteOnVelocity = m.getVelocity();
			this->lastNoteOnTS = blockStartTime + offset;
		}
		else if (m.isNoteOff())
		{
			this->lastNoteOffTS = blockStartTime + offset;
		}
		else if (m.isPitchWheel())
		{
			this->lastPitchWheelValue = m.getPitchWheelValue();
		}
		else if (m.isControllerOfType(1))
		{
			this->lastModWheelValue = m.getControllerValue();
		}
	}
}

That looks correct!

By the way there’s no need to use this-> for the member function/variables with C++!

1 Like

I’ll share with you my code to handle MIDI events at the current sample index when iterating over the audio buffer’s samples one-by-one.

This is useful for me, as I need to perform audio processing based on the MIDI input on a per-sample basis.

	MidiMessage midiMessage;
	int midiMessageTime;
	auto midiIt = MidiBuffer::Iterator(midiMessages);

	for (int i = 0; i < buffer.getNumSamples(); i++) {
		// fetch MIDI events that apply to the current timestamp
		midiIt.setNextSamplePosition(i);
		while (midiIt.getNextEvent(midiMessage, midiMessageTime) && midiMessageTime == i) {
			// we have a MIDI message that applies to the current timestamp
			// TODO: handle the MIDI message here
		}

		// [... process the current sample ]
	}
1 Like

Thanks to both of you for your prompt and helpful responses!

Thanks, I was wondering on the correct usage of the setNextSamplePosition. I got 90% ok, just missed the midiMEssageTime == theCurrenttime :wink: