Airwindows Dattorro: Free Mac/Windows/Linux/Pi CLAP/AU/VST3/VST2/LV2/Rack

VST, AU, AAX, CLAP, etc. Plugin Virtual Effects Discussion
RELATED
PRODUCTS

Post



TL;DW: Dattorro is the resonant lowpass filter out of Donut.

Dattorro.zip (496k) standalone(AU, VST2)
Dattorro in Airwindows Consolidated (a separate project) under 'Filter' (CLAP, AU, VST3, LV2)

Here's the filter out of Donut! This started as an experiment to see if I could code an SVF. That's a State Variable filter, and now that the other plugin makers have stopped laughing I'll tell you what it is :D

Turns out a State Variable filter is about the simplest way you can do biquad-filter-like things (read: controllable and flexible) and plugin devs really like this one. That includes heavyweight genius devs like Andy from Cytomic who made The Glue and The Drop (Andy is a 'model every component' guy doing stuff I choose not to do, a rigorous circuit modeler). Dattorro is not that: Dattorro is me taking the concept of the state variable filter and doing Airwindowsy things with it.

For instance, the frequency control's designed to go right up to the high frequency limit of the filter no matter what sample rate it's running under. It does this not by restricting the max frequency, but by altering the logarithm taper of the control so midrange frequencies will always be roughly in the middle of the control's travel. That means you never see exactly what frequency you're using, but neither do you see it on a 303 or x0xb0x and those are great, and this is very much a synth style filter.

There's code for every kind of SVF inside Dattorro's source code, commented out, but the lowpass you get (and the resonant behavior, it has a great reso flavor) is not stock SVF, but airwindowsized. That's because I'm using a sin() function in there (for code simplicity. PurestSaturation would work just as well for this, or TapeHack) but not in the way you'd think. The obvious thing to do is put it on as a post clipper for simply adding distortion.

But you know I'm always interested in anti-saturation, and so the softclip is going on the bandpass output… which is then SUBTRACTED from the lowpass (well, 0.5 of bandpass into sin() and then subtracted, I was working out what sounded best) and that's the filter. It's nearly as simple as the stock SVF but it sounds way, way slicker and that's what's in Donut and now here it is as a standalone filter for you.

The sound is like the filtered-out part gets deeper and more vivid and interesting. Applying inverted saturation is like expansion: it's part of Dubly, and is like inverse Density, and is the buss section of every Console plugin in one way or another. It makes stuff sound farther away. Applying it to a synth filter in this way gives sonic depth and also a curious side-effect: the rolloff actually got shallower, even when it's resonant.

This might be a clue towards something that could make a better Baxandall-style filter. I'll keep experimenting. Enjoy Dattorro :D

Airwindows Consolidated Download
Most recent VCV Rack module
download 64 Bit Windows VSTs.zip
download Signed M1/Intel Mac AUs.dmg
download Signed M1/Intel Mac VSTs.dmg
download LinuxVSTs.zip
download LinuxARMVSTs.zip for the Pi
download Retro 32 Bit Windows VSTs.zip
download Retro PPC/32/64 Mac AUs.zip
download Retro PPC/32/64 Mac VSTs.zip
Mediafire Backup of all downloads
All this is free and open source under the MIT license, brought to you by my Patreon.

Post

Hi Chris.
I hate to correct you but I can't stop myself.
SVFs are biquads. Asking the difference between SVF and biquad is similar to asking the difference between bird and animal.
"Biquadratic" means "ratio of quadratic polynomials". It applies to any 2-pole (or second-order) filter — even an analog one.

Andy Cytomic is pro TPT (Topology Preserving Transform) which inherently comes with ZDF (Zero-Delay-Feedback) as opposed to what could be called "old-fashioned" or "traditional" BLT (Bilinear Transform) — RBJ for instance.
Andy calls it "Trapezoidal integration", referring to the fact that he replaces integrators in analog block diagrams with trapezoidal integrators — while traditional BLT replaces differentiators in transfer functions with trapezoidal differentiators.

Both topologies are trapezoidal, they're both BLT and they're both z-transforms. Both can use any of the 4 direct forms.

A sticky OCD of mine: https://github.com/antoineportes/DSP/bl ... menclature

or: https://github.com/antoineportes/DSP/bl ... 0low-pass) (lines 852 to 945)

I sincerely hope I didn't offend you, you're amongst my heroes and the main reasons why I'm into DSP (at your place, I'd like getting corrected, that's all).

((Also hope my first draft in the Youtube comment section never shows up! — Redundancy: another OCD...))
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

Oh no, it's quite all right! I appreciate it. I'm doing my best and at least I called it 'Dattorro' rather than 'this time NOT AT ALL a biquad filter' :D

I'll have to call a filter Suzan, for you :)

Post

I'd be both honoured and laughing out loud!
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

Is there a sort you don't already see? I already have an anti-saturated mixture of forms in Dattorro, so perhaps just the regulation SVF outputs? One thing that troubles me is they don't seem to create outputs that sum losslessly together to create the exact original input, but I have ways of getting that anyway :D

Post

Well there's a sort I've failed to design for weeks!
https://www.desmos.com/calculator/zazhaduvpb
Moog-like 4-pole SVF transistor ladder...

I might be wrong but I seem to understand that you're new to ZDF equations — if I'm right, welcome Chris! You're not ready for the lot of fun it is — if I'm wrong, sorry for the noise.
If I'm right, the SVF Moog is an ill-advised project (it probably has no solution because of the fact that the BP version has a positive general feedback while HP and LP have a negative one).
If I'm right AND you're as stubborn as I am... sorry for the spell.

I've made this out of frustration:
https://github.com/antoineportes/DSP/bl ... Sallen-Key
It's basically the 2-pole version of the yet-to-be-proven-impossible 4-pole SVF transistor ladder.
Could be the model for a solution: 2 in series with duplicated mixing gains and common general positive feedback.
I haven't tried yet: I then moved to the Diode Ladder with resonance-dependant cutoff and now I'm writing a book full-time: https://github.com/antoineportes/Workin ... ter-design (not much of an innocent drop, I've been not daring to request a bit of your time for a peer review for some time now).


About lossless sum of outputs (assuming a fully linear SVF):
If I recall correctly, lowPass + highPass + normalised_bandPass = input
normalised_bandPass = bandPass / Q (RBJ's constant gain BP)
( with Q = 1 / (Suzan + Suzan) )
Or maybe LP + HP + BP (not normalised)... One of the two for sure.

!!! HP = input - LP is only true for 1-pole filters. With biquads, it gives a HP but its curve is not the same as the one produced by the HP output of an SVF. (Sorry if it's obvious but I personally had it wrong for years.)

Also with 1-pole multimodes, lowPass - highPass = allPass[1] and highPass - lowPass = allPass[2] (each allPass being the polarity inversion of the other)
This should apply to higher-orders as well but I'm not 100% sure here — easy to verify though.


With non-linearities, I don't see an easy way to retrieve the input with a simple sum. But identical saturators on every output (LP, BP and HP), then a corresponding anti-saturator on the mixture would be the Airwindows Console concept applied to an SVF. There might be something to dig here.
Then input - mixture produces a delta signal that might find an unusual use (I don't know, something like a harmonic-distortion-follower-spectral-sidechain — could be a very geeky compressor that no man has heard before — with "cutoff" and "reso" where you'd expect "threshold" and "ratio"...).
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

I could believe the normalized bandpass, because I didn't try that: I did have 'low+band+high' as one of the things I was trying, but it gave me a peaky result. Clearly it's worth experimenting some more. I'm already looking into doing a super-Baxandall by interleaving two Dattorro type (with the subtracting half of band) and that might not even need the (anti)saturation I put in Dattorro…

Be cautious of thinking in terms of getting me for peer review: your math-fu is way superior to mine, and me having an ear and wanting things to sound a certain way has no commercial value outside of me being able to make plugins that sound that way. Should you make a great sounding Moog ladder filter, me agreeing about that has no commercial value. I just think it's cool you're trying, that's the important part.

I feel like a significant part of the classic Moog ladder is that Moog circuits which aren't the Polymoog, don't run super-high headroom. In other words the Polymoog (or was it Memorymoog?) was the departure, with a different designer, and less beefy-sounding, and therefore you could come up with somewhere to use a saturation curve in the equations that would sound Moogish.

I feel like Dattorro, with its saturation on specifically the subtracting of the band section, is giving opposite-Moog, perhaps along the line of 303ish filter resonance: that way that even a x0xb0x can make the resonance squawk and go super loud. Maybe what I'd do for a more Moogish take is, stack them up a little (two in series?) and instead ADD the mid and saturate it? Because saturating isn't only 'hit distortion', it will also bring up some higher harmonics and when you are doing SOFT saturation the way I am with sin() it really just brings up one harmonic at a time. That might be what gets you there. And again I'm assuming for a Moog style sound you want more saturation and solidness, and less antisaturation and super peakiness. Or do something weird like two stages, but you simply add the first stage's saturated mid twice and the second stage is just the series low band, ignoring the second stage's mid. Or that one's subtracted instead… bound to be something that sounds cool. Test it on completed track audio that has reverb and such so you can hear if anything interesting happens there, that's how I got Dattorro, was hearing something interesting happen in the reverb, far-field area.

I love the idea of playing with this a bit more. Mind you if I do one that acts like the perfect Moog ladder, I can't call it 'Moog' because I've totally stopped chasing names of other IP. Maybe that becomes 'Suzan' :D

Post

The book is not about the Moog, it's about self-teaching from someone who went homeless after high-school (well French Lycée to be precise) while others went to engineering schools. What I ironically call "peer review" is actually closer to "philosophical validation".
You having no commercial value is what made me call you my peer.
(I say "book" because it's shorter than "anarcho-nihilistic polymath pedagogy in an experimental open format" — it's deliberately meant to remain a GitHub repository [free, public and easily downloadable / editable]. The global education system is made by and for top-down thinkers: I'm trying to provide an alternative.)

A moogish take on Dattorro wouldn't sound like Moog.
Good! Everybody does Moog.
You're right: the transistors' limited headroom (and the fact that they're in the negative feedback path) produces a very saturated characteristic sound (especially with high resonance).
This gets emulated 5 times a year... 'this time NOT AT ALL another clickbait'.

Dattorro is rather clean and bright with the soft clipper used as a spectral enhancer more than a smasher.
Two in series would have a thinner peak and a steeper roll-off, it would be 4-pole. So yeah, reminding of the Moog but still Airwindows.
You could store the first BP output and add or subtract both (first and second I mean) together at the end, soft-clip the sum once or soft-clip both individually... (No idea what it would sound like!)
Your unconventional way of mixing outputs allows dozens of possible experiments once you start stacking!

Then if people want an old-school transistor VCF crush, there's Airwindows Edge (for instance).

A pseudo-ladder based upon an SVF has at least one great advantage over actual ladder designs: no amount of resonance will make the filter explode, it's inherently stable (as long as the damping factor is > 0, that is as long as 0 < Q < 1/(2*0)) — even with 1000 dB of resonance (don't know where you'd need that but I like the idea!).
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

Awww. But it's fun when filters explode :lol:

Keep making the book. I like it. You're my kind of KVRian :D

Post

Philosophical validation? Check.
Motivation? Back.
Thanks.

(Next time I mention the book, it will have its dedicated thread. I feel bad about hijacking yours.)
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

EEL2 (JSFX):

Code: Select all

desc:diodeTest (0im's filtering)
/*
  LICENSE:
  
    MIT License
    
    Copyright (c) 2026 Antoine Portes
    
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
  
  
  MANUAL:
  
    This plugin solely aims at testing the designed filter (see source).
    It has no non-linearities, no parameter smoothing, no user interface, no oversampling (Reaper provides native FIR OS though).
    
    Plugin developers often rely on free papers randomly happening to pop-up on the internet.
    This design can be regarded as just another free paper... But I rather meant it as an example / tutorial
    on how to free oneself from depending on randomness.
  
*/

source:   https://github.com/antoineportes/DSP/blob/main/filters/Ladder%20(ZDF)/Diode%20Ladder%20(4-pole%2C%20low-pass)
author:   Antoine Portes
license:  MIT



/*########################################################
==================     PARAMETERS     ====================
########################################################*/
slider1:TEST.Hz=666<20,17000,.1:log=666>Cutoff (Hz): 
slider2:res=0<0,1,.001>Resonance: 
slider3:TEST.justForFun=0<0,1,1{nope,yep}>Monitor feedback? 



/*########################################################
==================      IN/OUT        ====================
########################################################*/
in_pin:input L
in_pin:input R
out_pin:output L
out_pin:output R



/*########################################################
==================        INIT        ====================
########################################################*/
@init
  ext_noInit = 1;

  //  Constants
  ////  Pseudo-booleans
  TRUE  = (1 === 1);
  FALSE = (1 !== 1);
  ////  Cutoff computation
  //PI_SRATE = 3.14159265358979323846 / sRate;
  SRATE_PI = sRate / 3.14159265358979323846;      //  Better approximation (?)
  ////  Cutoff normalisation
  r4 = 2.65565947517041966654;
  ////  Anti-denormal threshold
  epsilon = 2;
  loop (50, epsilon *= 2);
  epsilon = 1 / epsilon;        //  2^-51  
  /*
    If fast computation is prefered over precision:
    
    <code>
      epsilon = 2;
      loop (5, epsilon *= epsilon);
      epsilon = 1 / epsilon;
    </code>
    
    gives:    1 / 2^(2^5)  =  2^-32  ~=  2.328306e-10
  */
  ////  Dummy variable for further implementations including oversampling
  os.factor = 1;
  ////  Max user-facing cutoff
  /*
    Binding the cutoff so that Hz * offset <= Nyquist
    Max offset is r4:   https://www.desmos.com/calculator/j45xxvjnrd
    So:
      aTan2 (HzMax * r4, SRATE_PI * os.factor)  =  aTan2 ( (sRate * os.factor) / 2, SRATE_PI * os.factor )
      (HzMax * r4) / ((sRate / $pi) * os.factor)  =  ( (sRate * os.factor) / 2 ) / ((sRate / $pi) * os.factor)
      HzMax * r4  =  (sRate * os.factor) / 2
  */
  HzMax = (sRate * os.factor) / (2 * r4);
  /*
    Min offset is 1 / sqRt (2).
    So:
      aTan2 (HzMin * pow (2, -.5), SRATE_PI * os.factor)  =  epsilon
      HzMin  =  tan (epsilon) * SRATE_PI * os.factor * sqRt (2)
      
      tan (epsilon) gives a very bad approximation... Better use a constant.
      10 Hz seems safe and not really limiting.
  */
  
  //  Slider conditioning
  ////  Branch
  function getLast ()
  (
    this.last != this  ?  TRUE  :  FALSE;
  );
  function setLast ()
  (
    this.last = this;
  );
  ////  Bind
  function range (x*, xMin, xMax)
  (
    x  =  max (xMin, min (x, xMax));
  );
  
  //  Diode Ladder generic functions
  //      (diodeLin_[...] where "Lin" stands for "linear". Update functions if non-linearities get involved.)
  ////  Update cutoff offset 
  function diodeLin_updtOffset ()
    global (r4)
    instance (res offset)
    local (tmp1 tmp2)
  (
    tmp1    = res * -0.5;
    tmp2    = 1 - res;    loop (2, tmp2 *= tmp2);   //  (1 - res)^4
    
    offset  = pow (2, tmp1) * pow (r4, tmp2);
  );
  ////  Update main gains and denominators
  function diodeLin_updtCutoff ()
    global (HzMax SRATE_PI os.factor)
    instance (Hz offset g1 g2 g3 g4 g5)
    local (fc)
  (
    range (Hz, 10, HzMax);
    fc  = offset * Hz;
    //////  Forward gains
    g1  = aTan2 (fc, SRATE_PI * os.factor);   //  SRATE_PI * os.factor is a pseudo-constant, it should be pre-computed when sRate or os.factor changes.
    g2  = g1 + g1;
    //////  Backward gain
    g3  = 1 + g2;
    //////  Forward denominator
    g4  = 1 / g3;
    //////  Backward denominator
    g5  = 1 / g1;
  );
  ////  Update feedback gains and denominator
  function diodeLin_updtRes ()
    instance (k res norm g1 g2 g3 g4 g5 FB_gX FB_gZ4 FB_gZ3 FB_gZ2 FB_gZ1 FB_den)
    local (g1p2 g1p3 g4p2 g4p3 g4p4 g3p2 g3p3 g5p2 g5p4 g_1142 g_1242 g_1243 g_1344 g_1444 g_5231 g_5232 g_5332 g_5433 g_5434)
  (
    //  Negative feedback gain
    k       = res * 17;
    //  Pass-band normalisation
    norm    = k + 1;
    //  y4 ZDF equation
    ////  Temporary variables (avoid multiple computation)
    g1p2  = g1 * g1;    g1p3  = g1p2 * g1;
    g4p2  = g4 * g4;    g4p3  = g4p2 * g4;    g4p4  = g4p3 * g4;
    g3p2  = g3 * g3;    g3p3  = g3p2 * g3;
    g5p2  = g5 * g5;    g5p4  = g5p2 * g5p2;
    g_1142  = g1 * g4p2;
    g_1242  = g1 * g_1142;
    g_1243  = g_1242 * g4;
    g_1344  = g1p3 * g4p4;
    g_1444  = g1 * g_1344;
    g_5231  = g5p2 * g3;
    g_5232  = g_5231 * g3;
    g_5332  = g5 * g_5232;
    g_5433  = g5p4 * g3p3;
    g_5434  = g_5433 * g3;
    ////  Actual equation
    FB_gX   = 2  -  6 * g_1242  +  4 * g_1444;
    FB_gZ4  = g_5433  -  6 * g_5231  +  11 * g4  -  6 * g_1243;
    FB_gZ3  = g_5332  -  5 * g5  +  8 * g_1142  -  4 * g_1344;
    FB_gZ2  = g_5231  -  3 * g4  +  2 * g_1243;
    FB_gZ1  = g5  -  3 * g_1142  +  2 * g_1344;
    FB_den  = g_5434  -  7 * g_5232  +  16  -  14 * g_1242  +  4 * g_1444  +  k * FB_gX;
    FB_den  = 1 / FB_den;
  );
  ////  Transposed Direct Form II (tdf2)
  //////  1-pole LP
  ////////  Backward
  function tdf2_1pole_LP_BW (y, z, _g, _den)
    local (x)
  (
    x = (_g * y  -  z) * _den;
    //  return
    x;
  );
  ////////  Forward
  function tdf2_1pole_LP (x, z*, g, den)
    global (epsilon)
    local (y)
  (
    y = (g * x  +  z) * den;
    z = y + y - z;
    abs (z) < epsilon  ?  z = 0;
    //  return
    y;
  );
  //////  4-pole Diode Ladder LP 
  function tdf2_diodeLin (x, z1*, z2*, z3*, z4*)
    global (monFB monFF)        //    "monitor FeedBack" and "monitor FeedForward".
    instance (norm FB_gX FB_gZ4 FB_gZ3 FB_gZ2 FB_gZ1 FB_den k g1 g2 g3 g4 g5)
    local (y4 y3 y2 fb y1)
  (
    //  Normalise pass-band
    x    *= norm;
    
    //  Get feedback signals
    ////  y4
    y4    = FB_gX * x  +  FB_gZ4 * z4  +  FB_gZ3 * z3  +  FB_gZ2 * z2  +  FB_gZ1 * z1;
    y4   *= FB_den;
    ////  y3
    y3    = tdf2_1pole_LP_BW (y4, z4, g3, g5);
    ////  y2
    y2    = tdf2_1pole_LP_BW (y3, z3, g3, g5)  -  y4; 
    //  Main negative feedback
    fb    = k * y4;
    x    -= fb; 
    //  LP 1
    ////  Positive feedback
    x    += y2;
    ////  Filter
    y1    = tdf2_1pole_LP (x, z1, g2, g4); 
    //  LP 2
    ////  Positive feedback
    y1   += y3;
    ////  Filter
    y2    = tdf2_1pole_LP (y1, z2, g1, g4); 
    //  LP 3
    ////  Positive feedback
    y2   += y4;
    ////  Filter
    y3    = tdf2_1pole_LP (y2, z3, g1, g4); 
    //  LP 4
    ////  Filter
    y4    = tdf2_1pole_LP (y3, z4, g1, g4); 
    //  return
    fb * monFB  +  y4 * monFF;
  );
  
  //  Diode Ladder instance ("TEST") function
  ////  Transposed Direct Form II
  function TEST_apply ()
  (
    this = TEST.tdf2_diodeLin (this, this.TEST.z1, this.TEST.z2, this.TEST.z3, this.TEST.z4);
  );
  ////  Reset
  function TEST_reset ()
  (
    this.TEST.z1 = this.TEST.z2 = this.TEST.z3 = this.TEST.z4 = 0;
  );
  
  //  Initialise miscellaneous (non-zero) variables
  sRate.last            = sRate;    //  Avoids re-computing everything on first block.
  res.last              = -1;       //  Lets @slider initialise the filter (any non-zero value would do).
  TEST.justForFun.last  = -1;
  L.TEST_reset ();
  R.TEST_reset ();



/*########################################################
==================       SLIDER       ====================
########################################################*/
@slider
  res.getLast () ?
  (
    /*
    //  Commented out to allow explosion (manually input any res value > 1)
    range (res, 0, 1);
    TEST.res  = res * res;    //  Curve refinement.
    */
    //  Start: added to allow explosion
    TEST.res  = res;
    //  Stop: added to allow explosion
    
    UPDATE_OFFSET   = TRUE;
    res.setLast ();
  );
  
  TEST.Hz.getLast () ?
  ( 
    UPDATE_CUTOFF   = TRUE;
    res.setLast ();
  );
  
  UPDATE_OFFSET ?
  (
    TEST.diodeLin_updtOffset ();
    
    UPDATE_OFFSET = FALSE;
    UPDATE_CUTOFF = TRUE;
  );
  
  UPDATE_CUTOFF ?
  (
    TEST.diodeLin_updtCutoff ();
    
    UPDATE_CUTOFF   = FALSE;
    UPDATE_FEEDBACK = TRUE;
  );  
  
  UPDATE_FEEDBACK ?
  (
    TEST.diodeLin_updtRes ();
    
    UPDATE_FEEDBACK = FALSE;
  );
  
  TEST.justForFun.getLast () ?
  (
    range (TEST.justForFun, 0, 1);
    TEST.justForFun = 0|TEST.justForFun;
    
    monFF = !TEST.justForFun;
    monFB = !monFF;
    
    TEST.justForFun.setLast ();
  );



/*########################################################
==================        BLOCK       ====================
########################################################*/
@block
  sRate.getLast () ?
  (
    SRATE_PI  = sRate / 3.14159265358979323846;
    HzMax     = (sRate * os.factor) / (2 * r4);
    L.TEST_reset ();
    R.TEST_reset ();
    
    sRate.setLast ();
  );



/*########################################################
==================       SAMPLE       ====================
########################################################*/
@sample
  L = spl0;
  R = spl1;
  
  L.TEST_apply ();
  R.TEST_apply ();
  
  spl0  = L;
  spl1  = R;
This filter — now that I've just customised it for this very purpose — can explode.
(A safety belt is a camisole in denial.)

CMD+C, CMD+V, CMD+S
--> Have fun!
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

antoineportes wrote: Mon Apr 06, 2026 12:17 pm Philosophical validation? Check.
Motivation? Back.
Thanks.

(Next time I mention the book, it will have its dedicated thread. I feel bad about hijacking yours.)
You needn't feel bad. Without that, I wouldn't have Suzan :)

Yeah, I tried the experiment. Near as I can tell it will be great fun. Instead of one stage of subtract a sin(band*0.5) it's two stages with adding sin(band) and there you are. Seemed to me it had the mojo, and I shall name it Suzan and when it drops I'll tell people you're writing a book which might go over my head a bit, but no harm in that :)

Post

Chris, you've made my day. Plus Suzan's alive!
When the book drop happens, be sure that I'll dislike and subscribe (might have to unsubscribe first...).

It's funny how when I watch your videos I think "he's way ahead of me" (for instance all my plugins have a bit-wait_for_it-shift gain — I didn't come up with this nor working at 96k with ultrasonic filtering); and now you say my book goes over your head.
Don't know how to interpret that... Perhaps it says something about integrity / humility?

Oh you think my humility is impressive? Just wait until you hear my meta-jokes.
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)

Post

antoineportes wrote: Mon Mar 30, 2026 7:03 am Andy Cytomic is pro TPT (Topology Preserving Transform) which inherently comes with ZDF (Zero-Delay-Feedback) as opposed to what could be called "old-fashioned" or "traditional" BLT (Bilinear Transform) — RBJ for instance.
Andy calls it "Trapezoidal integration", referring to the fact that he replaces integrators in analog block diagrams with trapezoidal integrators — while traditional BLT replaces differentiators in transfer functions with trapezoidal differentiators.
I solve MNA (Modified Nodal Analysis) systems of non-linear implicit equations, and tailor the numerical integration on a per component basis. I don't use TPT, or ZDF, which are confusing labels for various well established equation formulation and non-linear integration methods.

I have published technical papers outlining how to use trapezoidal integration to solve various linear filter circuits, and have also outline how these methods can be applied to non-linear systems of equations.
The Glue, The Drop, The Scream - www.cytomic.com

Post

I like when filters go bow-wow, zap and zip!
Look guys, I’m almost as smart as you!
Serious part: thanks guys for experimenting with things, it really is fun to f**k around with the things you make.

Post Reply

Return to “Effects”