【问题标题】:naive filtering using fft in python在 python 中使用 fft 进行朴素过滤
【发布时间】:2014-06-05 13:02:39
【问题描述】:

我正在尝试使用 Python 编写 naiv 低通滤波器。 高于特定频率的傅立叶变换的值应该等于0,对吧? 据我所知,这应该可以工作。

但是在逆傅立叶变换之后,我得到的只是噪声。

Program1 从麦克风记录 RECORD_SECONDS 并将有关 fft 的信息写入 fft.bin 文件中。

Program2 读取该文件,执行ifft 并在扬声器上播放结果。

此外,我发现,fft 中的每一个,即使是很小的变化都会导致 Program2 失败。

我在哪里犯错了?

程序1:

import pickle
import pyaudio
import wave
import numpy as np

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1 #1-mono, 2-stereo
RATE = 44100
RECORD_SECONDS = 2

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

f = open("fft.bin", "wb")

Tsamp = 1./RATE
#arguments for a fft
fft_x_arg = np.fft.rfftfreq(CHUNK/2, Tsamp)
#max freq
Fmax = 4000


print("* recording")

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):

    #read one chunk from mic
    SigString = stream.read(CHUNK)

    #convert string to int
    SigInt = np.fromstring(SigString, 'int')

    #calculate fft
    fft_Sig = np.fft.rfft(SigInt)
    """
    #apply low pass filter, maximum freq = Fmax
    j=0
    for value in fft_x_arg:
        if value > Fmax:
            fft_Sig[j] = 0
        j=j+1
    """

    #write one chunk of data to file
    pickle.dump(fft_Sig,f)

print("* done recording")


f.close()

stream.stop_stream()
stream.close()
p.terminate()

程序2:

import pyaudio
import pickle
import numpy as np

CHUNK = 1024


p = pyaudio.PyAudio()

stream = p.open(format=pyaudio.paInt16,
                channels=1,
                rate=44100/2,   #anyway, why 44100 Hz plays twice faster than normal?
                output=True)

f = open("fft.bin", "rb")

#load first value from file
fft_Sig = pickle.load(f)
#calculate ifft and cast do int
SigInt = np.int16(np.fft.irfft(fft_Sig))
#convert once more - to string
SigString = np.ndarray.tostring(SigInt)

while SigString != '':
    #play sound
    stream.write(SigString)
    fft_Sig = pickle.load(f)
    SigInt = np.int16(np.fft.irfft(fft_Sig))
    SigString = np.ndarray.tostring(SigInt)

f.close()

stream.stop_stream()
stream.close()

p.terminate()

【问题讨论】:

    标签: python numpy signal-processing fft lowpass-filter


    【解决方案1】:

    FFT 对复数进行运算。您也许可以为它们提供实数(通过将虚部设置为 0 将其转换为复数),但它们的输出将始终是复数。

    这可能会使您的样本计数减少 2 次。它还应该破坏您的输出,因为您没有转换回真实数据。

    另外,您忘记将 1/N 比例因子应用于 IFFT 输出。而且您需要记住,FFT 的频率范围是负数的一半,也就是说它的范围大约是 -1/(2T) Nyquist frequency,对于实际输入数据,FFT 输出的负半部分将反映正半部分(即对于 y(f) = F{x(t)}(其中F{} 是前锋Fourier transform) y(f) == y(-f)。

    我认为您需要进一步了解使用 FFT 的 DSP 算法。您正在尝试做的事情称为brick wall filter

    另外,对您有很大帮助的是matplotlib,它将帮助您查看中间步骤中的数据是什么样的。您需要查看这些中间数据以找出问题所在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-17
      • 2011-02-25
      • 2018-03-06
      • 1970-01-01
      • 1970-01-01
      • 2016-11-23
      • 2020-03-22
      • 2022-01-01
      相关资源
      最近更新 更多