VAD(VoiceActivityDetection)语音活动检测,作用是从一段语音中,识别出语音片段和非语音片段。比如在语音增强中谱减法,我们我们通过将带噪信号频谱减掉噪声信号频谱得到希望的语音信号,那么噪声信号的获得我们就可通过VAD来获取。
VAD可通过提取语音信号的多个特征进行判断来设计,一般来说取的特征越多,vad越精细。查看各种文献,发现语音信号的特征有十多个,现在设计一款比较简单方法,仅取语音信号的两个特征,这两个特征是短时能量和过零率,当然由于取用的特征较少,该方法在vad的使用中有很大的局限性,后续在了解其他特征原理后再行进行优化。。
1、短时能量,即每帧语音信号的能量,之前程序中已实现过。
2、过零率:即每帧语音信号中,信号通过时间轴即零点的次数。这个特征对于敲击类声音可明显分辨出。
此次设计要求:按照帧长160,帧移80的分帧设置读取pcm音频文件后,计算每帧的平均能量和过零率,用作VAD的判定值。
过零率的设计:A^B:按位异或,带符号的数据A和B,当A、B符号相同时,返回0,反之返回1,再使用for循环得到每帧的过零率。
过零率案例:
int crossingNum = 0;int i = 0;int array[10] = {1,-1,-1,1,-1,1,-1,1};for(i=1;i<10;i++){crossingNum+=((array[i]^array[i-1])<0);}
int型数据首位是符号位,当两个符号位相同的时候,异或结果的符号为0,是正数,不满足<0的条件,crossingNum自加0.反之,异或结果的符号为为1,满足<0的条件,crossingNum自加1。
本次代码实现如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
const int FRAMELEN = 160; //帧长
const int STEP = 80; //帧移
const float MAX_AMPLITUDE_16S_P = 32767; //short-float转换
int i;
float power_average = 0;
float power_threshold = 0.00005;
short zero_crossing_rate_threshold = 35;
int array_sum; //存放计算过零率
int vad1; //根据平均能量判定得出vad1
int vad2; //根据过零率判定得出vad2
int vad; //根据两个特征得判定出vad
typedef struct {
FILE *input_ptr;
FILE *output_ptr;