bool IPlugStandalone::SendMidiMsg(IMidiMsg* pMsg) { #ifdef OS_IOS mIOSLink->SendMidiMsg(pMsg); #else if (DoesMIDI()) { IMidiMsg newMsg = *pMsg; // if the midi channel out filter is set, reassign the status byte appropriately if (!*mMidiOutChan == 0) { newMsg.mStatus = (*mMidiOutChan)-1 | ((unsigned int) newMsg.StatusMsg() << 4) ; } std::vector<unsigned char> message; message.push_back( newMsg.mStatus ); message.push_back( newMsg.mData1 ); message.push_back( newMsg.mData2 ); mMidiOut->sendMessage( &message ); return true; } #endif return false; }
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); }
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); } }
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; }