Как я могу добавить гауссовский шум с указанным SNR в аудиофайл со звуковым файлом в Python?
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()
Это то, что я делаю, и это добавляет шума, но я не знаю, что такое SNR шума. Как мне откалибровать добавление шума для соответствия указанному SNR?
Спасибо
1 ответ
Для начала немного теории:
Вы можете вычислить SNR, разделив среднюю мощность сигнала на среднюю мощность шума.
Для любого данного сигнала вы можете оценить его среднюю мощность, используя его спектральную плотность мощности. Короче говоря, это усредненная амплитуда его БПФ.
Вот рабочий пример с использованием 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)
Со значениями, приведенными выше, я получаю теоретическое SNR 16,989 дБ и измеренное SNR 16,946 дБ. Следовательно, если вы хотите добавить белый шум с заданным отношением сигнал / шум к любому заданному аудиосигналу, вы можете вычислить мощность белого шума, изменив формулу в обратном порядке:SNR = 10*np.log10(cleanPS/noisePS)
и соответственно выбрал noiseAmplitude и noiseSigma.