MIDI sending plugins and hanging notes


#1

Hi,

I have a question regarding handling of hanging note for audio plugins that send out MIDI events.
I have an internal module that sends out MIDI events based on some audio analysis calculations, and that module has these functions:

[code] /** Tells the module that Process will be called from now on. */
void StartProcessing();

/** Processes one mono input sample and indicates whether events occurred or not.
	@param		inAudioInput	input sample
	@param		outAudioOutput	output sample
	@return		true if events occurred while processing the current sample, false otherwise	*/
bool Process(const float inAudioInput,float* outAudioOutput);

/** Tells the module that Process will not be called any more. 
	All currently playing notes will be released and you can use GetEventMessages 
	to retrieve the corresponding note off messages.
	@return True if events were generated. False otherwise. */
bool StopProcessing();[/code]

I am embedding this into a Juce audio processor, I was wondering if this the right way to do this:

in prepareToPlay:

module.SetSampleRate((float)sampleRate); module.StartProcessing();
in processBlock:

if (module.Process(inSample,&outSample)) { // send out MIDI note on or off message }
in releaseResources:

if (module.StopProcessing()) { // send out MIDI note off messages }
This is the approach I used in VST world (where sendVstEventsToHost is used to send out the MIDI messages).

Question:
since all MIDI message passing is done through the processBlock call in Juce, how will the note off messages that are only obtained when processing stops (so in releaseResources) get sent to the host? I need something like this to avoid hanging notes.

Any advice?


#2

Sounds sensible.

If you need to send note-offs, you’d have to check the AudioPlayHead to see when the host starts and stops. Most hosts will leave the plugin running when stopped, so you can still send messages after the playhead stops.


#3

AudioPlayHead: OK, that sounds good. I will look into that.

That leaves three cases though:

  1. what if the host doesn’t support transport state (getAudioPlayHead returns 0)?
    How will I then be able to send note offs?

  2. what happens when the host application stops?
    The detection of stopped transport state is done by checking the AudioPlayHead in processBlock, right (isPlaying changes to false)?
    If the host doesn’t stop transport before shutting down, I will never be able to detect it and send the appropriate note offs.
    If the host does stop transport, then:

  • at least one procesBlock call is needed after the transport stopped, so I can detect it and send the appropriate note off messages through the supplied MIDI buffer
  • if there is no extra call to processBlock, the only place left to do something would be releaseResources, but I can’t send note off messages to the host from there as I did in VST directly
  1. what if the plugin is removed from the host?
    Will the plugin then be able to detect this (would require a processBlock call where isPlaying went from true to false, and I’m not sure if hosts usually stop transport when a plugin is removed from the processing chain)? Does that work?

It feels like a way to still hand over midi messages to the host when processing is stopped (like when releaseResources is called) could make this more robust.


#4

Don’t worry about it - if the host stops processing, then wouldn’t be able to do anything with your note-off messages anyway. Generally the host will handle that kind of thing by monitoring your events and generating its own note-offs if it thinks they’re needed.