print('Processing: ', filepath)
path, file = os.path.split(filepath)
noisy_path = path.replace('dev-clean', 'dev-noise-gassian')
print(path, file)
if not os.path.exists(noisy_path):
os.makedirs(noisy_path)
noisy_filepath = os.path.join(noisy_path, file)
audio_signal, samplerate = sf.read(filepath)
noise = np.random.normal(0, 0.1, audio_signal.shape[0])
noisy_signal = audio_signal + noise
print(audio_signal)
print(noisy_signal)
sf.write(noisy_filepath, noisy_signal, samplerate)
quit()
That's what I'm doing, and it adds noise, but I don't know what the SNR of the noise is. How do I calibrate the addition of noise to match a specified SNR?
Thanks
First, some theory:
You can compute the SNR by dividing the average power of the signal by the average power of the noise.
For any given signal, you can estimate its average power using its power spectral density. In brief, it's the averaged amplitude of its FFT.
Here's a working example using numpy FFT:
import numpy as np
import soundfile as sf
sampling_rate = 42000 #42kHz sampling rate is enough for audio
Nsamples = 100000 # a bit more than 2 seconds of signal at the current sampling rate
freq = 440 # musical A
A = 5
noiseAmplitude = 5
noiseSigma = 0.1
noise = noiseAmplitude * np.random.normal(0, noiseSigma, Nsamples)
# Generate a pure sound sampled at our sampling_rate for a duration of roughly 2s
cleanSound = A*np.sin(2*np.pi*freq/sampling_rate*np.arange(Nsamples))
sampleSound = cleanSound + noise
# For a pure sine and a white noise, the theoretical SNR in dB is:
theoreticalSNR = 20*np.log10(A/(np.sqrt(2)*noiseAmplitude*noiseSigma)) # the sqrt of 2 is because of root-mean square amplitude
## Experimental measurement using FFT (we use sampling_rate//2 points for Nyquist)
# power spectrum of the clean sound (averaged spectral density)
cleanPS = np.sum(np.abs(np.fft.fft(cleanSound,sampling_rate//2)/Nsamples)**2)
# same for noise
noisePS = np.sum(np.abs(np.fft.fft(noise,sampling_rate//2)/Nsamples)**2)
# 10 instead of 20 because we're using power instead of RMS amplitude
measuredSNR = 10*np.log10(cleanPS/noisePS)
# write to output sound file
sf.write('/tmp/sample.wav',sampleSound,sampling_rate)
With the values from above, I get a theoretical SNR of 16.989 dB and a measured SNR of 16.946 dB.
Therefore, if you want to add white noise with a given SNR to any given audio signal, you can compute the white noise power by reversing the formula: SNR = 10*np.log10(cleanPS/noisePS)
and chose the noiseAmplitude and noiseSigma accordingly.