Modulating filter patch

Home Forums OWL Patches Modulating filter patch

This topic contains 10 replies, has 4 voices, and was last updated by  Martin Klang 3 years, 9 months ago.

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • #1188

    blondinou
    Participant

    Hi,

    here is a first version of my first patch. This is a filter (the filter itself is Moog VCF filter) with a modulation on the resonance (Q factor). It actually sounds more like a tremolo.

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    // 2014-01-12 – blondinou – first version
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    #ifndef __PsycheFilterPatch_hpp__
    #define __PsycheFilterPatch_hpp__

    #include “StompBox.h”
    #include <math.h>

    #define TWOPI 6.2831853071f

    #define MOD_SPEED 0.14f
    #define MOD_LEVEL 1.0f
    #define WET_DRY_COMPENSATION 1.5f
    #define RES_MIN 0.1f
    #define RES_MULT 0.4f

    class PsycheFilterPatch : public Patch {
    public:
    PsycheFilterPatch() :
    k(0.0f),
    p(0.0f),
    r(0.0f),
    oldX(0.0f),
    oldBuf0(0.0f),
    oldBuf1(0.0f),
    oldBuf2(0.0f),
    x(0.0f),
    buf0(0.0f),
    buf1(0.0f),
    buf2(0.0f),
    buf3(0.0f),
    phase(0.0f)
    {
    registerParameter(PARAMETER_A, “Resonance”);
    registerParameter(PARAMETER_B, “Cutoff”, “Cutoff frequency”);
    registerParameter(PARAMETER_C, “Modulation”, “Resonance modulation speed”);
    registerParameter(PARAMETER_D, “Level”, “Effect level”);

    sampleRate = getSampleRate();
    for (int i = 0; i < 6; i++) { knobs[i] = 0.f; }
    }

    void processAudio(AudioBuffer &buffer) {
    if (parametersChanged()) {
    // update filter factors if knobs were moved
    updateFactors();
    }

    // modulation resonance
    float q = r;
    if (knobs[PARAMETER_C] > 0.0f) {
    phase += MOD_SPEED * knobs[PARAMETER_C];
    if (phase >= 1.0) {
    phase -= 1.0;
    }
    q += q * MOD_LEVEL * sinf(phase * TWOPI);
    }

    // apply filter
    float level = knobs[PARAMETER_D];
    int size = buffer.getSize();
    for (int ch = 0; ch < buffer.getChannels(); ++ch) {
    float* buf = buffer.getSamples(ch);
    for (int i = 0; i < size; i++) {
    x = buf[i] – q * buf3;

    buf0 = x * p + oldX * p – k * buf0;
    buf1 = buf0 * p + oldBuf0 * p – k * buf1;
    buf2 = buf1 * p + oldBuf1 * p – k * buf2;
    buf3 = buf2 * p + oldBuf2 * p – k * buf3;

    buf3 -= (buf3 * buf3 * buf3) / 6.f;

    oldX = x;
    oldBuf0 = buf0;
    oldBuf1 = buf1;
    oldBuf2 = buf2;

    buf[i] = (1.0f – level) * buf[i] + level * buf3 * WET_DRY_COMPENSATION;
    }
    }
    }

    private:
    float knobs[6];
    float k;
    float p;
    float r;
    float oldX;
    float oldBuf0;
    float oldBuf1;
    float oldBuf2;
    float x;
    float buf0;
    float buf1;
    float buf2;
    float buf3;
    float phase;
    double sampleRate;

    bool parametersChanged() {
    return getParameterValue(PARAMETER_A) != knobs[PARAMETER_A]
    || getParameterValue(PARAMETER_B) != knobs[PARAMETER_B]
    || getParameterValue(PARAMETER_C) != knobs[PARAMETER_C]
    || getParameterValue(PARAMETER_D) != knobs[PARAMETER_D];
    }

    void updateFactors() {
    // update
    knobs[PARAMETER_A] = getParameterValue(PARAMETER_A);
    knobs[PARAMETER_B] = getParameterValue(PARAMETER_B);
    knobs[PARAMETER_C] = getParameterValue(PARAMETER_C);
    knobs[PARAMETER_D] = getParameterValue(PARAMETER_D);

    // compute filter factors
    float resonance = RES_MIN + RES_MULT * knobs[PARAMETER_A];
    float cutoff = knobs[PARAMETER_B];
    cutoff = (cutoff * 4250.f) + 250.f;
    double sampleRate = getSampleRate();

    if (sampleRate == 0) {
    sampleRate = 44100.0;
    }

    float f = (cutoff + cutoff) / (float)sampleRate;
    p = f * (1.8f – 0.8f * f);
    k = p + p – 1.f;

    float t = (1.f – p) * 1.386249f;
    float t2 = 12.f + t * t;
    r = resonance * (t2 + 6.f*t) / (t2 – 6.f * t);
    }
    };

    #endif // __PsycheFilterPatch_hpp__

    #1190

    giom
    Keymaster

    Cool !
    It is nice to have a first implementation of the Moog VCF.
    Makes me wanna add a distortion term in the feedback loop!

    I will test it on the Owl and include it in OwlPatches if you like.

    • This reply was modified 3 years, 11 months ago by  giom.
    #1193

    Martin Klang
    Keymaster

    Nice one –
    if you send a git pull request then I will pull it into the OwlPatches main branch.
    https://help.github.com/articles/using-pull-requests

    If you don’t fancy doing the whole git thing, let me know and I’ll simply add the source file.

    #1196

    blondinou
    Participant

    The distortion in the feedback loop seems a nice idea. As all four knobs are already used, maybe I should find the better spot for the resonance to reuse the knob.

    I think I’ve done a commit. That git thing seems very complicated, although I’m accustomed to SVN and ClearCase.

    #1197

    Martin Klang
    Keymaster

    I think you have to fork the OwlPatches repository on github, create a branch, add and commit your file, then send a pull request to merge it with the master branch…
    It’s a hassle if you’re not used to it, but it sets you up to submit more changes and patches in the future. If not, I’ll happily just add the file in, if you like. I’ve got it compiling and running on the pedal already – sounds good!

    #1199

    blondinou
    Participant

    Ok, I think I managed to send the pull request.

    #1200

    sleeven
    Participant

    Thanks for putting this together!

    #1350

    blondinou
    Participant

    Here is a sample :
    PsycheFilter

    #1363

    blondinou
    Participant

    I set up a blog to publish the sample and introduce the patch :
    http://audionomics-en.eklablog.com/psychefilter-patch-for-the-owl-a106632026

    #1407

    blondinou
    Participant

    I added the possibility to use an expression pedal to control the cutoff. To do this, cutoff and resonance must be set at 0.

    Pull request sent ! It also fix clicks in stereo mode.

    #1409

    Martin Klang
    Keymaster

    ok cool, thanks!

    With the expression pedal, we’ve found that using it to modulate another parameter works well. You can see this in the Overdrive (latest version, just pushed to github).

        float expr = 1 - getParameterValue(PARAMETER_E);
        float drive = expr*getParameterValue(PARAMETER_A);
    

    This way, if no pedal is plugged in the drive value will be set simply by knob A (multiplier is 1). If the pedal is active, it will control the drive from 0 up to whatever value A is set to. Thus A sets the upper limit of the drive – quite useful!

Viewing 11 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic.


Latest News

Links

Follow us on Twitter