实施Hann Window

时间:2010-08-24 09:59:43

标签: c signal-processing fft fftw

我获取输入数据块并通过fftw传递它们以获取一些光谱信息。一切似乎都在起作用,但我认为我遇到了一些别名问题。

我一直在努力研究如何在我的数据块上实现一个hann窗口。谷歌让我失望的例子。我应该关注的任何想法或链接?

double dataIn[2048] > /* windowing here? */ > FFT > double freqBins[2048]

更新

感谢Oli指出我实际上要解决的问题是频谱泄漏,而不是别名......

6 个答案:

答案 0 :(得分:16)

http://en.wikipedia.org/wiki/Hann_function。该实现非常直接地从定义开始。只需使用w(n)函数作为乘数,循环遍历所有样本(随时更改n),就是这样。

for (int i = 0; i < 2048; i++) {
    double multiplier = 0.5 * (1 - cos(2*PI*i/2047));
    dataOut[i] = multiplier * dataIn[i];
}

答案 1 :(得分:4)

为什么不使用Math.NET的Hann窗口实现?

double[] hannDoubles = MathNet.Numerics.Window.HannPeriodic(dataIn.Length);
for (int i = 0; i < dataIn.Length; i++)
{
    dataOut[i] = hannDoubles[i] * dataIn[i];
}

位于:https://numerics.mathdotnet.com/api/MathNet.Numerics/Window.htm

答案 2 :(得分:2)

维基百科是你的朋友:Hanning window

你的谷歌搜索确实提出了维基百科?!无论如何,只需创建一个函数,该函数返回一个长度为N且带有汉宁系数的数组,并将此数组乘以dataIn[2048]

答案 3 :(得分:2)

不是你问题的答案,而是你的问题。窗口化有助于解决频谱泄漏问题,而不是别名问题。

当波形的频率成分不是采样率的整数倍时,会发生频谱泄漏效应。

如果你有别名,那么你从根本上搞砸了。在采样之前,您需要提高采样率,或者放入(更好的)抗锯齿滤波器。

答案 4 :(得分:2)

可以找到相当于MATLAB hanning.m的完整函数here

/*  function w = hanning(varargin)
%   HANNING   Hanning window.
%   HANNING(N) returns the N-point symmetric Hanning window in a column
%   vector.  Note that the first and last zero-weighted window samples
%   are not included.
%
%   HANNING(N,'symmetric') returns the same result as HANNING(N).
%
%   HANNING(N,'periodic') returns the N-point periodic Hanning window,
%   and includes the first zero-weighted window sample.
%
%   NOTE: Use the HANN function to get a Hanning window which has the
%          first and last zero-weighted samples.ep
    itype = 1 --> periodic
    itype = 0 --> symmetric
    default itype=0 (symmetric)

    Copyright 1988-2004 The MathWorks, Inc.
%   $Revision: 1.11.4.3 $  $Date: 2007/12/14 15:05:04 $
*/

float *hanning(int N, short itype)
{
    int half, i, idx, n;
    float *w;

    w = (float*) calloc(N, sizeof(float));
    memset(w, 0, N*sizeof(float));

    if(itype==1)    //periodic function
        n = N-1;
    else
        n = N;

    if(n%2==0)
    {
        half = n/2;
        for(i=0; i<half; i++) //CALC_HANNING   Calculates Hanning window samples.
            w[i] = 0.5 * (1 - cos(2*PI*(i+1) / (n+1)));

        idx = half-1;
        for(i=half; i<n; i++) {
            w[i] = w[idx];
            idx--;
        }
    }
    else
    {
        half = (n+1)/2;
        for(i=0; i<half; i++) //CALC_HANNING   Calculates Hanning window samples.
            w[i] = 0.5 * (1 - cos(2*PI*(i+1) / (n+1)));

        idx = half-2;
        for(i=half; i<n; i++) {
            w[i] = w[idx];
            idx--;
        }
    }

    if(itype==1)    //periodic function
    {
        for(i=N-1; i>=1; i--)
            w[i] = w[i-1];
        w[0] = 0.0;
    }
    return(w);
}

答案 5 :(得分:1)

这很好但是大多数人可能想要在数千个充满数据的阵列上执行此操作。您可以在程序初始化时填充一组常数乘数(使用与FFT相同的大小数组),然后将实数组中的每个点乘以乘法器数组中的每个点。比每次重复使用所有这些余弦更快/更便宜。