最近一个项目需要对声音文件进行一个滤波处理,由于并没有这种经验,所以借助图像的滤波来实现一下
- 首先导入需要的包和设置路径
import wave as we
import numpy as np
import matplotlib.pyplot as plt
dir = r'路径'
- 现在写读入音频和傅里叶变换的函数,载入数据,查看现在的状态
def read_wav(wavfile, plots=True, normal=False):
f = wavfile
params = f.getparams()
# print(params)
nchannels, sampwidth, framerate, nframes = params[:4]
strData = f.readframes(nframes) # 读取音频,字符串格式
waveData = np.frombuffer(strData, dtype=np.int16) # 将字符串转化为int
# wave幅值归一化
if normal == True:
waveData = waveData*1.0/(max(abs(waveData)))
# 绘图
if plots == True:
time = np.arange(0, nframes)*(1.0 / framerate)
plt.figure(dpi=100)
plt.plot(time, waveData)
plt.xlabel("Time")
plt.ylabel("Amplitude")
plt.title("Single channel wavedata")
plt.show()
return (waveData, time)
def fft_wav(waveData, plots=True):
f_array = np.fft.fft(waveData) # 傅里叶变换,结果为复数数组
f_abs = f_array
axis_f = np.linspace(0, 250, np.int(len(f_array)/2)) # 映射到250
# axis_f = np.linspace(0, 250, np.int(len(f_array))) # 映射到250
if plots == True:
plt.figure(dpi=100)
plt.plot(axis_f, np.abs(f_abs[0:len(axis_f)]))
# plt.plot(axis_f, np.abs(f_abs))
plt.xlabel("Frequency")
plt.ylabel("Amplitude spectrum")
plt.title("Tile map")
plt.show()
return f_abs
调用绘制声波图
f = we.open(dir+r'\test.wav', 'rb')
waveData, time = read_wav(f)
绘制傅里叶变换的图像
wavefft = fft_wav(waveData)
- 现在把后面的不需要的磨平
# 截取
step_hz = 250 / (len(waveData) / 2)
tab_hz = 20
savewav = []
for i in range(int(tab_hz/step_hz)):
savewav.append(wavefft[i])
for j in range(int(tab_hz/step_hz), (len(wavefft) - int(tab_hz/step_hz))):
savewav.append(0)
for i in range((len(wavefft) - int(tab_hz/step_hz)), len(wavefft)):
savewav.append(wavefft[i])
# 绘图
axis_f = np.linspace(0, 250, np.int(len(wavefft)/2)) # 映射到250
# axis_f = np.linspace(0, 250, np.int(len(wavefft))) # 映射到250
plt.figure(dpi=100)
plt.plot(axis_f, np.abs(savewav[0:len(axis_f)]))
# plt.plot(axis_f, np.abs(savewav))
plt.xlabel("Frequency")
plt.ylabel("Amplitude spectrum")
plt.title("Tile map after wave filtering")
plt.show()
绘制变换后的声波图
# 傅里叶逆变换
i_array = np.fft.ifft(savewav)
# 绘图
plt.figure(dpi=100)
plt.plot(time, i_array.real)
plt.xlabel("Time")
plt.ylabel("Amplitude")
plt.title("Single channel wavedata after wave filtering")
plt.show()
- 保存声音文件
# 保存
save_wav = i_array.real.reshape((len(i_array), 1)).T.astype(np.short)
# print(save_wav.shape)
# i_array.real.tofile(dir+r'\test.bin')
f = we.open(dir+r'\test_wf.wav', "wb")
# 配置声道数、量化位数和取样频率
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(16000)
# 将wav_data转换为二进制数据写入文件
f.writeframes(save_wav.tostring())
f.close()