学习如何将噪声加入到audio data中,后续可以将不同SNR的噪声加入原始信号样本,评估不同噪声条件下的模型性能
首先读取原始audio.wav(里面是一段话:“leave my dog alone”)
import librosa
signal, sr = librosa.load(“path/to/audio.wav”)
绘制信号图:
import matplotlib.pyplot as plt
plt.plot(signal)
RMS是均方根
计算信号的RMS:
import numpy as np
RMS=math.sqrt(np.mean(signal**2))
dB = 20 × log ? 10 ( RMS ) \text{dB} = 20 \times \log_{10}(\text{RMS}) dB=20×log10?(RMS)
噪声是服从高斯分布,均值为0,标准差是
R
M
S
n
o
i
s
e
RMS_{noise}
RMSnoise?
noise=np.random.normal(0, STD_n, signal.shape[0])
# np.random.normal() 函数用于生成服从正态分布的随机数
# 生成一个形状与输入信号(signal)相同的数组,其中每个元素都服从均值为 0、方差为 STD_n 的正态分布。
生成的噪声图:
使用快速傅里叶变化来分析噪声的频率部分
X=np.fft.rfft(noise)
radius,angle=to_polar(X)
频率分布非常平稳,符合“白”的特征
signal_noise = signal+noise
SNR=10dB
加入噪声的完整代码
#SNR in dB
#given a signal and desired SNR, this gives the required AWGN what should be added to the signal to get the desired SNR
def get_white_noise(signal,SNR) :
#RMS value of signal
RMS_s=math.sqrt(np.mean(signal**2))
#RMS values of noise
RMS_n=math.sqrt(RMS_s**2/(pow(10,SNR/10)))
#Additive white gausian noise. Thereore mean=0
#Because sample length is large (typically > 40000)
#we can use the population formula for standard daviation.
#because mean=0 STD=RMS
STD_n=RMS_n
noise=np.random.normal(0, STD_n, signal.shape[0])
return noise
#***convert complex np array to polar arrays (2 apprays; abs and angle)
def to_polar(complex_ar):
return np.abs(complex_ar),np.angle(complex_ar)
#**********************************
#*************add AWGN noise******
#**********************************
signal_file='/home/sleek_eagle/research/emotion/code/audio_processing/signal.wav'
signal, sr = librosa.load(signal_file)
signal=np.interp(signal, (signal.min(), signal.max()), (-1, 1))
noise=get_white_noise(signal,SNR=10)
#analyze the frequency components in the signal
X=np.fft.rfft(noise)
radius,angle=to_polar(X)
plt.plot(radius)
plt.xlabel("FFT coefficient")
plt.ylabel("Magnitude")
plt.show()
signal_noise=signal+noise
plt.plot(signal_noise)
plt.xlabel("Sample number")
plt.ylabel("Amplitude")
plt.show()
将有噪声的音频加入到原始音频中
我们需要计算原始音频的RMS和噪声音频的RMS,为了能得到规定的SNR,我们需要修改噪声的RMS值,办法就是将每个噪声元素都乘上一个常数,这样就能使得噪声的RMS值也乘上一个常数,达到需要的噪声RMS。
噪声音频(水流的声音):
加入噪声的音频:
To listen to the signal and noise I used and also to the noise-added audio files that were created by adding noise to the signal, go to
#given a signal, noise (audio) and desired SNR, this gives the noise (scaled version of noise input) that gives the desired SNR
def get_noise_from_sound(signal,noise,SNR):
RMS_s=math.sqrt(np.mean(signal**2))
#required RMS of noise
RMS_n=math.sqrt(RMS_s**2/(pow(10,SNR/10)))
#current RMS of noise
RMS_n_current=math.sqrt(np.mean(noise**2))
noise=noise*(RMS_n/RMS_n_current)
return noise
#**********************************
#*************add real world noise******
#**********************************
signal, sr = librosa.load(signal_file)
signal=np.interp(signal, (signal.min(), signal.max()), (-1, 1))
plt.plot(signal)
plt.xlabel("Sample number")
plt.ylabel("Signal amplitude")
plt.show()
noise_file='/home/sleek_eagle/research/emotion/code/audio_processing/noise.wav'
noise, sr = librosa.load(noise_file)
noise=np.interp(noise, (noise.min(), noise.max()), (-1, 1))
#crop noise if its longer than signal
#for this code len(noise) shold be greater than len(signal)
#it will not work otherwise!
if(len(noise)>len(signal)):
noise=noise[0:len(signal)]
noise=get_noise_from_sound(signal,noise,SNR=10)
signal_noise=signal+noise
print("SNR = " + str(20*np.log10(math.sqrt(np.mean(signal**2))/math.sqrt(np.mean(noise**2)))))
plt.plot(signal_noise)
plt.xlabel("Sample number")
plt.ylabel("Amplitude")
plt.show()
参考链接:click here