• python对音频进行加噪的处理方法


    python对音频进行加噪的处理方法

    为了实现我们相对来说是纯净音频的噪声添加,我们分三步走:

    • 第一步,读取原始音频,并输出相关图像

    • 第二步,加入指定信噪比的高斯白噪声,并输出相关图像

    • 第三步,加入其他的噪声类,并输出相关图像

    一、读取原始音频

    读取原始音频的方法一般可以分成四类:scipy、pysoundfile、wave和librosa。

    注:代码里标粗部分就是读取方式

    1).scipy读取原始音频

    from scipy.io import wavfile
    import numpy as np
    import matplotlib.pyplot as plt

    sample_rate, sig = wavfile.read('C:/Users/Lenovo/Desktop/test_0_desc_30_100.wav')
    print("采样率: %d" % sample_rate)
    print(sig)

    if sig.dtype == np.int16:
       print("PCM16位整形")
    if sig.dtype == np.float32:
       print("PCM32位浮点")

    plt.figure(1)
    plt.subplot(4,1,1)
    plt.plot(sig[:,0])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,2)
    plt.plot(sig[:,1])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,3)
    plt.plot(sig[:,2])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,4)
    plt.plot(sig[:,3])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.show()

    #结果显示
    采样率: 44100
    [[  7  -9   3 -35]
    [ 25   1   8   2]
    [-32  -3   6  -6]
    ...
    [  5   7   5  20]
    [  3 -11  16  20]
    [-21   9  -8   2]]
    PCM16位整形

    因为音频是4通道的,所以图片分布为[1,2;3,4]

    2).pysoundfile读取音频

    import soundfile as sf
    import matplotlib.pyplot as plt

    sig, sample_rate = sf.read('C:/Users/Lenovo/Desktop/test_0_desc_30_100.wav')

    print("采样率:%d" % sample_rate)
    print(sig)

    plt.figure(1)
    plt.subplot(2,2,1)
    plt.plot(sig[:,0])
    plt.ylabel('Frequency1(Hz)')
    plt.xlabel('Time1(s)')

    plt.subplot(2,2,2)
    plt.plot(sig[:,1])
    plt.ylabel('Frequency2(Hz)')
    plt.xlabel('Time2(s)')

    plt.subplot(2,2,3)
    plt.plot(sig[:,2])
    plt.ylabel('Frequency3(Hz)')
    plt.xlabel('Time3(s)')

    plt.subplot(2,2,4)
    plt.plot(sig[:,3])
    plt.ylabel('Frequency4(Hz)')
    plt.xlabel('Time4(s)')

    plt.show()

    #结果显示
    采样率:44100
    [[ 2.13623047e-04 -2.74658203e-04  9.15527344e-05 -1.06811523e-03]
    [ 7.62939453e-04  3.05175781e-05  2.44140625e-04  6.10351562e-05]
    [-9.76562500e-04 -9.15527344e-05  1.83105469e-04 -1.83105469e-04]
    ...
    [ 1.52587891e-04  2.13623047e-04  1.52587891e-04  6.10351562e-04]
    [ 9.15527344e-05 -3.35693359e-04  4.88281250e-04  6.10351562e-04]
    [-6.40869141e-04  2.74658203e-04 -2.44140625e-04  6.10351562e-05]]

    图片分布位置同上

    3).wave读取音频

    import wave
    import numpy as np
    import matplotlib.pyplot as plt

    f = wave.open(r"D:/奇怪的东西/杂/ov1_split1/doa_data/wav_ov1_split1_30db/test_0_desc_30_100.wav", "rb")
    params = f.getparams()
    nchannels, sampwidth, framerate, nframes = params[:4]
    strData = f.readframes(nframes)#读取音频,字符串格式
    waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int
    waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化
    waveData = np.reshape(waveData,[nframes,nchannels])
    f.close()

    print('采样率:',framerate)
    plt.figure(1)
    plt.subplot(2,2,1)
    plt.plot(waveData[:,0])
    plt.ylabel('Frequency1(Hz)')
    plt.xlabel('Time1(s)')

    plt.subplot(2,2,2)
    plt.plot(waveData[:,1])
    plt.ylabel('Frequency2(Hz)')
    plt.xlabel('Time2(s)')

    plt.subplot(2,2,3)
    plt.plot(waveData[:,2])
    plt.ylabel('Frequency3(Hz)')
    plt.xlabel('Time3(s)')

    plt.subplot(2,2,4)
    plt.plot(waveData[:,3])
    plt.ylabel('Frequency4(Hz)')
    plt.xlabel('Time4(s)')

    plt.show()

    #结果显示
    采样率: 44100

    图片分布顺序同上:

    4).librosa读取音频

    import librosa.display
    import matplotlib.pyplot as plt
    import numpy as np

    path = "D:/奇怪的东西/杂/ov1_split1/doa_data/wav_ov1_split1_30db/test_0_desc_30_100.wav"
    fs = 44100  # 按多少采样率来加载音频,如果为none,则默认为22050

    sig1,sr1 = librosa.load(path, sr=fs, mono=True, offset=0.0, duration=None)
    sig2,sr2 = librosa.load(path, sr=fs, mono=False, offset=0.0, duration=None)

    print(sig1.shape)
    print(type(sig1))
    print(sig2.shape)
    print(type(sig2))

    original_fs = librosa.get_samplerate(path)  # 读取原始音频的采样率
    print('原始音频采样率:',original_fs)

    plt.figure(1)
    plt.subplot(2,1,1)
    librosa.display.waveplot(sig1, sr=fs, x_axis='time', offset=0.0, ax=None)
    plt.subplot(2,1,2)
    librosa.display.waveplot(sig2, sr=fs, x_axis='time', offset=0.0, ax=None)

    plt.show()

    #结果显示
    (1255275,)
    <class 'numpy.ndarray'>
    (4, 1255275)
    <class 'numpy.ndarray'>
    原始音频采样率: 44100

    由于librosa.display.waveplot只有打印单音频和立体声的形式,所以多通道的音频只能是一个合成立体声,如图,第一个为单音频,第二幅图为立体声

     

    如果想看多个通道的图,可以将librosa.display.waveplot都替换为plt.plot,可以生成如下图例(上图中的第二幅展开图):

    二、加入指定信噪比的高斯白噪声

    加入指定信噪比的高斯白噪声,我们首先可以定义一个高斯白噪声加入的文件,此处我命名为awgn.py文件,这个文件是由matlab中awgn函数改编过来的,可以直接复制粘贴使用,效果已经反复验证,是正确的。

    import numpy as np


    def awgn(x, snr, out='signal', method='vectorized', axis=0):

       # Signal power
       if method == 'vectorized':
           N = x.size
           Ps = np.sum(x ** 2 / N)

       elif method == 'max_en':
           N = x.shape[axis]
           Ps = np.max(np.sum(x ** 2 / N, axis=axis))

       elif method == 'axial':
           N = x.shape[axis]
           Ps = np.sum(x ** 2 / N, axis=axis)

       else:
           raise ValueError('method "' + str(method) + '" not recognized.')

       # Signal power, in dB
       Psdb = 10 * np.log10(Ps)

       # Noise level necessary
       Pn = Psdb - snr

       # Noise vector (or matrix)
       n = np.sqrt(10 ** (Pn / 10)) * np.random.normal(0, 1, x.shape)

       if out == 'signal':
           return x + n
       elif out == 'noise':
           return n
       elif out == 'both':
           return x + n, n
       else:
           return x + n

    然后,开始在原始音频加入高斯白噪声,这里就以第三种读取音频方式wave为例,添加指定信噪比为20dB和0dB的高斯白噪声,其他读取音频的添加方式一样。

    import wave
    import numpy as np
    import matplotlib.pyplot as plt
    from awgn import awgn


    f = wave.open(r"D:/奇怪的东西/杂/ov1_split1/doa_data/wav_ov1_split1_30db/test_0_desc_30_100.wav", "rb")
    params = f.getparams()
    nchannels, sampwidth, framerate, nframes = params[:4]
    strData = f.readframes(nframes)#读取音频,字符串格式
    waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int
    waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化
    waveData = np.reshape(waveData,[nframes,nchannels]).T

    snr = 0 #可以改成自己想要的
    waveData2 = awgn(waveData, snr, out='signal', method='vectorized', axis=0)
    f.close()

    plt.figure(1)
    plt.subplot(4,1,1)
    plt.plot(waveData[0])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,2)
    plt.plot(waveData[1])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,3)
    plt.plot(waveData[2])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,4)
    plt.plot(waveData[3])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.figure(2)
    plt.subplot(4,1,1)
    plt.plot(waveData2[0])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,2)
    plt.plot(waveData2[1])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,3)
    plt.plot(waveData2[2])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(4,1,4)
    plt.plot(waveData2[3])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')
    plt.show()

    这里就是第一种读取音频方式的图像输出,与上面生成的图像是一样的。

    下面是添加了指定信噪比20dB、0dB的高斯白噪声的生成图像

    下面是0dB的生成图像:

    三、加入指定噪声,如DEMAND、Noise92等噪声库的噪声

    原始音频为4通道,所以下面定义的空数组横坐标为4,通道数为几可以改成几。

    import wave
    import numpy as np
    import matplotlib.pyplot as plt


    f = wave.open(r"D:/奇怪的东西/杂/ov1_split1/doa_data/wav_ov1_split1_30db/test_0_desc_30_100.wav", "rb")
    params = f.getparams()
    nchannels, sampwidth, framerate, nframes = params[:4]
    strData = f.readframes(nframes)#读取音频,字符串格式
    waveData = np.frombuffer(strData,dtype=np.int16)#将字符串转化为int
    waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化
    waveData = np.reshape(waveData,[nframes,nchannels]).T

    g = wave.open(r"C:/Users/Lenovo/Desktop/ch04.wav", "rb")
    params2 = g.getparams()
    nchannels2, sampwidth2, framerate2, nframes2 = params2[:4]
    strData2 = g.readframes(nframes2)#读取音频,字符串格式
    waveData2 = np.frombuffer(strData2,dtype=np.int16)#将字符串转化为int
    waveData2 = waveData2*1.0/(max(abs(waveData2)))#wave幅值归一化
    waveData2 = np.reshape(waveData2,[nframes2,nchannels2]).T

    new = np.zeros(shape=(4,nframes))
    for i in range(4):
       # 对不同长度的音频用数据零对齐补位,保证纯净音频长度
       if nframes < nframes2:
           rwaveData = waveData[i]
           rwaveData2 = waveData2[:,0:nframes]
       elif nframes > nframes2:
           length = abs(nframes2 - nframes)
           temp_array = np.zeros(length, dtype=np.int16)
           rwaveData2 = np.concatenate((waveData2, temp_array))
           rwaveData = waveData[i]
       else:
           rwaveData = waveData[i]
           rwaveData2 = waveData2
           
    # ================================
       # 合并1和2的数据
       new_waveData = rwaveData + rwaveData2
       new[i] = new_waveData

    f.close()
    g.close()

    plt.figure(1)
    plt.subplot(2,2,1)
    plt.plot(waveData[0])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(2,2,2)
    plt.plot(waveData[1])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(2,2,3)
    plt.plot(waveData[2])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(2,2,4)
    plt.plot(waveData[3])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')


    plt.figure(2)
    plt.subplot(2,2,1)
    plt.plot(new[0])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(2,2,2)
    plt.plot(new[1])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(2,2,3)
    plt.plot(new[2])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')

    plt.subplot(2,2,4)
    plt.plot(new[3])
    plt.ylabel('Frequency(Hz)')
    plt.xlabel('Time(s)')
    plt.show()

    生成如下结果图:

     

  • 相关阅读:
    [Android]XML那些事儿-manifest属性2
    [Android]数据存储-SharedPreferences1
    [Android]2013.5.4日志
    [Android]获得Andriod手机屏幕分辨率的两种方法
    [Android]Java-break(label)/return/continue语句详解
    [WordPress]欢迎使用 WordPress for SAE
    [Webkit]最简单易用的webkit学习环境-ISee
    [Webkit]了解WebKit与Qt WebKit对比区别
    [PhoneGap]开发环境搭建与简单应用
    LeetCode-62.Unique Paths
  • 原文地址:https://www.cnblogs.com/minyuan/p/14078114.html
Copyright © 2020-2023  润新知