-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmix_noise.py
126 lines (91 loc) · 3.5 KB
/
mix_noise.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Feb 17 15:46:56 2020
@author: sleek_eagle
"""
import math
import numpy as np
import librosa
import matplotlib.pyplot as plt
'''
Signal to noise ratio (SNR) can be defined as
SNR = 20*log(RMS_signal/RMS_noise)
where RMS_signal is the RMS value of signal and RMS_noise is that of noise.
log is the logarithm of 10
*****additive white gausian noise (AWGN)****
- This kind of noise can be added (arithmatic element-wise addition) to the signal
- mean value is zero (randomly sampled from a gausian distribution with mean value of zero. standard daviation can varry)
- contains all the frequency components in an equal manner (hence "white" noise)
'''
#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
#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
#***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()
#**********************************
#*************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()
from scipy.io.wavfile import write
write("/home/sleek_eagle/research/emotion/code/audio_processing/bbb.wav",sr,signal_noise)