和图像处理一样,我们在进行音频任务的模型训练时,也需要对音频进行一些随机处理,作为训练数据的增广。本文主要介绍音频低音消除,音频增加噪声,音频变速。
低音消除
低音消除可以使用在训练过程中,使用librosa,根据frame_length和分贝数来进行低音片段的裁剪,代码如下
代码语言:txt复制librosa.effects.trim(myrecording, top_db=50, frame_length=256, hop_length=64)
也可以在数据预处理就将低音切除,我一般使用的webrtcvad检测出低音片段,然后删除低音片段。
webrtcvad低音检测参考:https://github.com/wiseman/py-webrtcvad/blob/master/example.py
其中检测主要代码如下:
代码语言:txt复制vad = webrtcvad.Vad(3)
frames = frame_generator(30, audio, sample_rate)
def vad_collector(sample_rate, frame_duration_ms,
padding_duration_ms, vad, frames, num_max_voice=0.8, num_max_no_voice=0.3):
"""
提取有效音频片段列表(300/30) 10次vad检测结果通过num_max_voice阈值判断是否保存
:param sample_rate: 采样率
:param frame_duration_ms: vad检测时长:30ms
:param padding_duration_ms: 采样音频间隔:300ms
:param vad: vad检测对象
:param frames: 生成采样数据(gen_frames)列表
:param num_max_voice: vad占比阈值
"""
num_padding_frames = int(padding_duration_ms / frame_duration_ms)
ring_buffer = collections.deque(maxlen=num_padding_frames)
triggered = False
voiced_frames = []
count = 0
for frame in frames:
count = count 1
# sys.stdout.write('n1_count=' str(count) if vad.is_speech(frame.bytes, sample_rate) else 'n0_count=' str(count))
if not triggered:
ring_buffer.append(frame)
num_voiced = len([f for f in ring_buffer if vad.is_speech(f.bytes, sample_rate)])
# 累计是否为speech个数,大于阈值个数,记录
if num_voiced >= num_max_voice * ring_buffer.maxlen:
# sys.stdout.write(' voice_start--(%s)' % (ring_buffer[0].timestamp,))
triggered = True
voiced_frames.extend(ring_buffer)
ring_buffer.clear()
else:
voiced_frames.append(frame)
ring_buffer.append(frame)
num_unvoiced = len([f for f in ring_buffer if not vad.is_speech(f.bytes, sample_rate)])
# 持续记录,累计非speech个数大于阈值个数,退出当前保存片段,循环下一段
if num_unvoiced >= num_max_no_voice * ring_buffer.maxlen:
triggered = False
yield b''.join([f.bytes for f in voiced_frames])
ring_buffer.clear()
voiced_frames = []
if triggered:
sys.stdout.write('-(%s)' % (frame.timestamp frame.duration))
sys.stdout.write('n')
if voiced_frames:
yield b''.join([f.bytes for f in voiced_frames])
音频增加噪声
在训练过程中,通常我们会随机为音频添加噪声。这里一般可以随机生成一段白噪声,或者读取噪声文件(风,街道,敲键盘,嘈杂环境等),然后按一定比例加入到原始音频即可。
代码如下:
代码语言:txt复制#音频文件
data, sr = librosa.core.load(in_path, sr=16000)
#随机生成白噪声
noise = np.random.rand(len(data))
#噪声文件
noise = librosa.core.load(noise_path, sr=16000)
音频融合
data = percent*data (1-percent)* noise
data = clip(-1,1)
音频变速
除了常用的剔除静音,mix数据来做增强,我们好可以通过对音频变速来对做数据扩展。
我通常会使用sonic库来实现,代码如下:
代码语言:txt复制def speed_audio(path,save_path ,speed):
lib = ctypes.cdll.LoadLibrary
sonic_lib = lib("./sonic-master/libsonic.so")
fs, wav = wavfile.read(path)
wav = np.array(wav, dtype='int16')
wav_speech_change = sonic_lib.wavChangeSpeed
wav_speech_change.argtypes = [ndpointer(ctypes.c_short), ndpointer(ctypes.c_short), ctypes.c_int, ctypes.c_int,
ctypes.c_int, ctypes.c_float]
wav_speech_change.restypes = None
result = np.zeros((int(wav.shape[0] / speed)), dtype='int16')
# wav,result,nunchannel,framesample,wavlen,speech
wav_speech_change(wav, result, 1, fs, wav.shape[0], speed)
wavfile.write(save_path, SAMPLE_RATE, result.astype(np.int16))