| @@ -522,7 +522,7 @@ struct AAXClasses | |||
| { | |||
| public: | |||
| JuceAAX_Processor() : pluginInstance (createPluginFilterOfType (AudioProcessor::wrapperType_AAX)), | |||
| busUtils (*pluginInstance, false, maxAAXChannels), | |||
| isPrepared (false), busUtils (*pluginInstance, false, maxAAXChannels), | |||
| sampleRate (0), lastBufferSize (1024), maxBufferSize (1024), | |||
| hasSidechain (false) | |||
| { | |||
| @@ -540,6 +540,17 @@ struct AAXClasses | |||
| return new JuceAAX_Processor(); | |||
| } | |||
| AAX_Result Uninitialize() override | |||
| { | |||
| if (isPrepared && pluginInstance != nullptr) | |||
| { | |||
| isPrepared = false; | |||
| pluginInstance->releaseResources(); | |||
| } | |||
| return AAX_CEffectParameters::Uninitialize(); | |||
| } | |||
| AAX_Result EffectInit() override | |||
| { | |||
| AAX_Result err; | |||
| @@ -1103,6 +1114,7 @@ struct AAXClasses | |||
| AAX_Result preparePlugin() | |||
| { | |||
| AudioProcessor& audioProcessor = getPluginInstance(); | |||
| bool hasSomethingChanged = false; | |||
| #if JucePlugin_IsMidiEffect | |||
| // MIDI effect plug-ins do not support any audio channels | |||
| @@ -1120,39 +1132,74 @@ struct AAXClasses | |||
| if ( (inputSet == AudioChannelSet::disabled() && inputStemFormat != AAX_eStemFormat_None) | |||
| || (outputSet == AudioChannelSet::disabled() && outputStemFormat != AAX_eStemFormat_None)) | |||
| { | |||
| if (isPrepared) | |||
| { | |||
| isPrepared = false; | |||
| audioProcessor.releaseResources(); | |||
| } | |||
| return AAX_ERROR_UNIMPLEMENTED; | |||
| } | |||
| bool success = true; | |||
| if (busUtils.getBusCount (true) > 0) | |||
| success = audioProcessor.setPreferredBusArrangement (true, 0, inputSet); | |||
| success = setPreferredBusArrangement (busUtils, true, 0, inputSet, hasSomethingChanged); | |||
| if (success && busUtils.getBusCount (false) > 0) | |||
| success = audioProcessor.setPreferredBusArrangement (false, 0, outputSet); | |||
| success = setPreferredBusArrangement (busUtils, false, 0, outputSet, hasSomethingChanged); | |||
| // This should never happen as the plugin reported that this layout is supported | |||
| jassert (success); | |||
| hasSidechain = enableAuxBusesForCurrentFormat (busUtils, inputSet, outputSet); | |||
| if (hasSidechain) | |||
| hasSidechain = enableAuxBusesForCurrentFormat (busUtils, inputSet, outputSet, hasSomethingChanged); | |||
| if (hasSidechain && hasSomethingChanged) | |||
| sideChainBuffer.realloc (static_cast<size_t> (maxBufferSize)); | |||
| // recheck the format | |||
| if ( (busUtils.getBusCount (true) > 0 && busUtils.getChannelSet (true, 0) != inputSet) | |||
| || (busUtils.getBusCount (false) > 0 && busUtils.getChannelSet (false, 0) != outputSet) | |||
| || (hasSidechain && busUtils.getNumChannels(true, 1) != 1)) | |||
| { | |||
| if (isPrepared) | |||
| { | |||
| isPrepared = false; | |||
| audioProcessor.releaseResources(); | |||
| } | |||
| return AAX_ERROR_UNIMPLEMENTED; | |||
| } | |||
| rebuildChannelMapArrays (true); | |||
| rebuildChannelMapArrays (false); | |||
| if (hasSomethingChanged) | |||
| { | |||
| rebuildChannelMapArrays (true); | |||
| rebuildChannelMapArrays (false); | |||
| } | |||
| #endif | |||
| audioProcessor.setRateAndBufferSizeDetails (sampleRate, maxBufferSize); | |||
| audioProcessor.prepareToPlay (sampleRate, lastBufferSize); | |||
| maxBufferSize = lastBufferSize; | |||
| hasSomethingChanged = (sampleRate != audioProcessor.getSampleRate() | |||
| || maxBufferSize != lastBufferSize | |||
| || hasSomethingChanged); | |||
| if (hasSomethingChanged || (! isPrepared)) | |||
| { | |||
| if (isPrepared) | |||
| { | |||
| isPrepared = false; | |||
| audioProcessor.releaseResources(); | |||
| } | |||
| audioProcessor.setRateAndBufferSizeDetails (sampleRate, lastBufferSize); | |||
| audioProcessor.prepareToPlay (sampleRate, lastBufferSize); | |||
| maxBufferSize = lastBufferSize; | |||
| } | |||
| check (Controller()->SetSignalLatency (audioProcessor.getLatencySamples())); | |||
| isPrepared = true; | |||
| return AAX_SUCCESS; | |||
| } | |||
| @@ -1197,6 +1244,7 @@ struct AAXClasses | |||
| ScopedJuceInitialiser_GUI libraryInitialiser; | |||
| ScopedPointer<AudioProcessor> pluginInstance; | |||
| bool isPrepared; | |||
| PluginBusUtilities busUtils; | |||
| MidiBuffer midiBuffer; | |||
| Array<float*> channelList; | |||
| @@ -1271,7 +1319,8 @@ struct AAXClasses | |||
| } | |||
| static bool enableAuxBusesForCurrentFormat (PluginBusUtilities& busUtils, const AudioChannelSet& inputLayout, | |||
| const AudioChannelSet& outputLayout) | |||
| const AudioChannelSet& outputLayout, | |||
| bool& hasSomethingChanged) | |||
| { | |||
| const int numOutBuses = busUtils.getBusCount (false); | |||
| const int numInputBuses = busUtils.getBusCount(true); | |||
| @@ -1289,7 +1338,7 @@ struct AAXClasses | |||
| if (layout == AudioChannelSet::disabled()) | |||
| { | |||
| layout = busUtils.getDefaultLayoutForBus (false, busIdx); | |||
| busUtils.processor.setPreferredBusArrangement (false, busIdx, layout); | |||
| setPreferredBusArrangement (busUtils, false, busIdx, layout, hasSomethingChanged); | |||
| } | |||
| } | |||
| @@ -1297,15 +1346,17 @@ struct AAXClasses | |||
| bool success = true; | |||
| if (numInputBuses > 0) | |||
| success = busUtils.processor.setPreferredBusArrangement (true, 0, inputLayout); | |||
| success = setPreferredBusArrangement (busUtils, true, 0, inputLayout, hasSomethingChanged); | |||
| if (success) | |||
| success = busUtils.processor.setPreferredBusArrangement (false, 0, outputLayout); | |||
| success = setPreferredBusArrangement (busUtils, false, 0, outputLayout, hasSomethingChanged); | |||
| // was the above successful | |||
| if (success && (numInputBuses == 0 || busUtils.getChannelSet (true, 0) == inputLayout) | |||
| && busUtils.getChannelSet (false, 0) == outputLayout) | |||
| layoutRestorer.release(); | |||
| else | |||
| hasSomethingChanged = true; | |||
| } | |||
| // does the plug-in have side-chain support? Check the following: | |||
| @@ -1319,10 +1370,12 @@ struct AAXClasses | |||
| const AudioChannelSet set = busUtils.getDefaultLayoutForChannelNumAndBus (true, 1, 1); | |||
| if (! set.isDisabled()) | |||
| hasSidechain = busUtils.processor.setPreferredBusArrangement (true, 1, set); | |||
| hasSidechain = setPreferredBusArrangement (busUtils, true, 1, set, hasSomethingChanged); | |||
| if (! hasSidechain) | |||
| success = busUtils.processor.setPreferredBusArrangement (true, 1, AudioChannelSet::disabled()); | |||
| success = setPreferredBusArrangement (busUtils, true, 1, | |||
| AudioChannelSet::disabled(), | |||
| hasSomethingChanged); | |||
| // AAX requires your processor's first sidechain to be either mono or that | |||
| // it can be disabled | |||
| @@ -1331,7 +1384,9 @@ struct AAXClasses | |||
| // disable all other input buses | |||
| for (int busIdx = 2; busIdx < numInputBuses; ++busIdx) | |||
| { | |||
| success = busUtils.processor.setPreferredBusArrangement (true, busIdx, AudioChannelSet::disabled()); | |||
| success = setPreferredBusArrangement (busUtils, true, busIdx, | |||
| AudioChannelSet::disabled(), | |||
| hasSomethingChanged); | |||
| // AAX can only have a single side-chain input. Therefore, your processor must either | |||
| // only have a single side-chain input or allow disabling all other side-chains | |||
| @@ -1341,21 +1396,34 @@ struct AAXClasses | |||
| if (hasSidechain) | |||
| { | |||
| if (busUtils.getBusCount (false) == 0 || busUtils.getBusCount (true) == 0 || | |||
| (busUtils.getChannelSet (true, 0) == inputLayout && busUtils.getChannelSet (false, 0) == outputLayout)) | |||
| (busUtils.getChannelSet (true, 0) == inputLayout && busUtils.getChannelSet (false, 0) == outputLayout)) | |||
| return true; | |||
| // restore the old layout | |||
| if (busUtils.getBusCount(true) > 0) | |||
| busUtils.processor.setPreferredBusArrangement (true, 0, inputLayout); | |||
| setPreferredBusArrangement (busUtils, true, 0, inputLayout, hasSomethingChanged); | |||
| if (busUtils.getBusCount (false) > 0) | |||
| busUtils.processor.setPreferredBusArrangement (false, 0, outputLayout); | |||
| setPreferredBusArrangement (busUtils, false, 0, outputLayout, hasSomethingChanged); | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| // wrap setPreferredBusArrangement calls with this to prevent excessive calls to the plug-in | |||
| static bool setPreferredBusArrangement (PluginBusUtilities& busUtils, bool isInput, int busIdx, | |||
| const AudioChannelSet& layout, | |||
| bool& didChangePlugin) | |||
| { | |||
| // no need to do anything | |||
| if (busUtils.getChannelSet (isInput, busIdx) == layout) | |||
| return true; | |||
| didChangePlugin = true; | |||
| return busUtils.processor.setPreferredBusArrangement (isInput, busIdx, layout); | |||
| } | |||
| //============================================================================== | |||
| static void createDescriptor (AAX_IComponentDescriptor& desc, int configIndex, PluginBusUtilities& busUtils, | |||
| const AudioChannelSet& inputLayout, const AudioChannelSet& outputLayout, | |||
| @@ -1418,7 +1486,8 @@ struct AAXClasses | |||
| properties->AddProperty (AAX_eProperty_SupportsSaveRestore, false); | |||
| #endif | |||
| if (enableAuxBusesForCurrentFormat (busUtils, inputLayout, outputLayout)) | |||
| bool ignore; | |||
| if (enableAuxBusesForCurrentFormat (busUtils, inputLayout, outputLayout, ignore)) | |||
| { | |||
| check (desc.AddSideChainIn (JUCEAlgorithmIDs::sideChainBuffers)); | |||
| properties->AddProperty (AAX_eProperty_SupportsSideChainInput, true); | |||