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

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 = 4.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. //frame_energyvariance = (frame_energyvariance);
  427. average_noiseenergy = 0.0;
  428. for(i=0; i<10; i++)
  429. {
  430. average_noiseenergy += noise_energy[i];
  431. }
  432. average_noiseenergy /= 10;
  433. }
  434. /*****功能:更新门限energy_threshhold****
  435. ******使之能自适应信道的变化        ****
  436. ******输入:一帧数据                 ****
  437. ******输出:门限energy_threshhold值  ***/
  438. void noise_update(void)
  439. {
  440. int i;
  441. float old_noiseenergyvar;
  442. float new_noiseenergyvar;
  443. float ratio;
  444. float t;
  445.         
  446. average_noiseenergy = 0.0;
  447. for(i=0; i<10; i++)
  448. {
  449. average_noiseenergy += noise_energy[i];
  450. }
  451. average_noiseenergy /= 10;
  452.         
  453. old_noiseenergyvar = 0.0;
  454. for(i=0; i<10; i++)
  455. old_noiseenergyvar += (noise_energy[i]-average_noiseenergy)*(noise_energy[i]-average_noiseenergy);
  456.         
  457. for(i=0; i<9; i++) //这里i最高只能取8!!!        
  458. {
  459. noise_energy[i+1] = noise_energy[i];
  460. noise_energy[0] =  signal_energy;
  461. }
  462. average_noiseenergy = 0.0;
  463. for(i=0; i<10; i++)
  464. {
  465. average_noiseenergy += noise_energy[i];
  466. }
  467. average_noiseenergy /= 10;
  468. new_noiseenergyvar = 0.0;
  469. for(i=0; i<10; i++)
  470. new_noiseenergyvar += (noise_energy[i]-average_noiseenergy)*(noise_energy[i]-average_noiseenergy);
  471. old_noiseenergyvar = sqrt(old_noiseenergyvar);
  472. new_noiseenergyvar = sqrt(new_noiseenergyvar);
  473. //old_noiseenergyvar = (old_noiseenergyvar);
  474. //new_noiseenergyvar = (new_noiseenergyvar);
  475. //根据当前噪声能量方差与先澳芰糠讲畹谋戎道炊詐赋值,借此自适应的跟踪信道的噪声变化;                    
  476.         
  477. ratio = new_noiseenergyvar/old_noiseenergyvar;
  478. if(ratio>=1.25)
  479. t=0.15;
  480. else if(ratio>=1.10)
  481. t=0.10;
  482. else if(ratio>=1.00)
  483. t=0.08;        
  484. else
  485. t=0.05;
  486. energy_threshhold = energy_threshhold*(1-t)+t*noise_energy[0];
  487.        
  488. }
  489. int main(void)
  490. {
  491. float a; //avv判决语音起始点的倍数
  492. float b;  //avv判决语音结束点的倍数
  493. float c; //第一级能量倍数
  494. float d;   //第二级能量倍数
  495. float f;
  496. int dip1,dip2,dip3,dip4;
  497. int value;  
  498. bool flag;
  499.     void Enhance(void);
  500. CSR &= (~0x00000001);
  501. IER = 0;
  502. data_init();
  503. buf_init();
  504. timer1_init();
  505. spark_led();
  506. sys_init();
  507. for(int t = 0; t < 128; t++)
  508. {
  509. out1[t] = 0.0;
  510.         dm[t] = 0.0;
  511. }
  512.     for(int t = 0; t < 129; t++)
  513. {
  514.         predp[t] = 0.0;
  515. prexp[t] = 0.0;
  516. }
  517. for(int i = 0; i < 200; i++)   //取200帧,用于能量直方图的更新,放音           
  518. {
  519. p = read_data();
  520.         for(int t = 0; t < 128; t++)
  521.         {
  522. dm[t+128] = (float)p[t];   
  523. }
  524. for (int h = 0; h < FRAMELEN; h++)
  525. {
  526. d1[h] = dm[h]*hamming[h];   //加hamming窗处理
  527. }
  528.         //计算信号能量
  529. pre_energy[i] = 0.0;
  530. for(int h = 0; h < FRAMELEN; h++)
  531. {
  532. pre_energy[i] += d1[h]*d1[h];
  533. }
  534. for(int t = 0; t < 128; t++)
  535.         {
  536. cm[t] = (int16)( (d1[t]+out1[t])*0.5 ); 
  537.      out1[t] = d1[t+128]; 
  538.      }
  539. write_data(cm);
  540. for(int t = 0; t < 128; t++)
  541. {
  542. dm[t] = dm[t+128];
  543. }
  544. }
  545. //循环判断每帧数据    
  546. while(1)
  547. {         
  548. //用十帧数据来训练整个算法,并得到相关参数.
  549. train();
  550. flag = false;//初始化flag:语音有无标志
  551. //找语音的起始点
  552.         
  553. while(!flag)
  554. {            
  555. value = REG32(GPIO_GPVAL);
  556. dip1 = value & 0x00000001;
  557. dip2 = value & 0x00000080;
  558. dip3 = value & 0x00000040;
  559. dip4 = value & 0x00000020; 
  560. if((!dip1) && (dip2) && (dip3) && (dip4))
  561. {
  562. a = 25;
  563. b = 1;
  564. c = 5;
  565. d = 3;
  566. f = 1.8;
  567. }
  568. else if((!dip1) && (dip2) && (dip3) && (!dip4))
  569. {
  570. a = 1.0;
  571. b = 1;
  572. c = 5;
  573. d = 4;
  574. f = 1.8;
  575. }
  576. else if((!dip1) && (dip2) && (!dip3) && (dip4))
  577. {
  578. a = 2;
  579. b = 1.5;
  580. c = 6;
  581. d = 4;
  582. f = 1.8;
  583. }
  584. else if((!dip1) && (dip2) && (!dip3) && (!dip4))
  585. {
  586. a = 7;
  587. b = 4;
  588. c = 6;
  589. d = 4;
  590. f=1.8;
  591. }
  592. else 
  593. ;
  594. Enhance();
  595. read_signal();
  596. //能量判决,如果读入帧的能量与门限值比较,如果大于门限,则输出                            
  597. if(signal_energy > c*energy_threshhold)
  598. {                  
  599. subframe_energyvar();
  600.           
  601. if(frame_energyvariance>(a)*(average_noiseenergy))
  602. {            
  603. flag = true;                       
  604. write_data(qq);   
  605. }
  606. else
  607. {
  608. compress_signal();
  609. flag = false;
  610. write_data(qq);
  611. noise_update();
  612. }
  613. }
  614.     //如果是d倍门限以上则需看avv;         
  615. else if(signal_energy > d*energy_threshhold)
  616. {
  617. subframe_energyvar();
  618. //avv判决           
  619. if(frame_energyvariance > (a)*(average_noiseenergy))
  620. {            
  621. flag = true;
  622. write_data(qq);
  623. }           
  624. else
  625. {                            
  626. compress_signal();
  627. flag = false;
  628. write_data(qq);
  629. noise_update();
  630. }
  631. }
  632.     
  633.         
  634. else if(signal_energy > 1.8*energy_threshhold)
  635. {                  
  636. subframe_energyvar();
  637. //avv判决;
  638. if(frame_energyvariance>a*(average_noiseenergy))
  639. {                        
  640. compress_signal();
  641. write_data(qq);
  642. Enhance();
  643. read_signal();
  644. subframe_energyvar();
  645. //avv判决;
  646. if(frame_energyvariance>(a)*(average_noiseenergy))
  647. {
  648. flag = true;
  649. write_data(qq);
  650. }
  651. else
  652. {
  653. compress_signal();
  654. write_data(qq);
  655. flag = false;
  656. noise_update();
  657. }
  658. }                
  659. //当判为静音帧时进行噪声更新;                  
  660. else                  
  661. {                        
  662. compress_signal();                        
  663. write_data(qq);
  664. flag = false;                        
  665. noise_update();                  
  666. }             
  667. }
  668. //小能量帧用avv判决 
  669. /* else
  670. {
  671. subframe_energyvar();
  672. if(frame_energyvariance>(a+0.5)*(average_noiseenergy))//文献中用的是frame_noisereference
  673. {
  674. compress_signal();
  675. write_data(qq);
  676. Enhance();
  677. read_signal();
  678. subframe_energyvar();
  679. //进一步avv判决;
  680. if(frame_energyvariance>(a+0.5)*(average_noiseenergy))
  681. {
  682. flag = true;
  683. write_data(qq);
  684. }
  685. else
  686. {
  687. compress_signal();
  688. write_data(qq);
  689. flag = false;
  690. noise_update();
  691. }
  692. }
  693. else
  694. {
  695. compress_signal();
  696. write_data(qq);
  697. flag = false;
  698. noise_update();
  699. }
  700. }*///if(signal_energy > 8*energy_threshhold)
  701. }//while(!flag)结束
  702.         //找语音的结束点
  703. //如果有连续        
  704. while(flag)
  705. {    
  706.     value = REG32(GPIO_GPVAL);
  707. dip1 = value & 0x00000001;
  708. dip2 = value & 0x00000080;
  709. dip3 = value & 0x00000040;
  710. dip4 = value & 0x00000020;
  711. if((!dip1) && (dip2) && (dip3) && (dip4))
  712. {
  713. a = 10;
  714. b = 1;
  715. c = 500;
  716. d = 300;
  717. f = 1.8;
  718. }
  719. else if((!dip1) && (dip2) && (dip3) && (!dip4))
  720. {
  721. a = 1.0;
  722. b = 1;
  723. c = 5;
  724. d = 4;
  725. f = 1.8;
  726. }
  727. else if((!dip1) && (dip2) && (!dip3) && (dip4))
  728. {
  729. a = 1.5;
  730. b = 1.5;
  731. c = 6;
  732. d = 4;
  733. f = 1.8;
  734. }
  735. else if((!dip1) && (dip2) && (!dip3) && (!dip4))
  736. {
  737. a = 3;
  738. b = 3;
  739. c = 6;
  740. d = 4;
  741. f = 2.0;
  742. }
  743. else 
  744. ;
  745. //这种判断方法是在50帧中如果有15帧的能量小于1.5倍门限则进一步用avv判决  
  746. int s = 100;
  747. int totalenergynum = 0;
  748. int totalavvnum = 0;
  749. int totalnum = 0;
  750. // read_signal();
  751. Enhance();
  752. read_signal();
  753. //能量判决,如果读入k帧的能量与门限值比较,如果大于门限,则输出,否则进一步用AVV判决;               
  754. while(s!=0)
  755. {
  756. if(signal_energy < f*energy_threshhold)
  757. {
  758. totalenergynum++;
  759. noise_update();
  760. }
  761. else if(signal_energy < 1.8*energy_threshhold)
  762. {
  763. totalnum++;
  764. }
  765. else
  766. ;
  767. subframe_energyvar();
  768. //根据子帧能量方差与子帧的平均能量比较来做判决;
  769. if(frame_energyvariance<(b)*(average_noiseenergy))
  770. {
  771. totalavvnum++;
  772. }
  773.                    
  774. write_data(qq);
  775. Enhance();
  776. read_signal();
  777. s--;
  778. }
  779. //if(totalnum>60 && totalavvnum<60)
  780. //{
  781. // flag = true;  
  782. // write_data(qq);
  783. //}
  784. //else
  785. {
  786. if(totalenergynum>80)
  787. {
  788. totalenergynum=0;
  789. //语音结束点,并更新噪声
  790. flag = false;
  791. compress_signal();
  792. write_data(qq);
  793. noise_update();//当判为静音帧时进行噪声更新          
  794. }//if(totalenergynum>70 && totalavvnum>50)结束
  795. else
  796. {
  797. flag = true;
  798. write_data(qq);
  799. }
  800. }//while(s!=0)结束
  801. }//while(flag)结束
  802.     }//while(1)结束
  803. }//主函数结束