我获取输入数据块并通过 fftw 传递它们以获取一些光谱信息。一切似乎都在工作,但是我认为我遇到了一些混叠问题。
我一直在努力研究如何在我的数据块上实现一个 hann 窗口。谷歌让我失望了。我应该看的任何想法或链接?
double dataIn[2048] > /* windowing here? */ > FFT > double freqBins[2048]
更新
感谢 Oli 指出我实际上要解决的问题是频谱泄漏,而不是混叠...
我获取输入数据块并通过 fftw 传递它们以获取一些光谱信息。一切似乎都在工作,但是我认为我遇到了一些混叠问题。
我一直在努力研究如何在我的数据块上实现一个 hann 窗口。谷歌让我失望了。我应该看的任何想法或链接?
double dataIn[2048] > /* windowing here? */ > FFT > double freqBins[2048]
更新
感谢 Oli 指出我实际上要解决的问题是频谱泄漏,而不是混叠...
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];
}
hanning.m
可以在此处找到等效于 MATLAB 的完整函数:
/* 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);
}
不是你问题的答案,而是你问题的旁白。加窗有助于解决频谱泄漏问题,而不是混叠问题。
当波形的频率分量不是采样率的整数约数时,就会出现频谱泄漏效应。
如果你有混叠,那么你从根本上搞砸了。您要么需要提高采样率,要么在采样之前放入(更好的)抗混叠滤波器。
为什么不使用 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
维基百科是你的朋友:汉宁窗
当然,您的谷歌搜索想出了维基百科?!无论如何,只需创建一个函数,该函数返回一个长度为 N 且带有汉宁系数的数组,然后将该数组乘以您的dataIn[2048]
.
这很好,但大多数人可能希望在数千个充满数据的数组上执行此操作。您可以在程序初始化时填充一个仅包含常量乘数的数组(使用您提供给 FFT 的相同大小的数组),然后只需将实数数组中的每个点乘以乘数数组中的每个点。比每次都重新计算所有这些余弦更快/更便宜。