Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add alternate MIT-licensed ladder filter module #200

Merged
merged 2 commits into from
Jan 29, 2024

Conversation

ndonald2
Copy link
Contributor

Description

Adds a new, MIT-licensed ladder filter implementation with additional features and stability compared to the previous DaisySP moogladder (now in LGPL modules).

This implementation is ported from MIT-licensed code in the Teensy Audio Library, with the implementation derived from work in this paper from Computer Music Journal by Välimäki and Huovilainen.

This version brings the following advantages:

  • Stability across all valid (and internally clamped) parameter ranges
  • Stable self oscillation at higher resonances
  • 4x linear oversampling for aliasing mitigation
  • Input drive and passband gain adjustment
  • Filter mode selection (LP/BP/HP 2- or 4-pole outputs)
    • Could also provide parallel outputs with some additional modification

However it is a little bit more computationally expensive without additional optimizations not included here (block-based processing helps a bit). Still plenty fast enough to run multiple instances on a Seed.

I believe the OSS license stuff is all in order (preserved MIT license in header with original copyright, added copyright for modifications, and documentation of modifications).

Testing

I've used this code extensively in my own projects

Demos / Example Code

I don't have any audio or video demos handy but I could make some on request.

Example program

#include "daisysp.h"
#include "daisy_seed.h"

using namespace daisysp;
using namespace daisy;

static DaisySeed  hw;
static Oscillator osc, lfo;
static LadderFilter ladder;

static void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                          AudioHandle::InterleavingOutputBuffer out,
                          size_t                                size)
{
    float sig;
    float cutoff;
    for(size_t i = 0; i < size; i += 2)
    {
        cutoff = 2000.0f;
        cutoff *= exp2f(lfo.Process() * 2.0f);
        ladder.SetFreq(cutoff);

        sig = osc.Process();
        sig = ladder.Process(sig);

        // left out
        out[i] = sig;

        // right out
        out[i + 1] = sig;
    }
}

int main(void)
{
    // initialize seed hardware and oscillator daisysp module
    float sample_rate;
    hw.Configure();
    hw.Init();
    hw.SetAudioBlockSize(4);
    sample_rate = hw.AudioSampleRate();

    osc.Init(sample_rate);
    lfo.Init(sample_rate);
    ladder.Init(sample_rate);

    // Set parameters for oscillator
    osc.SetWaveform(osc.WAVE_SAW);
    osc.SetFreq(220.0f);
    osc.SetAmp(0.5f);

    // Set parameters for filter
    ladder.SetRes(0.5f);
    ladder.SetInputDrive(2.0f);
    //ladder.SetFilterMode(LadderFilter::FilterMode::BP12); // set alt filter mode

    // Set parameters for lfo
    lfo.SetWaveform(lfo.WAVE_SIN);
    lfo.SetFreq(0.5f);
    lfo.SetAmp(1.0f);

    // start callback
    hw.StartAudio(AudioCallback);

    while(1) {}
}

- Configurable drive and passband gain
- Alternate filter output modes (BP/LP/HP 2- or 4-pole)
@stephenhensley
Copy link
Collaborator

This is awesome! We'll get this reviewed and merged within the next week!

Thanks for the contribution, @ndonald2 !!

@beserge
Copy link
Contributor

beserge commented Jan 29, 2024

Sounds great!
Tested the module with your example code, tried a bunch of different settings.
Did a quick code review as well, looks great!

Nice work! Thanks as always for the well documented PR and the phenomenal code. 🚀

@beserge beserge merged commit d54d875 into electro-smith:master Jan 29, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants