Forums > MaxMSP

fft tuning


February 23, 2008 | 8:48 pm

hi guys -

trying build a basic fft analyzer for general spectral information, and also as a base for a polyphonic tuner. (have already tried the fiddle~ based externals (fiddle~, analyzer~, pitch~) but have had a number of issues with these). i seem to be getting close using pfft~ but i’m running into a couple problems coordinating the index with the amp/phase calculation.

using this equation inside pfft~ that i pulled from a past post on the forum:

frequency = phasediff*(samplerate/(hopsize*(2pi))) + fftindex*fftfundamental

but for some reason, using a test cycle~ tone, and peek~ to scroll through the calculated frequencies written to the buffer~, i’m two main issues i think:

1) the amplitude and frequency indexes get off from each other, sometimes the peak amplitude will be 1-2 indexes above or below the test tone, sometimes it will be perfect.

this seems to vary with the pitch of the sine wave as well as with the fft size. i’m guessing it has something to do with the way i’m using the buffer~, or maybe could it be some kind of timing issue?

2) more generally, once aligned, the freq/amp readings seems to spread into the neighboring bins – which i’ve also read can happen – but i’d like to figure out how to focus it more if possible.

i’m pretty new to fft – so maybe i’m doing something else wrong?
any advice would be great.

cheers,

rama

here’s the patch (two parts with the pfft~):

save this first one as: pfft_bincalc2
//////////////////////////////////

max v2;
#N vpatcher 315 44 1011 799;
#P origin -33 0;
#P window setfont "Sans Serif" 9.;
#P flonum 528 254 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 494 253 29 196617 t f b;
#P newex 425 284 27 196617 f;
#P flonum 425 337 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P comment 68 63 546 196617 using an equation I found on the forum: frequency = phasediff*(samplerate/(hopsize*(2pi))) + fftindex*fftfundamental;
#P newex 425 311 79 196617 / 44100.;
#P newex 270 396 27 196617 *~;
#P newex 270 437 64 196617 +~;
#P newex 494 228 65 196617 * 6.283185;
#P toggle 79 485 15 0;
#P newex 79 441 56 196617 r startrec;
#P newex 111 485 93 196617 record~ pfftbuff 2;
#P newex 135 527 51 196617 fftout~ 1;
#P flonum 341 249 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 324 278 27 196617 *~;
#P flonum 494 203 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 341 222 46 196617 / 1024.;
#P flonum 378 198 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 378 168 53 196617 fftinfo~;
#P newex 341 142 29 196617 t f b;
#P flonum 341 118 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 327 92 54 196617 dspstate~;
#P message 491 94 33 196617 clear;
#P newex 491 118 124 196617 buffer~ pfftbuff 50000 2;
#P newex 182 174 64 196617 phasewrap~;
#P newex 182 152 65 196617 framedelta~;
#P newex 138 125 53 196617 cartopol~;
#P newex 138 93 45 196617 fftin~ 1;
#P connect 17 0 18 0;
#P fasten 20 0 16 0 275 470 116 470;
#P connect 18 0 16 0;
#P connect 0 0 1 0;
#P connect 1 0 16 1;
#P connect 0 1 1 1;
#P connect 1 1 2 0;
#P connect 2 0 3 0;
#P connect 3 0 21 0;
#P connect 21 0 20 0;
#P fasten 24 0 21 1 430 380 292 380;
#P fasten 0 2 13 0 177 115 329 115;
#P connect 13 0 20 1;
#P connect 6 1 7 0;
#P connect 7 0 8 0;
#P connect 8 0 11 0;
#P connect 11 0 14 0;
#P connect 14 0 13 1;
#P connect 10 0 11 1;
#P connect 8 1 9 0;
#P connect 9 0 10 0;
#P fasten 26 1 25 0 518 277 430 277;
#P connect 25 0 22 0;
#P connect 22 0 24 0;
#P fasten 7 0 25 1 346 138 447 138;
#P connect 5 0 4 0;
#P connect 9 2 12 0;
#P connect 12 0 19 0;
#P connect 19 0 26 0;
#P connect 26 0 22 1;
#P connect 19 0 27 0;
#P pop;

//////////////////////////
and here’s the main patch

max v2;
#N vpatcher 382 169 957 642;
#P window setfont "Sans Serif" 9.;
#P flonum 165 68 54 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P comment 188 313 48 196617 bin amp.;
#P comment 92 312 48 196617 bin freq.;
#P comment 123 225 131 196617 scroll through buffer index;
#P user ezdac~ 100 115 144 148 0;
#P flonum 175 291 71 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 84 290 65 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 84 223 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 175 262 83 196617 peek~ pfftbuff 2;
#P newex 84 262 83 196617 peek~ pfftbuff 1;
#P toggle 239 79 15 0;
#P newex 239 100 56 196617 s startrec;
#P newex 165 100 61 196617 cycle~ 880;
#P newex 165 130 127 196617 pfft~ fft_bincalc2 2048 4;
#P comment 261 80 207 196617 < -- record some test tone to buffer in pfft~;
#P connect 7 0 5 0;
#P connect 5 0 8 0;
#P connect 14 0 2 0;
#P connect 2 0 1 0;
#P connect 7 0 6 0;
#P connect 6 0 9 0;
#P connect 4 0 3 0;
#P pop;

February 24, 2008 | 6:44 pm

sorry about the broken sentences above – rereading i think i edited it down too much : )

i’m guessing now both of those problems above are connected – does anyone know how to "cook" the bin reading? (ala fiddle~ etc.) maybe this is the way to go?

will try going through the fiddle docs some more. i hesitate because using fiddle~ and pitch~ i get incorrect 2nd and 3rd pitches. and analyzer~ crashes my system, seems like i’m the only one though. (mbp os 10.4 and now also on 10.5).

sorting the data using coll for this seems not to be ideal. i really have no clue as to programming c or java externals – but maybe i have to in order to deal with the data in the buffer…hmm.

well – i’ll keep at it!

let me know if anyone has any ideas

cheers,

rama

here’s a new version of the patch.

///////// save as: fft_bincalc4

max v2;
#N vpatcher 296 44 1094 753;
#P origin -33 0;
#P window setfont "Sans Serif" 9.;
#P newex 662 546 83 196617 poke~ pfftbuff 2;
#P newex 561 546 83 196617 poke~ pfftbuff 1;
#P flonum 535 309 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 501 308 29 196617 t b f;
#P newex 451 338 27 196617 f;
#P flonum 451 391 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P comment 105 75 546 196617 using an equation I found on the forum: frequency = phasediff*(samplerate/(hopsize*(2pi))) + fftindex*fftfundamental;
#P newex 451 365 79 196617 / 44100.;
#P newex 296 450 27 196617 *~;
#P newex 296 491 64 196617 +~;
#P newex 501 283 65 196617 * 6.283185;
#P newex 161 581 51 196617 fftout~ 1;
#P flonum 367 303 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 350 332 27 196617 *~;
#P flonum 501 258 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 367 276 46 196617 / 1024.;
#P flonum 403 251 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 403 222 53 196617 fftinfo~;
#P newex 367 196 29 196617 t f b;
#P flonum 367 172 61 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 353 146 54 196617 dspstate~;
#P message 562 116 33 196617 clear;
#P newex 562 140 124 196617 buffer~ pfftbuff 50000 2;
#P newex 207 228 64 196617 phasewrap~;
#P newex 207 206 65 196617 framedelta~;
#P newex 164 179 53 196617 cartopol~;
#P newex 164 147 97 196617 fftin~ 1;
#P connect 0 0 1 0;
#P connect 0 1 1 1;
#P connect 1 1 2 0;
#P connect 2 0 3 0;
#P connect 3 0 18 0;
#P connect 18 0 17 0;
#P fasten 21 0 18 1 456 434 318 434;
#P fasten 0 2 13 0 255 167 355 167;
#P lcolor 6;
#P connect 13 0 17 1;
#P connect 6 1 7 0;
#P connect 7 0 8 0;
#P connect 8 0 11 0;
#P connect 11 0 14 0;
#P connect 14 0 13 1;
#P connect 8 1 9 0;
#P connect 9 0 10 0;
#P connect 10 0 11 1;
#P fasten 23 0 22 0 506 331 456 331;
#P connect 22 0 19 0;
#P connect 19 0 21 0;
#P fasten 7 0 22 1 372 192 473 192;
#P connect 9 2 12 0;
#P connect 12 0 16 0;
#P connect 16 0 23 0;
#P connect 23 1 19 1;
#P connect 16 0 24 0;
#P fasten 17 0 25 0 301 523 566 523;
#P lcolor 7;
#P connect 5 0 4 0;
#P fasten 0 2 25 1 255 167 602 167;
#P lcolor 6;
#P fasten 1 0 26 0 169 533 667 533;
#P lcolor 12;
#P fasten 0 2 26 1 255 167 703 167;
#P lcolor 6;
#P pop;

///////// main patch:

max v2;
#N vpatcher 115 44 1101 791;
#P window setfont "Sans Serif" 9.;
#P message 55 424 33 196617 clear;
#P message 178 134 14 196617 2;
#P message 161 134 14 196617 1;
#P newex 206 163 71 196617 selector~ 2 1;
#P newex 94 368 27 196617 t b l;
#N coll ;
#P newobj 111 423 53 196617 coll;
#P message 51 397 47 196617 sort 1 2;
#P newex 94 344 50 196617 pack i f f;
#P flonum 384 108 54 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 345 130 35 196617 *~ 1.;
#P newex 345 108 31 196617 adc~;
#P flonum 272 100 54 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 272 132 61 196617 cycle~ 440;
#P button 118 280 15 0;
#P newex 231 410 67 196617 zl group 512;
#P toggle 139 230 15 0;
#P newex 139 255 52 196617 metro 10;
#P user multiSlider 231 437 619 21 0. 256. 256 2681 15 0 0 2 0 0 0;
#M frgb 0 0 0;
#M brgb 255 255 255;
#M rgb2 127 127 127;
#M rgb3 0 0 0;
#M rgb4 37 52 91;
#M rgb5 74 105 182;
#M rgb6 112 158 18;
#M rgb7 149 211 110;
#M rgb8 187 9 201;
#M rgb9 224 62 37;
#M rgb10 7 114 128;
#P newex 139 280 44 196617 uzi 512;
#P flonum 206 100 54 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P comment 307 366 48 196617 bin amp.;
#P comment 208 365 48 196617 bin freq.;
#P comment 239 278 131 196617 scroll through buffer index;
#P user ezdac~ 137 177 181 210 0;
#P flonum 294 344 71 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 200 343 65 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 200 276 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 294 315 83 196617 peek~ pfftbuff 2;
#P newex 200 315 83 196617 peek~ pfftbuff 1;
#P newex 206 132 61 196617 cycle~ 880;
#P newex 206 193 127 196617 pfft~ fft_bincalc4 1024 4;
#P connect 12 2 23 0;
#P connect 23 0 26 0;
#P connect 30 0 25 0;
#P connect 24 0 25 0;
#P connect 26 1 25 0;
#P connect 2 0 23 1;
#P connect 3 0 23 2;
#P connect 15 0 14 0;
#P connect 14 0 12 0;
#P connect 17 0 12 0;
#P connect 12 2 2 0;
#P connect 4 0 2 0;
#P connect 2 0 5 0;
#P connect 11 0 1 0;
#P connect 28 0 27 0;
#P connect 29 0 27 0;
#P connect 27 0 0 0;
#P connect 3 0 16 0;
#P connect 16 0 13 0;
#P connect 18 0 27 1;
#P connect 1 0 27 1;
#P connect 21 0 27 2;
#P connect 19 0 18 0;
#P connect 12 2 3 0;
#P connect 4 0 3 0;
#P connect 3 0 6 0;
#P connect 20 0 21 0;
#P connect 22 0 21 1;
#P pop;

Viewing 2 posts - 1 through 2 (of 2 total)

Forums > MaxMSP