#N canvas 496 38 660 631 12;
#X declare -stdpath ./;
#X floatatom 266 492 4 0 1000 0 - - - 0;
#X floatatom 79 386 6 0 100 0 - - - 0;
#N canvas 453 53 560 665 fft-analysis 0;
#X obj 35 589 *~;
#X obj 142 287 *~;
#X obj 151 150 *~;
#X obj 35 72 *~;
#X obj 74 527 *~;
#X obj 35 44 inlet~;
#X obj 35 528 *~;
#X obj 34 101 rfft~;
#X obj 35 558 rifft~;
#X obj 36 616 outlet~;
#X obj 112 149 *~;
#X obj 112 176 +~;
#X obj 160 260 r mask-level;
#X obj 93 422 /~;
#X obj 124 312 -~;
#X obj 124 338 max~ 0;
#X obj 142 236 tabreceive~ \$0-mask;
#X obj 76 72 tabreceive~ \$0-hann;
#X obj 69 590 tabreceive~ \$0-hann;
#N canvas 459 59 615 591 calculate-mask 0;
#X obj 37 115 inlet~;
#X msg 279 332 0;
#X msg 279 215 0;
#X obj 202 249 + 1;
#X obj 148 193 bang~;
#X obj 148 218 spigot;
#X floatatom 319 267 7 0 0 0 - - - 0;
#X obj 37 413 -~;
#X obj 279 302 sel 0;
#X obj 37 446 *~;
#X obj 102 504 +~;
#X floatatom 279 362 9 0 0 0 - - - 0;
#X obj 148 268 t f f;
#X obj 279 153 r make-mask;
#X obj 279 190 t b f;
#X obj 319 223 /;
#X floatatom 369 218 8 0 0 0 - - - 0;
#X obj 369 153 r window-msec;
#X obj 369 185 / 4;
#X text 409 182 hop size (analysis;
#X text 430 198 period) in msec;
#X obj 102 360 tabreceive~ \$0-mask;
#X obj 102 538 tabsend~ \$0-mask;
#X obj 279 267 <;
#X text 216 20 calculate a mask using N msec of background noise;
#X text 30 64 current power (for each channel), f 14;
#X text 150 439 average the current power into the last mask to get the new mask. The new value is weighted 1/n on the nth iteration.;
#X text 350 356 weight to average in new power to mask, f 20;
#X text 166 59 This loops for "make-mask" milliseconds \, averaging power in each channel over that amount of time. This is done by a moving average whose weight is adjusted to average each new value equally with each of the accumulating ones., f 57;
#X text 379 268 number of frames;
#X text 61 207 loop counting to desired number of frames, f 10;
#X obj 148 245 f;
#X obj 180 294 + 1;
#X obj 180 318 expr 1/$f1;
#X connect 0 0 7 0;
#X connect 1 0 11 0;
#X connect 2 0 23 0;
#X connect 2 0 31 1;
#X connect 3 0 31 1;
#X connect 4 0 5 0;
#X connect 5 0 31 0;
#X connect 6 0 23 1;
#X connect 7 0 9 0;
#X connect 8 0 1 0;
#X connect 9 0 10 1;
#X connect 10 0 22 0;
#X connect 11 0 9 1;
#X connect 12 0 23 0;
#X connect 12 1 32 0;
#X connect 13 0 14 0;
#X connect 14 0 2 0;
#X connect 14 1 15 0;
#X connect 15 0 6 0;
#X connect 17 0 18 0;
#X connect 18 0 15 1;
#X connect 18 0 16 0;
#X connect 21 0 7 1;
#X connect 21 0 10 0;
#X connect 23 0 5 1;
#X connect 23 0 8 0;
#X connect 31 0 12 0;
#X connect 31 0 3 0;
#X connect 32 0 33 0;
#X connect 33 0 11 0;
#X restore 129 203 pd calculate-mask;
#X text 91 98 real Fourier transform;
#X text 186 338 ... but not less than zero;
#X text 87 558 real inverse Fourier transform;
#X text 161 312 current power ("s") minus level-adjusted mask ("m");
#X text 149 175 compute power (call it "s") in each channel;
#X obj 111 398 +~ 1e-20;
#X text 177 398 protect against division by zero;
#X obj 92 495 /~ 1536;
#X text 257 203 <-- subwindow calculates noise mask;
#X obj 92 448 sqrt~;
#X obj 303 38 r window-size;
#X msg 303 93 set \$1 4;
#X obj 303 124 block~;
#X text 145 431 compute sqrt((s-m)/s) where "s" is signal power and "m" is mask. (zero if s < m)., f 27;
#X floatatom 303 65 5 0 0 0 - - - 0;
#X text 375 87 set window size and overlap, f 15;
#X text 151 489 Divide by 3N/2 to normalize \, where N is window size., f 28;
#X connect 0 0 9 0;
#X connect 1 0 14 1;
#X connect 2 0 11 1;
#X connect 3 0 7 0;
#X connect 4 0 8 1;
#X connect 5 0 3 0;
#X connect 6 0 8 0;
#X connect 7 0 6 0;
#X connect 7 0 10 0;
#X connect 7 0 10 1;
#X connect 7 1 4 0;
#X connect 7 1 2 0;
#X connect 7 1 2 1;
#X connect 8 0 0 0;
#X connect 10 0 11 0;
#X connect 11 0 14 0;
#X connect 11 0 19 0;
#X connect 11 0 25 0;
#X connect 12 0 1 1;
#X connect 13 0 29 0;
#X connect 14 0 15 0;
#X connect 15 0 13 0;
#X connect 16 0 1 0;
#X connect 17 0 3 1;
#X connect 18 0 0 1;
#X connect 25 0 13 1;
#X connect 27 0 6 1;
#X connect 27 0 4 1;
#X connect 29 0 27 0;
#X connect 30 0 34 0;
#X connect 31 0 32 0;
#X connect 34 0 31 0;
#X restore 79 450 pd fft-analysis;
#N canvas 580 123 509 564 hann-window 0;
#N canvas 0 0 450 300 (subpatch) 0;
#X array \$0-hann 1024 float 0;
#X coords 0 1 1023 0 227 152 1;
#X restore 234 283 graph;
#X obj 93 419 osc~;
#X obj 93 444 *~ -0.5;
#X obj 93 468 +~ 0.5;
#X obj 76 511 tabwrite~ \$0-hann;
#X obj 92 256 /;
#X obj 110 224 samplerate~;
#X obj 45 249 swap;
#X obj 45 273 /;
#X obj 92 284 * 1000;
#X obj 92 311 s window-msec;
#X obj 64 146 t f b f;
#X msg 110 174 resize \$1;
#X obj 110 198 s \$0-hann;
#X msg 118 389 0;
#X obj 45 385 t f b;
#X obj 64 24 loadbang;
#X msg 64 52 1024;
#X floatatom 64 79 5 0 0 0 - - - 0;
#X obj 77 117 s window-size;
#X text 107 52 default window size;
#X floatatom 45 347 8 0 0 0 - - - 0;
#X text 111 347 window hz;
#X text 224 128 Calculate Hann window table (variable window size) by getting the period of the window and Hz. Also get the analysis window size in seconds and msec., f 33;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 5 0 9 0;
#X connect 6 0 5 1;
#X connect 6 0 7 1;
#X connect 7 0 8 0;
#X connect 7 1 8 1;
#X connect 8 0 21 0;
#X connect 9 0 10 0;
#X connect 11 0 5 0;
#X connect 11 0 7 0;
#X connect 11 1 6 0;
#X connect 11 2 12 0;
#X connect 12 0 13 0;
#X connect 14 0 1 1;
#X connect 15 0 1 0;
#X connect 15 1 4 0;
#X connect 15 1 14 0;
#X connect 16 0 17 0;
#X connect 17 0 18 0;
#X connect 18 0 19 0;
#X connect 18 0 11 0;
#X connect 21 0 15 0;
#X restore 365 579 pd hann-window;
#X text 169 362 noise;
#N canvas 621 135 735 607 insample 0;
#N canvas 0 0 450 300 (subpatch) 0;
#X array \$0-sample 155944 float 2;
#X coords 0 1 155944 -1 279 142 1 0 0;
#X restore 375 268 graph;
#X obj 121 246 soundfiler;
#X obj 477 461 declare -stdpath ./;
#X msg 188 276 \$1;
#X obj 163 307 swap;
#X obj 163 335 /;
#X floatatom 163 395 10 0 0 0 - - - 0;
#X obj 174 160 symbol \$0-sample;
#X obj 42 124 openpanel;
#X msg 121 215 read -resize \$1 \$2;
#X obj 121 188 pack s s;
#X obj 121 160 t a b;
#X floatatom 121 446 9 0 0 0 - - - 0;
#X floatatom 248 384 6 0 0 0 - - - 0;
#X text 219 271 sample rate, f 6;
#X obj 54 19 inlet;
#X obj 121 502 s \$0-size;
#X obj 163 421 s \$0-hz;
#X obj 54 63 route bang;
#X obj 42 97 bng 19 250 50 0 empty empty empty 0 -10 0 12 #dfdfdf #000000 #000000;
#X obj 352 107 adc~ 1;
#X obj 407 19 inlet;
#X obj 556 78 samplerate~;
#X obj 407 170 tabwrite~ \$0-sample;
#X obj 569 167 s \$0-sample;
#X msg 569 140 resize \$1;
#X obj 556 111 * 2;
#X text 588 112 2 seconds;
#X obj 556 199 s \$0-size;
#X text 169 57 Subpatch to initialize patch \, load file into array and record., f 22;
#X obj 203 547 outlet;
#X obj 248 411 / 1000;
#X obj 203 487 /;
#X obj 224 517 r \$0-ms;
#X obj 493 113 s \$0-hz;
#X msg 493 88 0.5;
#X msg 448 114 2000;
#X obj 448 139 s \$0-ms;
#X connect 1 0 4 0;
#X connect 1 0 12 0;
#X connect 1 1 3 0;
#X connect 3 0 4 1;
#X connect 3 0 13 0;
#X connect 4 0 5 0;
#X connect 4 1 5 1;
#X connect 5 0 6 0;
#X connect 6 0 17 0;
#X connect 7 0 10 1;
#X connect 8 0 11 0;
#X connect 9 0 1 0;
#X connect 10 0 9 0;
#X connect 11 0 10 0;
#X connect 11 1 7 0;
#X connect 12 0 16 0;
#X connect 12 0 32 0;
#X connect 13 0 31 0;
#X connect 15 0 18 0;
#X connect 18 0 19 0;
#X connect 18 1 11 0;
#X connect 19 0 8 0;
#X connect 20 0 23 0;
#X connect 21 0 22 0;
#X connect 21 0 23 0;
#X connect 21 0 36 0;
#X connect 21 0 35 0;
#X connect 22 0 26 0;
#X connect 25 0 24 0;
#X connect 26 0 25 0;
#X connect 26 0 28 0;
#X connect 31 0 32 1;
#X connect 32 0 30 0;
#X connect 33 0 30 0;
#X connect 35 0 34 0;
#X connect 36 0 37 0;
#X restore 417 500 pd insample;
#X obj 266 517 s mask-level;
#X floatatom 174 386 6 0 100 0 - - - 0;
#X text 267 431 on;
#X text 312 432 off;
#X text 267 415 masking;
#X msg 311 455 0;
#N canvas 306 38 521 612 test-signal 0;
#X obj 323 437 *~;
#X obj 167 401 *~;
#X obj 254 339 noise~;
#X obj 305 481 +~;
#X obj 185 311 dbtorms;
#X obj 341 351 dbtorms;
#X obj 185 156 inlet;
#X obj 341 156 inlet;
#X obj 305 536 outlet~;
#X obj 254 364 bp~ 10000 3;
#X text 142 86 looped sample playback;
#X text 258 306 filtered noise, f 8;
#X text 103 37 TEST SIGNAL: looped sample plus noise. The inlets control amplitude of each in dB., f 42;
#X obj 76 267 *~;
#X obj 76 233 phasor~;
#X obj 76 303 tabread4~ \$0-sample, f 9;
#X msg 341 383 \$1 10;
#X obj 341 407 line~;
#X msg 185 337 \$1 10;
#X obj 185 361 line~;
#X obj 76 204 r \$0-hz;
#X obj 110 268 r \$0-size;
#X connect 0 0 3 1;
#X connect 1 0 3 0;
#X connect 2 0 9 0;
#X connect 3 0 8 0;
#X connect 4 0 18 0;
#X connect 5 0 16 0;
#X connect 6 0 4 0;
#X connect 7 0 5 0;
#X connect 9 0 0 0;
#X connect 13 0 15 0;
#X connect 14 0 13 0;
#X connect 15 0 1 0;
#X connect 16 0 17 0;
#X connect 17 0 0 1;
#X connect 18 0 19 0;
#X connect 19 0 1 1;
#X connect 20 0 14 0;
#X connect 21 0 13 1;
#X restore 79 415 pd test-signal;
#X text 73 360 sampler;
#X text 264 330 calculate noise mask, f 10;
#X obj 79 487 output~;
#X msg 253 368 \; make-mask 2000;
#X msg 266 454 15;
#N canvas 647 275 498 424 mask-table 0;
#N canvas 0 0 450 300 (subpatch) 0;
#X array \$0-mask 512 float 0;
#X coords 0 500 511 0 400 300 1;
#X restore 49 96 graph;
#X text 108 22 This table is the average power measured in each channel of the spectrum \, presumed to represent the noise floor., f 41;
#X restore 257 579 pd mask-table;
#X text 86 333 amplitudes (dB);
#X text 101 68 This patch attempts to scrub the noise floor from a sample in two steps. First using the "make-mask" message (which is caught in the [pd fft-analysis] subpatch) \, you estimate the background spectrum. You would normally do this at a moment when only the background noise is audible. Then \, turn on "masking" (to 15 by default \, but try other values) and the patch will try to clean the background noise out of a signal., f 68;
#X text 101 174 For this demonstration \, you control the amplitudes of a looping sample and a filtered noise source. Normally you'd hit "calculate noise mask" with only the noise turned on \, then turn both the noise and the sampler on \, and also "masking" \, to see if the patch can clean the noise out of the signal. Open the [pd fft-analysis] window to see the algorithm \, or the "insample" window to change samples \, or "mask-table" to see the current mask (the average signal power of the noise to clean out of the signal)., f 68;
#X obj 76 25 cnv 5 5 25 empty empty Denoiser 15 13 0 16 #dfdfdf #202020 0;
#X obj 439 448 bng 19 250 50 0 empty empty empty 0 -10 0 12 #dfdfdf #000000 #000000;
#X msg 413 369 ../sound/bell.aiff;
#X msg 422 392 ../sound/voice.wav;
#X msg 429 416 ../sound/voice2.wav;
#X text 478 344 read input sound;
#X text 466 448 choose a file;
#X obj 413 342 loadbang;
#X obj 491 474 bng 19 250 50 0 empty empty empty 0 -10 0 12 #dfdfdf #000000 #000000;
#X text 517 469 record 2 sec, f 6;
#X floatatom 417 529 8 0 0 0 - - - 0;
#X text 482 529 length in ms;
#X connect 0 0 6 0;
#X connect 1 0 12 0;
#X connect 2 0 15 0;
#X connect 5 0 32 0;
#X connect 7 0 12 1;
#X connect 11 0 0 0;
#X connect 12 0 2 0;
#X connect 17 0 0 0;
#X connect 23 0 5 0;
#X connect 24 0 5 0;
#X connect 25 0 5 0;
#X connect 26 0 5 0;
#X connect 29 0 24 0;
#X connect 30 0 5 1;
