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