如題,這應該算是我前往語音這座大山的第一步,在此做出記錄。
一、工作背景
由於需要進行單通道降噪的實驗,但是現在只有純淨語音和噪聲數據,而在閱讀文章的過程中,大家並沒有將這個細小的內容寫道論文中(的確也不應該,做出來之後確實感覺蠻簡單的),所以只能自己通過純淨語音和噪聲合成自己需要的數據。
二、數據生成
需要復現的實驗是基於單通道的語音增強,同時根據張暉老師博士學位論文,在合成數據時使用TIMIT語料庫的核心訓練集中的1000局作爲訓練用的目標語音。再將這些語音與各種噪聲相混合(四種噪聲隨機一種),從NOISE-92中選取四種噪聲:嘈雜噪聲(babble noise)、工廠噪聲(factory1)、驅動艦動力室噪聲(destroyerops)和驅逐艦發動機噪聲(destroyerengine)。
每種噪聲3分55秒,將每種噪聲的前50%爲訓練集混合使用,後50%爲測試集混合使用,這樣訓練出的模型應該會有較好的泛化性。混合過程中分別使用-5dB、0dB作爲信噪比進行混合。
2.1 計算公式
首先我們對於公式進行解釋:
- 爲信噪比,單位爲dB
- 爲純淨語音能量
- 爲噪聲能量
爲了合成特定信噪比的混合語音,我們需要對噪聲能量進行調整,如:如需要q dB混合語音,調整噪聲能量的大小爲原來的倍,即新的噪聲信號爲,新的公式爲:
根據(2.2)可以推出:
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 合成結果
混合語音合成結果:
噪聲使用情況:
純淨語音: