diff options
-rw-r--r-- | examples/puredata/Makefile.am | 4 | ||||
-rw-r--r-- | examples/puredata/xtract/a_bavg.pd | 36 | ||||
-rw-r--r-- | examples/puredata/xtract/a_hann.pd | 30 | ||||
-rw-r--r-- | examples/puredata/xtract/a_mton.pd | 66 | ||||
-rw-r--r-- | examples/puredata/xtract/a_output~.pd | 71 | ||||
-rw-r--r-- | examples/puredata/xtract/a_spigot~.pd | 21 | ||||
-rw-r--r-- | examples/puredata/xtract/f0.pd | 292 | ||||
-rw-r--r-- | examples/puredata/xtract/mfcc.pd | 154 | ||||
-rw-r--r-- | examples/puredata/xtract/sonogram.pd | 1 | ||||
-rw-r--r-- | examples/puredata/xtract/xtract-help.pd | 69 | ||||
-rw-r--r-- | src/scalar.c | 364 |
11 files changed, 925 insertions, 183 deletions
diff --git a/examples/puredata/Makefile.am b/examples/puredata/Makefile.am index 97bad90..dda94f4 100644 --- a/examples/puredata/Makefile.am +++ b/examples/puredata/Makefile.am @@ -27,7 +27,9 @@ AM_LDFLAGS = @PD_LDFLAGS@ -lxtract -L$(top_builddir)/src/ ## Install the documentation. install: - -mv $(top_builddir)/examples/puredata/.libs/xtract.@PD_SUFFIX@ $(pdinstalldir)/xtract~.@PD_SUFFIX@ + install -m 644 $(top_builddir)/examples/puredata/.libs/xtract.@PD_SUFFIX@ $(pdinstalldir)/xtract~.@PD_SUFFIX@ + install -d $(pddir)/doc/5.reference/xtract + cp xtract/* $(PDDIR)/doc/5.reference/xtract #pdinstallref_DATA = \ # help/aubioonset-help.pd \ diff --git a/examples/puredata/xtract/a_bavg.pd b/examples/puredata/xtract/a_bavg.pd new file mode 100644 index 0000000..38c8c71 --- /dev/null +++ b/examples/puredata/xtract/a_bavg.pd @@ -0,0 +1,36 @@ +#N canvas 0 0 450 300 10; +#X obj 140 183 +; +#X obj 243 216 f; +#X obj 242 124 f; +#X obj 275 124 + 1; +#X msg 244 193 0; +#X obj 175 223 f; +#X obj 175 245 / \$1; +#X obj 242 147 % \$1; +#X obj 319 172 f \$1; +#X obj 319 192 - 1; +#X obj 243 170 sel; +#X obj 319 146 loadbang; +#X obj 161 60 inlet; +#X obj 165 84 t b f; +#X obj 175 271 outlet; +#X text 28 12 Averages a series of N numbers where N is given by the +first arument (works in blocks); +#X connect 0 0 1 0; +#X connect 0 0 5 1; +#X connect 1 0 0 1; +#X connect 2 0 3 0; +#X connect 2 0 7 0; +#X connect 3 0 2 1; +#X connect 4 0 1 0; +#X connect 5 0 6 0; +#X connect 6 0 14 0; +#X connect 7 0 10 0; +#X connect 8 0 9 0; +#X connect 9 0 10 1; +#X connect 10 0 4 0; +#X connect 10 0 5 0; +#X connect 11 0 8 0; +#X connect 12 0 13 0; +#X connect 13 0 2 0; +#X connect 13 1 0 0; diff --git a/examples/puredata/xtract/a_hann.pd b/examples/puredata/xtract/a_hann.pd new file mode 100644 index 0000000..bc150b0 --- /dev/null +++ b/examples/puredata/xtract/a_hann.pd @@ -0,0 +1,30 @@ +#N canvas 379 192 709 463 10; +#X obj 368 85 samplerate~; +#X obj 371 153 phasor~; +#X msg 457 83 0; +#X obj 371 182 expr~ 0.5 - cos($v1 * 6.28) * 0.5; +#X obj 618 10 block~ \$1; +#X obj 368 107 /~ \$1; +#X text 43 20 Creation arg gives window size; +#X obj 346 38 t b b b b; +#X obj 490 58 float \$1; +#X obj 346 10 inlet; +#X obj 40 268 tabreceive~ \$0-hann; +#X obj 40 307 outlet~; +#X msg 491 80 resize \$1; +#X obj 493 104 s \$0-hann; +#X obj 373 308 table \$0-hann; +#X obj 371 207 tabwrite~ \$0-hann; +#X connect 0 0 5 0; +#X connect 1 0 3 0; +#X connect 2 0 1 1; +#X connect 3 0 15 0; +#X connect 5 0 1 0; +#X connect 7 0 15 0; +#X connect 7 1 2 0; +#X connect 7 2 0 0; +#X connect 7 3 8 0; +#X connect 8 0 12 0; +#X connect 9 0 7 0; +#X connect 10 0 11 0; +#X connect 12 0 13 0; diff --git a/examples/puredata/xtract/a_mton.pd b/examples/puredata/xtract/a_mton.pd new file mode 100644 index 0000000..7829dbe --- /dev/null +++ b/examples/puredata/xtract/a_mton.pd @@ -0,0 +1,66 @@ +#N canvas 165 175 599 406 10; +#X obj 151 123 inlet; +#X obj 151 179 % 12; +#X obj 151 232 sel 0 1 2 3 4 5 6 7 8 9 10 11; +#X obj 483 268 / 12; +#X obj 483 291 int; +#X obj 483 313 outlet; +#X msg 80 272 C; +#X msg 110 272 C#; +#X msg 142 273 D; +#X msg 174 273 D#; +#X msg 203 273 E; +#X msg 236 274 F; +#X msg 269 274 F#; +#X msg 299 274 G; +#X msg 329 274 G#; +#X msg 359 275 A; +#X msg 393 275 A#; +#X msg 425 275 B; +#X obj 235 342 symbol; +#X obj 235 368 outlet; +#X obj 569 206 int; +#X obj 537 184 t f f; +#X obj 537 207 -; +#X obj 538 313 outlet; +#X text 51 30 a_mton takes midi note number as a float and outputs +note name \, octave and deviation in cents.; +#X obj 537 231 * 100; +#X obj 537 250 - 50; +#X connect 0 0 1 0; +#X connect 0 0 3 0; +#X connect 0 0 21 0; +#X connect 1 0 2 0; +#X connect 2 0 6 0; +#X connect 2 1 7 0; +#X connect 2 2 8 0; +#X connect 2 3 9 0; +#X connect 2 4 10 0; +#X connect 2 5 11 0; +#X connect 2 6 12 0; +#X connect 2 7 13 0; +#X connect 2 8 14 0; +#X connect 2 9 15 0; +#X connect 2 10 16 0; +#X connect 2 11 17 0; +#X connect 3 0 4 0; +#X connect 4 0 5 0; +#X connect 6 0 18 0; +#X connect 7 0 18 0; +#X connect 8 0 18 0; +#X connect 9 0 18 0; +#X connect 10 0 18 0; +#X connect 11 0 18 0; +#X connect 12 0 18 0; +#X connect 13 0 18 0; +#X connect 14 0 18 0; +#X connect 15 0 18 0; +#X connect 16 0 18 0; +#X connect 17 0 18 0; +#X connect 18 0 19 0; +#X connect 20 0 22 1; +#X connect 21 0 22 0; +#X connect 21 1 20 0; +#X connect 22 0 25 0; +#X connect 25 0 26 0; +#X connect 26 0 23 0; diff --git a/examples/puredata/xtract/a_output~.pd b/examples/puredata/xtract/a_output~.pd new file mode 100644 index 0000000..8cbf956 --- /dev/null +++ b/examples/puredata/xtract/a_output~.pd @@ -0,0 +1,71 @@ +#N canvas 0 0 757 675 12; +#X obj 516 522 t b; +#X obj 516 469 f; +#X obj 516 547 f; +#X msg 630 546 0; +#X obj 516 499 moses 1; +#X obj 630 518 t b f; +#X obj 596 479 moses 1; +#X obj 29 97 dbtorms; +#X obj 85 170 inlet~; +#X msg 278 300 \; pd dsp 1; +#X obj 29 170 line~; +#X obj 64 242 *~; +#X obj 64 272 dac~; +#X obj 29 127 pack 0 50; +#X text 121 146 audio in; +#X text 301 496 test if less than 1 -->; +#X text 267 523 if true convert to bang -->; +#X text 100 96 <-- convert from dB to linear units; +#X floatatom 31 13 3 0 100 0 dB - -; +#X obj 44 37 bng 15 250 50 0 empty empty mute -38 7 0 10 -262144 -1 +-1; +#X text 118 126 <-- make a ramp to avoid clicks or zipper noise; +#X obj 148 170 inlet~; +#X obj 154 241 *~; +#X text 502 399 MUTE logic:; +#X obj 293 247 s \$0-master-out; +#X obj 29 71 r \$0-master-out; +#X obj 596 450 r \$0-master-out; +#X text 182 8 Level control abstraction \, used in many of the Pd example +patches. The level and mute controls show up on the parent \, calling +patch.; +#X text 229 549 previous nonzero master-lvl -->; +#X text 301 453 recall previous; +#X text 301 471 value of master-lvl -->; +#X text 16 310 automatically start DSP -->; +#X obj 85 192 hip~ 3; +#X obj 147 192 hip~ 3; +#X text 26 608 NOTE: This abstraction was written by Miller Puckette +\, and is include with the PD examples as part of the 'standard' PD +documentation. JB 23/05/05; +#X obj 278 193 r \$0-master-lvl-stereo; +#X obj 516 573 s \$0-master-lvl-stereo; +#X obj 623 215 inlet; +#X connect 0 0 2 0; +#X connect 1 0 4 0; +#X connect 2 0 36 0; +#X connect 3 0 36 0; +#X connect 4 0 0 0; +#X connect 4 1 5 0; +#X connect 5 0 3 0; +#X connect 6 1 2 1; +#X connect 7 0 13 0; +#X connect 8 0 32 0; +#X connect 10 0 22 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 13 0 10 0; +#X connect 18 0 9 0; +#X connect 18 0 24 0; +#X connect 19 0 1 0; +#X connect 21 0 33 0; +#X connect 22 0 12 1; +#X connect 25 0 7 0; +#X connect 26 0 1 1; +#X connect 26 0 6 0; +#X connect 32 0 11 1; +#X connect 33 0 22 1; +#X connect 35 0 18 0; +#X connect 37 0 18 0; +#X coords 0 0 1 1 65 55 1 0 0; diff --git a/examples/puredata/xtract/a_spigot~.pd b/examples/puredata/xtract/a_spigot~.pd new file mode 100644 index 0000000..86ebd54 --- /dev/null +++ b/examples/puredata/xtract/a_spigot~.pd @@ -0,0 +1,21 @@ +#N canvas 0 0 450 300 10; +#X obj 153 112 inlet~; +#X obj 152 229 outlet~; +#X obj 153 186 expr~ $v1 * $v2; +#X obj 252 162 line~; +#X msg 258 121 1 20; +#X msg 299 121 0 20; +#X obj 255 14 inlet; +#X obj 255 36 > 0; +#X obj 255 63 select 1 0; +#X text 49 261 Audio spigot. Same behaviour as spigot but for audio +; +#X connect 0 0 2 0; +#X connect 2 0 1 0; +#X connect 3 0 2 1; +#X connect 4 0 3 0; +#X connect 5 0 3 0; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 8 0 4 0; +#X connect 8 1 5 0; diff --git a/examples/puredata/xtract/f0.pd b/examples/puredata/xtract/f0.pd new file mode 100644 index 0000000..d178c82 --- /dev/null +++ b/examples/puredata/xtract/f0.pd @@ -0,0 +1,292 @@ +#N canvas 814 127 584 590 10; +#N canvas 162 173 901 522 guts 0; +#X obj 205 48 osc~; +#X obj 338 70 a_spigot~; +#X obj 205 70 a_spigot~; +#X obj 331 -26 line; +#X msg 331 -50 \$1 50; +#X obj 357 282 ftom; +#X obj 3 48 ftom; +#N canvas 0 0 450 300 fm 0; +#X obj 181 114 osc~; +#X obj 138 175 osc~; +#X obj 137 154 +~; +#X obj 144 209 outlet~; +#X obj 182 82 *; +#X obj 137 26 inlet; +#X obj 204 6 inlet; +#X obj 179 54 f; +#X obj 204 30 t b f; +#X obj 182 143 *~; +#X obj 238 81 - 2; +#X obj 225 113 * 100000; +#X connect 0 0 9 0; +#X connect 1 0 3 0; +#X connect 2 0 1 0; +#X connect 4 0 0 0; +#X connect 5 0 2 0; +#X connect 5 0 4 0; +#X connect 5 0 7 1; +#X connect 6 0 8 0; +#X connect 7 0 4 0; +#X connect 7 0 2 0; +#X connect 8 0 7 0; +#X connect 8 1 4 1; +#X connect 8 1 10 0; +#X connect 9 0 2 1; +#X connect 10 0 11 0; +#X connect 11 0 9 1; +#X restore 339 47 pd fm; +#X obj 459 69 a_spigot~; +#X obj 253 168 +~; +#N canvas 0 0 450 300 noise 0; +#X obj 260 126 noise~; +#X obj 269 161 *~; +#X obj 270 194 lop~; +#X obj 305 161 * 10000; +#X obj 320 124 inlet; +#X obj 268 236 outlet~; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 2 0 5 0; +#X connect 3 0 2 1; +#X connect 4 0 3 0; +#X connect 4 0 1 1; +#X restore 587 66 pd noise; +#N canvas 604 77 496 580 pda 0; +#X obj 99 100 xtract~ f0; +#X obj 197 6 inlet~; +#X obj 147 195 xtract~ magnitude_spectrum; +#X obj 149 299 xtract~ lowest_match; +#X msg 361 203 list \$1; +#X obj 244 115 *~; +#X obj 59 25 r sr; +#X obj 148 222 xtract~ peaks; +#X obj 148 245 tabsend~ freqs; +#X obj 401 30 table freqs; +#X obj 148 276 tabreceive~ freqs; +#X obj 6 220 != 0; +#X obj 4 331 spigot; +#X obj 57 331 spigot; +#X obj 67 217 == 0; +#X obj 27 369 f; +#X obj 28 415 lop~ 20; +#X obj 27 393 sig~; +#X obj 29 469 snapshot~; +#X obj 95 434 bang~; +#X obj 26 529 outlet; +#X obj 29 499 a_bavg 4; +#X obj 197 29 lop~ 5000; +#X obj 402 8 block~ 2048; +#X obj 200 51 hip~ 20; +#X msg 60 48 list \$1; +#X obj 274 80 a_hann 2048; +#X obj 274 59 r \$0-window-gen; +#X connect 0 0 4 0; +#X connect 0 0 11 0; +#X connect 0 0 12 0; +#X connect 0 0 14 0; +#X connect 1 0 22 0; +#X connect 2 0 7 0; +#X connect 3 0 13 0; +#X connect 4 0 3 1; +#X connect 5 0 2 0; +#X connect 6 0 25 0; +#X connect 7 0 8 0; +#X connect 10 0 3 0; +#X connect 11 0 12 1; +#X connect 12 0 15 0; +#X connect 13 0 15 0; +#X connect 14 0 13 1; +#X connect 15 0 17 0; +#X connect 16 0 18 0; +#X connect 17 0 16 0; +#X connect 18 0 21 0; +#X connect 19 0 18 0; +#X connect 21 0 20 0; +#X connect 22 0 24 0; +#X connect 24 0 0 0; +#X connect 24 0 5 0; +#X connect 25 0 0 1; +#X connect 26 0 5 1; +#X connect 27 0 26 0; +#X restore 357 262 pd pda; +#N canvas 0 0 596 417 d_saw 0; +#X obj 382 176 phasor~; +#X obj 397 96 noise~; +#X obj 346 116 sig~; +#X obj 381 149 +~; +#X obj 397 117 *~; +#X obj 242 198 phasor~; +#X obj 319 283 outlet~; +#X obj 385 215 *~ 0.5; +#X obj 240 227 *~ 0.3; +#X obj 270 173 * 0.01; +#X obj 241 174 +; +#X obj 460 97 * 0.1; +#X obj 312 249 lop~ 10000; +#X obj 369 51 inlet; +#X obj 261 55 inlet fund; +#X obj 258 138 f; +#X obj 286 105 t b f; +#X connect 0 0 7 0; +#X connect 1 0 4 0; +#X connect 2 0 3 0; +#X connect 3 0 0 0; +#X connect 4 0 3 1; +#X connect 5 0 8 0; +#X connect 7 0 12 0; +#X connect 8 0 12 0; +#X connect 9 0 10 1; +#X connect 10 0 5 0; +#X connect 11 0 4 1; +#X connect 12 0 6 0; +#X connect 13 0 16 0; +#X connect 14 0 2 0; +#X connect 14 0 11 0; +#X connect 14 0 15 1; +#X connect 14 0 10 0; +#X connect 15 0 10 0; +#X connect 15 0 9 0; +#X connect 16 0 15 0; +#X connect 16 1 9 1; +#X restore 457 45 pd d_saw; +#X obj 160 262 fiddle~ 2048; +#X obj 75 47 adc~; +#X obj 76 71 a_spigot~; +#X obj 2 69 a_mton; +#X obj 160 283 a_mton; +#X obj 357 301 a_mton; +#X obj 733 -70 loadbang; +#X obj 68 241 loadbang; +#X msg 67 263 symbol; +#X text 411 283 <-The magic happens in here; +#X obj 660 323 a_output~; +#X msg 747 271 0; +#X obj 263 46 r \$0-sine; +#X obj 134 48 r \$0-adc; +#X obj 396 48 r \$0-fm; +#X obj 521 43 r \$0-saw; +#X obj 586 41 r \$0-noisiness; +#X obj 473 -1 r \$0-inharmonicity; +#X obj 161 409 s \$0-fidd_f0_note; +#X obj 178 386 s \$0-fidd_f0_8ve; +#X obj 197 361 s \$0-fidd_f0_cent; +#X obj 356 367 s \$0-pda_f0_note; +#X obj 333 -73 r \$0-fund; +#X obj 375 345 s \$0-pda_f0_8ve; +#X obj 395 326 s \$0-pda_f0_cent; +#X obj 745 230 r \$0-master-lvl-stereo; +#X obj 747 252 r \$0-master-lvl-mute; +#X obj 747 291 s \$0-master-lvl-stereo; +#X msg 733 -20 \; pd dsp 1 \; \; \$1-window-gen bang \; sr 44100 \; +\; \$1-master-lvl-stereo 50; +#X obj 733 -45 f \$0; +#X obj 38 357 s \$0-f0_cent; +#X obj 19 378 s \$0-f0_8ve; +#X obj 0 406 s \$0-f0_note; +#X obj 254 261 s~ \$0-dacs; +#X obj 670 281 r~ \$0-dacs; +#X connect 0 0 2 0; +#X connect 1 0 9 0; +#X connect 2 0 9 0; +#X connect 3 0 0 0; +#X connect 3 0 12 0; +#X connect 3 0 7 0; +#X connect 3 0 6 0; +#X connect 4 0 3 0; +#X connect 5 0 18 0; +#X connect 6 0 16 0; +#X connect 7 0 1 0; +#X connect 8 0 9 0; +#X connect 9 0 11 0; +#X connect 9 0 13 0; +#X connect 9 0 46 0; +#X connect 10 0 9 1; +#X connect 11 0 5 0; +#X connect 12 0 8 0; +#X connect 13 0 17 0; +#X connect 14 0 15 0; +#X connect 15 0 9 0; +#X connect 16 0 45 0; +#X connect 16 1 44 0; +#X connect 16 2 43 0; +#X connect 17 0 31 0; +#X connect 17 1 32 0; +#X connect 17 2 33 0; +#X connect 18 0 34 0; +#X connect 18 1 36 0; +#X connect 18 2 37 0; +#X connect 19 0 42 0; +#X connect 20 0 21 0; +#X connect 21 0 31 0; +#X connect 21 0 34 0; +#X connect 21 0 45 0; +#X connect 24 0 23 2; +#X connect 24 0 40 0; +#X connect 25 0 2 1; +#X connect 26 0 15 1; +#X connect 27 0 1 1; +#X connect 28 0 8 1; +#X connect 29 0 10 0; +#X connect 30 0 7 1; +#X connect 35 0 4 0; +#X connect 38 0 23 2; +#X connect 39 0 24 0; +#X connect 42 0 41 0; +#X connect 47 0 23 0; +#X connect 47 0 23 1; +#X restore 519 -226 pd guts; +#X obj 11 -226 cnv 15 500 200 empty empty PDA_comparison 20 12 0 14 +-261681 -66577 0; +#X obj 34 -94 hsl 128 15 2 2.05 0 0 \$0-inharmonicity empty fm-inharmonicity +-2 -6 0 8 -225271 -1 -1 0 1; +#X obj 34 -50 hsl 128 15 0 0.5 0 0 \$0-noisiness empty noisiness -2 +-6 0 8 -225271 -1 -1 0 1; +#X obj 33 -135 hsl 128 15 30 3000 0 0 \$0-fund empty f0 -2 -6 0 8 -225271 +-1 -1 0 1; +#X obj 32 -172 tgl 15 0 \$0-sine empty sine 0 -6 0 8 -225280 -1 -1 +0 1; +#X obj 73 -172 tgl 15 0 \$0-fm empty fm 0 -6 0 8 -225280 -1 -1 0 1 +; +#X obj 110 -172 tgl 15 0 \$0-saw empty saw 0 -6 0 8 -225280 -1 -1 0 +1; +#X obj 227 -133 cnv 15 200 100 empty empty empty 20 12 0 14 -262131 +-66577 0; +#X obj 226 -199 cnv 15 200 60 empty empty empty 20 12 0 14 -225280 +-66577 0; +#X symbolatom 242 -170 5 0 0 0 f0 #0-f0_note -; +#X floatatom 312 -170 5 0 0 0 8ve #0-f0_8ve -; +#X symbolatom 245 -112 5 0 0 0 f0 #0-fidd_f0_note -; +#X floatatom 313 -112 5 0 0 0 8ve #0-fidd_f0_8ve -; +#X text 304 -200 Input; +#X text 308 -93 xtract~; +#X text 305 -134 fiddle~; +#X floatatom 315 -62 5 0 0 0 8ve #0-pda_f0_8ve -; +#X symbolatom 247 -62 5 0 0 0 f0 #0-pda_f0_note -; +#X text 20 8 Notes:; +#X text 20 36 In this patch xtract~ is used to provide a combination +of time domain and frequency domain fundamental frequency estimation. +; +#X text 27 233 A block size of 2048 has been used in this example. +Which allows for a theoretical limit of 21Hz. In reality xtract~ can +be used to detect frequencies down to 30Hz with this block size \, +but with a larger block size it could go lower!; +#X text 23 88 [xtract~ f0] uses a method based on the AMDF function +\, with centre and peak clipping used to provide noise robustness. +This could be further improved \, as could the efficiency of the algorithm. +; +#X text 26 154 If [xtract~ f0] is unable to find a fundamental (i.e. +its output is 0 \, the lowest frequency in the peak spectrum is used. +In general this happens for very low frequencies. [xtract~ magnitude_spectrum] +\, [xtract~ peaks] \, and [xtract~ lowest_match] are used to achieve +this.; +#X obj 147 -172 tgl 15 0 \$0-adc empty adc~ 0 -6 0 8 -257472 -1 -1 +0 1; +#X floatatom 386 -171 5 0 0 0 cent #0-f0_cent -; +#X floatatom 386 -63 5 0 0 0 cent #0-pda_f0_cent -; +#X floatatom 386 -113 5 0 0 0 cent #0-fidd_f0_cent -; +#X obj 465 -187 vsl 10 100 0 127 0 0 \$0-master-lvl-stereo \$0-master-lvl-stereo +out -4 -8 0 8 -262131 -1 -1 3898 1; +#X obj 465 -77 bng 10 250 50 0 \$0-master-lvl-mute empty mute -6 16 +0 8 -262131 -1 -1; diff --git a/examples/puredata/xtract/mfcc.pd b/examples/puredata/xtract/mfcc.pd new file mode 100644 index 0000000..7e12479 --- /dev/null +++ b/examples/puredata/xtract/mfcc.pd @@ -0,0 +1,154 @@ +#N canvas 667 28 576 568 10; +#N canvas 397 309 590 228 guts 0; +#X obj 318 37 loadbang; +#X obj 318 64 f \$0; +#N canvas 0 0 450 300 dacs 0; +#X obj 164 152 a_output~; +#X msg 251 100 0; +#X obj 249 59 r \$0-master-lvl-stereo; +#X obj 251 81 r \$0-master-lvl-mute; +#X obj 251 120 s \$0-master-lvl-stereo; +#X obj 174 110 inlet~; +#X connect 1 0 0 2; +#X connect 1 0 4 0; +#X connect 2 0 0 2; +#X connect 3 0 1 0; +#X connect 5 0 0 0; +#X connect 5 0 0 1; +#X restore 85 126 pd dacs; +#N canvas 0 0 450 300 analysis 0; +#X obj 191 201 xtract~ mfcc; +#X obj 195 176 xtract~ magnitude_spectrum; +#X obj 194 153 *~; +#X obj 219 104 r \$0-window-gen; +#X obj 190 225 tabsend~ \$0-mfcc; +#X obj 181 69 inlet~; +#X obj 299 45 block~ 1024 2 1; +#X obj 219 125 a_hann 1024; +#X connect 0 0 4 0; +#X connect 1 0 0 0; +#X connect 2 0 1 0; +#X connect 3 0 7 0; +#X connect 5 0 2 0; +#X connect 7 0 2 1; +#X restore 32 167 pd analysis; +#X obj 16 24 r \$0-fund; +#X msg 318 88 \; pd dsp 1 \; \$1-master-lvl-stereo 60 \; \$1-window-gen +bang \; \$1-mfcc xticks 0 5 5 \; \$1-mfcc yticks 0 50 1 \; \$1-mfcc +xlabel -120 0 5 10 15 20; +#N canvas 308 141 679 510 paf 0; +#X obj 331 95 / 10; +#X obj 331 120 pack 0 50; +#X obj 139 412 fexpr~ $x1 * $x2; +#X obj 241 188 cos~; +#X obj 241 166 expr~ ($v1 * 0.5) - 0.25; +#X obj 380 197 *~ 256; +#X obj 462 209 line~; +#X obj 462 189 pack 0 50; +#X obj 289 194 *~; +#X obj 282 216 +~ 256; +#X obj 118 328 cos~; +#X obj 118 305 *~; +#X obj 161 328 cos~; +#X obj 161 305 +~; +#X obj 154 358 -~; +#X obj 174 390 *~; +#X obj 136 390 +~; +#X obj 230 291 wrap~; +#X obj 199 291 -~; +#X obj 199 259 samphold~; +#X obj 331 142 line~; +#X obj 138 438 outlet~; +#X obj 462 167 inlet bandwidth; +#X obj 47 121 phasor~; +#X obj 48 100 line~; +#X msg 47 78 \$1 20; +#X obj 48 57 inlet fund; +#X obj 331 73 inlet cf; +#X obj 282 316 tabread4~ \$0-hann; +#X obj 466 426 table \$0-hann; +#X connect 0 0 1 0; +#X connect 1 0 20 0; +#X connect 2 0 21 0; +#X connect 3 0 8 0; +#X connect 4 0 3 0; +#X connect 5 0 8 1; +#X connect 6 0 5 0; +#X connect 7 0 6 0; +#X connect 8 0 9 0; +#X connect 9 0 28 0; +#X connect 10 0 14 1; +#X connect 10 0 16 0; +#X connect 11 0 13 0; +#X connect 11 0 10 0; +#X connect 12 0 14 0; +#X connect 13 0 12 0; +#X connect 14 0 15 0; +#X connect 15 0 16 1; +#X connect 16 0 2 0; +#X connect 17 0 18 1; +#X connect 17 0 15 1; +#X connect 18 0 11 1; +#X connect 19 0 18 0; +#X connect 19 0 17 0; +#X connect 20 0 19 0; +#X connect 22 0 7 0; +#X connect 23 0 19 1; +#X connect 23 0 13 1; +#X connect 23 0 11 0; +#X connect 23 0 4 0; +#X connect 24 0 23 0; +#X connect 25 0 24 0; +#X connect 26 0 25 0; +#X connect 27 0 0 0; +#X connect 28 0 2 1; +#X restore 35 80 pd paf; +#X obj 85 25 r \$0-cf; +#X obj 140 23 r \$0-bw; +#X connect 0 0 1 0; +#X connect 1 0 5 0; +#X connect 4 0 6 0; +#X connect 6 0 2 0; +#X connect 6 0 3 0; +#X connect 7 0 6 1; +#X connect 8 0 6 2; +#X restore 516 -222 pd guts; +#X obj 6 -225 cnv 15 500 200 empty empty MFCC 20 12 0 14 -261681 -66577 +0; +#X obj 184 -202 cnv 15 250 150 empty empty empty 20 12 0 14 -262131 +-66577 0; +#X obj 465 -187 vsl 10 100 0 127 0 0 \$0-master-lvl-stereo \$0-master-lvl-stereo +out -4 -8 0 8 -262131 -1 -1 4677 1; +#X obj 465 -77 bng 10 250 50 0 \$0-master-lvl-mute empty mute -6 16 +0 8 -262131 -1 -1; +#X obj 32 -114 hsl 128 15 20 2000 0 0 \$0-cf empty centre_frequency +-2 -6 0 8 -225271 -1 -1 4000 1; +#X obj 33 -153 hsl 128 15 80 2000 0 0 \$0-fund empty fundamental -2 +-6 0 8 -225271 -1 -1 3100 1; +#X text 19 7 Notes:; +#X text 20 36 In this patch [xtract~ magnitude_spectrum] is first used +to extract the magnitude spectrum from an audio signal in overlapping +blocks of 1024 samples.; +#X text 20 87 [xtract~ mfcc] outputs a series 20 Mel-Frequency Cepstral +Coefficients. When it is instantiated \, an initialisation function +creates a bank of 20 mel-spaced filters \, between 80Hz and 1800Hz +on a linear scale. All filters have the same gain; +#X text 23 165 Whilst DSP is running the input vector (magnitude spectrum) +is filtered by this filterbank \, and the total energy output from +each filter is appended to a new vector. This new vector (mel-filtered +spectrum) is then subjected to a fast cosine transfor. The output can +be visualised in the graph labelled \$0-mfcc.; +#X text 23 255 With LibXtract it is possible to change the number of +Mel filters as well as the range of frequencies over which they operate +\, and the filter scaling (equal area/equal gain). With this PD example +\, sensible defaults have been chosen to improve usability; +#N canvas 0 0 450 300 graph2 0; +#X array \$0-mfcc 20 float 5; +#A 0 -173.776 -23.5876 -0.366171 -3.06397 -0.349543 -1.22577 -0.205707 +-0.846186 -0.420453 -0.62197 -0.362943 -0.731029 -0.492134 -0.787504 +-0.453503 -0.578885 -0.402549 -0.51454 -0.395146 -0.515564; +#X coords 0 50 19 -100 200 100 1; +#X restore 212 -178 graph; +#X text 28 -188 PAF synthesiser; +#X obj 34 -71 hsl 128 15 1 500 0 0 \$0-bw empty formant_bandwidth -2 +-6 0 8 -225271 -1 -1 5300 1; diff --git a/examples/puredata/xtract/sonogram.pd b/examples/puredata/xtract/sonogram.pd new file mode 100644 index 0000000..78a7b42 --- /dev/null +++ b/examples/puredata/xtract/sonogram.pd @@ -0,0 +1 @@ +#N canvas 0 0 450 300 10; diff --git a/examples/puredata/xtract/xtract-help.pd b/examples/puredata/xtract/xtract-help.pd new file mode 100644 index 0000000..eff8381 --- /dev/null +++ b/examples/puredata/xtract/xtract-help.pd @@ -0,0 +1,69 @@ +#N canvas 685 60 450 725 10; +#X text 21 12 [xtract~]; +#X text 24 19 ________; +#X text 22 52 [xtract~] provides a wrapper for the feature extraction +library: LibXtract. Please refer to the documentation at libxtract.sourceforge.net +\, for a full explanation of the library and the functions it provides. +Only the operation of the PD external will be explained here along +with a few use case scenarios.; +#X text 20 148 [xtract~] must always be called with one argument \, +in the following form: [xtract~ <feature>] \, where <feature> is a +feature supported by the LibXtract library. A complete list of features +may be obtained by sending the external a |help( message:; +#X obj 27 262 xtract~; +#X msg 27 233 help; +#X text 26 298 Other than this help message \, the data sent to the +left inlet should always be a 'signal' (i.e. audio rate). This is the +data from a which a given feature will be extracted.; +#X text 27 405 Any additional arguments that need to be passed to the +feature extraction funtion must be provided as a list to the right +inlet \, e.g.; +#X obj 182 490 xtract~ mean; +#X floatatom 132 586 10 0 0 0 - - -; +#X floatatom 253 523 5 0 0 0 - - -; +#X msg 182 522 list \$1; +#X obj 132 556 xtract~ variance; +#X obj 181 466 phasor~ 0.1; +#X text 39 641 Below are some possible use cases (click to open):; +#X text 26 352 The outlet may be a scalar (control rate) \, or a vector +(audio rate) \, depending on the nature of the feature that is being +extracted.; +#X obj 44 674 cnv 15 82 22 empty empty empty 20 12 0 14 -99865 -66577 +0; +#X obj 47 675 bng 15 250 50 0 f0-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 64 675 bng 15 250 50 0 f0-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 79 675 bng 15 250 50 0 f0-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 96 675 bng 15 250 50 0 f0-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 42 672 cnv 15 80 20 f0-open empty f0 20 12 0 14 -195568 -66577 +0; +#N canvas 0 0 450 300 hidden 0; +#X msg 27 133 \; pd open f0.pd ./ \;; +#X obj 27 110 r f0-open; +#X obj 26 42 r mfcc-open; +#X msg 26 65 \; pd open mfcc.pd ./ \;; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X restore 379 736 pd hidden; +#X obj 136 675 cnv 15 82 22 empty empty empty 20 12 0 14 -99865 -66577 +0; +#X obj 140 678 bng 15 250 50 0 mfcc-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 155 678 bng 15 250 50 0 mfcc-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 170 678 bng 15 250 50 0 mfcc-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 185 678 bng 15 250 50 0 mfcc-open empty empty 0 -6 0 8 -262144 +-1 -1; +#X obj 134 673 cnv 15 80 20 f0-open empty MFCC 20 12 0 14 -195568 -66577 +0; +#X connect 5 0 4 0; +#X connect 8 0 10 0; +#X connect 8 0 11 0; +#X connect 11 0 12 1; +#X connect 12 0 9 0; +#X connect 13 0 8 0; +#X connect 13 0 12 0; diff --git a/src/scalar.c b/src/scalar.c index 8767621..d5d9837 100644 --- a/src/scalar.c +++ b/src/scalar.c @@ -26,104 +26,104 @@ #include <stdlib.h> int xtract_mean(float *data, int N, void *argv, float *result){ - + int n = N; while(n--) - *result += *data++; - + *result += *data++; + *result /= N; } int xtract_variance(float *data, int N, void *argv, float *result){ - + int n = N; while(n--) - *result += *data++ - *(float *)argv; - + *result += *data++ - *(float *)argv; + *result = SQ(*result) / (N - 1); } int xtract_standard_deviation(float *data, int N, void *argv, float *result){ - + *result = sqrt(*(float *)argv); - + } int xtract_average_deviation(float *data, int N, void *argv, float *result){ - + int n = N; while(n--) - *result += fabs(*data++ - *(float *)argv); - + *result += fabs(*data++ - *(float *)argv); + *result /= N; } int xtract_skewness(float *data, int N, void *argv, float *result){ - + int n = N; while(n--) - *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1]; - + *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1]; + *result = pow(*result, 3) / N; } int xtract_kurtosis(float *data, int N, void *argv, float *result){ - + int n = N; while(n--) - *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1]; - + *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1]; + *result = pow(*result, 4) / N - 3; - + } int xtract_centroid(float *data, int N, void *argv, float *result){ - + int n = N; - float *freqs, *amps, FA, A; + float *freqs, *amps, FA, A; + + freqs = data; + amps = data + (N >> 1); - freqs = data; - amps = data + (N >> 1); - while(n--){ - FA += freqs[n] * amps[n]; - A += amps[n]; - } - - *result = FA / A; + FA += freqs[n] * amps[n]; + A += amps[n]; + } + + *result = FA / A; } int xtract_irregularity_k(float *data, int N, void *argv, float *result){ - + int n, - M = M - 1; + M = M - 1; for(n = 1; n < M; n++) - *result += abs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3); + *result += abs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3); } int xtract_irregularity_j(float *data, int N, void *argv, float *result){ - + int n = N; float num, den; while(n--){ - num += data[n] - data[n+1]; - den += data[n] * data[n]; + num += data[n] - data[n+1]; + den += data[n] * data[n]; } - + *result = num / den; } @@ -135,52 +135,52 @@ int xtract_tristimulus_1(float *data, int N, void *argv, float *result){ float den; while(n--) - den += data[n]; + den += data[n]; *result = data[0] / den; } int xtract_tristimulus_2(float *data, int N, void *argv, float *result){ - + int n = N; float den; while(n--) - den += data[n]; + den += data[n]; *result = (data[1] + data[2] + data[3]) / den; - + } int xtract_tristimulus_3(float *data, int N, void *argv, float *result){ - + int n = N; float den, num; while(n--) - den += data[n]; + den += data[n]; num = den - data[0] + data[1] + data[2] + data[3]; - + *result = num / den; - + } int xtract_smoothness(float *data, int N, void *argv, float *result){ - + int n = N; if (data[0] <= 0) data[0] = 1; if (data[1] <= 0) data[1] = 1; - + for(n = 2; n < N; n++){ - if(data[n] <= 0) data[n] = 1; - *result += abs(20 * log(data[n-1]) - (20 * log(data[n-2]) + - 20 * log(data[n-1]) + 20 * log(data[n])) / 3); - } + if(data[n] <= 0) data[n] = 1; + *result += abs(20 * log(data[n-1]) - (20 * log(data[n-2]) + + 20 * log(data[n-1]) + 20 * log(data[n])) / 3); + } } int xtract_spread(float *data, int N, void *argv, float *result){ @@ -190,49 +190,49 @@ int xtract_spread(float *data, int N, void *argv, float *result){ float num, den, tmp; while(n--){ - tmp = n - *(float *)argv; - num += SQ(tmp) * data[n]; - den += data[n]; + tmp = n - *(float *)argv; + num += SQ(tmp) * data[n]; + den += data[n]; } *result = sqrt(num / den); - + } int xtract_zcr(float *data, int N, void *argv, float *result){ int n = N; - + for(n = 1; n < N; n++) - if(data[n] * data[n-1] < 0) (*result)++; - + if(data[n] * data[n-1] < 0) (*result)++; + *result /= N; - + } int xtract_rolloff(float *data, int N, void *argv, float *result){ int n = N; float pivot, temp; - + while(n--) pivot += data[n]; - + pivot *= *(float *)argv; - + for(n = 0; temp < pivot; temp += data[n++]); *result = n; - + } int xtract_loudness(float *data, int N, void *argv, float *result){ - + int n = BARK_BANDS; - + /*if(n != N) return BAD_VECTOR_SIZE; */ while(n--) - *result += pow(data[n], 0.23); + *result += pow(data[n], 0.23); } @@ -241,43 +241,43 @@ int xtract_flatness(float *data, int N, void *argv, float *result){ int n = N; float num, den; - + while(n--){ - if(data[n] !=0){ - num *= data[n]; - den += data[n]; - } + if(data[n] !=0){ + num *= data[n]; + den += data[n]; + } } num = pow(num, 1 / N); den /= N; - + *result = 10 * log10(num / den); - + } int xtract_tonality(float *data, int N, void *argv, float *result){ - + float sfmdb, sfm; - + sfm = *(float *)argv; sfmdb = (sfm > 0 ? (10 * log10(sfm)) / -60 : 0); - + *result = MIN(sfmdb, 1); - + } int xtract_crest(float *data, int N, void *argv, float *result){ - - NOT_IMPLEMENTED; - + + NOT_IMPLEMENTED; + } int xtract_noisiness(float *data, int N, void *argv, float *result){ - - NOT_IMPLEMENTED; - + + NOT_IMPLEMENTED; + } int xtract_rms_amplitude(float *data, int N, void *argv, float *result){ @@ -287,32 +287,32 @@ int xtract_rms_amplitude(float *data, int N, void *argv, float *result){ while(n--) *result += SQ(data[n]); *result = sqrt(*result / N); - + } int xtract_inharmonicity(float *data, int N, void *argv, float *result){ int n = N; float num, den, - *fund, *freq; + *fund, *freq; fund = *(float **)argv; freq = fund+1; - + while(n--){ - num += abs(freq[n] - n * *fund) * SQ(data[n]); - den += SQ(data[n]); + num += abs(freq[n] - n * *fund) * SQ(data[n]); + den += SQ(data[n]); } *result = (2 * num) / (*fund * den); - + } int xtract_power(float *data, int N, void *argv, float *result){ - NOT_IMPLEMENTED; - + NOT_IMPLEMENTED; + } int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){ @@ -322,161 +322,161 @@ int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){ float num, den; while(n--){ - j = n * 2; - k = j - 1; - num += data[k]; - den += data[j]; + j = n * 2; + k = j - 1; + num += data[k]; + den += data[j]; } *result = num / den; - + } int xtract_sharpness(float *data, int N, void *argv, float *result){ NOT_IMPLEMENTED; - + } int xtract_slope(float *data, int N, void *argv, float *result){ NOT_IMPLEMENTED; - + } int xtract_lowest_match(float *data, int N, void *argv, float *result){ - + float lowest_match = SR_LIMIT; int n = N; while(n--) { - if(data[n] > 0) - lowest_match = MIN(lowest_match, data[n]); + if(data[n] > 0) + lowest_match = MIN(lowest_match, data[n]); } *result = (lowest_match == SR_LIMIT ? 0 : lowest_match); - + } int xtract_hps(float *data, int N, void *argv, float *result){ int n = N, M, m, l, peak_index, position1_lwr; float *coeffs2, *coeffs3, *product, L, - largest1_lwr, peak, ratio1, sr; + largest1_lwr, peak, ratio1, sr; + + sr = *(float*)argv; - sr = *(float*)argv; - coeffs2 = (float *)malloc(N * sizeof(float)); coeffs3 = (float *)malloc(N * sizeof(float)); product = (float *)malloc(N * sizeof(float)); - + while(n--) coeffs2[n] = coeffs3[n] = 1; M = N >> 1; L = N / 3; while(M--){ - m = M << 1; - coeffs2[M] = (data[m] + data[m+1]) * 0.5f; + m = M << 1; + coeffs2[M] = (data[m] + data[m+1]) * 0.5f; - if(M < L){ - l = M * 3; - coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3; - } + if(M < L){ + l = M * 3; + coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3; + } } - + peak_index = peak = 0; - + for(n = 1; n < N; n++){ - product[n] = data[n] * coeffs2[n] * coeffs3[n]; - if(product[n] > peak){ - peak_index = n; - peak = product[n]; - } + product[n] = data[n] * coeffs2[n] * coeffs3[n]; + if(product[n] > peak){ + peak_index = n; + peak = product[n]; + } } largest1_lwr = position1_lwr = 0; for(n = 0; n < N; n++){ - if(data[n] > largest1_lwr && n != peak_index){ - largest1_lwr = data[n]; - position1_lwr = n; - } + if(data[n] > largest1_lwr && n != peak_index){ + largest1_lwr = data[n]; + position1_lwr = n; + } } ratio1 = data[position1_lwr] / data[peak_index]; if(position1_lwr > peak_index * 0.4 && position1_lwr < - peak_index * 0.6 && ratio1 > 0.1) - peak_index = position1_lwr; + peak_index * 0.6 && ratio1 > 0.1) + peak_index = position1_lwr; *result = sr / (float)peak_index; - + free(coeffs2); free(coeffs3); free(product); - + } int xtract_f0(float *data, int N, void *argv, float *result){ - int M, sr, tau, n; - float f0, err_tau_1, err_tau_x, array_max, threshold_peak, threshold_centre; - - sr = *(float *)argv; -/* threshold_peak = *((float *)argv+1); - threshold_centre = *((float *)argv+2); - printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/ - /* add temporary dynamic control over thresholds to test clipping effects */ - -/* FIX: tweak and make into macros */ - threshold_peak = .8; - threshold_centre = .3; - M = N >> 1; - err_tau_1 = 0; - array_max = 0; - - /* Find the array max */ - for(n = 0; n < N; n++){ - if (data[n] > array_max) - array_max = data[n]; - } - - threshold_peak *= array_max; - - /* peak clip */ - for(n = 0; n < N; n++){ - if(data[n] > threshold_peak) - data[n] = threshold_peak; - else if(data[n] < -threshold_peak) - data[n] = -threshold_peak; - } - - threshold_centre *= array_max; - - /* Centre clip */ - for(n = 0; n < N; n++){ - if (data[n] < threshold_centre) - data[n] = 0; - else - data[n] -= threshold_centre; - } - - /* Estimate fundamental freq */ - for (n = 1; n < M; n++) - err_tau_1 = err_tau_1 + fabs(data[n] - data[n+1]); - /* FIX: this doesn't pose too much load if it returns 'early', but if it can't find f0, load can be significant for larger block sizes M^2 iterations! */ - for (tau = 2; tau < M; tau++){ - err_tau_x = 0; - for (n = 1; n < M; n++){ - err_tau_x = err_tau_x + fabs(data[n] - data[n+tau]); + int M, sr, tau, n; + float f0, err_tau_1, err_tau_x, array_max, threshold_peak, threshold_centre; + + sr = *(float *)argv; + /* threshold_peak = *((float *)argv+1); + threshold_centre = *((float *)argv+2); + printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/ + /* add temporary dynamic control over thresholds to test clipping effects */ + + /* FIX: tweak and make into macros */ + threshold_peak = .8; + threshold_centre = .3; + M = N >> 1; + err_tau_1 = 0; + array_max = 0; + + /* Find the array max */ + for(n = 0; n < N; n++){ + if (data[n] > array_max) + array_max = data[n]; + } + + threshold_peak *= array_max; + + /* peak clip */ + for(n = 0; n < N; n++){ + if(data[n] > threshold_peak) + data[n] = threshold_peak; + else if(data[n] < -threshold_peak) + data[n] = -threshold_peak; + } + + threshold_centre *= array_max; + + /* Centre clip */ + for(n = 0; n < N; n++){ + if (data[n] < threshold_centre) + data[n] = 0; + else + data[n] -= threshold_centre; + } + + /* Estimate fundamental freq */ + for (n = 1; n < M; n++) + err_tau_1 = err_tau_1 + fabs(data[n] - data[n+1]); + /* FIX: this doesn't pose too much load if it returns 'early', but if it can't find f0, load can be significant for larger block sizes M^2 iterations! */ + for (tau = 2; tau < M; tau++){ + err_tau_x = 0; + for (n = 1; n < M; n++){ + err_tau_x = err_tau_x + fabs(data[n] - data[n+tau]); + } + if (err_tau_x < err_tau_1) { + f0 = sr / (tau + (err_tau_x / err_tau_1)); + *result = f0; + return SUCCESS; + } } - if (err_tau_x < err_tau_1) { - f0 = sr / (tau + (err_tau_x / err_tau_1)); - *result = f0; - return SUCCESS; - } - } - return NO_RESULT; + return NO_RESULT; } |