#N canvas 324 40 941 686 12;
#X declare -stdpath ./;
#X obj 267 318 bob~, f 24;
#X msg 714 337 print;
#X obj 126 349 output~;
#X msg 706 307 clear;
#X obj 267 349 output~;
#X msg 692 277 saturation \$1;
#X msg 666 192 oversample \$1;
#N canvas 635 124 513 424 test 0;
#X obj 313 137 min~;
#X obj 367 123 -~ 1;
#X obj 367 148 *~ -50;
#X floatatom 105 105 5 0 128 0 - - - 0;
#X obj 233 52 mtof;
#X text 301 49 test signal;
#X obj 313 90 phasor~ 220;
#X obj 233 107 osc~ 220;
#X obj 65 34 loadbang;
#X msg 105 70 57;
#X msg 65 102 1;
#X obj 362 244 noise~;
#X obj 233 277 *~ 0;
#X obj 313 244 *~ 0;
#X obj 362 287 *~ 0;
#X obj 295 338 +~;
#X obj 295 373 outlet~;
#X obj 59 316 declare -stdpath ./;
#X obj 105 127 vradio 19 1 0 3 empty empty empty 0 -8 0 10 #dfdfdf #000000 #000000 0;
#X obj 258 225 == 0;
#X obj 105 207 == 2;
#X obj 338 221 == 1;
#X obj 313 162 -~ 0.5;
#X text 127 126 Sine, f 8;
#X text 127 146 Sawtooth;
#X text 127 165 Noise, f 8;
#X text 144 104 Pitch;
#X obj 313 190 *~ 2;
#X connect 0 0 22 0;
#X connect 1 0 2 0;
#X connect 2 0 0 1;
#X connect 3 0 4 0;
#X connect 4 0 6 0;
#X connect 4 0 7 0;
#X connect 6 0 0 0;
#X connect 6 0 1 0;
#X connect 7 0 12 0;
#X connect 8 0 9 0;
#X connect 8 0 10 0;
#X connect 9 0 3 0;
#X connect 10 0 18 0;
#X connect 11 0 14 0;
#X connect 12 0 15 0;
#X connect 13 0 15 1;
#X connect 14 0 15 1;
#X connect 15 0 16 0;
#X connect 18 0 21 0;
#X connect 18 0 20 0;
#X connect 18 0 19 0;
#X connect 19 0 12 1;
#X connect 20 0 14 1;
#X connect 21 0 13 1;
#X connect 22 0 27 0;
#X connect 27 0 13 0;
#X coords 0 -1 1 1 93 90 2 100 100;
#X restore 126 162 pd test;
#X obj 33 15 bob~;
#X text 31 630 see also:;
#X obj 105 631 lop~;
#X obj 146 631 hip~;
#X obj 188 631 bp~;
#X obj 224 631 vcf~;
#X text 729 651 updated for Pd version 0.52;
#X obj 32 658 biquad~;
#X obj 91 658 slop~, f 7;
#X obj 150 658 cpole~, f 7;
#X obj 210 658 fexpr~;
#X text 266 657 - unfriendly filters;
#X obj 12 46 cnv 1 925 1 empty empty empty 8 12 0 13 #000000 #000000 0;
#X text 859 14 <= click;
#N canvas 767 190 571 371 reference 0;
#X obj 17 17 bob~;
#X text 57 18 - Runge-Kutte numerical simulation of the Moog analog resonant filter, f 69;
#X obj 9 52 cnv 5 550 5 empty empty INLETS: 8 18 0 13 #202020 #000000 0;
#X obj 8 85 cnv 1 550 1 empty empty 1st: 8 12 0 13 #000000 #000000 0;
#X obj 9 270 cnv 2 550 2 empty empty OUTLET: 8 12 0 13 #202020 #000000 0;
#X obj 9 307 cnv 2 550 2 empty empty ARGUMENTS: 8 12 0 13 #202020 #000000 0;
#X obj 8 339 cnv 5 550 5 empty empty empty 8 18 0 13 #202020 #000000 0;
#X obj 8 190 cnv 1 550 1 empty empty 2nd: 8 12 0 13 #000000 #000000 0;
#X obj 8 230 cnv 1 550 1 empty empty 3rd: 8 12 0 13 #000000 #000000 0;
#X text 89 199 float/signal - resonant or cutoff frequency in hertz., f 64;
#X text 131 280 signal - filtered signal.;
#X text 89 91 float/signal - input to be filtered., f 65;
#X text 138 145 clear - clear internal state., f 58;
#X text 138 164 print - post internal state and parameters on Pd's window.;
#X text 199 316 NONE;
#X text 89 239 float/signal - resonannce (> 4 to oscillate)., f 64;
#X text 47 127 oversample <float> - set oversampling (default 2)., f 71;
#X text 47 109 saturation <float> - set saturation point of "transistors" (default 3)., f 71;
#X restore 765 14 pd reference;
#X text 653 424 Compatibility note: there was a bug in this module \, fixed for Pd version 0.52. YOu can get the (incorrect) pre-0.52 behavior by setting pd's compatibility level to 0.51., f 32;
#X text 812 535 old behaviour;
#X text 812 576 new behaviour;
#X msg 666 528 \; pd compatibility 51;
#X msg 666 570 \; pd compatibility 52;
#X text 46 537 The saturation parameter determines at what signal level the "transistors" in the model saturate. The maximum output amplitude is about 2/3 of that value. "Clear" momentarily shorts out the capacitors in case the filter has gone unstable and stopped working., f 78;
#X obj 12 618 cnv 1 925 1 empty empty empty 8 12 0 13 #000000 #000000 0;
#X obj 349 246 line~;
#X text 325 188 Hz;
#X obj 349 215 pack f 50;
#X floatatom 349 188 8 0 0 0 - - - 0;
#X obj 352 160 hsl 162 19 60 5000 0 1 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 2672 1;
#X obj 666 374 s \$0-set;
#X obj 267 258 r \$0-set;
#X obj 435 211 hsl 162 19 0.1 100 1 1 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 16100 1;
#X floatatom 432 238 5 0 8 0 - - - 0;
#X obj 432 267 sig~;
#X text 474 238 (> 4 to oscillate);
#X text 266 631 - friendly filters;
#X obj 695 223 hsl 162 19 0 10 0 0 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 0 1;
#X floatatom 692 250 5 0 8 0 - - - 0;
#X obj 669 138 hsl 162 19 1 10 0 0 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 0 1;
#X floatatom 666 165 5 0 8 0 - - - 0;
#X text 73 16 - Moog analog lowpass resonant filter simulation;
#X text 22 205 test input ->;
#X text 46 430 By default [bob~] does one step of 4th-order Runge-Kutte integration per audio sample. This works OK for resonant/cutoff frequencies up to about 1/2 Nyquist. To improve accuracy and/or to extend the range of the filter to higher cutoff frequencies you can oversample by any factor - but note that computation time rises accordingly. At high cutoff frequencies/resonance values the Runge-Kutte approximation can go unstable. You can also raise the oversampling factor to combat this., f 78;
#X text 764 336 print state;
#X text 338 136 resonant/cutoff frequency;
#X text 43 356 input monitor ->, f 10;
#X text 388 369 <- output monitor;
#X text 69 63 This moog filter simulation is based on papers by Tim Stilson \, Timothy E. Stinchcombe \, and Antti Huovilainen (see [pd details] for pointers). The audio inputs are the signal to filter \, the cutoff/resonant frequency in herts \, and "resonance" (the sharpness of the filter). Nominally \, a resonance of 4 should be the limit of stability -- above that \, the filter oscillates., f 108;
#N canvas 642 49 638 537 details 0;
#X text 86 211 (sections 1 and 2 are a reasonably good introduction but the model they use is highly idealized.), f 69;
#X text 79 256 Timothy E. Stinchcombe \; Analysis of the Moog Transistor Ladder and Derivative Filters (long \, but a very thorough description of how the filter works including its nonlinearities), f 70;
#X text 81 133 Useful references:, f 63;
#X text 79 163 Tim Stilson \; Analyzing the Moog VCF with Considerations for Digital Implementation https://ccrma.stanford.edu/~stilti/papers/moogvcf.ps.gz, f 70;
#X text 79 72 The [bob~] object Imitates a Moog resonant filter by Runge-Kutte numerical integration of a differential equation approximately describing the dynamics of the circuit., f 70;
#X text 79 323 Antti Huovilainen \; Non-linear digital implementation of the moog ladder filter (comes close to giving a differential equation for a reasonably realistic model of the filter)., f 70;
#X text 79 395 The differential equations are \; y1' = k * (S(x - r * y4) - S(y1)) \; y2' = k * (S(y1) - S(y2)) \; y3' = k * (S(y2) - S(y3)) \; y4' = k * (S(y3) - S(y4)) \; where k controls the cutoff frequency \, r is feedback (<= 4 for stability) \, and S(x) is a saturation function., f 70;
#X text 64 26 Copied from README.txt;
#X restore 515 309 pd details;
#X text 477 189 resonance;
#X text 801 277 (default 3);
#X text 769 193 (default 2);
#X connect 0 0 4 0;
#X connect 1 0 35 0;
#X connect 3 0 35 0;
#X connect 5 0 35 0;
#X connect 6 0 35 0;
#X connect 7 0 2 0;
#X connect 7 0 0 0;
#X connect 30 0 0 1;
#X connect 32 0 30 0;
#X connect 33 0 32 0;
#X connect 34 0 33 0;
#X connect 36 0 0 0;
#X connect 37 0 38 0;
#X connect 38 0 39 0;
#X connect 39 0 0 2;
#X connect 42 0 43 0;
#X connect 43 0 5 0;
#X connect 44 0 45 0;
#X connect 45 0 6 0;
