ASPiK SDK
Loading...
Searching...
No Matches
MIDI Message Processing

MIDI messages are sent to the PluginCore's buffer processing function as part of the normal The Buffer Processing Cycle and arrive in a queue, timestamped with the sample number corresponding to locations in the DAW I/O buffers. The PluginBase implements the processAudioBuffers method and fires MIDI events into the processing loop depending on your audio processing method. The midiEvent structure holds the information for each MIDI message and has many member variables; here I am only showing the normal message members and the sample-accurate index value:

struct midiEvent
{
// --- constructors and overloaded = operators removed here
//
uint32_t midiMessage = 0;
uint32_t midiChannel = 0;
uint32_t midiData1 = 0;
uint32_t midiData2 = 0;
uint32_t midiSampleOffset = 0;
};
Information about a MIDI event.
Definition: pluginstructures.h:562
uint32_t midiData1
BYTE data 1 as UINT.
Definition: pluginstructures.h:643
uint32_t midiMessage
BYTE message as UINT.
Definition: pluginstructures.h:641
uint32_t midiChannel
BYTE channel as UINT.
Definition: pluginstructures.h:642
uint32_t midiSampleOffset
sample offset of midi event within audio buffer
Definition: pluginstructures.h:645
uint32_t midiData2
BYTE data 2 as UINT.
Definition: pluginstructures.h:644

Regardless of the processing paradigm, the same MIDI function is usd to process these messages and uses a simple midiEvent structure to store the message data:

//
{
// --- IF PROCESSING AUDIO BLOCKS: push into vector for block processing
{
processBlockInfo.pushMidiEvent(event);
return true;
}
// --- IF PROCESSING AUDIO FRAMES: decode AND service this MIDI event here
// for sample accurate MIDI
// myMIDIMessageHandler(event); // <-- you write this
return true;
}
//
//
PluginDescriptor pluginDescriptor
description strings
Definition: pluginbase.h:415
virtual bool processMIDIEvent(midiEvent &event)
process a MIDI event
Definition: plugincore.cpp:606
bool processFrames
want frames (default)
Definition: pluginstructures.h:1280
void pushMidiEvent(midiEvent event)
Definition: pluginstructures.h:1082

Notice how this function works:
Processing sub-blocks or buffers:
The pluginDescriptor.processFrames boolean will be false; in this case a special function is called to load the incoming MIDI message into a vector that will be usually be serviced, all at once, at the top of the block processing function; note that you may also perform this in a sample accurate manner, but it will require some coding on your part to match up the midiEvent's midiSampleOffset index (the sample location within the DAW audio buffers) with the block or buffer (for buffer processing this is trivial as the sample offsets will match up with your for( ) loop), but for sub-block processing, you will need to keep track of the blocks and samples per buffer (see the preProcessAudioBuffers function for a location to set this up). However, there are good reasons for procssing the MIDI at the top of sub-blocks as detailed in my Synth book (and many synth manufacturers use this same paradigm).

// --- process all MIDI events in this block (same as SynthLab)
uint32_t midiEvents = blockInfo.getMidiEventCount();
for (uint32_t i = 0; i < midiEvents; i++)
{
// --- get the event
midiEvent event = *blockInfo.getMidiEvent(i);
// --- do something with it...
// myMIDIMessageHandler(event); // <-- you write this
}
// --- render a block of audio; here it is silence but in your synth
// it will likely be dependent on the MIDI processing you just did above
for (uint32_t sample = blockInfo.blockStartIndex, i = 0;
sample < blockInfo.blockStartIndex + blockInfo.blockSize;
sample++, i++)
{
// --- write outputs
for (uint32_t channel = 0; channel < blockInfo.numAudioOutChannels; channel++)
{
// --- silence (or, your synthesized block of samples)
blockInfo.outputs[channel][sample] = 0.0;
}
}
return true;
//

Processing Frames:
You insert your MIDI processing function (e.g. myMIDIMessageHandler( )) right inside of the processMIDIMessage( ) call here; the PluginBase will interleave the MIDI message function calls with the processAudioFrames function calls and your MIDI messaging is automatically sample accurate!

// --- IF PROCESSING AUDIO FRAMES: decode AND service this MIDI event here
// for sample accurate MIDI
// myMIDIMessageHandler(event); // <-- you write this