[SCM] calf/master: + Monosynth: use interpolated biquad to reduce filter zipper noise

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:39:19 UTC 2013


The following commit has been merged in the master branch:
commit abacf0970eb161a41e23ad48f45e75d168befcec
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Sat Feb 7 02:00:06 2009 +0000

    + Monosynth: use interpolated biquad to reduce filter zipper noise

diff --git a/src/calf/biquad.h b/src/calf/biquad.h
index 2e6b4f2..a0a4b8a 100644
--- a/src/calf/biquad.h
+++ b/src/calf/biquad.h
@@ -468,6 +468,113 @@ struct biquad_d2: public biquad_coeffs<Coeff>
     }
 };
 
+/**
+ * Two-pole two-zero filter, for floating point values.
+ * Uses "traditional" Direct I form (separate FIR and IIR halves).
+ * don't use this for integers because it won't work
+ */
+template<class Coeff = float, class T = float>
+struct biquad_d1_lerp: public biquad_coeffs<Coeff>
+{
+    using biquad_coeffs<Coeff>::a0;
+    using biquad_coeffs<Coeff>::a1;
+    using biquad_coeffs<Coeff>::a2;
+    using biquad_coeffs<Coeff>::b1;
+    using biquad_coeffs<Coeff>::b2;
+    Coeff a0cur, a1cur, a2cur, b1cur, b2cur;
+    Coeff a0delta, a1delta, a2delta, b1delta, b2delta;
+    /// input[n-1]
+    T x1; 
+    /// input[n-2]
+    T x2; 
+    /// output[n-1]
+    T y1; 
+    /// output[n-2]
+    T y2; 
+    /// Constructor (initializes state to all zeros)
+    biquad_d1_lerp()
+    {
+        reset();
+    }
+    #define _DO_COEFF(coeff) coeff##delta = (coeff - coeff##cur) * (frac)
+    void big_step(Coeff frac)
+    {
+        _DO_COEFF(a0);
+        _DO_COEFF(a1);
+        _DO_COEFF(a2);
+        _DO_COEFF(b1);
+        _DO_COEFF(b2);
+    }
+    #undef _DO_COEFF
+    /// direct I form with four state variables
+    inline T process(T in)
+    {
+        T out = in * a0cur + x1 * a1cur + x2 * a2cur - y1 * b1cur - y2 * b2cur;
+        x2 = x1;
+        y2 = y1;
+        x1 = in;
+        y1 = out;
+        a0cur += a0delta;
+        a1cur += a1delta;
+        a2cur += a2delta;
+        b1cur += b1delta;
+        b2cur += b2delta;
+        return out;
+    }
+    
+    /// direct I form with zero input
+    inline T process_zeroin()
+    {
+        T out = - y1 * b1 - y2 * b2;
+        y2 = y1;
+        y1 = out;
+        b1cur += b1delta;
+        b2cur += b2delta;
+        return out;
+    }
+    
+    /// simplified version for lowpass case with two zeros at -1
+    inline T process_lp(T in)
+    {
+        T out = a0*(in + x1 + x1 + x2) - y1 * b1 - y2 * b2;
+        x2 = x1;
+        y2 = y1;
+        x1 = in;
+        y1 = out;
+        return out;
+    }
+    /// Sanitize (set to 0 if potentially denormal) filter state
+    inline void sanitize() 
+    {
+        dsp::sanitize(x1);
+        dsp::sanitize(y1);
+        dsp::sanitize(x2);
+        dsp::sanitize(y2);
+        dsp::sanitize(a0cur);
+        dsp::sanitize(a1cur);
+        dsp::sanitize(a2cur);
+        dsp::sanitize(b1cur);
+        dsp::sanitize(b2cur);
+    }
+    /// Reset state variables
+    inline void reset()
+    {
+        dsp::zero(x1);
+        dsp::zero(y1);
+        dsp::zero(x2);
+        dsp::zero(y2);
+        dsp::zero(a0cur);
+        dsp::zero(a1cur);
+        dsp::zero(a2cur);
+        dsp::zero(b1cur);
+        dsp::zero(b2cur);
+    }
+    inline bool empty() {
+        return (y1 == 0.f && y2 == 0.f);
+    }
+    
+};
+    
 };
 
 #endif
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 376757c..608fecb 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -53,8 +53,8 @@ public:
     float buffer[step_size], buffer2[step_size];
     uint32_t output_pos;
     dsp::onepole<float> phaseshifter;
-    dsp::biquad_d1<float> filter;
-    dsp::biquad_d1<float> filter2;
+    dsp::biquad_d1_lerp<float> filter;
+    dsp::biquad_d1_lerp<float> filter2;
     int wave1, wave2, filter_type, last_filter_type;
     float freq, start_freq, target_freq, cutoff, decay_factor, fgain, fgain_delta, separation;
     float detune, xpose, xfade, pitchbend, ampctl, fltctl, queue_vel;
@@ -83,8 +83,9 @@ public:
     /// Update oscillator frequency based on base frequency, detune amount, pitch bend scaling factor and sample rate.
     inline void set_frequency()
     {
-        osc1.set_freq(freq * (2 - detune) * pitchbend * lfo_bend, srate);
-        osc2.set_freq(freq * (detune)  * pitchbend * lfo_bend * xpose, srate);
+        float detune_scaled = (detune - 1); // * log(freq / 440);
+        osc1.set_freq(freq * (1 - detune_scaled) * pitchbend * lfo_bend, srate);
+        osc2.set_freq(freq * (1 + detune_scaled)  * pitchbend * lfo_bend * xpose, srate);
     }
     /// Handle control change messages.
     void control_change(int controller, int value);
diff --git a/src/monosynth.cpp b/src/monosynth.cpp
index 5243e34..a1cdcda 100644
--- a/src/monosynth.cpp
+++ b/src/monosynth.cpp
@@ -208,7 +208,7 @@ bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int
             typedef complex<double> cfloat;
             double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
             
-            dsp::biquad_d1<float> &f = subindex ? filter2 : filter;
+            dsp::biquad_d1_lerp<float> &f = subindex ? filter2 : filter;
             float level = f.freq_gain(freq, srate);
             if (!is_stereo_filter())
                 level *= filter2.freq_gain(freq, srate);
@@ -246,6 +246,8 @@ void monosynth_audio_module::calculate_buffer_oscs(float lfo)
 
 void monosynth_audio_module::calculate_buffer_ser()
 {
+    filter.big_step(1.0 / step_size);
+    filter2.big_step(1.0 / step_size);
     for (uint32_t i = 0; i < step_size; i++) 
     {
         float wave = buffer[i] * fgain;
@@ -258,6 +260,7 @@ void monosynth_audio_module::calculate_buffer_ser()
 
 void monosynth_audio_module::calculate_buffer_single()
 {
+    filter.big_step(1.0 / step_size);
     for (uint32_t i = 0; i < step_size; i++) 
     {
         float wave = buffer[i] * fgain;
@@ -269,6 +272,8 @@ void monosynth_audio_module::calculate_buffer_single()
 
 void monosynth_audio_module::calculate_buffer_stereo()
 {
+    filter.big_step(1.0 / step_size);
+    filter2.big_step(1.0 / step_size);
     for (uint32_t i = 0; i < step_size; i++) 
     {
         float wave1 = buffer[i] * fgain;

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list