Question

I'm trying to make a frequency analyzer using a windowed fourier series in flash, but the size of my window greatly affects magnitude of the coefficients.

I'm using a formula from a textbook to calculate the coefficients at every frame:

     N-1
Ak = SUM { cos(freq*n*deltax) * pcmFloatValue}
     n=0

     N-1
Bk = SUM { sin(freq*n*deltax) * pcmFloatValue}
     n=0

Where deltax is the time interval in between samples, and pcmFloatValue is the time domain value at *n*deltax*. In the textbook, the integral limits are 0 to 2PI, and the integral is then divided by PI...but I thought I could use it for any interval and eliminate the division.

so my code to get the magnitude of the frequency is here:

        var deltax:Number = 1 / 44100;
        var sumCos:Number = 0;
        var sumSin:Number = 0;
        var c:Number = 0;

        while (frameba.bytesAvailable > 32) {
            //trace("getMag", frameba.bytesAvailable);
            c++;
            var freq:Number = (number / (2 * Math.PI));
            var sample:Number = frameba.readFloat();

            sumCos += sample * deltax;
            sumCos *= Math.cos(freq * c * deltax)

            sumSin += sample * deltax;
            sumSin *=Math.sin(freq * c * deltax)
        }


        return Math.sqrt(sumCos * sumCos + sumSin * sumSin);

number is frequency in Hz, and frameba is a mono sampling of the audio at 44100 hz. I call this function every frameba I grab, which corresponds to this code:

        var endCounter:Number = int(s.length / number); //get number of frames
        frameData = new Array();

        for ( var i:Number = 0; i < endCounter-1; i++) {
            var frameba:ByteArray = new ByteArray();

            var frameSize:Number = int((number / 1000) * 44100) * 4;
            monoba.readBytes(frameba, 0, frameSize);// grab new frame

            frameba.position = 0;
            var mag:Number=getMag(512, frameba); //this function is the code snippet i posted before this one
            frameData.push(mag*100000);

So the problem is that the magnitude of the two coefficients gets extremely large when I change the window sometimes, and it's not linear. When the window is 42 milliseconds I get values like this:

    ...,0.46867691675958506,0.40119205703768124,1.076056196209733,0.4138200126843882,1.288280385823108,1.1605685308155427,...

When I set it to 100ms:

...,3.487381020768127,7.610466058045129,45.780152579896324,77.46963149803167,35.531672823487014,0.6057853252694128,...

When I set it to 500ms:

   ...,0.7132093539701988,0.561741462535126,0.5303097469754452,0.6267107444675019,0.5205164960161707,0.4828724689303949,...

So it doesn't keep increasing in average size. I'm not sure if I'm doing something wrong or not, am I thinking about this correctly?

Was it helpful?

Solution

Fourier coefficients are sensitive to any rectangular window size (FFT/DFT length N) that is not an exact multiple of the period of any repetitive waveform being analyzed.

Think about it. If you chop off just part of a full sine wave, and the part you happen to chop off leaves a mostly positive or mostly negative lobe, then that will probably bias your result by some weighted positive or negative amount. As you move your window or change it length, different portions of one period your signal will be left over by this chopping, causing different results.

Some call it spectral leakage, others call it convolution with the window function (explicit or implied). You can compensate for this, but it's usually easier to just use a long enough fixed length FFT with a non-rectangular window function (Hamming or Von Hann, et.al.).

OTHER TIPS

In order to normalize your results you need to divide the values by N. You should then get more or less consistent values which are independent of N.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top