[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