代码之家  ›  专栏  ›  技术社区  ›  ggkmath

有什么经验法则可以用来平滑快速傅立叶变换频谱,防止手工调整时出现伪影吗?

  •  2
  • ggkmath  · 技术社区  · 14 年前

    我有一个快速傅立叶变换幅度谱,我想从中创建一个滤波器,有选择地通过周期性噪声源(如正弦波爆发)和零出与随机背景噪声相关的频率箱。我知道在频率域的急剧转换将创建振铃伪影一旦这个过滤器是ifft回到时间域…所以我想知道是否有经验法则,如何在这样的滤波器中平滑过渡,以避免这样的振铃。

    例如,如果FFT有1米频率的音箱,并且有5个音箱从背景噪声地板中突出来,我想将所有音箱归零,除了与5个音箱中每个音箱相关的峰值音箱。问题是如何处理相邻的分支箱以防止在时间域中出现伪影。例如,是否应将支线料仓两侧的料仓设置为50%振幅?是否应在支线料仓两侧使用两个料仓(最近的一个为50%,下一个为25%,等等)?任何想法都非常感谢。谢谢!

    1 回复  |  直到 14 年前
        1
  •  2
  •   mtrw    14 年前

    我喜欢以下方法:

    • 创建理想的幅度谱(记住使其与直流电对称)
    • 反变换到时间域
    • 将块旋转一半
    • 应用汉恩窗口

    我发现它能产生相当平滑的频域结果,尽管我从未尝试过像你建议的那样尖锐的东西。您可能可以使用凯撒贝塞尔窗口来制作更清晰的过滤器,但是您必须适当地选择参数。更尖锐的是,我猜也许你可以减少6分贝左右的旁瓣。

    下面是一些Matlab/Octave代码示例。为了测试结果,我使用 freqz(h, 1, length(h)*10); .

    function [ht, htrot, htwin] = ArbBandPass(N, freqs)
    %# N = desired filter length
    %# freqs = array of frequencies, normalized by pi, to turn into passbands
    %# returns raw, rotated, and rotated+windowed coeffs in time domain
    
    if any(freqs >= 1) || any(freqs <= 0)
        error('0 < passband frequency < 1.0 required to fit within (DC,pi)')
    end
    
    hf = zeros(N,1); %# magnitude spectrum from DC to 2*pi is intialized to 0
    %# In Matlabs FFT, idx 1 -> DC, idx 2 -> bin 1, idx N/2 -> Fs/2 - 1, idx N/2 + 1 -> Fs/2, idx N -> bin -1
    idxs = round(freqs * N/2)+1; %# indeces of passband freqs between DC and pi
    hf(idxs) = 1; %# set desired positive frequencies to 1
    hf(N - (idxs-2)) = 1; %# make sure 2-sided spectrum is symmetric, guarantees real filter coeffs in time domain
    ht = ifft(hf); %# this will have a small imaginary part due to numerical error
    if any(abs(imag(ht)) > 2*eps(max(abs(real(ht)))))
        warning('Imaginary part of time domain signal surprisingly large - is the spectrum symmetric?')
    end
    ht = real(ht); %# discard tiny imag part from numerical error
    htrot = [ht((N/2 + 1):end) ; ht(1:(N/2))]; %# circularly rotate time domain block by N/2 points
    win = hann(N, 'periodic'); %# might want to use a window with a flatter mainlobe
    htwin = htrot .* win;
    htwin = htwin .* (N/sum(win)); %# normalize peak amplitude by compensating for width of window lineshape