金融社区类网站建设,28网站制作,东阳建设局网站,网络工程可以从事什么工作使用谱减法去除音频底噪
上一篇文章我主要分享了短时傅立叶变换及其逆变换在python中的实现#xff0c;有兴趣的可以阅读一下该篇文章#xff0c;地址如下#xff1a; Python音频信号处理 1.短时傅里叶变换及其逆变换
那么在本篇文章中#xff0c;我们将利用短时傅立叶变…使用谱减法去除音频底噪
上一篇文章我主要分享了短时傅立叶变换及其逆变换在python中的实现有兴趣的可以阅读一下该篇文章地址如下 Python音频信号处理 1.短时傅里叶变换及其逆变换
那么在本篇文章中我们将利用短时傅立叶变换及其逆变换来实现谱减法。
Part 1 谱减法
谱减法的核心思路非常简单顾名思义谱减法是一种频域上的信号处理方法其基本思路就是提取出信号本身的频谱以及噪音的频谱通过两者之差获取降噪后信号的频谱最后利用傅立叶变换逆变换重构初始信号。
Part 2 使用谱减法降低或消除信号的底噪
要使用谱减法来进行信号处理显然我们首先需要计算出信号的频谱以及噪音的频谱。这里我们继续使用上篇文章所介绍的短时傅立叶变换及其逆变换的实现Python代码如下
# 短时傅立叶变换
def TFCT(trame, Fe, Nfft,fenetre,Nwin,Nhop):L round((len(trame) - len(fenetre))/Nhop)1M Nfftxmat np.zeros((M,L))print(xmat,xmat.shape)print(NwinNhop)for j in range(L):xmat[:,j] np.fft.fft(trame[j*Nhop:NwinNhop*j]*window,Nfft) x_temporel np.linspace(0,(1/Fe)*len(trame),len(trame))x_frequentiel np.linspace(0, Fe,Nfft)return xmat,x_temporel,x_frequentiel# 短时傅立叶变换逆变换
def ITFD(xmat,Fe,Nfft,Nwin,Nhop):window np.hamming(Nwin)Te 1/Feyvect np.zeros(Nfft (xmat.shape[1]-1)*Nhop)t_vecteur np.arange(0,Te*len(yvect),Te)index 0K 0L xmat.shape[1]yl np.zeros((Nfft,L))for j in range(L):yl[:,j] np.fft.ifft(xmat[:,j])for k in range(L):yvect[Nhop*k:NfftNhop*k] yl[:,k]for n in range(Nwin-1):K window[n]K / Nhopyvect /Kprint(yvect.shape)return t_vecteur, yvect有关于短时傅立叶变换及其逆变换的实现这里就不过多赘述有兴趣的可以参考上一篇文章其中详细解释了代码的构成。
首先我们先读取信号并观察其在时域中的图像
# 读取初始信号 mix.wav
Fe, mix wavfile.read(mix.wav)
mix mix/2**15
Te 1 / Fe
xtemp np.arange(0,Te*len(mix),Te)
plt.figure()
plt.plot(xtemp,mix)
plt.axis([0,1,-0.6,0.6])
plt.xlabel(t(s))
plt.ylabel(amplitude(V))
plt.title(representation of the original signal in time domain)
display(Audio(mix,rateFe))
Fe为原始信号的采样频率mix为复信号值。 Te 1/Fe 6.25e-5 我们不难发现0-0.4s时域上只有底噪因此我们可以利用这段时间来计算噪音的频谱。 这个例子中我们选择频域的采样点个数Nfft1024窗函数的长度Nwin1024每次窗函数滑动的长度Nhop512计算该信号的短时傅立叶变换。
Nfft 1024
Nwin 1024
Nhop 512
window np.hamming(Nwin)
xmat_sound,tvect,fvect TFCT(mix,Fe,Nfft,window,Nwin,Nhop)xmat_sound就是我们保存短时傅立叶变换值的矩阵该矩阵的每一行代表一个在0至采样频率范围内的频率单位为Hz每一列对应该段被窗函数截取的信号的FFT快速傅里叶变换值。 不难算出第一列代表的时域范围为0-Nwin*1/Fe 0.064s 在该例中我们就使用第一列的频谱近似认为是底噪的频谱。显然我们这里应该取尽可能多的纯噪音频谱并使用他们幅值的平均值这里为了简化仅使用第一个窗函数截取的信号部分作为噪声频谱。
我们可以先使用imshow画出原始信号的光谱图横轴为时间纵轴为频率。
module_tf_xmat abs(xmat_sound)
plt.figure()
xlim int(module_tf_xmat.shape[0]/2)
ylim int(module_tf_xmat.shape[1]/2)
plt.imshow(20*np.log10(module_tf_xmat[0:xlim,:]),extent[0,Te*len(mix),0,Fe/2],aspectauto)
plt.colorbar()
plt.xlabel(time(s))
plt.ylabel(frequence(Hz))
plt.title(spectrogram of the originql signal)接下来我们使用谱减法对信号频谱所有列减去第一列对应的噪音频谱注意这里的全部减法都是针对幅值。
module_tf_xmat abs(xmat_sound)
angle_tf_xmat np.angle(xmat_sound)
module_tf_bruit module_tf_xmat[:,0]module_reconstruit np.zeros(module_tf_xmat.shape)
for n in range(module_tf_xmat.shape[1]):module_reconstruit[:,n] module_tf_xmat[:,n] - module_tf_bruit
module_reconstruit[module_reconstruit0] 0谱减法之后的光谱图如下所示 最后我们使用短时傅立叶变换逆变换将获取的降噪后的幅值矩阵使用原始的信号相位重构降噪后的复信号。
# 将相位和降噪后的幅值重构复信号的频域分布
tf_reconstruit np.zeros(module_tf_xmat.shape,dtypecomplex)
for i in range(module_tf_xmat.shape[0]):for j in range(module_tf_xmat.shape[1]):tf_reconstruit[i,j] module_reconstruit[i,j] * np.exp(angle_tf_xmat[i,j]*1j)
# 使用短时傅立叶变换逆变换重构时域内的信号
t,yvect ITFD(tf_reconstruit,Fe,Nfft,Nwin,Nhop)
总结
在本例中我们仅仅使用了短时傅立叶变换矩阵的第一列来计算噪声的频谱实际是非常不准确的因为此时所取的噪声长度仅为0.064s。即使是对于平稳的噪音这段噪声的频谱仍然不能很好地代表噪音的真实频谱。在实际的信号处理过程中较好的方式是取足够长度的噪音并计算其幅值的平均值再使用这个噪音在各个频率幅值的平均值进行谱减法可以更加有效地降低底噪。