【问题标题】:How can I add gaussian noise with a specified SNR to an audio file with Soundfile in Python?如何在 Python 中使用 Soundfile 将具有指定 SNR 的高斯噪声添加到音频文件中?
【发布时间】:2019-10-16 21:28:56
【问题描述】:
    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?

谢谢

【问题讨论】:

    标签: python numpy soundfile


    【解决方案1】:

    首先,一些theory

    您可以通过将信号的平均功率除以噪声的平均功率来计算 SNR。

    对于任何给定信号,您可以使用其power spectral density 估算其平均功率。简而言之,就是它的 FFT 的平均幅度。

    这是一个使用 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)
    

    根据上面的值,我得到 16.989 dB 的理论 SNR 和 16.946 dB 的实测 SNR。 因此,如果您想将具有给定 SNR 的白噪声添加到任何给定的音频信号,您可以通过反转公式来计算白噪声功率:SNR = 10*np.log10(cleanPS/noisePS) 并相应地选择 noiseAmplitude 和 noiseSigma。

    【讨论】:

    • 这假设 OP 的“audio_signal”一开始就没有噪音,但除此之外是一个很好的答案
    • @mathewgunther 确实。考虑到音频文件中已经存在的噪音,情况就完全不同了!
    猜你喜欢
    • 1970-01-01
    • 2020-08-04
    • 2019-03-25
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 2020-10-08
    相关资源
    最近更新 更多