如何在幅频响应上使用逆FFT?

发布于 2024-12-10 18:00:55 字数 1471 浏览 1 评论 0原文

我正在尝试创建一个应用程序来计算图形均衡器 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 是错误的。我是否需要将 binamps 矢量的长度加倍并在其第二部分创建一个镜像?如果是这样的话,那么它只是一个 Matlab 的 ifft 实现还是其他 C/C++ FFT 库(特别是 Ooura FFT)也需要镜像数据来进行逆 FFT?

为了从 ifft 中获取 FIR 系数,我还应该知道什么吗?

I am trying to create an application for calculating coefficients for a graphic equalizer FIR filter. I am doing some prototyping in Matlab but I have some problems.

I have started with the following Matlab code:

    % 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  

But when I do the fft() of the coefficients, I see that the frequencies are stretched 2 times and the ending of my AFR data is lost:

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

So I guess, I am using ifft wrong. Do I need to make my binamps vector twice as long and create a mirror in the second part of it? If it is the case, then is it just a Matlab's implementation of ifft or also other C/C++ FFT libraries (especially Ooura FFT) need mirrored data for inverse FFT?

Is there anything else I should know to get the FIR coefficients out of ifft?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深陷 2024-12-17 18:00:55

您的频域向量需要是复数而不仅仅是实数,并且它需要关于中点对称才能获得纯实时域信号。将实部设置为所需的幅度值,并将虚部设置为零。实部需要具有偶数对称性,使得 A[N - i] = A[i]A[0]A[N / 2] 是“特殊”的,即 DC 和 Nyquist 分量 - 只需将它们设置为零。)

上述内容适用于任何通用复数到复数 FFT/IFFT,而不仅仅是 MATLAB 的实现。

请注意,如果您尝试设计具有任意频率响应的时域滤波器,那么您需要首先在频域中进行一些加窗操作。您可能会发现这篇文章很有帮助 - 它讨论了使用 MATLAB 进行任意 FIR 滤波器设计,特别是 fir2

Your frequency domain vector needs to be complex rather than just real, and it needs to be symmetric about the mid point in order to get a purely real time domain signal. Set the real parts to your desired magnitude values and set the imaginary parts to zero. The real parts need to have even symmetry such that A[N - i] = A[i] (A[0] and A[N / 2] are "special", being the DC and Nyquist components - just set these to zero.)

The above applies to any general purpose complex-to-complex FFT/IFFT, not just MATLAB's implementation.

Note that if you're trying to design a time domain filter with an arbitrary frequency response then you'll need to do some windowing in the frequency domain first. You might find this article helpful - it talks about arbitrary FIR filter design usign MATLAB, in particular fir2.

酒废 2024-12-17 18:00:55

为了获得真实的结果,任何典型的通用 IFFT(不仅仅是 Matlab 的实现)的输入都需要是复共轭对称的。因此,使用给定数量的独立规范点进行 IFFT 将需要 FFT 至少两倍的时间(最好甚至更长,以允许从最高频率截止到零的某种过渡)。

尝试通过丢弃复杂结果的“虚部”来获得真实结果是行不通的,因为您将丢弃时域滤波器对于输入到 IFFT 的给定频率响应所需的实际所需信息内容。然而,如果原始数据是共轭对称的,则 IFFT/FFT 结果的虚部将是(通常不显着的)舍入误差噪声,可以将其丢弃。

此外,有限频率响应的 DTFT 将产生无限长的 FIR。为了获得有限长度的 FIR,您需要对频率响应规范进行折衷,以便时域表示的后半部分只剩下很少的能量,必须从 FIR 中截断这些能量,以使其可实现或有限。一种常见(但不一定是最好)的方法是对 IFFT 生成的 FIR 结果加窗,并通过反复试验尝试不同的窗口,直到找到 FFT 为其生成结果的 FIR 滤波器“足够接近”您的原始频率规格。

To get a real result, the input to any typical generic IFFT (not just Matlab's implementation) needs to be complex-conjugate-symmetric. So doing an IFFT with a given number of independent specification points will require an FFT at least twice as long (preferably even longer to allow for some transition to zero from the highest frequency cut-off).

Trying to get a real result by throwing away the "imaginary" portion of a complex result won't work, as you will be throwing away actual required information content the time-domain filter needs for the given frequency response input to the IFFT. However, if the original data is conjugate-symmetric, then the imaginary portion of the IFFT/FFT result will be (usually insignificant) rounding-error noise that can be thrown away.

Also, the DTFT of a finite frequency response will produce an infinitely long FIR. To get a finite length FIR, you will need to compromise the specification for your frequency response specification so that there is little energy left in the latter portion of the time-domain representation that has to be truncated from the FIR to make it realizable or finite. One common (but not necessary the best) way to do this is to window the FIR result produced by the IFFT, and, by trial-and-error, try different windows until you find a FIR filter for which an FFT produces a result "close enough" to your original frequency spec.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文