webRTC : 如何通过从WAV文件获得的样本将webRTC的VAD应用于音频

webRTC : How to apply webRTC's VAD on audio through samples obtained from WAV file

本文关键字:webRTC 样本 VAD 音频 应用于 何通过 WAV 文件      更新时间:2023-10-16

目前,我正在解析wav文件并将样本存储在std::vector<int16_t> sample中。现在,我想对这些数据应用VAD(语音活动检测)来找出语音的"区域",更具体地说是单词的开头和结尾。

解析的wav文件是16KHz,16位PCM,单声道。我的代码是C++的。

我已经搜索了很多关于它的信息,但找不到有关webRTC的VAD函数的正确文档。

从我发现的情况来看,我需要使用的功能是WebRtcVad_Process().它的原型写在下面:

int WebRtcVad_Process(VadInst* handle, int fs, const int16_t* audio_frame,
size_t frame_length)

从我在这里发现的:https://stackoverflow.com/a/36826564/6487831

发送到 VAD 的每个音频帧长度必须为 10、20 或 30 毫秒。 下面是一个示例的概述,该示例假设audio_frame 16000 Hz 的音频为 10 毫秒(320 字节):

int is_voiced = WebRtcVad_Process(vad, 16000, audio_frame, 160);

这是有道理的:

1 sample = 2B = 16 bits  
SampleRate = 16000 sample/sec = 16 samples/ms  
For 10 ms, no of samples    =   160  

因此,基于此,我已经实现了:

const int16_t * temp = sample.data();
for(int i = 0, ms = 0; i < sample.size(); i += 160, ms++)
{
int isActive = WebRtcVad_Process(vad, 16000, temp, 160); //10 ms window
std::cout<<ms<<" ms : "<<isActive<<std::endl;
temp = temp + 160; // processed 160 samples
}

现在,我不太确定这是否正确。另外,我也不确定这是否给了我正确的输出。

所以

  • 是否可以使用直接从 wav 文件解析的示例,或者是否需要一些处理?
  • 我是否在寻找正确的功能来完成这项工作?
  • 如何使用该功能在音频流上正确执行VAD?
  • 是否可以区分口语?
  • 检查我得到的输出是否正确的最佳方法是什么?
  • 如果没有,完成此任务的最佳方法是什么?

我首先要说的是,不,我认为您将无法使用VAD将话语分割成单个单词。 来自维基百科中关于语音分割的文章:

人们可能会期望许多书面使用的单词间空格 英语或西班牙语等语言将对应于其暂停 口语版本,但这仅在非常慢的语音中是正确的,当 演讲者故意插入这些停顿。在正常语音中,一个 通常会发现许多连续说出的单词没有停顿 在它们之间,通常一个单词的最终声音平滑地混合或 与下一个单词的初始声音融合。

也就是说,我会尝试回答你的其他问题。

  1. 在运行 VAD 之前,您需要将可以压缩的 WAV 文件解码为原始 PCM 音频数据。 例如,请参阅在 C/C++ 中读取和处理 WAV 文件数据。 或者,您可以使用类似sox的内容在运行代码之前将 WAV 文件转换为原始音频。 此命令将以WebRTCVAD期望的格式将任何格式的WAV文件转换为16 KHz,16位PCM:

    sox my_file.wav -r 16000 -b 16 -c 1 -e signed-integer -B my_file.raw
    
  2. 看起来您正在使用正确的功能。 更具体地说,您应该这样做:

    #include "webrtc/common_audio/vad/include/webrtc_vad.h"
    // ...
    VadInst *vad;
    WebRtcVad_Create(&vad);
    WebRtcVad_Init(vad);
    const int16_t * temp = sample.data();
    for(int i = 0, ms = 0; i < sample.size(); i += 160, ms += 10)
    {
    int isActive = WebRtcVad_Process(vad, 16000, temp, 160); //10 ms window
    std::cout << ms << " ms : " << isActive << std::endl;
    temp = temp + 160; // processed 160 samples (320 bytes)
    }
    
  3. 要查看它是否有效,您可以运行已知文件并查看是否获得预期的结果。 例如,您可以从处理静音开始,并确认您永远不会(或很少 - 此算法并不完美)看到从WebRtcVad_Process返回的浊音结果。 然后,您可以尝试一个文件,该文件除了中间的一个简短话语外,其他所有文件都是静音的。 如果你想与现有的测试进行比较,py-webrtcvad 模块有一个单元测试来做到这一点;请参阅test_process_file函数。

  4. 要进行单词级分割,您可能需要找到一个语音识别库来执行此操作或允许您访问执行此操作所需的信息。 例如,Kaldi 邮件列表中的这个线程似乎在讨论如何按单词进行细分。