main_VAD_0909.cpp
上传用户:kepeng103
上传日期:2022-07-27
资源大小:2653k
文件大小:23k
源码类别:

DSP编程

开发平台:

C/C++

  1. /**********本函数的功能是用能量和自相*******************
  2. ***********关向量方差相结合的算法来进*******************
  3. ******************行VAD检测*****************************/
  4. /**********胡曙辉,2008年4月完成********************/
  5. /*4.3  加入了一些必须的初始化语句,*/
  6. /*4.7  在判断语音起始点和结束点加入了窗移动函数,即用连续多帧来进行判断*
  7. *******解决了训练过程的一个bug*******/
  8. /*4.8  把整个代码用函数实现**********/
  9. /*4.14 对语音的结束点判断采用了另一种方法*/
  10. /*4.16 静噪时候的压缩倍数必须增大,否则当输入信号的能量较大时,可以听到较小的压缩后输出。到1000倍左右,目前是150倍***
  11. ********为了减少误报率,必须提高能量门限,8倍到10倍左右,第二级门限设定到5至7倍,**
  12. ********找语音结束点的时候,采用的是两级判决方法,首先在50帧内计算出能量少于某一门限的帧数,如果帧数大于某一个值,这个值需要进行一定的试验调整(选15~25帧),然后对最后一帧用avv判决,这里好像有一定的偶然性,可能会提前终止语音。是否可以将avv加到能量判决那一部分中,统计同时满足两个条件的总帧数。*****
  13. ********当找到语音起始点的时候,默认输出100帧(1.6s),可能在换台的时候会使系统的静噪关断时延超过3s。因为后面还有50帧的统计,总时间为2.4s,如果第一次未能准确判决,将会有4.8s才能关断。将100帧换为75帧,时延减少0.4s,换为50帧,时延减少0.8s。********/
  14. /*k值有变换,今天试验的时候需要选择10,以前是2.5,有点奇怪。*/
  15. /*4.17 语音起始点判断的时候,连续两帧满足avv才判为语音起始点(效果很好,噪声误判率极低,试听了很久)*/
  16. /* 4.18 根据试验结果修改了一些参数值*/
  17. /* 4.23 改变了语音起始点的检测,起始点和结束点的参数也不一样,并不是判为噪声才进行噪声更新,在能量低于1.5倍门限的时候也进行噪声更新,防止长时间不更新噪声影响系统的判决。
  18.    每次找语音起始点之前重新训练信道*/
  19. #include "..commonhal.h"
  20. #include "device.h"
  21. #include "buf.h"
  22. #include <stdio.h>
  23. #include <math.h>
  24. #define FRAMELEN  256   
  25. #define PI       4.0*atan(1.0)
  26. float noise_energy[10]={0};
  27. float subframe_energy[32]={0}; 
  28. float input_signal[128]={0};
  29. float energy_threshhold=0;
  30. float average_noiseenergy=0;
  31. float signal_energy=0;
  32. float signal_temp[128];
  33. float frame_energyvariance=0;
  34. float frame_noisereference=0;
  35. float frame_energyreference;
  36. int16 qq[128]={0};
  37. int16 *p;
  38. /////////////////
  39. int16 cm[128];
  40. float w1[FRAMELEN]; //蝶形因子
  41. float fft1[FRAMELEN*2];    //每帧语音信号的FFT 
  42. float yp[FRAMELEN]; //未处理语音信号的功率谱
  43. float dp[129]; //噪声功率谱
  44. float xp[129]; //增强后语音信号的功率谱
  45. float predp[129];         //前一帧噪声信号的功率谱
  46. float prexp[129];         //前一帧增强后语音信号的功率谱
  47. float yo[FRAMELEN]; //增强后的时域信号
  48. float sita[FRAMELEN]; //相角
  49. float amp[FRAMELEN]; //幅度值
  50. float pre_energy[200]; //统计直方图所用每帧信号能量
  51. unsigned quota[129];
  52. float dm[FRAMELEN]; 
  53. float d1[FRAMELEN];
  54. float const hamming[FRAMELEN] = {0.0800, 0.0801, 0.0806, 0.0812, 0.0822, 0.0835, 0.0850, 0.0868, 
  55.      0.0888, 0.0912, 0.0938, 0.0967, 0.0998, 0.1032, 0.1069, 0.1108, 
  56.  0.1150, 0.1195, 0.1242, 0.1291, 0.1343, 0.1398, 0.1454, 0.1514, 
  57.                      0.1575, 0.1639, 0.1705, 0.1774, 0.1844, 0.1917, 0.1992, 0.2068, 
  58.                      0.2147, 0.2228, 0.2311, 0.2395, 0.2482, 0.2570, 0.2660, 0.2751, 
  59.                      0.2844, 0.2939, 0.3035, 0.3133, 0.3232, 0.3332, 0.3433, 0.3536, 
  60.                      0.3640, 0.3744, 0.3850, 0.3957, 0.4065, 0.4173, 0.4282, 0.4392, 
  61.                      0.4503, 0.4614, 0.4725, 0.4837, 0.4949, 0.5062, 0.5174, 0.5287, 
  62.                      0.5400, 0.5513, 0.5626, 0.5738, 0.5851, 0.5963, 0.6075, 0.6186, 
  63.                      0.6297, 0.6408, 0.6518, 0.6627, 0.6735, 0.6843, 0.6950, 0.7056, 
  64.                      0.7160, 0.7264, 0.7367, 0.7468, 0.7568, 0.7667, 0.7765, 0.7861, 
  65.                      0.7956, 0.8049, 0.8140, 0.8230, 0.8318, 0.8405, 0.8489, 0.8572, 
  66.                      0.8653, 0.8732, 0.8808, 0.8883, 0.8956, 0.9026, 0.9095, 0.9161, 
  67.                      0.9225, 0.9286, 0.9346, 0.9402, 0.9457, 0.9509, 0.9558, 0.9605, 
  68.                      0.9650, 0.9692, 0.9731, 0.9768, 0.9802, 0.9833, 0.9862, 0.9888, 
  69.                      0.9912, 0.9932, 0.9950, 0.9965, 0.9978, 0.9988, 0.9994, 0.9999, 
  70.                      1.0000, 0.9999, 0.9994, 0.9988, 0.9978, 0.9965, 0.9950, 0.9932, 
  71.                      0.9912, 0.9888, 0.9862, 0.9833, 0.9802, 0.9768, 0.9731, 0.9692, 
  72.                      0.9650, 0.9605, 0.9558, 0.9509, 0.9457, 0.9402, 0.9346, 0.9286, 
  73.                      0.9225, 0.9161, 0.9095, 0.9026, 0.8956, 0.8883, 0.8808, 0.8732, 
  74.                      0.8653, 0.8572, 0.8489, 0.8405, 0.8318, 0.8230, 0.8140, 0.8049, 
  75.                      0.7956, 0.7861, 0.7765, 0.7667, 0.7568, 0.7468, 0.7367, 0.7264, 
  76.                      0.7160, 0.7056, 0.6950, 0.6843, 0.6735, 0.6627, 0.6518, 0.6408, 
  77.                      0.6297, 0.6186, 0.6075, 0.5963, 0.5851, 0.5738, 0.5626, 0.5513, 
  78.                      0.5400, 0.5287, 0.5174, 0.5062, 0.4949, 0.4837, 0.4725, 0.4614, 
  79.                      0.4503, 0.4392, 0.4282, 0.4173, 0.4065, 0.3957, 0.3850, 0.3744, 
  80.                      0.3640, 0.3536, 0.3433, 0.3332, 0.3232, 0.3133, 0.3035, 0.2939, 
  81.                      0.2844, 0.2751, 0.2660, 0.2570, 0.2482, 0.2395, 0.2311, 0.2228, 
  82.                      0.2147, 0.2068, 0.1992, 0.1917, 0.1844, 0.1774, 0.1705, 0.1639, 
  83.                      0.1575, 0.1514, 0.1454, 0.1398, 0.1343, 0.1291, 0.1242, 0.1195, 
  84.                      0.1150, 0.1108, 0.1069, 0.1032, 0.0998, 0.0967, 0.0938, 0.0912, 
  85.                      0.0888, 0.0868, 0.0850, 0.0835, 0.0822, 0.0812, 0.0806, 0.0801}; //hamming窗
  86. float out1[FRAMELEN/2];
  87. ///////////
  88. void train(void);
  89. void read_signal(void);
  90. void compress_signal(void);
  91. void subframe_energyvar(void);
  92. void noise_update(void);
  93. void sys_init(void)
  94. {
  95. gpio_init();
  96. dac_reset();
  97. mcbsp0_init_serial();
  98. adc_init();
  99. mcasp_init();
  100. timer0_init();
  101. ADC_SE_HI();
  102. ISTP = 0x00000400;
  103. IER |= 0x00000002;
  104. CSR |= 0x00000001;
  105. }
  106. void spark_led(void)
  107. {
  108. REG32(MCASP1_PFUNC) |= 0x0000003e;
  109. REG32(MCASP1_PDIR) |= 0x0000003e;
  110. REG32(MCASP1_PDOUT) = 0x00000000;
  111. uint8 code = 1;  
  112. for(int k=0; k<10; k++) 
  113. {
  114. set_led(0xff, code);
  115. code <<= 1;
  116. code = (code == 0x20? 1:code);
  117. delay_ms(100);
  118. }
  119. REG32(MCASP1_PDOUT) = 0x00000000;
  120. }
  121. int16 data[128];
  122. void data_init(void)
  123. {
  124. for(int i=0; i<128; i++) 
  125. {
  126. data[i] = 30000*sin(i*PI*2/64);
  127. }
  128. }
  129. //////////////////////////
  130. void gen_w_r2(float* w, int n)     //产生旋转因子(n个)的函数
  131. {
  132.     int i;
  133.     float pi = 4.0*atan(1.0);
  134.     float e = pi*2.0/n;
  135.     for(i=0; i < ( n>>1 ); i++) {
  136.         w[2*i]   = cos(i*e);
  137.         w[2*i+1] = sin(i*e);
  138.     }
  139. }
  140. void bit_rev(float* x, int n)     //产生n比特翻转的函数,将x[]做n比特翻转
  141. {
  142.     int i, j, k;
  143.     float rtemp, itemp;
  144.     j = 0;
  145.     for(i=1; i < (n-1); i++) {
  146.         k = n >> 1;
  147.         while(k <= j) {
  148.             j -= k;
  149.             k >>= 1;
  150.         }
  151.         j += k;
  152.         if(i < j) {
  153.             rtemp    = x[j*2];
  154.             x[j*2]   = x[i*2];
  155.             x[i*2]   = rtemp;
  156.             itemp    = x[j*2+1];
  157.             x[j*2+1] = x[i*2+1];
  158.             x[i*2+1] = itemp;
  159.         }
  160.     }
  161. }
  162. void DSPF_sp_cfftr2_dit(float* x, float* w, short n)       //计算n点FFT的函数
  163. {                                                                   
  164.     short n2, ie, ia, i, j, k, m;                                    
  165.     float rtemp, itemp, c, s;                                        
  166.     n2 = n;                                                          
  167.     ie = 1;                                                          
  168.     for(k=n; k > 1; k >>= 1) {                                                                
  169.         n2 >>= 1; 
  170.         ia = 0;
  171.         for(j=0; j < ie; j++) {                                                             
  172.             c = w[2*j];
  173.             s = w[2*j+1];
  174.             for(i=0; i < n2; i++) {                                                          
  175.                 m = ia + n2;
  176.                 rtemp     = c * x[2*m]   + s * x[2*m+1];
  177.                 itemp     = c * x[2*m+1] - s * x[2*m];
  178.                 x[2*m]    = x[2*ia]   - rtemp;
  179.                 x[2*m+1]  = x[2*ia+1] - itemp;
  180.                 x[2*ia]   = x[2*ia]   + rtemp;
  181.                 x[2*ia+1] = x[2*ia+1] + itemp;
  182.                 ia++;
  183.             }
  184.         ia += n2;
  185.         }
  186.         ie <<= 1;                                               
  187.     }
  188. }
  189. void Stastic(void)
  190. {
  191. int h;
  192.    
  193. float term; //统计直方图的幅度间隔
  194. unsigned maxScript;     //记录统计直方图最大值下标
  195. float MAX; //200帧信号能量最大值
  196. float signal_energy;    //本帧信号能量
  197. float Threshold;        //直方图门限
  198. // float sum = 0.0; //本帧信号幅度值之和
  199. // float mean = 0.0; //平均每个点平均幅度
  200. float const coeffience1 = 3.8;   //3.8
  201. float const coeffience2 = 0.005; //0.007
  202. float const coeffience3 = 0.5;   //0.6
  203.     //做每帧信号的FFT
  204. for (h = 0; h < FRAMELEN; h++) 
  205. {
  206. fft1[h*2] = d1[h];      
  207.         fft1[h*2+1] = 0.0;    
  208. }
  209.         
  210. //做FRAMELEN个点FFT
  211.     gen_w_r2(w1, FRAMELEN);
  212.     bit_rev(w1, FRAMELEN/2);
  213.     DSPF_sp_cfftr2_dit(fft1, w1, FRAMELEN);   
  214.     bit_rev(fft1, FRAMELEN);
  215.           
  216.     
  217.     for (h=0; h < FRAMELEN; h++) 
  218.     {
  219.         yp[h] = fft1[h*2]*fft1[h*2] + fft1[h*2+1]*fft1[h*2+1];    //未处理语音信号的功率谱
  220.         sita[h] = atan2( fft1[h*2+1], fft1[h*2] );   //保留相角  
  221. /////////////////////////////////////////////////////////////////////////////////////////////////
  222. //                    下面的代码作能量值方图的统计,其原理为:
  223. //        短时能量的概率密度最大值点对应着噪声帧能量概率密度最大值点.因此具体实
  224. //    现时maxScript为带噪语音信号的短时能量概率密度达到最大值时对应的点,可以通
  225. //    过连续统计一定长度带噪语音信号的短时能量直方图得到.计算统计直方图的门限由
  226. //    maxScript可以得到判别有声帧和无声帧的门限.
  227. /////////////////////////////////////////////////////////////////////////////////////////////////
  228. signal_energy = 0.0;
  229. for(h = 0; h < FRAMELEN; h++)
  230. {
  231. signal_energy += d1[h]*d1[h];
  232. }
  233.     //计算统计直方图的门限
  234. MAX = 0.0;                                      
  235. for(h = 0; h < 199; h++)               
  236. {
  237. pre_energy[h] = pre_energy[h+1];
  238. }
  239. pre_energy[199] = signal_energy;
  240. for(h = 0; h < 200; h++)
  241. {
  242. if(pre_energy[h] > MAX)
  243. MAX = pre_energy[h];
  244. }
  245. term = MAX / 128;
  246. for(h = 0; h < 129; h++)
  247. {
  248. quota[h] = 0;
  249. }
  250. int flag;
  251. for(h = 0; h < 200; h++)
  252. {
  253. flag = ceil(pre_energy[h]/term);
  254. quota[flag]++;
  255. }
  256. maxScript = 0;
  257. for(h = 1; h < 129; h++)
  258. {
  259. if(quota[h] > quota[maxScript])
  260. maxScript = h;
  261. }
  262. Threshold = 285.0*(maxScript+0.5)*term/254.0;  //门限
  263.     
  264. /////////////////////////////////////////////////////////////////////////////////////////////////
  265. //                    下面的代码作噪声估计和语音增强,其原理为:
  266. //        由本帧信号短时能量与上述门限值比较,判别有声/无声帧.判为有声帧时,
  267. //    不更新噪声;判为噪声值时,更新噪声功率谱.
  268. /////////////////////////////////////////////////////////////////////////////////////////////////
  269.     for (h = 0; h < 129; h++)
  270. {
  271. if( signal_energy < Threshold )
  272. {
  273. dp[h] = 0.84*predp[h]+0.16*yp[h]; 
  274. xp[h] = coeffience3*(0.2*prexp[h]+0.8*((yp[h]-coeffience1*dp[h]>0.0) ? (yp[h]-coeffience1*dp[h]) : coeffience2*yp[h]));//为减小音乐噪声,噪声帧作衰减
  275. }
  276. else
  277. {
  278. dp[h] = predp[h];
  279.          xp[h] = 0.2*prexp[h]+0.8*((yp[h]-coeffience1*dp[h]>0.0) ? (yp[h]-coeffience1*dp[h]) : coeffience2*yp[h]); 
  280. }
  281. predp[h] = dp[h];
  282. prexp[h] = xp[h]; 
  283.         
  284.      //计算信号幅度
  285. amp[h] = sqrt( xp[h] );
  286.             
  287.         //计算了前129点的幅度,后面的127点利用FFT幅度的对称关系计算
  288.         if( h == 0 || h == 128 )
  289.             ;
  290.         else
  291.             amp[256-h] = amp[h];  
  292. }
  293.     //做IFFT   
  294. for (h = 0; h < FRAMELEN; h++) 
  295. {
  296.         fft1[h*2] = amp[h]*cos(sita[h]);         //IFFT变换输出结果的实部赋初值(输入信号的虚部)  
  297.         fft1[h*2+1] = -amp[h]*sin(sita[h]);      //IFFT变换输出结果的虚部赋初值(输入信号的实部)
  298.     }
  299.     DSPF_sp_cfftr2_dit(fft1, w1, FRAMELEN);   
  300.     bit_rev(fft1, FRAMELEN);
  301.     for(h=0; h < FRAMELEN; h++)
  302.         yo[h] = fft1[h*2]/FRAMELEN;
  303.     }
  304. }
  305. void Enhance(void)
  306. {
  307. int t, h;
  308. float const coeffience4 = 4.0; //3.0
  309. void Stastic(void);
  310. p = read_data();
  311. for(t = 0; t < 128; t++)
  312. {
  313. dm[t+128] = (float)p[t]; 
  314. }
  315. for (h = 0; h < FRAMELEN; h++)
  316. {
  317. d1[h] = dm[h]*hamming[h];   //加hamming窗处理
  318. }
  319. Stastic();
  320. for(t = 0; t < 128; t++)
  321.     cm[t] = (int16)( (yo[t]+out1[t])*0.5*coeffience4 ); 
  322. out1[t] = yo[t+128];   
  323. }
  324.   
  325. for(t=0; t < 128; t++)
  326. {
  327. dm[t] = dm[t+128];
  328. }
  329. }
  330. ///////////////////////////////////////////
  331. /**本函数的目的是训练信道******
  332. ***输入:读入10帧数据     ******
  333. ***输出:得到average_noiseenergy值和energy_threshhold值*/
  334. void train(void)
  335. {
  336. int i;
  337. int j;
  338. for(i=0; i<10; i++)
  339. {
  340. noise_energy[i] = 0.0;
  341. }
  342. for(i=0; i<10; i++)
  343. {
  344. p = read_data();
  345. for(j=0; j<128; j++)
  346. {
  347. input_signal[j] = (float)p[j];
  348. noise_energy[i] += input_signal[j]*input_signal[j]; 
  349. qq[j] = input_signal[j];
  350. }
  351. noise_energy[i]/=128;
  352. compress_signal();//训练的时候默认是关断输出
  353. write_data(qq);
  354. }
  355. average_noiseenergy = 0.0;
  356. for(i=0; i<10; i++)
  357. {
  358. average_noiseenergy += noise_energy[i];
  359. }
  360. average_noiseenergy /= 10;
  361. //能量判决门限初始化为起始10帧数据的平均能量值;        
  362. energy_threshhold = average_noiseenergy;
  363. }//训练结束
  364. /*****功能:读取一帧数据,并计算出signal_energy****
  365. ******输入:无                                 ****
  366. ******输出:一帧数据和此数据帧的signal_energy值***/
  367. void read_signal(void)
  368. {
  369. int i;
  370. // p = read_data();
  371. signal_energy = 0.0;
  372. for(i=0; i<128; i++)
  373. {
  374. input_signal[i] = (float)cm[i];
  375. qq[i] = (int16)input_signal[i];
  376. signal_energy += input_signal[i]*input_signal[i];
  377.     
  378. }     
  379. signal_energy /= 128;
  380. }
  381. /****功能:对qq[128]赋值零****
  382. *****输入:无             ****
  383. *****输出:qq[128]        ***/
  384. void compress_signal(void)
  385. {
  386. int i;
  387. for(i=0; i<128; i++)
  388.     {
  389. qq[i] = 0;
  390. }
  391. }
  392. /*****功能:把一帧数据分成32个子帧,计算出子帧      ****
  393. ******的frame_energyvariance与frame_energyreference****
  394. ******输入:一帧数据                                ****
  395. ******输出:frame_energyvariance与frame_energyreference值***/
  396. void subframe_energyvar(void)
  397. {
  398. int i;
  399. int j;
  400. int subframe_number = 32;
  401. float subframe_total;
  402. float subframelength=128/subframe_number;
  403.         
  404. for(i=0; i<subframe_number; i++)
  405. {
  406. subframe_energy[i]=0;
  407. }
  408. for(i=0; i<subframe_number; i++)
  409. {
  410. for(j=0; j<subframelength; j++)
  411. subframe_energy[i] += input_signal[i*4+j]*input_signal[i*4+j];
  412. subframe_energy[i] /= subframelength;
  413. }
  414. subframe_total = 0;
  415. for(i=0; i<subframe_number; i++)
  416. {
  417. subframe_total += subframe_energy[i];
  418. }
  419. frame_energyreference = subframe_total/subframe_number;
  420. frame_energyvariance = 0.0;
  421. for(i=0; i<subframe_number; i++)
  422. {
  423. frame_energyvariance += (subframe_energy[i]-frame_energyreference)*(subframe_energy[i]-frame_energyreference);
  424. }
  425. frame_energyvariance = sqrt(frame_energyvariance);
  426. }
  427. /*****功能:更新门限energy_threshhold****
  428. ******使之能自适应信道的变化        ****
  429. ******输入:一帧数据                 ****
  430. ******输出:门限energy_threshhold值  ***/
  431. void noise_update(void)
  432. {
  433. int i;
  434. float old_noiseenergyvar;
  435. float new_noiseenergyvar;
  436. float ratio;
  437. float t;
  438.         
  439. average_noiseenergy = 0.0;
  440. for(i=0; i<10; i++)
  441. {
  442. average_noiseenergy += noise_energy[i];
  443. }
  444. average_noiseenergy /= 10;
  445.         
  446. old_noiseenergyvar = 0.0;
  447. for(i=0; i<10; i++)
  448. old_noiseenergyvar += (noise_energy[i]-average_noiseenergy)*(noise_energy[i]-average_noiseenergy);
  449.         
  450. for(i=8; i<0; i++) //这里i最高只能取8!!!        
  451. {
  452. noise_energy[i+1] = noise_energy[i];
  453. noise_energy[0] =  signal_energy;
  454. }
  455. average_noiseenergy = 0.0;
  456. for(i=0; i<10; i++)
  457. {
  458. average_noiseenergy += noise_energy[i];
  459. }
  460. average_noiseenergy /= 100;
  461. new_noiseenergyvar = 0.0;
  462. for(i=0; i<10; i++)
  463. new_noiseenergyvar += (noise_energy[i]-average_noiseenergy)*(noise_energy[i]-average_noiseenergy);
  464. old_noiseenergyvar = sqrt(old_noiseenergyvar);
  465. new_noiseenergyvar = sqrt(new_noiseenergyvar);
  466. //根据当前噪声能量方差与先澳芰糠讲畹谋戎道炊詐赋值,借此自适应的跟踪信道的噪声变化;                    
  467.         
  468. ratio = new_noiseenergyvar/old_noiseenergyvar;
  469. if(ratio>=1.25)
  470. t=0.45;
  471. else if(ratio>=1.10)
  472. t=0.35;
  473. else if(ratio>=1.00)
  474. t=0.25;        
  475. else
  476. t=0.15;
  477. energy_threshhold = energy_threshhold*(1-t)+t*noise_energy[0];
  478.        
  479. }
  480. int main(void)
  481. {
  482. float a; //avv判决语音起始点的倍数
  483. float b;  //avv判决语音结束点的倍数
  484. float c; //第一级能量倍数
  485. float d;   //第二级能量倍数
  486. float f;
  487. int dip1,dip2,dip3,dip4;
  488. int value;  
  489. bool flag;
  490.     void Enhance(void);
  491. CSR &= (~0x00000001);
  492. IER = 0;
  493. data_init();
  494. buf_init();
  495. timer1_init();
  496. spark_led();
  497. sys_init();
  498. for(int t = 0; t < 128; t++)
  499. {
  500. out1[t] = 0.0;
  501.         dm[t] = 0.0;
  502. }
  503.     for(int t = 0; t < 129; t++)
  504. {
  505.         predp[t] = 0.0;
  506. prexp[t] = 0.0;
  507. }
  508. for(int i = 0; i < 200; i++)   //取200帧,用于能量直方图的更新,放音           
  509. {
  510. p = read_data();
  511.         for(int t = 0; t < 128; t++)
  512.         {
  513. dm[t+128] = (float)p[t];   
  514. }
  515. for (int h = 0; h < FRAMELEN; h++)
  516. {
  517. d1[h] = dm[h]*hamming[h];   //加hamming窗处理
  518. }
  519.         //计算信号能量
  520. pre_energy[i] = 0.0;
  521. for(int h = 0; h < FRAMELEN; h++)
  522. {
  523. pre_energy[i] += d1[h]*d1[h];
  524. }
  525. for(int t = 0; t < 128; t++)
  526.         {
  527. cm[t] = (int16)( (d1[t]+out1[t])*0.5 ); 
  528.      out1[t] = d1[t+128]; 
  529.      }
  530. write_data(cm);
  531. for(int t = 0; t < 128; t++)
  532. {
  533. dm[t] = dm[t+128];
  534. }
  535. }
  536. //循环判断每帧数据    
  537. while(1)
  538. {         
  539. //用十帧数据来训练整个算法,并得到相关参数.
  540. train();
  541. flag = false;//初始化flag:语音有无标志
  542. //找语音的起始点
  543.         
  544. while(!flag)
  545. {            
  546. value = REG32(GPIO_GPVAL);
  547. dip1 = value & 0x00000001;
  548. dip2 = value & 0x00000080;
  549. dip3 = value & 0x00000040;
  550. dip4 = value & 0x00000020; 
  551. if((!dip1) && (dip2) && (dip3) && (dip4))
  552. {
  553. a = 0.6;
  554. b = 0.2;
  555. c = 5;
  556. d = 3;
  557. f = 1.2;
  558. }
  559. else if((!dip1) && (dip2) && (dip3) && (!dip4))
  560. {
  561. a = 1.0;
  562. b = 1;
  563. c = 5;
  564. d = 4;
  565. f = 1.5;
  566. }
  567. else if((!dip1) && (dip2) && (!dip3) && (dip4))
  568. {
  569. a = 1.5;
  570. b = 1.5;
  571. c = 6;
  572. d = 4;
  573. f = 1.8;
  574. }
  575. else if((!dip1) && (dip2) && (!dip3) && (!dip4))
  576. {
  577. a = 4;
  578. b = 4;
  579. c = 6;
  580. d = 4;
  581. f=1.8;
  582. }
  583. else 
  584. ;
  585. Enhance();
  586. read_signal();
  587. //能量判决,如果读入帧的能量与门限值比较,如果大于门限,则输出                            
  588. if(signal_energy > c*energy_threshhold)
  589. {                  
  590. subframe_energyvar();
  591.           
  592. if(frame_energyvariance>(a)*(average_noiseenergy))
  593. {            
  594. flag = true;                       
  595. write_data(qq);   
  596. }
  597. else
  598. {
  599. compress_signal();
  600. flag = false;
  601. write_data(qq);
  602. noise_update();
  603. }
  604. }
  605.     //如果是d倍门限以上则需看avv;         
  606. else if(signal_energy > d*energy_threshhold)
  607. {
  608. subframe_energyvar();
  609. //avv判决           
  610. if(frame_energyvariance > (a)*(average_noiseenergy))
  611. {            
  612. flag = true;
  613. write_data(qq);
  614. }           
  615. else
  616. {                            
  617. compress_signal();
  618. flag = false;
  619. write_data(qq);
  620. noise_update();
  621. }
  622. }
  623.     
  624.         
  625. else if(signal_energy > 1.8*energy_threshhold)
  626. {                  
  627. subframe_energyvar();
  628. //avv判决;
  629. if(frame_energyvariance>a*(average_noiseenergy))
  630. {                        
  631. compress_signal();
  632. write_data(qq);
  633. Enhance();
  634. read_signal();
  635. subframe_energyvar();
  636. //avv判决;
  637. if(frame_energyvariance>(a)*(average_noiseenergy))
  638. {
  639. flag = true;
  640. write_data(qq);
  641. }
  642. else
  643. {
  644. compress_signal();
  645. write_data(qq);
  646. flag = false;
  647. noise_update();
  648. }
  649. }                
  650. //当判为静音帧时进行噪声更新;                  
  651. else                  
  652. {                        
  653. compress_signal();                        
  654. write_data(qq);
  655. flag = false;                        
  656. noise_update();                  
  657. }             
  658. }
  659. //小能量帧用avv判决 
  660. else
  661. {
  662. subframe_energyvar();
  663. if(frame_energyvariance>(a)*(average_noiseenergy))//文献中用的是frame_noisereference
  664. {
  665. compress_signal();
  666. write_data(qq);
  667. Enhance();
  668. read_signal();
  669. subframe_energyvar();
  670. //进一步avv判决;
  671. if(frame_energyvariance>(a)*(average_noiseenergy))
  672. {
  673. flag = true;
  674. write_data(qq);
  675. }
  676. else
  677. {
  678. compress_signal();
  679. write_data(qq);
  680. flag = false;
  681. noise_update();
  682. }
  683. }
  684. else
  685. {
  686. compress_signal();
  687. write_data(qq);
  688. flag = false;
  689. noise_update();
  690. }
  691. }//if(signal_energy > 8*energy_threshhold)
  692. }//while(!flag)结束
  693.         //找语音的结束点
  694. //如果有连续        
  695. while(flag)
  696. {    
  697.     value = REG32(GPIO_GPVAL);
  698. dip1 = value & 0x00000001;
  699. dip2 = value & 0x00000080;
  700. dip3 = value & 0x00000040;
  701. dip4 = value & 0x00000020;
  702. if((!dip1) && (dip2) && (dip3) && (dip4))
  703. {
  704. a = 0.6;
  705. b = 0.2;
  706. c = 5;
  707. d = 3;
  708. f = 1.2;
  709. }
  710. else if((!dip1) && (dip2) && (dip3) && (!dip4))
  711. {
  712. a = 1.0;
  713. b = 1;
  714. c = 5;
  715. d = 4;
  716. f = 1.5;
  717. }
  718. else if((!dip1) && (dip2) && (!dip3) && (dip4))
  719. {
  720. a = 1.5;
  721. b = 1.5;
  722. c = 6;
  723. d = 4;
  724. f = 1.8;
  725. }
  726. else if((!dip1) && (dip2) && (!dip3) && (!dip4))
  727. {
  728. a = 3;
  729. b = 3;
  730. c = 6;
  731. d = 4;
  732. f = 2.0;
  733. }
  734. else 
  735. ;
  736. //这种判断方法是在50帧中如果有15帧的能量小于1.5倍门限则进一步用avv判决  
  737. int s = 100;
  738. int totalenergynum = 0;
  739. int totalavvnum = 0;
  740. int totalnum = 0;
  741. // read_signal();
  742. Enhance();
  743. read_signal();
  744. //能量判决,如果读入k帧的能量与门限值比较,如果大于门限,则输出,否则进一步用AVV判决;               
  745. while(s!=0)
  746. {
  747. if(signal_energy < f*energy_threshhold)
  748. {
  749. totalenergynum++;
  750. noise_update();
  751. }
  752. else if(signal_energy < 1.8*energy_threshhold)
  753. {
  754. totalnum++;
  755. }
  756. else
  757. ;
  758. subframe_energyvar();
  759. //根据子帧能量方差与子帧的平均能量比较来做判决;
  760. if(frame_energyvariance<(b)*(average_noiseenergy))
  761. {
  762. totalavvnum++;
  763. }
  764.                    
  765. write_data(qq);
  766. Enhance();
  767. read_signal();
  768. s--;
  769. }
  770. //if(totalnum>60 && totalavvnum<60)
  771. //{
  772. // flag = true;  
  773. // write_data(qq);
  774. //}
  775. //else
  776. {
  777. if(totalenergynum>80 && totalavvnum>85)
  778. {
  779. totalenergynum=0;
  780. //语音结束点,并更新噪声
  781. flag = false;
  782. compress_signal();
  783. write_data(qq);
  784. noise_update();//当判为静音帧时进行噪声更新          
  785. }//if(totalenergynum>70 && totalavvnum>50)结束
  786. else
  787. {
  788. flag = true;
  789. write_data(qq);
  790. }
  791. }//while(s!=0)结束
  792. }//while(flag)结束
  793.     }//while(1)结束
  794. }//主函数结束