#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 755 157 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 239 float/signal - resonannce., f 64; #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 139 316 NONE; #X text 47 109 saturation - set saturation point of "transistors"., f 71; #X text 47 127 oversample - set oversampling., 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 8 0 1 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 2012 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 1 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 4830 1; #X floatatom 692 250 5 0 8 0 - - - 0; #X obj 669 138 hsl 162 19 1 10 0 1 empty empty empty -2 -8 0 10 #dfdfdf #000000 #000000 1789 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 458 189 "resonance" (0-8); #X text 43 366 input monitor ->, f 10; #X text 390 375 <- 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 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;