InternalPlugin (const PluginDescription& descr, const AudioChannelSet& channelSetToUse = AudioChannelSet::stereo()) : AudioPluginInstance (getBusProperties (descr.numInputChannels == 0, channelSetToUse)), name (descr.fileOrIdentifier.upToFirstOccurrenceOf (":", false, false)), state (descr.fileOrIdentifier.fromFirstOccurrenceOf (":", false, false)), isGenerator (descr.numInputChannels == 0), hasMidi (descr.isInstrument), channelSet (channelSetToUse) { jassert (channelSetToUse.size() == descr.numOutputChannels); }
//============================================================================== void AudioProcessor::BusesProperties::addBus (bool isInput, const String& name, const AudioChannelSet& dfltLayout, bool isActivatedByDefault) { jassert (dfltLayout.size() != 0); BusProperties props; props.busName = name; props.defaultLayout = dfltLayout; props.isActivatedByDefault = isActivatedByDefault; (isInput ? inputLayouts : outputLayouts).add (props); }
//============================================================================== bool setPreferredBusArrangement (bool isInputBus, int busIndex, const AudioChannelSet& preferred) override { const int numChannels = preferred.size(); // do not allow disabling channels if (numChannels == 0) return false; // always have the same channel layout on both input and output on the main bus if (! AudioProcessor::setPreferredBusArrangement (! isInputBus, busIndex, preferred)) return false; return AudioProcessor::setPreferredBusArrangement (isInputBus, busIndex, preferred); }
//============================================================================== bool setPreferredBusArrangement (bool isInputBus, int busIndex, const AudioChannelSet& preferred) override { const int numChannels = preferred.size(); const bool isMainBus = (busIndex == 0); // do not allow disabling the main output bus if (isMainBus && preferred.isDisabled()) return false; // only support mono or stereo (or disabling) buses if (numChannels > 2) return false; // pass the call on to the base class return AudioProcessor::setPreferredBusArrangement (isInputBus, busIndex, preferred); }
bool EQPluginProcessor::setPreferredBusArrangement (bool isInput, int bus, const AudioChannelSet& preferredSet) { // Reject any bus arrangements that are not compatible with your plugin const int numChannels = preferredSet.size (); #if JucePlugin_IsMidiEffect if (numChannels != 0) return false; #elif JucePlugin_IsSynth if (isInput || (numChannels != 1 && numChannels != 2)) return false; #else if (numChannels != 1 && numChannels != 2) return false; if (!AudioProcessor::setPreferredBusArrangement (!isInput, bus, preferredSet)) return false; #endif return AudioProcessor::setPreferredBusArrangement (isInput, bus, preferredSet) && mAudealizeAudioProcessor->setPreferredBusArrangement (isInput, bus, preferredSet); }
//============================================================================== bool AudioProcessor::setPreferredBusArrangement (bool isInput, int busIndex, const AudioChannelSet& preferredSet) { const int oldNumInputs = getTotalNumInputChannels(); const int oldNumOutputs = getTotalNumOutputChannels(); Array<AudioProcessorBus>& buses = isInput ? busArrangement.inputBuses : busArrangement.outputBuses; const int numBuses = buses.size(); if (! isPositiveAndBelow (busIndex, numBuses)) return false; #ifdef JucePlugin_MaxNumInputChannels if (isInput && preferredSet.size() > JucePlugin_MaxNumInputChannels) return false; #endif #ifdef JucePlugin_MaxNumOutputChannels if (! isInput && preferredSet.size() > JucePlugin_MaxNumOutputChannels) return false; #endif AudioProcessorBus& bus = buses.getReference (busIndex); #ifdef JucePlugin_PreferredChannelConfigurations // the user is using the deprecated way to specify channel configurations if (numBuses > 0 && busIndex == 0) { const short channelConfigs[][2] = { JucePlugin_PreferredChannelConfigurations }; const int numChannelConfigs = sizeof (channelConfigs) / sizeof (*channelConfigs); // we need the main bus in the opposite direction Array<AudioProcessorBus>& oppositeBuses = isInput ? busArrangement.outputBuses : busArrangement.inputBuses; AudioProcessorBus* oppositeBus = (busIndex < oppositeBuses.size()) ? &oppositeBuses.getReference (0) : nullptr; // get the target number of channels const int mainBusNumChannels = preferredSet.size(); const int mainBusOppositeChannels = (oppositeBus != nullptr) ? oppositeBus->channels.size() : 0; const int dir = isInput ? 0 : 1; // find a compatible channel configuration on the opposite bus which is the closest match // to the current number of channels on that bus int distance = std::numeric_limits<int>::max(); int bestConfiguration = -1; for (int i = 0; i < numChannelConfigs; ++i) { // is the configuration compatible with the preferred set if (channelConfigs[i][dir] == mainBusNumChannels) { const int configChannels = channelConfigs[i][dir^1]; const int channelDifference = std::abs (configChannels - mainBusOppositeChannels); if (channelDifference < distance) { distance = channelDifference; bestConfiguration = configChannels; // we can exit if we found a perfect match if (distance == 0) break; } } } // unable to find a good configuration if (bestConfiguration == -1) return false; // did the number of channels change on the opposite bus? if (mainBusOppositeChannels != bestConfiguration && oppositeBus != nullptr) { // if the channels on the opposite bus are the same as the preferred set // then also copy over the layout information. If not, then assume // a cononical channel layout if (bestConfiguration == mainBusNumChannels) oppositeBus->channels = preferredSet; else oppositeBus->channels = AudioChannelSet::canonicalChannelSet (bestConfiguration); } } #endif bus.channels = preferredSet; if (oldNumInputs != getTotalNumInputChannels() || oldNumOutputs != getTotalNumOutputChannels()) { updateSpeakerFormatStrings(); numChannelsChanged(); } return true; }
AudioProcessor::BusesLayout AudioProcessor::getNextBestLayoutInList (const BusesLayout& layouts, const Array<InOutChannelPair>& legacyLayouts) const { const int numChannelConfigs = legacyLayouts.size(); jassert (numChannelConfigs > 0); bool hasInputs = false, hasOutputs = false; for (int i = 0; i < numChannelConfigs; ++i) { if (legacyLayouts[i].inChannels > 0) { hasInputs = true; break; } if (legacyLayouts[i].outChannels > 0) { hasOutputs = true; break; } } BusesLayout nearest = layouts; nearest.inputBuses .resize (hasInputs ? 1 : 0); nearest.outputBuses.resize (hasOutputs ? 1 : 0); AudioChannelSet* inBus = (hasInputs ? &nearest.inputBuses. getReference (0) : nullptr); AudioChannelSet* outBus = (hasOutputs ? &nearest.outputBuses.getReference (0) : nullptr); const int16 inNumChannelsRequested = static_cast<int16> (inBus != nullptr ? inBus->size() : 0); const int16 outNumChannelsRequested = static_cast<int16> (outBus != nullptr ? outBus->size() : 0); int32 distance = std::numeric_limits<int32>::max(); int bestConfiguration = 0; for (int i = 0; i < numChannelConfigs; ++i) { const int16 inChannels = legacyLayouts.getReference (i).inChannels; const int16 outChannels = legacyLayouts.getReference (i).outChannels; const int32 channelDifference = ((std::abs (inChannels - inNumChannelsRequested) & 0xffff) << 16) | ((std::abs (outChannels - outNumChannelsRequested) & 0xffff) << 0); if (channelDifference < distance) { distance = channelDifference; bestConfiguration = i; // we can exit if we found a perfect match if (distance == 0) return nearest; } } const int16 inChannels = legacyLayouts.getReference (bestConfiguration).inChannels; const int16 outChannels = legacyLayouts.getReference (bestConfiguration).outChannels; BusesLayout currentState = getBusesLayout(); AudioChannelSet currentInLayout = (getBusCount (true) > 0 ? currentState.inputBuses .getReference(0) : AudioChannelSet()); AudioChannelSet currentOutLayout = (getBusCount (false) > 0 ? currentState.outputBuses.getReference(0) : AudioChannelSet()); if (inBus != nullptr) { if (inChannels == 0) *inBus = AudioChannelSet::disabled(); else if (inChannels == currentInLayout. size()) *inBus = currentInLayout; else if (inChannels == currentOutLayout.size()) *inBus = currentOutLayout; else *inBus = AudioChannelSet::canonicalChannelSet (inChannels); } if (outBus != nullptr) { if (outChannels == 0) *outBus = AudioChannelSet::disabled(); else if (outChannels == currentOutLayout.size()) *outBus = currentOutLayout; else if (outChannels == currentInLayout .size()) *outBus = currentInLayout; else *outBus = AudioChannelSet::canonicalChannelSet (outChannels); } return nearest; }