Best Practice: Capture MIDI event timing from Host


#1

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();
		}
	}
}

#2

That looks correct!

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


#3

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 ]
	}

#4

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