#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 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 5272 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 8500 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 1 10 1 0 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 0 1;
#X floatatom 692 250 5 1 10 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 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 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 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 restore 515 309 pd details;
#X text 477 189 resonance;
#X text 801 277 (default 3);
#X text 769 193 (default 2);
#X text 46 528 The saturation parameter determines at what signal level the "transistors" in the model saturate \, or start limiting. Lower values limit the signal earlier (more distortion \, quieter) \, while higher values limit it later (cleaner \, louder). A good range is from 2-5 (default is 3). "Clear" momentarily shorts out the capacitors in case the filter has gone unstable and stopped working., f 78;
#X text 46 424 One step of 4th-order Runge-Kutte integration per audio sample 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 integer factor (default is 2). At high cutoff frequencies and resonance values the Runge-Kutte approximation can go unstable. You can also raise the oversampling factor to combat this \, but note that computation time rises accordingly for greater oversampling values., f 78;
#X connect 0 0 4 0;
#X connect 1 0 34 0;
#X connect 3 0 34 0;
#X connect 5 0 34 0;
#X connect 6 0 34 0;
#X connect 7 0 2 0;
#X connect 7 0 0 0;
#X connect 29 0 0 1;
#X connect 31 0 29 0;
#X connect 32 0 31 0;
#X connect 33 0 32 0;
#X connect 35 0 0 0;
#X connect 36 0 37 0;
#X connect 37 0 38 0;
#X connect 38 0 0 2;
#X connect 41 0 42 0;
#X connect 42 0 5 0;
#X connect 43 0 44 0;
#X connect 44 0 6 0;
