LFO on IIR FIlter


#1

Hi Again!
I’m ultimating the touches to my Filter Delay and I need to apply an LFO on a IIR Filter.
I have this code:

float lfoRate = 2 * float_Pi / (lfoFreq / rate);
lfo += lfoRate;
if(lfo > 2 * float_Pi) lfo -= 2 * float_Pi;
output = std::sin(lfo);
output *= lfoAmplitude;

I can control lfoFreq an lfoAmplitude by sliders BUT the filter:

filterA->setCoefficients(IIRCoefficients::makeLowPass(rate, afreq + output, aq));

takes the output value only at one time, in the definition.

How can I LFO with my code, the filter frequency?


#2

Best not using any filter that requires Coefficients. There are ways to do this but they are quite complex. Try using a one or two pole filter like a Biquad as these are much more tolerant to change.

What’s is the use case of this?


#3

I’m making a plugin that filters a simple delay effect, and I want to modulate the filter…
Excuse me but I tried a BiQuad filter in the past… it requires coefficients too…
EDIT: I switch form LowPass, HighPass, BandPass, Notch, Peak, AllPass, LowShelf, HighShelf


#4

Okay should have been more clear I meant an analogue style filter as apposed to digital like FIR or IIR. The reason is the delay is only one or two samples and its tolerant to change in the sense that it does not require going through taps that could produces artifacts if changed mid processing - especially when modulating …


#5

Excuse me, I don’t understand… The goal for me is to modulate each delay repetition…to obtain a feedback modulated effect… I don’t understand too much DSP programming, I0m using only the IIR classes of JUCE.
Can you tell me how to implement an analogue filter?


#6

You might want to try out dsp::StateVariableFilter. Haven’t tried it myself yet but the design goal was to implement a filter that can easily cope with modulation.


#7

Ok, excuse me for the late… I’m trying to use dip::StateVariableFilter, but I ear no filtering… I’m using this code:

in prepare to play:
filterABuffer.setSize(1, samplesPerBlock);

filterA = new dsp::StateVariableFilter::Filter<double>();
filterA->parameters->type = dsp::StateVariableFilter::Parameters<double>::Type::lowPass;
filterA->parameters->setCutOffFrequency(rate, acutoff);

In processBlock:

    auto numSamples = buffer.getNumSamples();

float lfoRate = 2 * float_Pi / (arate / rate);
lfo += lfoRate;
if(lfo > 2 * float_Pi) lfo -= 2 * float_Pi;
output = std::sin(lfo);
output *= afactor;

acutoff += output;

DBG(acutoff);

// Delay A
switch ((int)atype)
{
    case 0:
        filterA->parameters->type = dsp::StateVariableFilter::Parameters<double>::Type::lowPass;
        filterA->parameters->setCutOffFrequency(rate, acutoff);
        break;
    case 1:
        filterA->parameters->type = dsp::StateVariableFilter::Parameters<double>::Type::highPass;
        filterA->parameters->setCutOffFrequency(rate, acutoff);
        break;
    case 2:
        filterA->parameters->type = dsp::StateVariableFilter::Parameters<double>::Type::bandPass;
        filterA->parameters->setCutOffFrequency(rate, acutoff);
        break;
}

delayA.setDelay(atime * 44.100);
delayA.setGain(afeedback / 100.0);

filterABuffer.copyFrom(0, 0, buffer.getReadPointer(0), numSamples);

for (int i = 0; i < numSamples; ++i)
{
    float* buf = filterABuffer.getWritePointer(0);
    filterA->processSample(buf[i]);
}

delayABuffer.copyFrom(0, 0, filterABuffer.getReadPointer(0), numSamples);

for (int i = 0; i < numSamples; ++i)
{
    float* buf = delayABuffer.getWritePointer(0);
    float* delayBuf = delayBufferA.getWritePointer(0);
    
    float inBuf = buf[i];
    buf[i] += delayBuf[i];
    delayBuf[i] = (delayA.tick(delayBuf[i]) + inBuf) * (amix / 100.0);
}

auto anglea = jmap(apan * 1.0, -1.0, 1.0, 0.0, float_Pi * 0.5);

buffer.addFrom(0, 0, delayABuffer.getReadPointer(0), numSamples, std::cos(anglea));
buffer.addFrom(1, 0, delayABuffer.getReadPointer(0), numSamples, std::sin(anglea));

where am I wrong?