之所以加了括号是因为效果还不是太好
主要使用了滑窗、汉明窗、scipy库的fft/ifft,通过频域整体缩小的方式来降频
代码的解释都在注释中
import numpy as np
from matplotlib import pyplot as plt
from scipy.fftpack import fft, ifft
from scipy.io import wavfile
wavFile = "女声降频前.wav" # 这段音频是从一段完整对话截下来的一句开头的“你好”
Fs, Data = wavfile.read(wavFile)
try:
Data = Data[:, 0] # 若为双声道音频则需取其中一个声道
except IndexError:
pass
win_size = int(Fs * (25 / 1000)) # 以25ms作为窗口大小进行分窗
step_size = win_size // 4 # 设置步长为窗口大小的四分之一
win_ham = np.hamming(win_size) # 汉明窗,用于缓解加窗造成的信号畸变
lens = Data.shape[0] # 音频长度
conv_len = 10 # 频率偏移量
temp_data = [0] * win_size # 存放每窗进行傅里叶变换后处理的音频
ifft_data = [0] * len(Data) # 存放逆傅里叶变换后的音频,即结果音频
i = 0
while i + win_size <= lens:
win = Data[i:i + win_size]
win = win * win_ham
FFT = fft(win)
# 通过整段平移频谱的方式来降低音频频率,效果欠佳
# FFT[0:int(Win_size / 2) - conv_len] = FFT[conv_len:int(Win_size / 2)]
# FFT[int(Win_size / 2) - conv_len:int(Win_size / 2)] = 0
# FFT[int(Win_size / 2) + conv_len:] = FFT[int(Win_size / 2):-conv_len]
# FFT[int(Win_size / 2):int(Win_size / 2) + conv_len] = 0
# 通过整段缩小的方式来降低音频频率,效果相对较好
for k in range(win_size // 3):
temp_data[k] = FFT[int(k * 3 / 2)]
temp_data[win_size // 2:] = temp_data[0:win_size // 2]
ifft_data[i:i + win_size] += ifft(temp_data)
i = i + step_size
# 处理前的频率
plt.figure(figsize=(10, 6), dpi=150)
plt.plot(np.linspace(0, 400 * Fs / len(Data), 400), fft(Data)[0:400], color='b')
# 处理后的频率
plt.figure(figsize=(10, 6), dpi=150)
plt.plot(np.linspace(0, 400 * Fs / len(ifft_data), 400), fft(ifft_data)[0:400], color='r')
plt.show()
# 保存音频
male_audio = np.array(ifft_data).real
wavfile.write('女声降频后.wav', Fs, male_audio.astype(np.int16))