Python中复数的FFT过滤

时间:2015-05-05 00:32:15

标签: python audio numpy filter fft

我的问题与A. Levy的解释有关: Analyze audio using Fast Fourier Transform

如何在这些复数上生成带通滤波器 ...

[-636.00000000 +0.00000000e+00j  -47.84161618 -2.80509841e+02j
30.69754505 -1.30624718e+01j -109.94022791 +7.58155488e+00j
-3.18538186 +1.44880882e+01j -120.36687555 +5.45225425e+00j
50.48671763 +1.69504204e+01j   31.56751791 -7.22728042e+01j
-17.96079093 -3.17853727e+01j  -19.25527276 +5.08151876e+00j
18.38143611 -2.60879726e+01j  -27.15617871 -4.39789289e+01j...

...已经知道我将使用ifft将我的复杂数组转换回时域。我的乐队通行证应该只允许18500Hz到19500Hz(超音速,我知道。我特意寻找那些从房间的音调发生器到达的音调)。我的采样率为44100Hz,我的FFT中的点数为128。

我将在这里使用频率检测代码(已经在我的非滤波样本上工作)Python frequency detection,以便在到达时给出音频音调。如果在19000HZ(例如)没有播放音调,则音高检测功能的输出应返回0.

我当前的过滤器代码(没有给我正确的结果):

samp = [-10 -16 -15 -11 -8 -10 -9  -12 -7 -13 -4 -10 
        -1  -4  -11 -6 -8 -8 -10 -6 -9 -7 -16 -11 5 -14   
        -9 -3 -9 -7 -7 -6 -3 -11 -13 -9 -10 -4 -6 -7 
        -11 -15 -15 -3 -5 -15 -11 -8 -13 -9 -12 -10 -8 -16  
        -13 -5 -4 -12 -14 -8 -14 -6 -7 -7 -4 -6 -9 -4 -4  
        -4  1 -10 -3 -9 -9  -1 -5 -2 -5 -3 -3  2 -3  2  
        -5 -4 -6  1 -2 -6 -8  -3 -10 -11 -6 -2 -5  -3   
         0  3  0  1  1 -1 -3 -3  1  3 -3 -3  3 -3 -1  
        -3  -1  2  1  0 -8  0  6 -3 -4 -7 -5 -10 -4 -4]

sample_time = 0.000022675   # 1/44100

low_cut = 18500
high_cut = 19500

float_samp = np.float32(samp)
fft_spectrum = np.fft.fft(float_samp)

freqs = np.fft.fftfreq(len(fft_spectrum), d=sample_time)

### wrong approach ###
for i in range(len(freqs)): # (H-red)

    if abs(freqs[i]) >= high or abs(freqs[i]) <= low:
        fft_spectrum[i] = 0.0 
### -------------- ###

time_domain = np.fft.ifft(fft_spectrum)
converted = np.int16(time_domain)

在音调检测之后,当前在18500Hz和19500Hz之间返回值,无论音调是否存在。我相信情况就是这样,因为我会从我的 fft_spectrum 列表中删除所有信息,除了那些带有我的过滤器值的信息。即使音调不存在,剩下的唯一信息就是在该频段内,这就是音调检测器正在读取的内容。这是我的假设。

请注意:我不能使用Scipy,因为我在Android上部署了这个,并且该平台上没有该库。我希望通过Numpy有办法做到这一点。

1 个答案:

答案 0 :(得分:1)

您链接的频率检测代码正在执行FFT,然后找到幅度最大的bin。它返回零的唯一方法是最大幅度是否在第0个区间。即使你可能没有以你感兴趣的频率产生音调,那里肯定有能量,因此是最大的候选者。为了帮助您,您需要修改引用的代码以提供所需的行为。例如,您可以应用某种最低阈值。

which = fftData[1:].argmax() + 1
if (fftData[which] < threshold)
    return -1; // no peak found

当你遇到它时:我不明白你为什么要通过带通滤波信号的过程来限制频率检测以搜索感兴趣的箱子:

binMin = floor(low_cut / 22050.0 * 128)
binMax = ceil(high_cut / 22050.0 * 128)
which = fftData[binMin:binMax].argmax() + 1