【问题标题】:Resultant of fourier coefficients is very sensitive to window size?傅立叶系数的结果对窗口大小非常敏感?
【发布时间】:2011-11-03 23:38:18
【问题描述】:

我正在尝试使用闪存中的窗口傅立叶级数制作频率分析仪,但我的窗口大小会极大地影响系数的大小。

我正在使用教科书中的公式来计算每一帧的系数:

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

number 是以 Hz 为单位的频率,frameba 是 44100 Hz 音频的单声道采样。我每抓到一个frameba就调用这个函数,对应这段代码:

        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,...

所以它的平均大小不会不断增加。我不确定我是否做错了什么,我是否正确地考虑了这一点?

【问题讨论】:

  • 你有什么理由使用傅里叶级数而不是像FFTW这样的FFT库吗?这将需要你做很多工作..

标签: actionscript-3 math signal-processing fft frequency-analysis


【解决方案1】:

傅立叶系数对任何矩形窗口大小(FFT/DFT 长度 N)敏感,它不是被分析的任何重复波形的周期的精确倍数。

考虑一下。如果你只剪掉一个完整的正弦波的一部分,而你碰巧剪掉的部分留下了一个大部分为正或大部分为负的波瓣,那么这可能会使你的结果偏离一些加权的正数或负数。当您移动窗口或更改窗口长度时,您的信号会在一个周期的不同部分被这种斩波留下,从而导致不同的结果。

有人称其为频谱泄漏,其他人称其为与窗函数的卷积(显式或隐式)。您可以对此进行补偿,但通常只使用足够长的固定长度 FFT 和非矩形窗函数(Hamming 或 Von Hann 等)会更容易。

【讨论】:

  • 这很有趣,因为我试图生成一个单音频率信号,并且在某些帧它给了我正确的常数系数,而在其他帧它给了我系数的周期性变化,这使得感觉我们没有以正确的倍数采样,希望我能正确地看到这一点。谢谢!
【解决方案2】:

为了标准化您的结果,您需要将这些值除以 N。然后您应该得到或多或少一致的值,这些值与 N 无关。

【讨论】:

  • 我看不出这会有什么不同,因为 N 对于所有值都是相同的。
  • @Prasad:可能是我不理解你的代码,但看起来你有一个固定的采样率(44.1 kHz)并且你改变了窗口持续时间,因此在您的 DFT,N,也将与您的窗口大小成比例变化?
  • 是的,DFT 会根据窗口大小而变化,因此它们本质上是归一化的。
  • 好的——首先添加一个窗口函数——这应该可以解决你的一些问题——我想你会发现如果你想比较不同大小的 DFT,你仍然需要一个 1/N 项。
猜你喜欢
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 2019-12-28
  • 2019-02-18
相关资源
最近更新 更多