Forums > MaxMSP

Getting out Frequency from a signal

October 22, 2009 | 8:49 pm

Hi there, i’m currently trying to figure out the workings on FFT and how i can use it to get the frequency of a signal (music/adc)

I’m well aware of the presence of objects like fiddler. However i’m here to learn something in the process. Could someone be so kind to point out a few friendly tips how to accomplish this, for the moment i don’t really see how i can use the fft/ifft components to generate any data that i can use to sort with.

I do know that i have to get out phase speed and the wavelength
do be able to get out the frequency in a wave, is this the way todo this?

Any help is appriciated, if you do have a patch doing something like this, that would also be highly appriciated.

Kind Regards Hiam


October 22, 2009 | 8:59 pm
Hiam wrote on Thu, 22 October 2009 22:49
Hi there, I’m currently trying to figure out the workings on FFT and how i can use it to get the frequency of a signal (music/adc)

I’m well aware of the presence of objects like fiddler. However I’m here to learn something in the process. Could someone be so kind to point out a few friendly tips how to accomplish this, for the moment i don’t really see how i can use the fft/ifft components to generate any data that i can use to sort with.

Any help is appreciated, if you do have a patch doing something like this, that would also be highly appreciated.

Kind Regards Hiam

Hi,

Since your goal is about learning, I suggest to read these tutorials by Stephan M. Bernsee.
And especially, the tutorial called "The DFT "à Pied": Mastering The Fourier Transform in One Day".

HTH,
Philippe


October 26, 2009 | 2:42 am
Hiam wrote on Thu, 22 October 2009 13:49
Hi there, i’m currently trying to figure out the workings on FFT and how i can use it to get the frequency of a signal (music/adc)

Once you’ve gotten into the frequency domain (with fft) then you look for peaks in the spectrum. In a simple case, you could find one big peak at the fundamental frequency. Usually, there are a bunch of peaks; hopefully they are partials in an harmonic spectrum. I think fiddle compares the analyzed peaks to and idea harmonic spectrum and tries to find the best fit. There are academic papers out there, and the source code is available. This is a good starting point:

D. Gerhard. Pitch Extraction and Fundamental Frequency: History and Current Techniques, technical report, Dept. of Computer Science, University of Regina, 2003.

mz


October 27, 2009 | 10:18 pm

I’ve read through the guide you posted PhiDjee, thanks a bunch for that!

Now i’ve switched over to practics here in Max.

using pfft, fftin, dspstate

I’m successfully getting out near correct Frequency out of a cycle.
However, that faultyness can be very very bad if you try to for instance harmonise for instance
a instrument of some sort.

Im currently using the formula: Centrer Frequency(27) * Bin index which has the highest value

So if the bin index 33 has the highest value

it will be for example 27 * 33 = 891hZ
I get the center frequency from Samplerate / FFT Size(2048)

The faultyness varies all from 30 to 0, and the higher FFT Size, obviously the more accurate
result. However that won’t really work good, since if you use a higher FFT Size you can’t handle
higher frequency well.

I also made some extended calculations based on Hop-Size and Pi to be able to make even sophisticated math equations.

Is there any way to take out the values more accuratly?


October 27, 2009 | 11:23 pm

You might try looking at the bins around the highest and taking a weighted average.

ie, if bin 100 is the highest, then ((freq_of_bin99*amp_of_bin99)+(freq_of_bin100*amp_of_bin100)+(freq_of_bin101*amp_of_bin101))/(amp_of_bin99+amp_of_bin100+amp_of_bin101)

Or, go looking for the second partial and use it to refine the fundamental.

mz


October 28, 2009 | 10:31 am

I tried the suggestion above, however the value outputted is actually worse than the Bin index * Center frequency.
And i can’t really use it to round of the bin index * center frequency either, cause it’s kind of random.

For instance here is one example: I have a cycle generating the frequency: 556Hz

My patch figures bin index 52 has the highest peak.
My center Frequency is 10.76 (because im using 4096 as FFT Size)

52 * 10.76 = 559,52 Which is almost the correct answer.

Using the suggested weighted average formula i get:

Bin Index
51 | 52 | 53
———————————–
AMP:68.19 | 90.61 | 6.880
FRQ:545 | 556 | 566.766
———————————-
Summed Total AMP & FRQ:
51: 37163,55
52: 50379,16
53: 3899,35008

Sum: 91442,06008

Using the weighted avarage formula:
91442,06008 / 165,68 = 551,9197….

As the bin * center frequency = 559,52Hz
and the weighted avarage = 551.91Hz

I get a diffrence of 8 and in this particial case i could divide 8 by 2 to get a correct frequency, however that does not apply all the time sadfully. And at diffrent frequencies the bin * center freq is lower than the weighted avarage which also does make it hard to make a good estimate.

I did discover something else allthough.

Let’s say I have the chosen input frequency 556Hz.

My Patch notices a peak at bin index 52.

Then i take out the Amplitude,Frequency value from 51,52,53

And i find that that value one of those bin indexes has the right value each time, and i do mean, THE correct value.

However i can’t really seem to find a pattern which i can use to
see which of them is the right each diffrent input frequency.

Thanks for all your help, much appriciated!


October 28, 2009 | 6:57 pm

hi
to get the correct frequency from a detected peak in the freq spectrum, using frame to frame phase differences is the most precise method in my experience.
you calculate the so called ‘true frequency’ by monitoring the phase advance of the selected bin from frame to frame.
if the input freq falls on the center of a bin, the phase difference is 0. if it is not quite on the bin freq, phase differences start to grow (in either direction), growing faster the further the input freq deviates from the bin freq. from this you can calculate ‘how far’ the actual frequency is from the bin freq.
see the attachment.
hth,
volker.


October 29, 2009 | 3:34 pm

Thanks a bunch Volker for pointing that out, i’d never come up with that alone. I now have working example utlizing your technique
and it works like a charm!

I’d also like to give thanks to you other guys for giving me hints and idea’s how to solve this question!

Kind Regards

Hiam


February 4, 2010 | 11:50 pm

hello maxers,

volker, can i ask you to resend your attachment, please?

regards,
p.


February 7, 2010 | 9:49 am

the forum, how i love it – can’t handle attachments anymore. things are getting better and better, he?

think it was this one. take care, these are two patches.
first copy and safe the pfft patch, then the main patch.
hth,
volker.

/* save as "true_pfft.mxb" */

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 133 278 42 196617 *~;
#P newex 133 252 61 196617 phasewrap~;
#P newex 199 190 27 196617 *~;
#N vpatcher 10 59 376 423;
#P window setfont "Sans Serif" 9.;
#P newex 126 228 31 196617 !/ 1.;
#P comment 177 205 81 196617 phase;
#P flonum 99 204 68 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 99 181 27 196617 / 1.;
#P comment 125 150 40 196617 2π;
#P button 66 101 15 0;
#P flonum 66 148 49 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 66 122 86 196617 expr 2*acos(-1);
#P number 116 76 46 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 116 50 27 196617 / 1;
#P comment 164 78 54 196617 overlap;
#P inlet 133 30 15 0;
#P inlet 116 30 15 0;
#P outlet 99 256 15 0;
#P outlet 126 256 15 0;
#P connect 6 0 9 0;
#P connect 9 0 7 0;
#P connect 7 0 8 0;
#P connect 8 0 11 0;
#P connect 11 0 12 0;
#P connect 12 0 1 0;
#P connect 2 0 5 0;
#P connect 5 0 6 0;
#P connect 6 0 11 1;
#P connect 12 0 14 0;
#P connect 14 0 0 0;
#P connect 3 0 5 1;
#P pop;
#P newobj 317 131 88 196617 p pre_calc_phase;
#P comment 466 89 70 196617 Hop size;
#P comment 263 88 65 196617 framesize;
#P number 417 87 46 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 317 87 46 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 317 63 162 196617 fftinfo~;
#P number 367 87 44 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P hidden newex 30 205 80 196617 buffer~ mag 25;
#P hidden newex 34 168 57 196617 poke~ mag;
#P comment 191 341 100 196617 * delta bin freq;
#P newex 172 444 81 196617 buffer~ true 25;
#P newex 204 389 126 196617 poke~ true;
#P comment 648 235 100 196617 delta-bin-freq;
#P window linecount 2;
#P comment 532 142 56 196617 sampling rate;
#P window linecount 1;
#P newex 435 132 27 196617 t b i;
#P flonum 591 231 51 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 591 190 46 196617 / 1024.;
#P newex 540 83 48 196617 loadbang;
#P flonum 591 144 54 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 540 105 61 196617 adstatus sr;
#P newex 133 339 51 196617 *~ 43;
#P newex 133 305 110 196617 +~;
#P newex 133 224 76 196617 -~;
#P newex 133 191 61 196617 phasewrap~;
#P newex 133 159 62 196617 framedelta~;
#P newex 75 123 68 196617 cartopol~;
#P newex 75 87 135 196617 fftin~ 1;
#P comment 181 292 100 196617 + bin index;
#P connect 13 1 11 1;
#P connect 11 0 12 0;
#P connect 13 0 11 0;
#P connect 9 0 11 0;
#P connect 8 1 9 0;
#P connect 10 0 8 0;
#P connect 23 0 27 0;
#P connect 23 0 13 0;
#P connect 22 2 24 0;
#P connect 24 0 27 1;
#P connect 22 1 21 0;
#P connect 22 0 23 0;
#P hidden connect 1 2 19 1;
#P connect 1 2 28 0;
#P fasten 1 2 6 1 204 135 238 135;
#P fasten 1 2 16 1 204 121 267 121;
#P connect 27 0 28 1;
#P fasten 7 0 16 0 138 372 209 372;
#P connect 28 0 5 1;
#P fasten 12 0 7 1 596 331 179 331;
#P connect 27 1 30 1;
#P connect 6 0 7 0;
#P connect 30 0 6 0;
#P connect 29 0 30 0;
#P connect 5 0 29 0;
#P connect 4 0 5 0;
#P connect 3 0 4 0;
#P connect 2 1 3 0;
#P fasten 1 1 2 1 142 113 138 113;
#P connect 1 0 2 0;
#P hidden connect 2 0 19 0;
#P window clipboard copycount 31;

/* and the main patch */

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P comment 312 384 37 196617 Hz;
#P comment 328 384 88 196617 detected freq;
#P comment 145 385 72 196617 input freq;
#P hidden newex 157 501 60 196617 loadmess 2;
#P hidden newex 433 504 48 196617 loadbang;
#P flonum 157 522 48 9 0. 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 435 610 35 9 0. 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 430 536 45 196617 set mag;
#P message 435 629 55 196617 vzoom $1;
#P user waveform~ 68 536 363 137 3 9;
#W mode move;
#W mouseoutput none;
#W clipdraw 1;
#W unit samples;
#W grid 22.675737;
#W ticks 0;
#W labels 1;
#W vlabels 0;
#W vticks 0;
#W vzoom 97.;
#W voffset 1.;
#W bpm 120. 4.;
#W frgb 33 0 0;
#W brgb 60 178 173;
#W rgb2 0 95 255;
#W rgb3 0 0 0;
#W rgb4 0 0 0;
#W rgb5 146 179 217;
#W rgb6 100 100 100;
#W rgb7 100 100 100;
#P newex 241 330 29 196617 sig~;
#P newex 241 352 62 196617 index~ true;
#P comment 276 90 39 196617 bin x+2;
#P comment 163 90 39 196617 bin x+1;
#P number 104 179 35 9 0 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 69 178 27 196617 + 4.;
#P user panel 234 103 60 14;
#X brgb 236 131 110;
#X frgb 0 0 0;
#X border 0;
#X rounded 0;
#X shadow 0;
#X done;
#P user panel 181 103 54 14;
#X brgb 238 231 124;
#X frgb 0 0 0;
#X border 0;
#X rounded 0;
#X shadow 0;
#X done;
#P flonum 69 158 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 69 137 39 196617 * 0.02;
#P user hslider 69 119 13 211 101 1 0 0;
#P user panel 70 103 58 14;
#X brgb 238 231 124;
#X frgb 0 0 0;
#X border 0;
#X rounded 0;
#X shadow 0;
#X done;
#P comment 57 90 39 196617 bin x;
#P user panel 125 103 56 14;
#X brgb 236 131 110;
#X frgb 0 0 0;
#X border 0;
#X rounded 0;
#X shadow 0;
#X done;
#P comment 143 180 100 196617 starting bin index;
#P window setfont "Sans Serif" 14.;
#P comment 66 61 310 196622 sweep between consecutive bins;
#P user panel 45 38 287 181;
#X brgb 223 223 223;
#X frgb 0 0 0;
#X border 1;
#X rounded 0;
#X shadow 0;
#X done;
#P window setfont "Sans Serif" 9.;
#P user number~ 241 382 312 397 9 3 3 2 0. 0. 0 0. 250 0. 0 0 0 255 227 23 222 222 222 0 0 0;
#P flonum 69 383 58 9 0 0 0 3 0 0 0 255 227 23 222 222 222 0 0 0;
#P newex 241 286 34 196617 + 0.5;
#P flonum 495 253 51 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 69 285 29 196617 * 1.;
#P newex 495 229 40 196617 / 512.;
#P newex 444 142 48 196617 loadbang;
#P flonum 495 203 54 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 444 164 61 196617 adstatus sr;
#P flonum 69 244 48 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P user ezdac~ 496 374 540 407 0;
#P number 241 308 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 69 408 40 196617 cycle~;
#P newex 69 442 108 196617 pfft~ true_pfft 512 2;
#P comment 509 274 100 196617 delta-bin-freq;
#P comment 121 247 68 196617 bin index;
#P comment 277 288 57 196617 round;
#P comment 127 385 37 196617 Hz;
#P comment 539 230 100 196617 / fft-szie;
#P connect 13 0 15 0;
#P connect 11 0 13 0;
#P connect 10 1 11 0;
#P connect 12 0 10 0;
#P hidden connect 39 0 37 0;
#P hidden connect 41 0 38 0;
#P connect 34 0 18 0;
#P connect 35 0 34 0;
#P connect 7 0 35 0;
#P connect 16 0 7 0;
#P connect 9 0 14 0;
#P fasten 9 0 16 0 74 270 246 270;
#P hidden connect 42 0 40 0;
#P hidden connect 40 0 36 1;
#P fasten 15 0 14 1 500 276 93 276;
#P connect 31 0 30 1;
#P connect 6 0 5 0;
#P connect 17 0 6 0;
#P connect 14 0 17 0;
#P connect 30 0 9 0;
#P connect 27 0 30 0;
#P connect 26 0 27 0;
#P connect 25 0 26 0;
#P hidden connect 37 0 36 0;
#P hidden connect 38 0 36 0;
#P window clipboard copycount 46;


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