一,什么是VAD
VAD, 也就是语音端点检测技术,是Voice Activity Detection的缩写。这个技术的主要任务是从带有噪声的语音中准确的定位出语音的开始和结束点,因为语音中含有很长的静音,也就是把静音和实际语音 分离开来,因为是语音数据的原始处理,所以VAD是语音信号处理过程的关键技术之一。它的好坏,直接影响成败,由于技术本身的特殊性,所以在涉及语音信号 处理的领域,端点检测技术的应用非常广泛。语音识别系统在识别或者声学模型训练阶段所遇到的第一个技术就是端点检测,把静音和噪声作为干扰信号从原始数据中去除,并且端点检测对于语音识别系统的性能至关重要。
二,VAD的作用
现 在流行的语音识别系统大部分,或者是相当一部分都是基于统计和训练的原理所构建的系统,因此对数据来源和训练环境都是很敏感的。在识别的过程中,经常存在 实际语音因背景噪声的干扰而与训练失配的情况,实际这也是造成语音识别系统鲁棒性差的一个根本原因(另一个主要的是无法处理非预期的输入),从而导致识别 错误,性能下降。哪怕是两段内容上是完全一致的语音信号,可能由于语速不一样,所以语音信号的时间也不相同,音素之间的时间间隙也就不一样,对于时变而非 平稳的语音信号来说,其特征就完全不相同了。有音素之间的间隙,也有静音和语音本身的间隙,为了对数据从时间上进行相对的校准,语音端点检测技术就应运而 生了,因此端点检测技术可以决定这种校准的相对精度,使得同一内容的特征更趋于相同,当然,一般情况下是不可能完全相同的。大量研究表明,如果环境是安静 的环境,没有太多背景噪声,此时语音识别系统的主要错误来源于端点检测技术不精确。
但在实际应用中,不可能没有背景噪声,另外由于麦克风的录制和信号增益也会带来噪声,所以语音识别系统的错误是由多方面影响的,至少包括:端点检测、特征提取、语音模型、声学模型、解码器等多个方面。
假定读取的语音数据是WAV文件格式的数据。
三,WAV数据头结构定义
- typedef struct{
- char FLAG[4];
- int resource_length;
-
- char WAVE_FLAG[4];
-
- char format_flag[4];
- int pcm_header_len;
- short int format_tag;
- short int channel_count;
- int sample_rate;
- int bytespersec;
- short int block_align;
- short int bits_per_samples;
- } wav_header;
上面是WAV文件格式的头定义 ,数据定义如下
- typedef struct{
- char data_flag[4];
- int length;
- }data_header;
在该结构之后,就是采样数据了。
下面读取文件代码:
-
-
-
-
-
-
- int read_wave_file(char *filename, short ** v_data, int *sampleRate){
- FILE *fp = fopen(filename, "rb");
- if (fp == NULL) {
- fprintf(stderr, "open wav file %s error\n", wfn);
- exit(-1);
- }
- char buf[20];
- wav_header *wav = new wav_header;
- data_header *data = new data_header;
-
-
- if (fread((void *) wav, sizeof (wav_header), 1, fp) != 1){
- fprintf(stderr, "cant read wav header\n");
- exit(-1);
- }
-
- for(int i=0;i<4;i++)
- buf[i] = wav->FLAG[i];
- buf[4] = 0;
- if(strcmp(buf,"RIFF")!=0){
- fprintf(stderr, "%s bad RIFF format\n", buf);
- exit(-1);
- }
-
- for(int i=0;i<4;i++)
- buf[i] = wav->WAVE_FLAG[i];
- buf[4] = 0;
- if(strcmp(buf,"WAVE")!=0){
- fprintf(stderr, "%s bad WAVE format\n", buf);
- exit(-1);
- }
-
- for(int i=0;i<3;i++)
- buf[i] = wav->format_flag[i];
- buf[3] = 0;
- if(strcmp(buf,"fmt")!=0){
- fprintf(stderr, "%s bad fmt format\n", buf);
- exit(-1);
- }
-
-
- if(wav->format_tag!=1){
- fprintf(stderr, "bad wav format tag\n");
- exit(-1);
- }
-
- if(wav->bits_per_samples != 16){
- fprintf(stderr, "bad wav bits per sample\n");
- exit(-1);
- }
-
- if (sampleRate != NULL)
- *sampleRate = wav->sample_rate;
-
-
- int skip = 1;
- while(skip!=0){
-
- if(skip>10){
- fprintf(stderr, "too many chunks\n");
- exit(-1);
- }
-
-
- if (fread((void *)data,sizeof(data_header),(size_t)1,fp) != 1){
- fprintf(stderr, "cant read chunk\n");
- exit(-1); }
-
-
-
- for(int i=0;i<4;i++)
- buf[i] = data->data_flag[i];
- buf[4] = 0;
-
- if(strcmp(buf,"data")==0)
- break;
-
-
- skip++;
- fseek(fp,data->length,SEEK_CUR);
- }
-
-
- int wbuff_len = data->length;
- char * wbuff = new char [wbuff_len];
- if(wbuff==NULL){
- fprintf(stderr, "alloc memory failed\n");
- exit(-1);
- }
-
- int nsample = data->length/(wav->bits_per_samples / 8);
-
-
- if (fread((void *)wbuff,wbuff_len,(size_t)1,fp) != 1){
- fprintf(stderr, "cant read wbuff\n");
- exit(-1);
- }
-
-
- *v_data = (short *) wbuff;
-
- fclose(fp);
-
-
- return nsample;
- }
(lv_xinmy) |