如何对 python 上的录音应用低通滤波器?
How to apply low-pass filter to a sound record on python?
我必须减少声音中的白噪声 record.Because 我使用了傅立叶 transform.But 我不知道如何使用 fft 函数的 return 值 domain.How 我可以使用 fft 数据来降低噪声吗?
这是我的代码
from scipy.io import wavfile
import matplotlib.pyplot as plt
import simpleaudio as sa
from numpy.fft import fft,fftfreq,ifft
#reading wav file
fs,data=wavfile.read("a.wav","wb")
n=len(data)
freqs=fftfreq(n)
mask=freqs>0
#calculating raw fft values
fft_vals=fft(data)
#calculating theorical fft values
fft_theo=2*np.abs(fft_vals/n)
#ploting
plt.plot(freqs[mask],fft_theo[mask])
plt.show()```
此类问题最好构建一个综合示例,这样您就不必 post 一个大数据文件,人们仍然可以关注您的问题 (MCVE)。
绘制中间结果也很重要,因为我们讨论的是对复数的运算,所以我们经常需要分别取 re、im 部分或绝对值和角度。
实函数的傅立叶变换很复杂,但正频率和负频率是对称的。也可以从信息论的角度来看:你不希望 N 个独立的实数及时产生 2N 个独立的实数来描述频谱。
虽然您通常绘制频谱的绝对值或绝对平方(电压与功率),但在应用过滤器时可以让它变得复杂。通过 IFFT 反向转换为时间后,要绘制它,您必须再次将其转换为实数,在这种情况下采用绝对值。
如果在时域设计滤波器内核(高斯的FFT就是高斯),滤波器的FFT与频谱的乘积IFFT只有很小的虚部,可以然后取实数部分(从物理学的角度来看更有意义,你从实数部分开始,以实数部分结束)。
import numpy as np
import matplotlib.pyplot as p
%matplotlib inline
T=3 # secs
d=0.04 # secs
n=int(T/d)
print(n)
t=np.arange(0,T,d)
fr=1 # Hz
y1= np.sin(2*np.pi*fr*t) +1 # dc offset helps with backconversion, try setting it to zero
y2= 1/5*np.sin(2*np.pi*7*fr*t+0.5)
y=y1+y2
f=np.fft.fftshift(np.fft.fft(y))
freq=np.fft.fftshift(np.fft.fftfreq(n,d))
filter=np.exp(- freq**2/6) # simple Gaussian filter in the frequency domain
filtered_spectrum=f*filter # apply the filter to the spectrum
filtered_data = np.fft.ifft(filtered_spectrum) # then backtransform to time domain
p.figure(figsize=(24,16))
p.subplot(321)
p.plot(t,y1,'.-',color='red', lw=0.5, ms=1, label='signal')
p.plot(t,y2,'.-',color='blue', lw=0.5,ms=1, label='noise')
p.plot(t,y,'.-',color='green', lw=4, ms=4, alpha=0.3, label='noisy signal')
p.xlabel('time (sec)')
p.ylabel('amplitude (Volt)')
p.legend()
p.subplot(322)
p.plot(freq,np.abs(f)/n, label='raw spectrum')
p.plot(freq,filter,label='filter')
p.xlabel(' freq (Hz)')
p.ylabel('amplitude (Volt)');
p.legend()
p.subplot(323)
p.plot(t, np.absolute(filtered_data),'.-',color='green', lw=4, ms=4, alpha=0.3, label='cleaned signal')
p.legend()
p.subplot(324)
p.plot(freq,np.abs(filtered_spectrum), label = 'filtered spectrum')
p.legend()
p.subplot(326)
p.plot(freq,np.log( np.abs(filtered_spectrum)), label = 'filtered spectrum')
p.legend()
p.title(' in the log plot the noise is still visible');
我必须减少声音中的白噪声 record.Because 我使用了傅立叶 transform.But 我不知道如何使用 fft 函数的 return 值 domain.How 我可以使用 fft 数据来降低噪声吗?
这是我的代码
from scipy.io import wavfile
import matplotlib.pyplot as plt
import simpleaudio as sa
from numpy.fft import fft,fftfreq,ifft
#reading wav file
fs,data=wavfile.read("a.wav","wb")
n=len(data)
freqs=fftfreq(n)
mask=freqs>0
#calculating raw fft values
fft_vals=fft(data)
#calculating theorical fft values
fft_theo=2*np.abs(fft_vals/n)
#ploting
plt.plot(freqs[mask],fft_theo[mask])
plt.show()```
此类问题最好构建一个综合示例,这样您就不必 post 一个大数据文件,人们仍然可以关注您的问题 (MCVE)。
绘制中间结果也很重要,因为我们讨论的是对复数的运算,所以我们经常需要分别取 re、im 部分或绝对值和角度。
实函数的傅立叶变换很复杂,但正频率和负频率是对称的。也可以从信息论的角度来看:你不希望 N 个独立的实数及时产生 2N 个独立的实数来描述频谱。
虽然您通常绘制频谱的绝对值或绝对平方(电压与功率),但在应用过滤器时可以让它变得复杂。通过 IFFT 反向转换为时间后,要绘制它,您必须再次将其转换为实数,在这种情况下采用绝对值。
如果在时域设计滤波器内核(高斯的FFT就是高斯),滤波器的FFT与频谱的乘积IFFT只有很小的虚部,可以然后取实数部分(从物理学的角度来看更有意义,你从实数部分开始,以实数部分结束)。
import numpy as np
import matplotlib.pyplot as p
%matplotlib inline
T=3 # secs
d=0.04 # secs
n=int(T/d)
print(n)
t=np.arange(0,T,d)
fr=1 # Hz
y1= np.sin(2*np.pi*fr*t) +1 # dc offset helps with backconversion, try setting it to zero
y2= 1/5*np.sin(2*np.pi*7*fr*t+0.5)
y=y1+y2
f=np.fft.fftshift(np.fft.fft(y))
freq=np.fft.fftshift(np.fft.fftfreq(n,d))
filter=np.exp(- freq**2/6) # simple Gaussian filter in the frequency domain
filtered_spectrum=f*filter # apply the filter to the spectrum
filtered_data = np.fft.ifft(filtered_spectrum) # then backtransform to time domain
p.figure(figsize=(24,16))
p.subplot(321)
p.plot(t,y1,'.-',color='red', lw=0.5, ms=1, label='signal')
p.plot(t,y2,'.-',color='blue', lw=0.5,ms=1, label='noise')
p.plot(t,y,'.-',color='green', lw=4, ms=4, alpha=0.3, label='noisy signal')
p.xlabel('time (sec)')
p.ylabel('amplitude (Volt)')
p.legend()
p.subplot(322)
p.plot(freq,np.abs(f)/n, label='raw spectrum')
p.plot(freq,filter,label='filter')
p.xlabel(' freq (Hz)')
p.ylabel('amplitude (Volt)');
p.legend()
p.subplot(323)
p.plot(t, np.absolute(filtered_data),'.-',color='green', lw=4, ms=4, alpha=0.3, label='cleaned signal')
p.legend()
p.subplot(324)
p.plot(freq,np.abs(filtered_spectrum), label = 'filtered spectrum')
p.legend()
p.subplot(326)
p.plot(freq,np.log( np.abs(filtered_spectrum)), label = 'filtered spectrum')
p.legend()
p.title(' in the log plot the noise is still visible');