Результирующий коэффициент Фурье очень чувствителен к размеру окна?

Я пытаюсь сделать частотный анализатор, использующий оконный ряд Фурье во вспышке, но размер моего окна сильно влияет на величину коэффициентов.

Я использую формулу из учебника для расчета коэффициентов в каждом кадре:

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

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

Где deltax - временной интервал между выборками, а pcmFloatValue - значение временной области в *n*deltax*. В учебнике пределы интеграла составляют от 0 до 2PI, а затем интеграл делится на PI... но я подумал, что могу использовать его для любого интервала и устранить деление.

поэтому мой код для получения значения частоты здесь:

        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);

число - это частота в Гц, а frameba - это моносэмплирование звука с частотой 44100 Гц. Я вызываю эту функцию каждый кадр, который я беру, что соответствует этому коду:

        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);

Так что проблема в том, что величина двух коэффициентов становится чрезвычайно большой, когда я иногда меняю окно, а оно не линейное. Когда окно составляет 42 миллисекунды, я получаю такие значения:

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

Когда я установил его на 100 мс:

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

Когда я установил его на 500 мс:

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

Таким образом, это не продолжает увеличиваться в среднем размере. Я не уверен, что делаю что-то не так или нет, правильно ли я думаю об этом?

2 ответа

Решение

Коэффициенты Фурье чувствительны к любому размеру прямоугольного окна (длина N БПФ / ДПФ), который не является точным кратным периоду любого анализируемого повторяющегося сигнала.

Думаю об этом. Если вы отрежете только часть полной синусоидальной волны, и часть, от которой вы откололись, оставляет в основном положительную или в основном отрицательную долю, то это, вероятно, сместит ваш результат на некоторую взвешенную положительную или отрицательную величину. По мере того, как вы перемещаете свое окно или изменяете его длину, эта порция оставляет разные части одного периода вашего сигнала, что приводит к различным результатам.

Некоторые называют это спектральной утечкой, другие называют это сверткой с оконной функцией (явной или подразумеваемой). Вы можете компенсировать это, но обычно проще просто использовать достаточно длинную БПФ фиксированной длины с непрямоугольной оконной функцией (Hamming или Von Hann, et.al.).

Чтобы нормализовать результаты, вам нужно разделить значения на N. Затем вы должны получить более или менее согласованные значения, которые не зависят от N.

Другие вопросы по тегам