//-------------------------------------------------------------------------------------------------------------- void ParameterChangeTransfer::transferChangesTo (ParameterChanges& dest) { ParamID pid; ParamValue value; int32 sampleOffset; int32 index; while (getNextChange (pid, value, sampleOffset)) { IParamValueQueue* queue = dest.addParameterData (pid, index); if (queue) { queue->addPoint (sampleOffset, value, index); } } }
//------------------------------------------------------------------------ tresult PLUGIN_API UIDescriptionTestProcessor::process (ProcessData& data) { ParamValue peak = 0.; for (int32 sample = 0; sample < data.numSamples; sample++) { for (int32 channel = 0; channel < data.inputs[0].numChannels; channel++) { float value = data.inputs[0].channelBuffers32[channel][sample]; data.outputs[0].channelBuffers32[channel][sample] = value; value = fabs (value); if (value > peak) peak = value; } } if (data.outputParameterChanges) { int32 index; IParamValueQueue* queue = data.outputParameterChanges->addParameterData (kPeakParam, index); if (queue) queue->addPoint (0, peak, index); } return kResultTrue; }
//------------------------------------------------------------------------ tresult PLUGIN_API AGainSimple::process (ProcessData& data) { // finally the process function // In this example there are 4 steps: // 1) Read inputs parameters coming from host (in order to adapt our model values) // 2) Read inputs events coming from host (we apply a gain reduction depending of the velocity of pressed key) // 3) Process the gain of the input buffer to the output buffer // 4) Write the new VUmeter value to the output Parameters queue //---1) Read inputs parameter changes----------- IParameterChanges* paramChanges = data.inputParameterChanges; if (paramChanges) { int32 numParamsChanged = paramChanges->getParameterCount (); // for each parameter which are some changes in this audio block: for (int32 i = 0; i < numParamsChanged; i++) { IParamValueQueue* paramQueue = paramChanges->getParameterData (i); if (paramQueue) { int32 offsetSamples; double value; int32 numPoints = paramQueue->getPointCount (); switch (paramQueue->getParameterId ()) { case kGainId: // we use in this example only the last point of the queue. // in some wanted case for specific kind of parameter it makes sense to retrieve all points // and process the whole audio block in small blocks. if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue) fGain = (float)value; break; case kBypassId: if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue) bBypass = (value > 0.5f); break; } } } } //---2) Read input events------------- 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) { switch (event.type) { //---------------------- case Event::kNoteOnEvent: // use the velocity as gain modifier fGainReduction = event.noteOn.velocity; break; //---------------------- case Event::kNoteOffEvent: // noteOff reset the reduction fGainReduction = 0.f; break; } } } } //------------------------------------- //---3) Process Audio--------------------- //------------------------------------- if (data.numInputs == 0 || data.numOutputs == 0) { // nothing to do return kResultOk; } // (simplification) we suppose in this example that we have the same input channel count than the output int32 numChannels = data.inputs[0].numChannels; //---get audio buffers---------------- float** in = data.inputs[0].channelBuffers32; float** out = data.outputs[0].channelBuffers32; //---check if silence--------------- // normally we have to check each channel (simplification) if (data.inputs[0].silenceFlags != 0) { // mark output silence too data.outputs[0].silenceFlags = data.inputs[0].silenceFlags; // the Plug-in has to be sure that if it sets the flags silence that the output buffer are clear int32 sampleFrames = data.numSamples; for (int32 i = 0; i < numChannels; i++) { // dont need to be cleared if the buffers are the same (in this case input buffer are already cleared by the host) if (in[i] != out[i]) { memset (out[i], 0, sampleFrames * sizeof (float)); } } // nothing to do at this point return kResultOk; } // mark our outputs has not silent data.outputs[0].silenceFlags = 0; //---in bypass mode outputs should be like inputs----- if (bBypass) { int32 sampleFrames = data.numSamples; for (int32 i = 0; i < numChannels; i++) { // dont need to be copied if the buffers are the same if (in[i] != out[i]) memcpy (out[i], in[i], sampleFrames * sizeof (float)); } // in this example we dont update the VuMeter in Bypass } else { float fVuPPM = 0.f; //---apply gain factor---------- float gain = (fGain - fGainReduction); if (bHalfGain) { gain = gain * 0.5f; } if (gain < 0.0000001) { int32 sampleFrames = data.numSamples; for (int32 i = 0; i < numChannels; i++) { memset (out[i], 0, sampleFrames * sizeof (float)); } data.outputs[0].silenceFlags = (1 << numChannels) - 1; // this will set to 1 all channels fVuPPM = 0.f; } else { // in real Plug-in it would be better to do dezippering to avoid jump (click) in gain value for (int32 i = 0; i < numChannels; i++) { int32 sampleFrames = data.numSamples; float* ptrIn = in[i]; float* ptrOut = out[i]; float tmp; while (--sampleFrames >= 0) { // apply gain tmp = (*ptrIn++) * gain; (*ptrOut++) = tmp; // check only positiv values if (tmp > fVuPPM) fVuPPM = tmp; } } } //---3) Write outputs parameter changes----------- IParameterChanges* paramChanges = data.outputParameterChanges; // a new value of VuMeter will be send to the host // (the host will send it back in sync to our controller for updating our editor) if (paramChanges && fVuPPMOld != fVuPPM) { int32 index = 0; IParamValueQueue* paramQueue = paramChanges->addParameterData (kVuPPMId, index); if (paramQueue) { int32 index2 = 0; paramQueue->addPoint (0, fVuPPM, index2); } } fVuPPMOld = fVuPPM; } return kResultOk; }