MIDI FX doesn't work in AAX

AFAIK, The only format that has the concept of MIDI FX is AU.

So, when deploying MIDI FX, the solution that worked for me so far was to declare the plugin as both a Synth and MIDI FX:


That’s totally fine for VST/VST3 as you can open the plugin as a synth and route the MIDI to another track.

However, that makes the plugin completely fail and not produce MIDI in AAX under Pro Tools.

If I set IS_MIDI_EFFECT to FALSE it works fine in Pro Tools, but fails in Logic under AU.

Is it possible to completely ignore IS_MIDI_EFFECT for AAX?

1 Like

Well… MIDI FX work in VST in practice on most hosts, although some hosts (notably Live and DP) don’t work at all. For these hosts we simply add an output bus (pretend to be an instrument) so that the user can route midi to another track with a real instrument on it. We don’t currently test on AAX (can’t support PT for other reasons) so I can’t guarantee that this would work, but I assume some combination of enabling an additional bus for Live and similar hosts and disabling an additional bus for other hosts would work. This is similar to what the MidiLogger example plugin does.

I’m not aware of ‘real’ MIDI FX support in any VST host I know of.

However, we used that trick of outputting MIDI from a synth and that works just fine in all hosts that we tested (Cubase/Live/Bitwig/Reaper/etc).

But in Pro Tools that issue is more complicated: I’m not aware of a way in JUCE/CMake to build with a different set of preprocessor flags for AAX and AU, so with the MIDI FX flag on, AAX breaks and AU works, and with the MIDI FX flag off AAX works fine and AU breaks.

VST2/3 works with both versions of the flag.

yes, it’s not “real”, but it functionally works just fine.

I’m not using the flags in that way, so I’d just look into manually writing those methods in your AudioProcessor. That also allows you to handle things differently either by plugin host (with PluginHostType) or by wrapper type (with AudioProcessor::wrapperType). Check out the uses of those flags in your project, and you’ll find that they just make boilerplate code for default plugin projects work. You can then just remove the flags themselves and replace them with either return values or expressions which return the right values.

This is also very helpful for users on hosts which don’t handle multiple synths in one track well or at all, so that people don’t need two tracks per synth.

1 Like

Thank you!
Yes, you’re right. I used to do that in the past when I used the Projucer, but couldn’t get it to work quite the same way with CMake, because from what I can tell only the VST2 wrapper is calling the isMidiEffect() virtual function, and the other wrappers just ignore it and use the preprocessor flags.

Apparently, those flags are used quite heavily by the AU and AAX wrappers:

CMake uses that flag to also set kAudioUnitType_MIDIProcessor which is needed by the AUWrapper in many places, and the AAX wrapper is using that flag directly multiple times to set the I/O and other things.

So, it seems definitely possible to just remove that flag and manually set kAudioUnitType_MIDIProcessor for AU to work, but I thought it’s still a JUCE bug that should be fixed.

Just as a quick update, this seems to work just fine for a MIDI effect in all formats that I tested so far:

AU_MAIN_TYPE kAudioUnitType_MIDIProcessor

But I think it would be nice if this is fixed or at least documented, as it’s not what you’d expect would happen.


Is your AU MIDI FX getting the sample rate in Logic with these settings ?
The only way I could find to get a MIDI FX get this, is to give it an audio bus. But then some other hosts don’t see it as a MIDI FX any more.

Yes, I still had to add an audio bus, but sample rate and block size appear correctly in all hosts that I tested.

The concept of 3rd party MIDI FX does not exist in hosts that aren’t Apple’s, so it shows up as a synth in those hosts, and as MIDI FX in Logic and MainStage.

Not sure if it’s helpful for you but as I’m looking into newer AAX SDK Integrations I see:
AAX_eProperty_PlugInID_NoProcessing which seems useful for your use case?