From 5753aa400494e941f985a1e7fca18e582cacd69c Mon Sep 17 00:00:00 2001 From: madeline Date: Thu, 9 Apr 2026 14:44:55 -0700 Subject: [PATCH] IIR filter --- src/dusk/audio/DuskDsp.cpp | 40 ++++++++++++++++++++++++++++++++++++++ src/dusk/audio/DuskDsp.hpp | 10 ++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/dusk/audio/DuskDsp.cpp b/src/dusk/audio/DuskDsp.cpp index e7dff6a2a5..b5c3e2588c 100644 --- a/src/dusk/audio/DuskDsp.cpp +++ b/src/dusk/audio/DuskDsp.cpp @@ -116,6 +116,14 @@ static void ResetChannel(JASDsp::TChannel& channel, ChannelAuxData& aux) { aux.resamplePos = 0.0; aux.resamplePrev = 0; + aux.prev_lp_out = 0.0f; + aux.prev_lp_in = 0.0f; + + aux.biq_in1 = 0.0f; + aux.biq_in2 = 0.0f; + aux.biq_out1 = 0.0f; + aux.biq_out2 = 0.0f; + for (auto& volume : aux.prevVolume) { volume = NAN; } @@ -519,6 +527,38 @@ static void RenderChannel( channelAux.resamplePos = pos; channelAux.resamplePrev = prev; + // IIR FILTER + + // IIR part 1, low-pass: out[n] = (in[n] - in[n-1]) * (coeff/128) + out[n-1] + if (s16 coeff = channel.iir_filter_params[4]; coeff != 0) { + for (f32& sample : audioLoadBuffer) { + f32 out = std::clamp( + (sample - channelAux.prev_lp_in) * ((f32)coeff / 128.0f) + channelAux.prev_lp_out, -1.0f, 1.0f + ); + + channelAux.prev_lp_in = sample; // in[n-1] = in[n] + sample = channelAux.prev_lp_out = out; // out[n-1] = out[n] + } + } + + // IIR part 2, biquad: out[n] = (b1*in[n-1] + b2*in[n-2] + a1*out[n-1] + a2*out[n-2]) / 32768 + if ((channel.mFilterMode & 0x20) != 0) { + for (f32& sample : audioLoadBuffer) { + f32 out = std::clamp(( + channel.iir_filter_params[0] * channelAux.biq_in1 + // b1 + channel.iir_filter_params[1] * channelAux.biq_in2 + // b2 + channel.iir_filter_params[2] * channelAux.biq_out1 + // a1 + channel.iir_filter_params[3] * channelAux.biq_out2 // a2 + ) / 32768.0f, -1.0f, 1.0f); + + // shift history, then store new input and output + channelAux.biq_in2 = channelAux.biq_in1; // in[n-2] = in[n-1] + channelAux.biq_in1 = sample; // in[n-1] = in[n] + channelAux.biq_out2 = channelAux.biq_out1; // out[n-2] = out[n-1] + sample = channelAux.biq_out1 = out; // out[n-1] = out[n] + } + } + // move any remaining samples in the decode buf to the beginning int remainingDecodeBuf = channelAux.decodeBufCount - srcIdx; if (remainingDecodeBuf > 0) { diff --git a/src/dusk/audio/DuskDsp.hpp b/src/dusk/audio/DuskDsp.hpp index c7cb751458..3ca90d6311 100644 --- a/src/dusk/audio/DuskDsp.hpp +++ b/src/dusk/audio/DuskDsp.hpp @@ -52,6 +52,16 @@ namespace dusk::audio { f32 resamplePos; // last consumed sample from decodeBuf s16 resamplePrev; + + // low pass previous state + f32 prev_lp_out; // out[n-1] + f32 prev_lp_in; // in[n-1] + + // biquad state + f32 biq_in1; // in[n-1] + f32 biq_in2; // in[n-2] + f32 biq_out1; // out[n-1] + f32 biq_out2; // out[n-2] }; extern ChannelAuxData ChannelAux[DSP_CHANNELS];