Browse Source

VCF: Add citations for TPT and ADAA.

v2
Andrew Belt 1 month ago
parent
commit
5fe39fa5be
1 changed files with 22 additions and 9 deletions
  1. +22
    -9
      src/VCF.cpp

+ 22
- 9
src/VCF.cpp View File

@@ -9,15 +9,15 @@ inline T rcp_newton1(T x) {
}


/** Approximates tan(pi*x) for x in [0, 0.5).
Optimized coefficients for max relative error: 1.18e-05.
/** Approximates tan(x) for x in [0, pi*0.5).
Optimized coefficients for max relative error: 2.78e-05.
*/
template <typename T>
inline T tan_pi_1_2(T x) {
inline T tan_1_2(T x) {
T x2 = x * x;
T num = T(1) + T(-0.9622845476351338) * x2;
T den = T(1) + x2 * (T(-4.252711329946427) + T(1.0108965067534537) * x2);
return T(M_PI) * x * num / den;
T num = T(1) + x2 * T(-0.09776575533683811);
T den = T(1) + x2 * (T(-0.43119539396382) + x2 * T(0.0105011966117302));
return x * num / den;
}


@@ -62,7 +62,7 @@ inline T ln_cosh_3_4(T x) {
}


/** 1st-order antiderivative anti-aliasing (ADAA) for tanh. */
/** 1st-order ADAA for tanh. */
template <typename T>
struct TanhADAA1 {
T xPrev = T(0);
@@ -92,7 +92,19 @@ struct TanhADAA1 {
};


/** 4-pole transistor ladder filter using TPT/ZDF (Zero-Delay Feedback).
/** 4-pole transistor ladder filter using TPT (Topology-Preserving Transform).
Feedback uses previous sample (i.e. 1 sample delayed) to avoid iterative solving.

For the equivalent state / trapezoidal integrator approach:
Zavalishin, V. "The Art of VA Filter Design". 2018
https://www.native-instruments.com/fileadmin/ni_media/downloads/pdf/VAFilterDesign_2.1.2.pdf

For Cytomic's formulation:
https://cytomic.com/files/dsp/SvfLinearTrapOptimised2.pdf

For antiderivative anti-aliasing (ADAA):
Parker, J., Zavalishin, V., Le Bihan, E. "Reducing the Aliasing of Nonlinear Waveshaping Using Continuous-Time Convolution". DAFx 2016
https://dafx.de/paper-archive/2016/dafxpapers/20-DAFx-16_paper_41-PN.pdf
*/
template <typename T>
struct LadderFilter {
@@ -126,13 +138,14 @@ struct LadderFilter {

void process(Frame& frame) {
// Pre-warped frequency
T g = tan_pi_1_2(frame.cutoff);
T g = tan_1_2(T(M_PI) * frame.cutoff);
// Integrator gain
T G = g / (T(1) + g);

// Feedback path
// Apply resonance scaling and soft-clip with tanh
T feedback = adaa[4].process(frame.resonance * state[3]);
// T feedback = tanh_2_3(frame.resonance * state[3]);
T u = frame.input - feedback;

// Stage 0


Loading…
Cancel
Save