利用純淨語音和噪聲合成不同信噪比的訓練數據

如題,這應該算是我前往語音這座大山的第一步,在此做出記錄。

一、工作背景

  由於需要進行單通道降噪的實驗,但是現在只有純淨語音和噪聲數據,而在閱讀文章的過程中,大家並沒有將這個細小的內容寫道論文中(的確也不應該,做出來之後確實感覺蠻簡單的),所以只能自己通過純淨語音和噪聲合成自己需要的數據。

二、數據生成

  需要復現的實驗是基於單通道的語音增強,同時根據張暉老師博士學位論文,在合成數據時使用TIMIT語料庫的核心訓練集中的1000局作爲訓練用的目標語音。再將這些語音與各種噪聲相混合(四種噪聲隨機一種),從NOISE-92中選取四種噪聲:嘈雜噪聲(babble noise)、工廠噪聲(factory1)、驅動艦動力室噪聲(destroyerops)和驅逐艦發動機噪聲(destroyerengine)。
  每種噪聲3分55秒,將每種噪聲的前50%爲訓練集混合使用,後50%爲測試集混合使用,這樣訓練出的模型應該會有較好的泛化性。混合過程中分別使用-5dB、0dB作爲信噪比進行混合。


2.1 計算公式

  首先我們對於公式進行解釋:
(2.1)SNR(s(t),n(t))=10log10ts2(t)tn2(t)SNR(s(t),n(t))=10·log_{10}{\frac {\sum_t s^2(t)}{\sum_t n^2(t)}} \tag{2.1}

  • SNRSNR爲信噪比,單位爲dB
  • ts2(t)\sum_ts^2(t)爲純淨語音能量
  • tn2(t){\sum_t n^2(t)}爲噪聲能量
      爲了合成特定信噪比的混合語音,我們需要對噪聲能量進行調整,如:如需要q dB混合語音,調整噪聲能量的大小爲原來的α\alpha倍,即新的噪聲信號爲αn(t)\alpha n(t),新的公式爲:
    (2.2)q=10log10ts2(t)α2tn2(t)q=10·log_{10}{\frac {\sum_t s^2(t)}{ \alpha^2 \sum_t n^2(t)}} \tag{2.2}
      根據(2.2)可以推出:
    (2.3)α=ts2(t)10q10tn2(t)\alpha = \sqrt{\frac {\sum_t s^2(t)}{10^{\frac{q}{10}}\sum_t n^2(t)}} \tag{2.3}

2.2 數據準備

  噪聲數據:
噪聲數據
可以看到,babble.wav是噪聲的原始文件,babble_test.wav爲babble.wav後50%切片,babble_train.wav爲babble.wav爲噪聲的前50%切片,其它同理。
切片實現:

from scipy.io import wavfile
import numpy as np
import soundfile as sf

sample_rate, sig = wavfile.read('D:/畢設數據/noise/factory1.wav')
# 採樣率:1S內對聲音信號的採樣次數
# print("採樣率: %d" % sample_rate)
# print(sig.shape)
# print(sig)
# 
# if sig.dtype == np.int16:
#     print("PCM16位整形")


half = sig.shape[0]/2
data_train = sig[:int(half)]
data_test = sig[int(half):]

sf.write('D:/畢設數據/noise/factory1_train.wav', data_train, sample_rate)
sf.write('D:/畢設數據/noise/factory1_test.wav', data_test, sample_rate)

2.3 數據合成

import numpy as np
import soundfile as sf
import librosa
import random
import os

sound_name = 'SI'


def switch(item):
    switcher = {
        0: 'babble',
        1: 'destroyerengine',
        2: 'destroyerops',
        3: 'factory1'
    }
    return switcher.get(item)


files = os.listdir('D:/畢設數據/TIMIT-TRAIN')

# 噪音的id
# [)
for i in range(0, 1000):

    # 隨機噪聲類型
    n_id = random.randint(0, 3)
    n_name = switch(n_id)
    # 原始語音
    a, a_sr = librosa.load('D:/畢設數據/TIMIT-TRAIN/' + files[i], sr=16000)
    # 噪音
    b, b_sr = librosa.load('D:/畢設數據/noise/' + n_name + '_train' + '.wav', sr=16000)
    # 隨機取一段噪聲,保證長度和純淨語音長度一致,保證不會越界
    start = random.randint(0, b.shape[0] - a.shape[0])
    # 切片
    n_b = b[int(start):int(start)+a.shape[0]]
    
    # 平方求和
    sum_s = np.sum(a ** 2)
    sum_n = np.sum(n_b ** 2)
    # 信噪比爲0dB時的權重
    x = np.sqrt(sum_s/(sum_n * pow(10, -0.5)))

    noise = x * n_b
    target = a + noise
    sf.write('D:/畢設數據/train_data/1dB/mix_sound/' + files[i].split('.')[0] + '_' + n_name + '.wav', target, 16000)
    sf.write('D:/畢設數據/train_data/1dB/sound/' + files[i].split('.')[0] + '.wav', a, 16000)
    sf.write('D:/畢設數據/train_data/1dB/noise/' + files[i].split('.')[0] + '_' + n_name + '_train' + '.wav', noise, 16000)

2.4 合成結果

混合語音合成結果:
合成結果
噪聲使用情況:
噪聲使用情況
純淨語音:
純淨語音

三、數據集

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章