main_VAD_0909.cpp
资源名称:se06.rar [点击查看]
上传用户:kepeng103
上传日期:2022-07-27
资源大小:2653k
文件大小:23k
源码类别:
DSP编程
开发平台:
C/C++
- /**********本函数的功能是用能量和自相*******************
- ***********关向量方差相结合的算法来进*******************
- ******************行VAD检测*****************************/
- /**********胡曙辉,2008年4月完成********************/
- /*4.3 加入了一些必须的初始化语句,*/
- /*4.7 在判断语音起始点和结束点加入了窗移动函数,即用连续多帧来进行判断*
- *******解决了训练过程的一个bug*******/
- /*4.8 把整个代码用函数实现**********/
- /*4.14 对语音的结束点判断采用了另一种方法*/
- /*4.16 静噪时候的压缩倍数必须增大,否则当输入信号的能量较大时,可以听到较小的压缩后输出。到1000倍左右,目前是150倍***
- ********为了减少误报率,必须提高能量门限,8倍到10倍左右,第二级门限设定到5至7倍,**
- ********找语音结束点的时候,采用的是两级判决方法,首先在50帧内计算出能量少于某一门限的帧数,如果帧数大于某一个值,这个值需要进行一定的试验调整(选15~25帧),然后对最后一帧用avv判决,这里好像有一定的偶然性,可能会提前终止语音。是否可以将avv加到能量判决那一部分中,统计同时满足两个条件的总帧数。*****
- ********当找到语音起始点的时候,默认输出100帧(1.6s),可能在换台的时候会使系统的静噪关断时延超过3s。因为后面还有50帧的统计,总时间为2.4s,如果第一次未能准确判决,将会有4.8s才能关断。将100帧换为75帧,时延减少0.4s,换为50帧,时延减少0.8s。********/
- /*k值有变换,今天试验的时候需要选择10,以前是2.5,有点奇怪。*/
- /*4.17 语音起始点判断的时候,连续两帧满足avv才判为语音起始点(效果很好,噪声误判率极低,试听了很久)*/
- /* 4.18 根据试验结果修改了一些参数值*/
- /* 4.23 改变了语音起始点的检测,起始点和结束点的参数也不一样,并不是判为噪声才进行噪声更新,在能量低于1.5倍门限的时候也进行噪声更新,防止长时间不更新噪声影响系统的判决。
- 每次找语音起始点之前重新训练信道*/
- #include "..commonhal.h"
- #include "device.h"
- #include "buf.h"
- #include <stdio.h>
- #include <math.h>
- #define FRAMELEN 256
- #define PI 4.0*atan(1.0)
- float noise_energy[10]={0};
- float subframe_energy[32]={0};
- float input_signal[128]={0};
- float energy_threshhold=0;
- float average_noiseenergy=0;
- float signal_energy=0;
- float signal_temp[128];
- float frame_energyvariance=0;
- float frame_noisereference=0;
- float frame_energyreference;
- int16 qq[128]={0};
- int16 *p;
- /////////////////
- int16 cm[128];
- float w1[FRAMELEN]; //蝶形因子
- float fft1[FRAMELEN*2]; //每帧语音信号的FFT
- float yp[FRAMELEN]; //未处理语音信号的功率谱
- float dp[129]; //噪声功率谱
- float xp[129]; //增强后语音信号的功率谱
- float predp[129]; //前一帧噪声信号的功率谱
- float prexp[129]; //前一帧增强后语音信号的功率谱
- float yo[FRAMELEN]; //增强后的时域信号
- float sita[FRAMELEN]; //相角
- float amp[FRAMELEN]; //幅度值
- float pre_energy[200]; //统计直方图所用每帧信号能量
- unsigned quota[129];
- float dm[FRAMELEN];
- float d1[FRAMELEN];
- float const hamming[FRAMELEN] = {0.0800, 0.0801, 0.0806, 0.0812, 0.0822, 0.0835, 0.0850, 0.0868,
- 0.0888, 0.0912, 0.0938, 0.0967, 0.0998, 0.1032, 0.1069, 0.1108,
- 0.1150, 0.1195, 0.1242, 0.1291, 0.1343, 0.1398, 0.1454, 0.1514,
- 0.1575, 0.1639, 0.1705, 0.1774, 0.1844, 0.1917, 0.1992, 0.2068,
- 0.2147, 0.2228, 0.2311, 0.2395, 0.2482, 0.2570, 0.2660, 0.2751,
- 0.2844, 0.2939, 0.3035, 0.3133, 0.3232, 0.3332, 0.3433, 0.3536,
- 0.3640, 0.3744, 0.3850, 0.3957, 0.4065, 0.4173, 0.4282, 0.4392,
- 0.4503, 0.4614, 0.4725, 0.4837, 0.4949, 0.5062, 0.5174, 0.5287,
- 0.5400, 0.5513, 0.5626, 0.5738, 0.5851, 0.5963, 0.6075, 0.6186,
- 0.6297, 0.6408, 0.6518, 0.6627, 0.6735, 0.6843, 0.6950, 0.7056,
- 0.7160, 0.7264, 0.7367, 0.7468, 0.7568, 0.7667, 0.7765, 0.7861,
- 0.7956, 0.8049, 0.8140, 0.8230, 0.8318, 0.8405, 0.8489, 0.8572,
- 0.8653, 0.8732, 0.8808, 0.8883, 0.8956, 0.9026, 0.9095, 0.9161,
- 0.9225, 0.9286, 0.9346, 0.9402, 0.9457, 0.9509, 0.9558, 0.9605,
- 0.9650, 0.9692, 0.9731, 0.9768, 0.9802, 0.9833, 0.9862, 0.9888,
- 0.9912, 0.9932, 0.9950, 0.9965, 0.9978, 0.9988, 0.9994, 0.9999,
- 1.0000, 0.9999, 0.9994, 0.9988, 0.9978, 0.9965, 0.9950, 0.9932,
- 0.9912, 0.9888, 0.9862, 0.9833, 0.9802, 0.9768, 0.9731, 0.9692,
- 0.9650, 0.9605, 0.9558, 0.9509, 0.9457, 0.9402, 0.9346, 0.9286,
- 0.9225, 0.9161, 0.9095, 0.9026, 0.8956, 0.8883, 0.8808, 0.8732,
- 0.8653, 0.8572, 0.8489, 0.8405, 0.8318, 0.8230, 0.8140, 0.8049,
- 0.7956, 0.7861, 0.7765, 0.7667, 0.7568, 0.7468, 0.7367, 0.7264,
- 0.7160, 0.7056, 0.6950, 0.6843, 0.6735, 0.6627, 0.6518, 0.6408,
- 0.6297, 0.6186, 0.6075, 0.5963, 0.5851, 0.5738, 0.5626, 0.5513,
- 0.5400, 0.5287, 0.5174, 0.5062, 0.4949, 0.4837, 0.4725, 0.4614,
- 0.4503, 0.4392, 0.4282, 0.4173, 0.4065, 0.3957, 0.3850, 0.3744,
- 0.3640, 0.3536, 0.3433, 0.3332, 0.3232, 0.3133, 0.3035, 0.2939,
- 0.2844, 0.2751, 0.2660, 0.2570, 0.2482, 0.2395, 0.2311, 0.2228,
- 0.2147, 0.2068, 0.1992, 0.1917, 0.1844, 0.1774, 0.1705, 0.1639,
- 0.1575, 0.1514, 0.1454, 0.1398, 0.1343, 0.1291, 0.1242, 0.1195,
- 0.1150, 0.1108, 0.1069, 0.1032, 0.0998, 0.0967, 0.0938, 0.0912,
- 0.0888, 0.0868, 0.0850, 0.0835, 0.0822, 0.0812, 0.0806, 0.0801}; //hamming窗
- float out1[FRAMELEN/2];
- ///////////
- void train(void);
- void read_signal(void);
- void compress_signal(void);
- void subframe_energyvar(void);
- void noise_update(void);
- void sys_init(void)
- {
- gpio_init();
- dac_reset();
- mcbsp0_init_serial();
- adc_init();
- mcasp_init();
- timer0_init();
- ADC_SE_HI();
- ISTP = 0x00000400;
- IER |= 0x00000002;
- CSR |= 0x00000001;
- }
- void spark_led(void)
- {
- REG32(MCASP1_PFUNC) |= 0x0000003e;
- REG32(MCASP1_PDIR) |= 0x0000003e;
- REG32(MCASP1_PDOUT) = 0x00000000;
- uint8 code = 1;
- for(int k=0; k<10; k++)
- {
- set_led(0xff, code);
- code <<= 1;
- code = (code == 0x20? 1:code);
- delay_ms(100);
- }
- REG32(MCASP1_PDOUT) = 0x00000000;
- }
- int16 data[128];
- void data_init(void)
- {
- for(int i=0; i<128; i++)
- {
- data[i] = 30000*sin(i*PI*2/64);
- }
- }
- //////////////////////////
- void gen_w_r2(float* w, int n) //产生旋转因子(n个)的函数
- {
- int i;
- float pi = 4.0*atan(1.0);
- float e = pi*2.0/n;
- for(i=0; i < ( n>>1 ); i++) {
- w[2*i] = cos(i*e);
- w[2*i+1] = sin(i*e);
- }
- }
- void bit_rev(float* x, int n) //产生n比特翻转的函数,将x[]做n比特翻转
- {
- int i, j, k;
- float rtemp, itemp;
- j = 0;
- for(i=1; i < (n-1); i++) {
- k = n >> 1;
- while(k <= j) {
- j -= k;
- k >>= 1;
- }
- j += k;
- if(i < j) {
- rtemp = x[j*2];
- x[j*2] = x[i*2];
- x[i*2] = rtemp;
- itemp = x[j*2+1];
- x[j*2+1] = x[i*2+1];
- x[i*2+1] = itemp;
- }
- }
- }
- void DSPF_sp_cfftr2_dit(float* x, float* w, short n) //计算n点FFT的函数
- {
- short n2, ie, ia, i, j, k, m;
- float rtemp, itemp, c, s;
- n2 = n;
- ie = 1;
- for(k=n; k > 1; k >>= 1) {
- n2 >>= 1;
- ia = 0;
- for(j=0; j < ie; j++) {
- c = w[2*j];
- s = w[2*j+1];
- for(i=0; i < n2; i++) {
- m = ia + n2;
- rtemp = c * x[2*m] + s * x[2*m+1];
- itemp = c * x[2*m+1] - s * x[2*m];
- x[2*m] = x[2*ia] - rtemp;
- x[2*m+1] = x[2*ia+1] - itemp;
- x[2*ia] = x[2*ia] + rtemp;
- x[2*ia+1] = x[2*ia+1] + itemp;
- ia++;
- }
- ia += n2;
- }
- ie <<= 1;
- }
- }
- void Stastic(void)
- {
- int h;
- float term; //统计直方图的幅度间隔
- unsigned maxScript; //记录统计直方图最大值下标
- float MAX; //200帧信号能量最大值
- float signal_energy; //本帧信号能量
- float Threshold; //直方图门限
- // float sum = 0.0; //本帧信号幅度值之和
- // float mean = 0.0; //平均每个点平均幅度
- float const coeffience1 = 3.8; //3.8
- float const coeffience2 = 0.005; //0.007
- float const coeffience3 = 0.5; //0.6
- //做每帧信号的FFT
- for (h = 0; h < FRAMELEN; h++)
- {
- fft1[h*2] = d1[h];
- fft1[h*2+1] = 0.0;
- }
- //做FRAMELEN个点FFT
- gen_w_r2(w1, FRAMELEN);
- bit_rev(w1, FRAMELEN/2);
- DSPF_sp_cfftr2_dit(fft1, w1, FRAMELEN);
- bit_rev(fft1, FRAMELEN);
- for (h=0; h < FRAMELEN; h++)
- {
- yp[h] = fft1[h*2]*fft1[h*2] + fft1[h*2+1]*fft1[h*2+1]; //未处理语音信号的功率谱
- sita[h] = atan2( fft1[h*2+1], fft1[h*2] ); //保留相角
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // 下面的代码作能量值方图的统计,其原理为:
- // 短时能量的概率密度最大值点对应着噪声帧能量概率密度最大值点.因此具体实
- // 现时maxScript为带噪语音信号的短时能量概率密度达到最大值时对应的点,可以通
- // 过连续统计一定长度带噪语音信号的短时能量直方图得到.计算统计直方图的门限由
- // maxScript可以得到判别有声帧和无声帧的门限.
- /////////////////////////////////////////////////////////////////////////////////////////////////
- signal_energy = 0.0;
- for(h = 0; h < FRAMELEN; h++)
- {
- signal_energy += d1[h]*d1[h];
- }
- //计算统计直方图的门限
- MAX = 0.0;
- for(h = 0; h < 199; h++)
- {
- pre_energy[h] = pre_energy[h+1];
- }
- pre_energy[199] = signal_energy;
- for(h = 0; h < 200; h++)
- {
- if(pre_energy[h] > MAX)
- MAX = pre_energy[h];
- }
- term = MAX / 128;
- for(h = 0; h < 129; h++)
- {
- quota[h] = 0;
- }
- int flag;
- for(h = 0; h < 200; h++)
- {
- flag = ceil(pre_energy[h]/term);
- quota[flag]++;
- }
- maxScript = 0;
- for(h = 1; h < 129; h++)
- {
- if(quota[h] > quota[maxScript])
- maxScript = h;
- }
- Threshold = 285.0*(maxScript+0.5)*term/254.0; //门限
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // 下面的代码作噪声估计和语音增强,其原理为:
- // 由本帧信号短时能量与上述门限值比较,判别有声/无声帧.判为有声帧时,
- // 不更新噪声;判为噪声值时,更新噪声功率谱.
- /////////////////////////////////////////////////////////////////////////////////////////////////
- for (h = 0; h < 129; h++)
- {
- if( signal_energy < Threshold )
- {
- dp[h] = 0.84*predp[h]+0.16*yp[h];
- xp[h] = coeffience3*(0.2*prexp[h]+0.8*((yp[h]-coeffience1*dp[h]>0.0) ? (yp[h]-coeffience1*dp[h]) : coeffience2*yp[h]));//为减小音乐噪声,噪声帧作衰减
- }
- else
- {
- dp[h] = predp[h];
- xp[h] = 0.2*prexp[h]+0.8*((yp[h]-coeffience1*dp[h]>0.0) ? (yp[h]-coeffience1*dp[h]) : coeffience2*yp[h]);
- }
- predp[h] = dp[h];
- prexp[h] = xp[h];
- //计算信号幅度
- amp[h] = sqrt( xp[h] );
- //计算了前129点的幅度,后面的127点利用FFT幅度的对称关系计算
- if( h == 0 || h == 128 )
- ;
- else
- amp[256-h] = amp[h];
- }
- //做IFFT
- for (h = 0; h < FRAMELEN; h++)
- {
- fft1[h*2] = amp[h]*cos(sita[h]); //IFFT变换输出结果的实部赋初值(输入信号的虚部)
- fft1[h*2+1] = -amp[h]*sin(sita[h]); //IFFT变换输出结果的虚部赋初值(输入信号的实部)
- }
- DSPF_sp_cfftr2_dit(fft1, w1, FRAMELEN);
- bit_rev(fft1, FRAMELEN);
- for(h=0; h < FRAMELEN; h++)
- {
- yo[h] = fft1[h*2]/FRAMELEN;
- }
- }
- void Enhance(void)
- {
- int t, h;
- float const coeffience4 = 4.0; //3.0
- void Stastic(void);
- p = read_data();
- for(t = 0; t < 128; t++)
- {
- dm[t+128] = (float)p[t];
- }
- for (h = 0; h < FRAMELEN; h++)
- {
- d1[h] = dm[h]*hamming[h]; //加hamming窗处理
- }
- Stastic();
- for(t = 0; t < 128; t++)
- {
- cm[t] = (int16)( (yo[t]+out1[t])*0.5*coeffience4 );
- out1[t] = yo[t+128];
- }
- for(t=0; t < 128; t++)
- {
- dm[t] = dm[t+128];
- }
- }
- ///////////////////////////////////////////
- /**本函数的目的是训练信道******
- ***输入:读入10帧数据 ******
- ***输出:得到average_noiseenergy值和energy_threshhold值*/
- void train(void)
- {
- int i;
- int j;
- for(i=0; i<10; i++)
- {
- noise_energy[i] = 0.0;
- }
- for(i=0; i<10; i++)
- {
- p = read_data();
- for(j=0; j<128; j++)
- {
- input_signal[j] = (float)p[j];
- noise_energy[i] += input_signal[j]*input_signal[j];
- qq[j] = input_signal[j];
- }
- noise_energy[i]/=128;
- compress_signal();//训练的时候默认是关断输出
- write_data(qq);
- }
- average_noiseenergy = 0.0;
- for(i=0; i<10; i++)
- {
- average_noiseenergy += noise_energy[i];
- }
- average_noiseenergy /= 10;
- //能量判决门限初始化为起始10帧数据的平均能量值;
- energy_threshhold = average_noiseenergy;
- }//训练结束
- /*****功能:读取一帧数据,并计算出signal_energy****
- ******输入:无 ****
- ******输出:一帧数据和此数据帧的signal_energy值***/
- void read_signal(void)
- {
- int i;
- // p = read_data();
- signal_energy = 0.0;
- for(i=0; i<128; i++)
- {
- input_signal[i] = (float)cm[i];
- qq[i] = (int16)input_signal[i];
- signal_energy += input_signal[i]*input_signal[i];
- }
- signal_energy /= 128;
- }
- /****功能:对qq[128]赋值零****
- *****输入:无 ****
- *****输出:qq[128] ***/
- void compress_signal(void)
- {
- int i;
- for(i=0; i<128; i++)
- {
- qq[i] = 0;
- }
- }
- /*****功能:把一帧数据分成32个子帧,计算出子帧 ****
- ******的frame_energyvariance与frame_energyreference****
- ******输入:一帧数据 ****
- ******输出:frame_energyvariance与frame_energyreference值***/
- void subframe_energyvar(void)
- {
- int i;
- int j;
- int subframe_number = 32;
- float subframe_total;
- float subframelength=128/subframe_number;
- for(i=0; i<subframe_number; i++)
- {
- subframe_energy[i]=0;
- }
- for(i=0; i<subframe_number; i++)
- {
- for(j=0; j<subframelength; j++)
- subframe_energy[i] += input_signal[i*4+j]*input_signal[i*4+j];
- subframe_energy[i] /= subframelength;
- }
- subframe_total = 0;
- for(i=0; i<subframe_number; i++)
- {
- subframe_total += subframe_energy[i];
- }
- frame_energyreference = subframe_total/subframe_number;
- frame_energyvariance = 0.0;
- for(i=0; i<subframe_number; i++)
- {
- frame_energyvariance += (subframe_energy[i]-frame_energyreference)*(subframe_energy[i]-frame_energyreference);
- }
- frame_energyvariance = sqrt(frame_energyvariance);
- }
- /*****功能:更新门限energy_threshhold****
- ******使之能自适应信道的变化 ****
- ******输入:一帧数据 ****
- ******输出:门限energy_threshhold值 ***/
- void noise_update(void)
- {
- int i;
- float old_noiseenergyvar;
- float new_noiseenergyvar;
- float ratio;
- float t;
- average_noiseenergy = 0.0;
- for(i=0; i<10; i++)
- {
- average_noiseenergy += noise_energy[i];
- }
- average_noiseenergy /= 10;
- old_noiseenergyvar = 0.0;
- for(i=0; i<10; i++)
- old_noiseenergyvar += (noise_energy[i]-average_noiseenergy)*(noise_energy[i]-average_noiseenergy);
- for(i=8; i<0; i++) //这里i最高只能取8!!!
- {
- noise_energy[i+1] = noise_energy[i];
- noise_energy[0] = signal_energy;
- }
- average_noiseenergy = 0.0;
- for(i=0; i<10; i++)
- {
- average_noiseenergy += noise_energy[i];
- }
- average_noiseenergy /= 100;
- new_noiseenergyvar = 0.0;
- for(i=0; i<10; i++)
- new_noiseenergyvar += (noise_energy[i]-average_noiseenergy)*(noise_energy[i]-average_noiseenergy);
- old_noiseenergyvar = sqrt(old_noiseenergyvar);
- new_noiseenergyvar = sqrt(new_noiseenergyvar);
- //根据当前噪声能量方差与先澳芰糠讲畹谋戎道炊詐赋值,借此自适应的跟踪信道的噪声变化;
- ratio = new_noiseenergyvar/old_noiseenergyvar;
- if(ratio>=1.25)
- t=0.45;
- else if(ratio>=1.10)
- t=0.35;
- else if(ratio>=1.00)
- t=0.25;
- else
- t=0.15;
- energy_threshhold = energy_threshhold*(1-t)+t*noise_energy[0];
- }
- int main(void)
- {
- float a; //avv判决语音起始点的倍数
- float b; //avv判决语音结束点的倍数
- float c; //第一级能量倍数
- float d; //第二级能量倍数
- float f;
- int dip1,dip2,dip3,dip4;
- int value;
- bool flag;
- void Enhance(void);
- CSR &= (~0x00000001);
- IER = 0;
- data_init();
- buf_init();
- timer1_init();
- spark_led();
- sys_init();
- for(int t = 0; t < 128; t++)
- {
- out1[t] = 0.0;
- dm[t] = 0.0;
- }
- for(int t = 0; t < 129; t++)
- {
- predp[t] = 0.0;
- prexp[t] = 0.0;
- }
- for(int i = 0; i < 200; i++) //取200帧,用于能量直方图的更新,放音
- {
- p = read_data();
- for(int t = 0; t < 128; t++)
- {
- dm[t+128] = (float)p[t];
- }
- for (int h = 0; h < FRAMELEN; h++)
- {
- d1[h] = dm[h]*hamming[h]; //加hamming窗处理
- }
- //计算信号能量
- pre_energy[i] = 0.0;
- for(int h = 0; h < FRAMELEN; h++)
- {
- pre_energy[i] += d1[h]*d1[h];
- }
- for(int t = 0; t < 128; t++)
- {
- cm[t] = (int16)( (d1[t]+out1[t])*0.5 );
- out1[t] = d1[t+128];
- }
- write_data(cm);
- for(int t = 0; t < 128; t++)
- {
- dm[t] = dm[t+128];
- }
- }
- //循环判断每帧数据
- while(1)
- {
- //用十帧数据来训练整个算法,并得到相关参数.
- train();
- flag = false;//初始化flag:语音有无标志
- //找语音的起始点
- while(!flag)
- {
- value = REG32(GPIO_GPVAL);
- dip1 = value & 0x00000001;
- dip2 = value & 0x00000080;
- dip3 = value & 0x00000040;
- dip4 = value & 0x00000020;
- if((!dip1) && (dip2) && (dip3) && (dip4))
- {
- a = 0.6;
- b = 0.2;
- c = 5;
- d = 3;
- f = 1.2;
- }
- else if((!dip1) && (dip2) && (dip3) && (!dip4))
- {
- a = 1.0;
- b = 1;
- c = 5;
- d = 4;
- f = 1.5;
- }
- else if((!dip1) && (dip2) && (!dip3) && (dip4))
- {
- a = 1.5;
- b = 1.5;
- c = 6;
- d = 4;
- f = 1.8;
- }
- else if((!dip1) && (dip2) && (!dip3) && (!dip4))
- {
- a = 4;
- b = 4;
- c = 6;
- d = 4;
- f=1.8;
- }
- else
- ;
- Enhance();
- read_signal();
- //能量判决,如果读入帧的能量与门限值比较,如果大于门限,则输出
- if(signal_energy > c*energy_threshhold)
- {
- subframe_energyvar();
- if(frame_energyvariance>(a)*(average_noiseenergy))
- {
- flag = true;
- write_data(qq);
- }
- else
- {
- compress_signal();
- flag = false;
- write_data(qq);
- noise_update();
- }
- }
- //如果是d倍门限以上则需看avv;
- else if(signal_energy > d*energy_threshhold)
- {
- subframe_energyvar();
- //avv判决
- if(frame_energyvariance > (a)*(average_noiseenergy))
- {
- flag = true;
- write_data(qq);
- }
- else
- {
- compress_signal();
- flag = false;
- write_data(qq);
- noise_update();
- }
- }
- else if(signal_energy > 1.8*energy_threshhold)
- {
- subframe_energyvar();
- //avv判决;
- if(frame_energyvariance>a*(average_noiseenergy))
- {
- compress_signal();
- write_data(qq);
- Enhance();
- read_signal();
- subframe_energyvar();
- //avv判决;
- if(frame_energyvariance>(a)*(average_noiseenergy))
- {
- flag = true;
- write_data(qq);
- }
- else
- {
- compress_signal();
- write_data(qq);
- flag = false;
- noise_update();
- }
- }
- //当判为静音帧时进行噪声更新;
- else
- {
- compress_signal();
- write_data(qq);
- flag = false;
- noise_update();
- }
- }
- //小能量帧用avv判决
- else
- {
- subframe_energyvar();
- if(frame_energyvariance>(a)*(average_noiseenergy))//文献中用的是frame_noisereference
- {
- compress_signal();
- write_data(qq);
- Enhance();
- read_signal();
- subframe_energyvar();
- //进一步avv判决;
- if(frame_energyvariance>(a)*(average_noiseenergy))
- {
- flag = true;
- write_data(qq);
- }
- else
- {
- compress_signal();
- write_data(qq);
- flag = false;
- noise_update();
- }
- }
- else
- {
- compress_signal();
- write_data(qq);
- flag = false;
- noise_update();
- }
- }//if(signal_energy > 8*energy_threshhold)
- }//while(!flag)结束
- //找语音的结束点
- //如果有连续
- while(flag)
- {
- value = REG32(GPIO_GPVAL);
- dip1 = value & 0x00000001;
- dip2 = value & 0x00000080;
- dip3 = value & 0x00000040;
- dip4 = value & 0x00000020;
- if((!dip1) && (dip2) && (dip3) && (dip4))
- {
- a = 0.6;
- b = 0.2;
- c = 5;
- d = 3;
- f = 1.2;
- }
- else if((!dip1) && (dip2) && (dip3) && (!dip4))
- {
- a = 1.0;
- b = 1;
- c = 5;
- d = 4;
- f = 1.5;
- }
- else if((!dip1) && (dip2) && (!dip3) && (dip4))
- {
- a = 1.5;
- b = 1.5;
- c = 6;
- d = 4;
- f = 1.8;
- }
- else if((!dip1) && (dip2) && (!dip3) && (!dip4))
- {
- a = 3;
- b = 3;
- c = 6;
- d = 4;
- f = 2.0;
- }
- else
- ;
- //这种判断方法是在50帧中如果有15帧的能量小于1.5倍门限则进一步用avv判决
- int s = 100;
- int totalenergynum = 0;
- int totalavvnum = 0;
- int totalnum = 0;
- // read_signal();
- Enhance();
- read_signal();
- //能量判决,如果读入k帧的能量与门限值比较,如果大于门限,则输出,否则进一步用AVV判决;
- while(s!=0)
- {
- if(signal_energy < f*energy_threshhold)
- {
- totalenergynum++;
- noise_update();
- }
- else if(signal_energy < 1.8*energy_threshhold)
- {
- totalnum++;
- }
- else
- ;
- subframe_energyvar();
- //根据子帧能量方差与子帧的平均能量比较来做判决;
- if(frame_energyvariance<(b)*(average_noiseenergy))
- {
- totalavvnum++;
- }
- write_data(qq);
- Enhance();
- read_signal();
- s--;
- }
- //if(totalnum>60 && totalavvnum<60)
- //{
- // flag = true;
- // write_data(qq);
- //}
- //else
- {
- if(totalenergynum>80 && totalavvnum>85)
- {
- totalenergynum=0;
- //语音结束点,并更新噪声
- flag = false;
- compress_signal();
- write_data(qq);
- noise_update();//当判为静音帧时进行噪声更新
- }//if(totalenergynum>70 && totalavvnum>50)结束
- else
- {
- flag = true;
- write_data(qq);
- }
- }//while(s!=0)结束
- }//while(flag)结束
- }//while(1)结束
- }//主函数结束