音频知识(五)--数据处理

2021-07-07 20:14:27 浏览数 (1)

和图像处理一样,我们在进行音频任务的模型训练时,也需要对音频进行一些随机处理,作为训练数据的增广。本文主要介绍音频低音消除,音频增加噪声,音频变速。

低音消除

低音消除可以使用在训练过程中,使用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))

0 人点赞