我正在尝试创建一个计算图形均衡器FIR滤波器系数的应用程序。我正在使用Matlab进行一些原型设计,但是我遇到了一些问题。
我已经开始使用以下Matlab代码:
% binamps vector holds 2^13 = 8192 bins of desired amplitude values for frequencies in range 0.001 .. 22050 Hz (half of samplerate 44100 Hz)
% it looks just fine, when I use Matlab plot() function
% now I get ifft
n = size(binamps,1);
iff = ifft(binamps, n);
coeffs = real(iff); % throw away the imaginary part, because FIR module will not use it anyway
但是当我对系数的fft()进行处理时,我发现频率被拉伸了2次并且我的AFR数据的结尾丢失了:
p = fft(coeffs, n); % take the fourier transform of coefficients for a test
nUniquePts = ceil((n+1)/2);
p = p(1:nUniquePts); % select just the first half since the second half
% is a mirror image of the first
p = abs(p); % take the absolute value, or the magnitude
p = p/n; % scale by the number of points so that
% the magnitude does not depend on the length
% of the signal or on its sampling frequency
p = p.^2; % square it to get the power
sampFreq = 44100;
freqArray = (0:nUniquePts-1) * (sampFreq / n); % create the frequency array
semilogx(freqArray, 10*log10(p))
axis([10, 30000 -Inf Inf])
xlabel('Frequency (Hz)')
ylabel('Power (dB)')
所以我想,我正在使用ifft错误。我需要让我的binamp矢量两倍长,并在它的第二部分创建一个镜子吗?如果是这种情况,那么它只是一个Matlab实现的ifft或其他C / C ++ FFT库(尤其是Ooura FFT)需要用于逆FFT的镜像数据吗?
还有什么我应该知道的,以便从ifft中获取FIR系数吗?
答案 0 :(得分:3)
您的频域向量需要复杂而不仅仅是实数,并且需要关于中点对称才能获得纯粹的实时域信号。将实部设置为所需的幅度值,并将虚部设置为零。实部需要具有均匀对称性,以使A[N - i] = A[i]
(A[0]
和A[N / 2]
为“特殊”,即DC和奈奎斯特分量 - 只需将它们设置为零。)
以上内容适用于任何通用的复杂到复杂的FFT / IFFT,而不仅仅是MATLAB的实现。
请注意,如果您尝试设计具有任意频率响应的时域滤波器,则需要首先在频域中进行一些窗口化。您可能会发现this article有用 - 它讨论了任意FIR滤波器设计使用MATLAB,特别是fir2。
答案 1 :(得分:2)
为了获得真实的结果,任何典型的通用IFFT(不仅仅是Matlab的实现)的输入都需要是复共轭对称的。因此,使用给定数量的独立规格点进行IFFT将需要至少两倍的FFT(优选甚至更长以允许从最高频率截止转变为零)。
试图通过丢弃复杂结果的“虚构”部分来获得真实结果将不起作用,因为您将丢弃实际所需的信息内容,时域滤波器需要输入给定的频率响应IFFT。但是,如果原始数据是共轭对称的,那么IFFT / FFT结果的虚部将是(通常无关紧要的)可以丢弃的舍入误差噪声。
此外,有限频率响应的DTFT将产生无限长的FIR。要获得有限长度的FIR,您需要妥协您的频率响应规范的规范,以便在时域表示的后一部分中留下很少的能量,必须从FIR截断以使其可实现或有限。一种常见(但不是必要的最佳)方法是窗口IFFT产生的FIR结果,并通过反复试验尝试不同的窗口,直到找到FFT产生结果的FIR滤波器“足够接近你的原始频率规格。