Please forgive me if this is a problem with the AUv3 format (or Logic Pro X itself). Probably not the case, but there is simply not enough information online to draw a sound conclusion...
When I build and run (with Logic Pro X) XCode's Audio Unit Extension template (for instrument) completely unmodified except for the following override of the handleMIDIEvent function:
the built Audio Unit seems to only receive incoming MIDI messages when it's in the currently selected track (ie. if I insert two instances and record a MIDI region in each, only the notes in the selected track print "I just got a midi event!" during playback).
Do I need to do something else in order to make my plugin be able to receive MIDI messages when it's not in the selected track (like any other synth plugin)?
Using XCode Version 12.3 (12C33), Logic Pro X 10.6.0 (Build Version 5407) in macOS Catalina 10.15.6 (19G2021).
When I build and run (with Logic Pro X) XCode's Audio Unit Extension template (for instrument) completely unmodified except for the following override of the handleMIDIEvent function:
Code Block language cpp void handleMIDIEvent(AUMIDIEvent const& midiEvent) override { printf("I just got a midi event!\n"); }
the built Audio Unit seems to only receive incoming MIDI messages when it's in the currently selected track (ie. if I insert two instances and record a MIDI region in each, only the notes in the selected track print "I just got a midi event!" during playback).
Do I need to do something else in order to make my plugin be able to receive MIDI messages when it's not in the selected track (like any other synth plugin)?
Using XCode Version 12.3 (12C33), Logic Pro X 10.6.0 (Build Version 5407) in macOS Catalina 10.15.6 (19G2021).
Whew! It took me days of relentless fiddling, but I finally found the problem. It seems my internalRenderBlock was returning early with kAudioUnitErr_TooManyFramesToProcess.
It appears Logic Pro X (and Garage Band on macOS too, for that matter) requests different buffer sizes for selected and unselected tracks.
Selected tracks are the I/O Buffer Size as per the Logic settings (eg. 256).
Unselected tracks are always 1024 frames, regardless of the I/O Buffer Size setting. (lower render priority than the selected track, I suppose?)
Since the Audio Unit Extension template stubs out
that makes it so that render fails, but only on unselected tracks. And when internalRenderBlock returns early, it never reaches processWithEvents, which in turn calls handleMIDIEvents, and MIDI events aren't processed (neither is audio, possibly resulting in periodic audio glitches).
Setting maxFramesToRender = 1024; fixes that problem in my case.
Now, I can't help but feel this default maxFramesToRender = 512; is setting newbies like me up for failure, since as far as I can tell it necessarily results in Logic (presumably the most obvious test host) failing to render in a highly elusive manner. But I'm just a newbie programmer, and I'm sure there must be a reason for that 512 not being higher that I just happen to not see. (theories on the reason for that default size of 512 are very welcome!)
Anyway, that's one reason less to lose sleep over. Whew!
It appears Logic Pro X (and Garage Band on macOS too, for that matter) requests different buffer sizes for selected and unselected tracks.
Selected tracks are the I/O Buffer Size as per the Logic settings (eg. 256).
Unselected tracks are always 1024 frames, regardless of the I/O Buffer Size setting. (lower render priority than the selected track, I suppose?)
Since the Audio Unit Extension template stubs out
Code Block language cpp AUAudioFrameCount maxFramesToRender = 512;
that makes it so that render fails, but only on unselected tracks. And when internalRenderBlock returns early, it never reaches processWithEvents, which in turn calls handleMIDIEvents, and MIDI events aren't processed (neither is audio, possibly resulting in periodic audio glitches).
Setting maxFramesToRender = 1024; fixes that problem in my case.
Now, I can't help but feel this default maxFramesToRender = 512; is setting newbies like me up for failure, since as far as I can tell it necessarily results in Logic (presumably the most obvious test host) failing to render in a highly elusive manner. But I'm just a newbie programmer, and I'm sure there must be a reason for that 512 not being higher that I just happen to not see. (theories on the reason for that default size of 512 are very welcome!)
Anyway, that's one reason less to lose sleep over. Whew!