void IPlugAAX::RenderAudio(AAX_SIPlugRenderInfo* ioRenderInfo) { TRACE_PROCESS; IMutexLock lock(this); // Get bypass parameter value bool bypass; mBypassParameter->GetValueAsBool(&bypass); AAX_EStemFormat inFormat, outFormat; Controller()->GetInputStemFormat(&inFormat); Controller()->GetOutputStemFormat(&outFormat); if (DoesMIDI()) { AAX_IMIDINode* midiIn = ioRenderInfo->mInputNode; AAX_CMidiStream* midiBuffer = midiIn->GetNodeBuffer(); AAX_CMidiPacket* midiBufferPtr = midiBuffer->mBuffer; uint32_t packets_count = midiBuffer->mBufferSize; // Setup MIDI Out node pointers // AAX_IMIDINode* midiNodeOut = instance->mMIDINodeOutP; // AAX_CMidiStream* midiBufferOut = midiNodeOut->GetNodeBuffer(); // AAX_CMidiPacket* midiBufferOutPtr = midiBufferOut->mBuffer; for (int i = 0; i<packets_count; i++, midiBufferPtr++) { IMidiMsg msg(midiBufferPtr->mTimestamp, midiBufferPtr->mData[0], midiBufferPtr->mData[1], midiBufferPtr->mData[2]); ProcessMidiMsg(&msg); } } AAX_IMIDINode* transportNode = ioRenderInfo->mTransportNode; mTransport = transportNode->GetTransport(); int32_t numSamples = *(ioRenderInfo->mNumSamples); int32_t numInChannels = AAX_STEM_FORMAT_CHANNEL_COUNT(inFormat); int32_t numOutChannels = AAX_STEM_FORMAT_CHANNEL_COUNT(outFormat); SetInputChannelConnections(0, numInChannels, true); SetInputChannelConnections(numInChannels, NInChannels() - numInChannels, false); AttachInputBuffers(0, NInChannels(), ioRenderInfo->mAudioInputs, numSamples); SetOutputChannelConnections(0, numOutChannels, true); SetOutputChannelConnections(numOutChannels, NOutChannels() - numOutChannels, false); AttachOutputBuffers(0, NOutChannels(), ioRenderInfo->mAudioOutputs); if (bypass) { PassThroughBuffers(0.0f, numSamples); } else { ProcessBuffers(0.0f, numSamples); } }
void IPlugVST::HostSpecificInit() { if (!mHostSpecificInitDone) { mHostSpecificInitDone = true; EHost host = GetHost(); switch (host) { case kHostAudition: case kHostOrion: case kHostForte: case kHostSAWStudio: LimitToStereoIO(); break; default: break; } // This won't always solve a picky host problem -- for example Forte // looks at mAEffect IO count before identifying itself. mAEffect.numInputs = mInputSpkrArr.numChannels = NInChannels(); mAEffect.numOutputs = mOutputSpkrArr.numChannels = NOutChannels(); OnHostIdentified(); } }
IPlugAAX::IPlugAAX(IPlugInstanceInfo instanceInfo, int nParams, const char* channelIOStr, int nPresets, const char* effectName, const char* productName, const char* mfrName, int vendorVersion, int uniqueID, int mfrID, int latency, bool plugDoesMidi, bool plugDoesChunks, bool plugIsInst, int plugScChans) : IPlugBase(nParams, channelIOStr, nPresets, effectName, productName, mfrName, vendorVersion, uniqueID, mfrID, latency, plugDoesMidi, plugDoesChunks, plugIsInst, kAPIAAX) , AAX_CIPlugParameters() , mTransport(0) { Trace(TRACELOC, "%s%s", effectName, channelIOStr); SetInputChannelConnections(0, NInChannels(), true); SetOutputChannelConnections(0, NOutChannels(), true); if (NInChannels()) { mDelay = new NChanDelayLine(NInChannels(), NOutChannels()); mDelay->SetDelayTime(latency); } SetBlockSize(DEFAULT_BLOCK_SIZE); SetHost("ProTools", vendorVersion); // TODO:vendor version correct? }
void IPlugVST::VSTPrepProcess(SAMPLETYPE** inputs, SAMPLETYPE** outputs, VstInt32 nFrames) { if (DoesMIDI()) { mHostCallback(&mAEffect, __audioMasterWantMidiDeprecated, 0, 0, 0, 0.0f); } AttachInputBuffers(0, NInChannels(), inputs, nFrames); AttachOutputBuffers(0, NOutChannels(), outputs); }
tresult PLUGIN_API IPlugVST3Plugin::setBusArrangements(SpeakerArrangement* inputs, int32 numIns, SpeakerArrangement* outputs, int32 numOuts) { TRACE; // disconnect all io pins, they will be reconnected in process SetInputChannelConnections(0, NInChannels(), false); SetOutputChannelConnections(0, NOutChannels(), false); int32 reqNumInputChannels = SpeakerArr::getChannelCount(inputs[0]); //requested # input channels int32 reqNumOutputChannels = SpeakerArr::getChannelCount(outputs[0]);//requested # output channels // legal io doesn't consider sidechain inputs if (!LegalIO(reqNumInputChannels, reqNumOutputChannels)) { return kResultFalse; } // handle input AudioBus* bus = FCast<AudioBus>(audioInputs.at(0)); // if existing input bus has a different number of channels to the input bus being connected if (bus && SpeakerArr::getChannelCount(bus->getArrangement()) != reqNumInputChannels) { audioInputs.remove(bus); addAudioInput(USTRING("Input"), getSpeakerArrForChans(reqNumInputChannels)); } // handle output bus = FCast<AudioBus>(audioOutputs.at(0)); // if existing output bus has a different number of channels to the output bus being connected if (bus && SpeakerArr::getChannelCount(bus->getArrangement()) != reqNumOutputChannels) { audioOutputs.remove(bus); addAudioOutput(USTRING("Output"), getSpeakerArrForChans(reqNumOutputChannels)); } if (!mScChans && numIns == 1) // No sidechain, every thing OK { return kResultTrue; } if (mScChans && numIns == 2) // numIns = num Input BUSes { int32 reqNumSideChainChannels = SpeakerArr::getChannelCount(inputs[1]); //requested # sidechain input channels bus = FCast<AudioBus>(audioInputs.at(1)); if (bus && SpeakerArr::getChannelCount(bus->getArrangement()) != reqNumSideChainChannels) { audioInputs.remove(bus); addAudioInput(USTRING("Sidechain Input"), getSpeakerArrForChans(reqNumSideChainChannels), kAux, 0); // either mono or stereo } return kResultTrue; } return kResultFalse; }
IPlugVST::IPlugVST(IPlugInstanceInfo instanceInfo, int nParams, const char* channelIOStr, int nPresets, const char* effectName, const char* productName, const char* mfrName, int vendorVersion, int uniqueID, int mfrID, int latency, int plugDoesMidi, bool plugDoesChunks, bool plugIsInst) : IPlugBase(nParams, channelIOStr, nPresets, effectName, productName, mfrName, vendorVersion, uniqueID, mfrID, latency, plugDoesMidi, plugDoesChunks, plugIsInst), mHostCallback(instanceInfo.mVSTHostCallback), mHostSpecificInitDone(false) { Trace(TRACELOC, "%s", effectName); mHasVSTExtensions = VSTEXT_NONE; int nInputs = NInChannels(), nOutputs = NOutChannels(); memset(&mAEffect, 0, sizeof(AEffect)); mAEffect.object = this; mAEffect.magic = kEffectMagic; mAEffect.dispatcher = VSTDispatcher; mAEffect.getParameter = VSTGetParameter; mAEffect.setParameter = VSTSetParameter; mAEffect.numPrograms = nPresets; mAEffect.numParams = nParams; mAEffect.numInputs = nInputs; mAEffect.numOutputs = nOutputs; mAEffect.uniqueID = uniqueID; mAEffect.version = GetEffectVersion(true); mAEffect.__ioRatioDeprecated = 1.0f; mAEffect.__processDeprecated = VSTProcess; mAEffect.processReplacing = VSTProcessReplacing; mAEffect.processDoubleReplacing = VSTProcessDoubleReplacing; mAEffect.initialDelay = latency; mAEffect.flags = effFlagsCanReplacing | effFlagsCanDoubleReplacing; if (plugDoesChunks) { mAEffect.flags |= effFlagsProgramChunks; } if (LegalIO(1, -1)) { mAEffect.flags |= __effFlagsCanMonoDeprecated; } if (plugIsInst) { mAEffect.flags |= effFlagsIsSynth; } memset(&mEditRect, 0, sizeof(ERect)); memset(&mInputSpkrArr, 0, sizeof(VstSpeakerArrangement)); memset(&mOutputSpkrArr, 0, sizeof(VstSpeakerArrangement)); mInputSpkrArr.numChannels = nInputs; mOutputSpkrArr.numChannels = nOutputs; mInputSpkrArr.type = VSTSpkrArrType(nInputs); mOutputSpkrArr.type = VSTSpkrArrType(nOutputs); // Default everything to connected, then disconnect pins if the host says to. SetInputChannelConnections(0, nInputs, true); SetOutputChannelConnections(0, nOutputs, true); SetBlockSize(DEFAULT_BLOCK_SIZE); }
IPlugVST3::IPlugVST3(IPlugInstanceInfo instanceInfo, int nParams, const char* channelIOStr, int nPresets, const char* effectName, const char* productName, const char* mfrName, int vendorVersion, int uniqueID, int mfrID, int latency, bool plugDoesMidi, bool plugDoesChunks, bool plugIsInst, int plugScChans) : IPlugBase(nParams, channelIOStr, nPresets, effectName, productName, mfrName, vendorVersion, uniqueID, mfrID, latency, plugDoesMidi, plugDoesChunks, plugIsInst) { mDoesMidi = plugDoesMidi; mScChans = plugScChans; mSideChainIsConnected = false; SetInputChannelConnections(0, NInChannels(), true); SetOutputChannelConnections(0, NOutChannels(), true); }
IPlugStandalone::IPlugStandalone(IPlugInstanceInfo instanceInfo, int nParams, const char* channelIOStr, int nPresets, const char* effectName, const char* productName, const char* mfrName, int vendorVersion, int uniqueID, int mfrID, int latency, bool plugDoesMidi, bool plugDoesChunks, bool plugIsInst, int plugScChans) : IPlugBase(nParams, channelIOStr, nPresets, effectName, productName, mfrName, vendorVersion, uniqueID, mfrID, latency, plugDoesMidi, plugDoesChunks, plugIsInst, kAPISA) { Trace(TRACELOC, "%s%s", effectName, channelIOStr); SetInputChannelConnections(0, NInChannels(), true); SetOutputChannelConnections(0, NOutChannels(), true); SetBlockSize(DEFAULT_BLOCK_SIZE); SetHost("standalone", vendorVersion); #ifdef OS_IOS mIOSLink = instanceInfo.mIOSLink; #else mMidiOutChan = instanceInfo.mMidiOutChan; mMidiOut = instanceInfo.mRTMidiOut; #endif }
tresult PLUGIN_API IPlugVST3Plugin::initialize (FUnknown* context) { TRACE; tresult result = SingleComponentEffect::initialize(context); String128 tmpStringBuf; char hostNameCString[128]; FUnknownPtr<IHostApplication>app(context); if (app) { app->getName(tmpStringBuf); Steinberg::UString(tmpStringBuf, 128).toAscii(hostNameCString, 128); SetHost(hostNameCString, 0); // Can't get version in VST3 } if (result == kResultOk) { int maxInputs = getSpeakerArrForChans(NInChannels()-mScChans); if(maxInputs < 0) maxInputs = 0; // add io buses with the maximum i/o to start with if (maxInputs) { Steinberg::UString(tmpStringBuf, 128).fromAscii(GetInputBusLabel(0)->Get(), 128); addAudioInput(tmpStringBuf, maxInputs); } if(!mIsInst) // if effect, just add one output bus with max chan count { Steinberg::UString(tmpStringBuf, 128).fromAscii(GetOutputBusLabel(0)->Get(), 128); addAudioOutput(tmpStringBuf, getSpeakerArrForChans(NOutChannels()) ); } else { for (int i = 0, busIdx = 0; i < NOutChannels(); i+=2, busIdx++) { Steinberg::UString(tmpStringBuf, 128).fromAscii(GetOutputBusLabel(busIdx)->Get(), 128); addAudioOutput(tmpStringBuf, SpeakerArr::kStereo ); } } if (mScChans) { if (mScChans > 2) mScChans = 2; Steinberg::UString(tmpStringBuf, 128).fromAscii(GetInputBusLabel(1)->Get(), 128); addAudioInput(tmpStringBuf, getSpeakerArrForChans(mScChans), kAux, 0); } if(DoesMIDI()) { addEventInput (STR16("MIDI Input"), 1); //addEventOutput(STR16("MIDI Output"), 1); } if (NPresets()) { parameters.addParameter(new Parameter(STR16("Preset"), kPresetParam, STR16(""), 0, NPresets(), ParameterInfo::kIsProgramChange)); } if(!mIsInst) { StringListParameter * bypass = new StringListParameter(STR16("Bypass"), kBypassParam, 0, ParameterInfo::kCanAutomate | ParameterInfo::kIsBypass | ParameterInfo::kIsList); bypass->appendString(STR16("off")); bypass->appendString(STR16("on")); parameters.addParameter(bypass); } for (int i=0; i<NParams(); i++) { IParam *p = GetParam(i); int32 flags = 0; UnitID unitID = kRootUnitId; const char* paramGroupName = p->GetParamGroupForHost(); if (CSTR_NOT_EMPTY(paramGroupName)) { for(int j = 0; j < mParamGroups.GetSize(); j++) { if(strcmp(paramGroupName, mParamGroups.Get(j)) == 0) { unitID = j+1; } } if (unitID == kRootUnitId) // new unit, nothing found, so add it { mParamGroups.Add(paramGroupName); unitID = mParamGroups.GetSize(); } } if (p->GetCanAutomate()) { flags |= ParameterInfo::kCanAutomate; } switch (p->Type()) { case IParam::kTypeDouble: case IParam::kTypeInt: { Parameter* param = new RangeParameter( STR16(p->GetNameForHost()), i, STR16(p->GetLabelForHost()), p->GetMin(), p->GetMax(), p->GetDefault(), 0, // continuous flags, unitID); param->setPrecision (p->GetPrecision()); parameters.addParameter(param); break; } case IParam::kTypeEnum: case IParam::kTypeBool: { StringListParameter* param = new StringListParameter (STR16(p->GetNameForHost()), i, STR16(p->GetLabelForHost()), flags | ParameterInfo::kIsList, unitID); int nDisplayTexts = p->GetNDisplayTexts(); assert(nDisplayTexts); for (int j=0; j<nDisplayTexts; j++) { param->appendString(STR16(p->GetDisplayText(j))); } parameters.addParameter(param); break; } default: break; } } } OnHostIdentified(); RestorePreset(0); return result; }
tresult PLUGIN_API IPlugVST3Plugin::process(ProcessData& data) { TRACE_PROCESS; IMutexLock lock(this); if(data.processContext) memcpy(&mProcessContext, data.processContext, sizeof(ProcessContext)); //process parameters IParameterChanges* paramChanges = data.inputParameterChanges; if (paramChanges) { int32 numParamsChanged = paramChanges->getParameterCount(); //it is possible to get a finer resolution of control here by retrieving more values (points) from the queue //for now we just grab the last one for (int32 i = 0; i < numParamsChanged; i++) { IParamValueQueue* paramQueue = paramChanges->getParameterData(i); if (paramQueue) { int32 numPoints = paramQueue->getPointCount(); int32 offsetSamples; double value; if (paramQueue->getPoint(numPoints - 1, offsetSamples, value) == kResultTrue) { int idx = paramQueue->getParameterId(); switch (idx) { case kBypassParam: { bool bypassed = (value > 0.5); if (bypassed != mIsBypassed) { mIsBypassed = bypassed; } break; } case kPresetParam: RestorePreset(FromNormalizedParam(value, 0, NPresets(), 1.)); break; //TODO pitch bend, modwheel etc default: if (idx >= 0 && idx < NParams()) { GetParam(idx)->SetNormalized((double)value); if (GetGUI()) GetGUI()->SetParameterFromPlug(idx, (double)value, true); OnParamChange(idx); } break; } } } } } if(DoesMIDI()) { //process events.. only midi note on and note off? IEventList* eventList = data.inputEvents; if (eventList) { int32 numEvent = eventList->getEventCount(); for (int32 i=0; i<numEvent; i++) { Event event; if (eventList->getEvent(i, event) == kResultOk) { IMidiMsg msg; switch (event.type) { case Event::kNoteOnEvent: { msg.MakeNoteOnMsg(event.noteOn.pitch, event.noteOn.velocity * 127, event.sampleOffset, event.noteOn.channel); ProcessMidiMsg(&msg); break; } case Event::kNoteOffEvent: { msg.MakeNoteOffMsg(event.noteOff.pitch, event.sampleOffset, event.noteOff.channel); ProcessMidiMsg(&msg); break; } } } } } } #pragma mark process single precision if (processSetup.symbolicSampleSize == kSample32) { if (data.numInputs) { if (mScChans) { if (getAudioInput(1)->isActive()) // Sidechain is active { mSidechainActive = true; SetInputChannelConnections(0, NInChannels(), true); } else { if (mSidechainActive) { ZeroScratchBuffers(); mSidechainActive = false; } SetInputChannelConnections(0, NInChannels(), true); SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - mScChans, false); } AttachInputBuffers(0, NInChannels() - mScChans, data.inputs[0].channelBuffers32, data.numSamples); AttachInputBuffers(mScChans, NInChannels() - mScChans, data.inputs[1].channelBuffers32, data.numSamples); } else { SetInputChannelConnections(0, data.inputs[0].numChannels, true); SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - data.inputs[0].numChannels, false); AttachInputBuffers(0, NInChannels(), data.inputs[0].channelBuffers32, data.numSamples); } } for (int outBus = 0, chanOffset = 0; outBus < data.numOutputs; outBus++) { int busChannels = data.outputs[outBus].numChannels; SetOutputChannelConnections(chanOffset, busChannels, (bool) getAudioOutput(outBus)->isActive()); SetOutputChannelConnections(chanOffset + busChannels, NOutChannels() - (chanOffset + busChannels), false); AttachOutputBuffers(chanOffset, busChannels, data.outputs[outBus].channelBuffers32); chanOffset += busChannels; } if (mIsBypassed) PassThroughBuffers(0.0f, data.numSamples); else ProcessBuffers(0.0f, data.numSamples); // process buffers single precision } #pragma mark process double precision else if (processSetup.symbolicSampleSize == kSample64) { if (data.numInputs) { if (mScChans) { if (getAudioInput(1)->isActive()) // Sidechain is active { mSidechainActive = true; SetInputChannelConnections(0, NInChannels(), true); } else { if (mSidechainActive) { ZeroScratchBuffers(); mSidechainActive = false; } SetInputChannelConnections(0, NInChannels(), true); SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - mScChans, false); } AttachInputBuffers(0, NInChannels() - mScChans, data.inputs[0].channelBuffers64, data.numSamples); AttachInputBuffers(mScChans, NInChannels() - mScChans, data.inputs[1].channelBuffers64, data.numSamples); } else { SetInputChannelConnections(0, data.inputs[0].numChannels, true); SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - data.inputs[0].numChannels, false); AttachInputBuffers(0, NInChannels(), data.inputs[0].channelBuffers64, data.numSamples); } } for (int outBus = 0, chanOffset = 0; outBus < data.numOutputs; outBus++) { int busChannels = data.outputs[outBus].numChannels; SetOutputChannelConnections(chanOffset, busChannels, (bool) getAudioOutput(outBus)->isActive()); SetOutputChannelConnections(chanOffset + busChannels, NOutChannels() - (chanOffset + busChannels), false); AttachOutputBuffers(chanOffset, busChannels, data.outputs[outBus].channelBuffers64); chanOffset += busChannels; } if (mIsBypassed) PassThroughBuffers(0.0, data.numSamples); else ProcessBuffers(0.0, data.numSamples); // process buffers double precision } // Midi Out // if (mDoesMidi) { // IEventList eventList = data.outputEvents; // // if (eventList) // { // Event event; // // while (!mMidiOutputQueue.Empty()) { // //TODO: parse events and add // eventList.addEvent(event); // } // } // } return kResultOk; }
IPlugVST3Plugin::IPlugVST3Plugin(IPlugInstanceInfo instanceInfo, int nParams, const char* channelIOStr, int nPresets, const char* effectName, const char* productName, const char* mfrName, int vendorVersion, int uniqueID, int mfrID, int latency, bool plugDoesMidi, bool plugDoesChunks, bool plugIsInst, int plugScChans) : IPlugBase(nParams, channelIOStr, nPresets, effectName, productName, mfrName, vendorVersion, uniqueID, mfrID, latency, plugDoesMidi, plugDoesChunks, plugIsInst, kAPIVST3) , mScChans(plugScChans) , mSidechainActive(false) { SetInputChannelConnections(0, NInChannels(), true); SetOutputChannelConnections(0, NOutChannels(), true); if (NInChannels()) { mDelay = new NChanDelayLine(NInChannels(), NOutChannels()); mDelay->SetDelayTime(latency); } // initialize the bus labels SetInputBusLabel(0, "Main Input"); if (mScChans) { SetInputBusLabel(1, "Aux Input"); } if (IsInst()) { int busNum = 0; char label[32]; for (int i = 0; i < NOutChannels(); i+=2) // stereo buses only { sprintf(label, "Output %i", busNum+1); SetOutputBusLabel(busNum++, label); } } else { SetOutputBusLabel(0, "Output"); } }
tresult PLUGIN_API IPlugVST3::initialize (FUnknown* context) { TRACE; tresult result = SingleComponentEffect::initialize (context); if (result == kResultOk) { addAudioInput (STR16("Audio Input"), getSpeakerArrForChans(NInChannels()) ); addAudioOutput (STR16("Audio Output"), getSpeakerArrForChans(NOutChannels()) ); if (mScChans == 1) addAudioInput(STR16("Sidechain Input"), SpeakerArr::kMono, kAux, 0); else if (mScChans >= 2) { mScChans = 2; addAudioInput(STR16("Sidechain Input"), SpeakerArr::kStereo, kAux, 0); } if(mDoesMidi) { addEventInput (STR16("MIDI In"), 1); addEventOutput(STR16("MIDI Out"), 1); } for (int i=0;i<NParams();i++) { IParam *p = GetParam(i); int32 flags = 0; if (p->GetCanAutomate()) { flags |= ParameterInfo::kCanAutomate; } switch (p->Type()) { case IParam::kTypeDouble: case IParam::kTypeInt: { Parameter* param = new RangeParameter ( STR16(p->GetNameForHost()), i, STR16(p->GetLabelForHost()), p->GetMin(), p->GetMax(), p->GetDefault(), p->GetStep(), flags); param->setPrecision (p->GetPrecision()); parameters.addParameter (param); break; } case IParam::kTypeEnum: case IParam::kTypeBool: { StringListParameter* param = new StringListParameter (STR16(p->GetNameForHost()), i, STR16(p->GetLabelForHost()), flags | ParameterInfo::kIsList); int nDisplayTexts = p->GetNDisplayTexts(); assert(nDisplayTexts); for (int j=0; j<nDisplayTexts; j++) { param->appendString(STR16(p->GetDisplayText(j))); } parameters.addParameter (param); break; } default: break; } } } return result; }
tresult PLUGIN_API IPlugVST3::setBusArrangements(SpeakerArrangement* inputs, int32 numIns, SpeakerArrangement* outputs, int32 numOuts) { TRACE; //inputs AudioBus* bus = getAudioInput(0); if (bus && bus->getArrangement() != inputs[0]) { if (inputs[0] == SpeakerArr::kMono) { //re-create the busses.. audioInputs.remove(bus); if (mScChans) { bus = getAudioInput(0); if (bus && bus->getArrangement() != inputs[1]) //sidechain SpeakerArr:: must match the input SpeakerArr:: { audioInputs.remove(bus); } } addAudioInput(USTRING ("Mono In"), SpeakerArr::kMono); addAudioInput(USTRING ("Mono Sidechain In"), SpeakerArr::kMono, kAux, 0); //disconnect the unused pins, don't worry about sidechain yet - it will get done at process() SetInputChannelConnections(1, NInChannels(), false); mSideChainIsConnected = false; } } //outputs bus = getAudioOutput(0); if (bus && bus->getArrangement() != outputs[0]) { if (outputs[0] == SpeakerArr::kMono) { audioOutputs.remove(bus); addAudioOutput(USTRING ("Mono Out"), SpeakerArr::kMono); //disconnect the unused pin SetOutputChannelConnections(1, NOutChannels(), false); } } if (mScChans) { if (getAudioInput(0)->getArrangement() == inputs[0] && getAudioOutput(0)->getArrangement() == outputs[0] && getAudioInput(1)->getArrangement() == inputs[1]) return kResultOk; } else { if (getAudioInput(0)->getArrangement() == inputs[0] && getAudioOutput(0)->getArrangement() == outputs[0]) return kResultOk; } return kResultFalse; }