Hi, I’m developing a FilterDelay vst/AU using stk c++ classes.
I hava a custom class (FilterDelay.h) that implements the biquad and the delay stk filter.
Now I have 2 instances of that object in PluginProcessor.cpp, the lFilter and the rFilter.
I instantiate them in prepareToPlay and set them in processBlock but in the lFilter instance, the panning function doesn’t work, instead in the rFilter it works great!
Any idea?
FilterDelay.h
#include <math.h>
class FilterDelay
{
public:
FilterDelay()
{
lBiQuad = stk::BiQuad();
rBiQuad = stk::BiQuad();
lDelay = stk::DelayA(22050.0, 44100.0);
rDelay = stk::DelayA(22050.0, 44100.0);
}
void clear()
{
lBiQuad.clear();
rBiQuad.clear();
lDelay.clear();
rDelay.clear();
}
void process(AudioSampleBuffer& buffer, AudioSampleBuffer& lDelayBuffer, AudioSampleBuffer& rDelayBuffer)
{
// Filter
A = pow((db / 40), 10);
w0 = 2 * M_PI * f0 / 44100.0;
alpha = sin(w0) / (2 * Q);
if (type == 0.0)
{
b0 = (1 - cos(w0)) / 2;
b1 = 1 - cos(w0);
b2 = (1 - cos(w0)) / 2;
a0 = 1 + alpha;
a1 = -2 * cos(w0);
a2 = 1 - alpha;
}
else if (type == 1.0)
{
b0 = (1 + cos(w0)) / 2;
b1 = -(1 + cos(w0));
b2 = (1 + cos(w0)) / 2;
a0 = 1 + alpha;
a1 = -2 * cos(w0);
a2 = 1 - alpha;
}
else if (type == 2.0)
{
b0 = Q * alpha;
b1 = 0;
b2 = -Q * alpha;
a0 = 1 + alpha;
a1 = -2 * cos(w0);
a2 = 1 - alpha;
}
else if (type == 3.0)
{
b0 = alpha;
b1 = 0;
b2 = -alpha;
a0 = 1 + alpha;
a1 = -2 * cos(w0);
a2 = 1 - alpha;
}
else if (type == 4.0)
{
b0 = 1;
b1 = -2 * cos(w0);
b2 = 1;
a0 = 1 + alpha;
a1 = -2 * cos(w0);
a2 = 1 - alpha;
}
else if (type == 5.0)
{
b0 = 1 - alpha;
b1 = -2 * cos(w0);
b2 = 1 + alpha;
a0 = 1 + alpha;
a1 = -2 * cos(w0);
a2 = 1 - alpha;
}
else if (type == 6.0)
{
b0 = 1 + alpha * A;
b1 = -2 * cos(w0);
b2 = 1 - alpha * A;
a0 = 1 + alpha / A;
a1 = -2 * cos(w0);
a2 = 1 - alpha / A;
}
else if (type == 7.0)
{
b0 = A * ((A+1) - (A-1) * cos(w0) + 2 * sqrt(A) * alpha);
b1 = 2 * A * ((A-1) - (A+1) * cos(w0));
b2 = A * ((A+1) - (A-1) * cos(w0) - 2 * sqrt(A) * alpha);
a0 = (A+1) + (A-1) * cos(w0) + 2 * sqrt(A) * alpha;
a1 = -2 * ((A-1) + (A+1) * cos(w0));
a2 = (A+1) + (A-1) * cos(w0) - 2 * sqrt(A) * alpha;
}
else if (type == 8.0)
{
b0 = A * ((A+1) + (A-1) * cos(w0) + 2 * sqrt(A) * alpha);
b1 = -2 * A * ((A-1) + (A+1) * cos(w0));
b2 = A * ((A+1) + (A-1) * cos(w0) - 2 * sqrt(A) * alpha);
a0 = (A+1) - (A-1) * cos(w0) + 2 * sqrt(A) * alpha;
a1 = 2 * ((A-1) - (A+1) * cos(w0));
a2 = (A+1) - (A-1) * cos(w0) - 2 * sqrt(A) * alpha;
}
b0 = b0 / a0;
b1 = b1 / a0;
b2 = b2 / a0;
a1 = a1 / a0;
a2 = a2 / a0;
lBiQuad.setCoefficients(b0, b1, b2, a1, a2);
//lBiQuad.setGain(lGain);
rBiQuad.setCoefficients(b0, b1, b2, a1, a2);
//rBiQuad.setGain(rGain);
// Delay
lDelay.setDelay(delayTime);
lDelay.setGain(lGain);
rDelay.setDelay(delayTime);
rDelay.setGain(rGain);
// Process Audio
const int numSamples = buffer.getNumSamples();
buffer.copyFrom(1, 0, buffer, 0, 0, numSamples);
for (int i = 0; i < numSamples; ++i)
{
float* lBuf = buffer.getWritePointer(0);
float* delayLBuf = lDelayBuffer.getWritePointer(0);
float inL = lBuf[i];
lBuf[i] += delayLBuf[i];
delayLBuf[i] = lDelay.tick(delayLBuf[i] * delayFeedback) + lBiQuad.tick(inL) * delayLevel;
float* rBuf = buffer.getWritePointer(1);
float* delayRBuf = rDelayBuffer.getWritePointer(0);
float inR = rBuf[i];
rBuf[i] += delayRBuf[i];
delayRBuf[i] = rDelay.tick(delayRBuf[i] * delayFeedback) + rBiQuad.tick(inR) * delayLevel;
}
}
void setFilterType(float value)
{
type = value;
}
void setFilterFrequency (float value)
{
f0 = value;
}
void setFilterGain (float value)
{
db = value;
}
void setFilterQ (float value)
{
Q = value;
}
void setGlobalPan (float pan)
{
if (pan < 0.0)
{
lGain = 0.5;
rGain = 0.5 - fabsf(pan / 2);
}
if (pan == 0.0)
{
lGain = 0.5;
rGain = 0.5;
}
if (pan > 0.0)
{
lGain = 0.5 - fabsf(pan / 2);
rGain = 0.5;
}
}
void setDelayTime(float value)
{
delayTime = value;
}
void setDelayFeedback(float value)
{
delayFeedback = value;
}
void setDelayLevel(float value)
{
delayLevel = value;
}
private:
// Filter
float type;
float f0, db, Q;
float lGain, rGain;
float A, w0, alpha;
float a0, a1, a2, b0, b1, b2;
stk::BiQuad lBiQuad, rBiQuad;
// Delay
float delayTime, delayFeedback, delayLevel;
stk::DelayA lDelay, rDelay;
};
PluginProcessor.cpp:
void FilterDelayAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Audio Buffers
lDelayBufferA.setSize(1, 12000);
lDelayBufferA.clear();
lDelayBufferB.setSize(1, 12000);
lDelayBufferB.clear();
rDelayBufferA.setSize(1, 12000);
rDelayBufferA.clear();
rDelayBufferB.setSize(1, 12000);
rDelayBufferB.clear();
// Left Filter
lFilter = FilterDelay();
const float ltype = *parameters.getRawParameterValue("lType");
lFilter.setFilterType(ltype);
const float ldb = *parameters.getRawParameterValue("lGain");
lFilter.setFilterGain(ldb);
const float lf0 = *parameters.getRawParameterValue("lFreq");
lFilter.setFilterFrequency(lf0);
const float lQ = *parameters.getRawParameterValue("lQ");
lFilter.setFilterQ(lQ);
const float lpan = *parameters.getRawParameterValue("lPan");
lFilter.setGlobalPan(lpan);
const float ltime = *parameters.getRawParameterValue("lTime");
lFilter.setDelayTime(ltime);
const float lfeedback = *parameters.getRawParameterValue("lFeedback");
lFilter.setDelayFeedback(lfeedback);
const float llevel = *parameters.getRawParameterValue("lLevel");
lFilter.setDelayLevel(llevel);
lFilter.clear();
// Right Filter
rFilter = FilterDelay();
const float rtype = *parameters.getRawParameterValue("rType");
rFilter.setFilterType(rtype);
const float rdb = *parameters.getRawParameterValue("rGain");
rFilter.setFilterGain(rdb);
const float rf0 = *parameters.getRawParameterValue("rFreq");
rFilter.setFilterFrequency(rf0);
const float rQ = *parameters.getRawParameterValue("rQ");
rFilter.setFilterQ(rQ);
const float rpan = *parameters.getRawParameterValue("rPan");
rFilter.setGlobalPan(rpan);
const float rtime = *parameters.getRawParameterValue("rTime");
rFilter.setDelayTime(rtime);
const float rfeedback = *parameters.getRawParameterValue("rFeedback");
rFilter.setDelayFeedback(rfeedback);
const float rlevel = *parameters.getRawParameterValue("rLevel");
rFilter.setDelayLevel(rlevel);
rFilter.clear();
}
void FilterDelayAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
// Left Filter
const float ltype = *parameters.getRawParameterValue("lType");
lFilter.setFilterType(ltype);
if (ltype > 5.0) { showLGain = true; }
else if (ltype <= 5.0) { showLGain = false; }
const float ldb = *parameters.getRawParameterValue("lGain");
lFilter.setFilterGain(ldb);
const float lf0 = *parameters.getRawParameterValue("lFreq");
lFilter.setFilterFrequency(lf0);
const float lQ = *parameters.getRawParameterValue("lQ");
lFilter.setFilterQ(lQ);
const float lpan = *parameters.getRawParameterValue("lPan");
lFilter.setGlobalPan(lpan);
const float ltime = *parameters.getRawParameterValue("lTime");
lFilter.setDelayTime(ltime);
const float lfeedback = *parameters.getRawParameterValue("lFeedback");
lFilter.setDelayFeedback(lfeedback);
const float llevel = *parameters.getRawParameterValue("lLevel");
lFilter.setDelayLevel(llevel);
lFilter.process(buffer, lDelayBufferA, rDelayBufferA);
// Right Filter
const float rtype = *parameters.getRawParameterValue("rType");
rFilter.setFilterType(rtype);
if (rtype > 5.0) { showRGain = true; }
else if (rtype <= 5.0) { showRGain = false; }
const float rdb = *parameters.getRawParameterValue("rGain");
rFilter.setFilterGain(rdb);
const float rf0 = *parameters.getRawParameterValue("rFreq");
rFilter.setFilterFrequency(rf0);
const float rQ = *parameters.getRawParameterValue("rQ");
rFilter.setFilterQ(rQ);
const float rpan = *parameters.getRawParameterValue("rPan");
rFilter.setGlobalPan(rpan);
const float rtime = *parameters.getRawParameterValue("rTime");
rFilter.setDelayTime(rtime);
const float rfeedback = *parameters.getRawParameterValue("rFeedback");
rFilter.setDelayFeedback(rfeedback);
const float rlevel = *parameters.getRawParameterValue("rLevel");
rFilter.setDelayLevel(rlevel);
rFilter.process(buffer, lDelayBufferB, rDelayBufferB);
}
