postfil.c
Upload User: hbbaokai
Upload Date: 2009-07-13
Package Size: 328k
Code Size: 12k
Category:

VOIP program

Development Platform:

Visual C++

  1. /*************************************************************************/
  2. /*                                                                       */
  3. /*                            LD-CELP  G.728                             */
  4. /*                                                                       */
  5. /*    Low-Delay Code Excitation Linear Prediction speech compression.    */
  6. /*                                                                       */
  7. /*                 Copyright: Analog Devices, Inc., 1993                 */
  8. /*                                                                       */
  9. /*                         Author: Alex Zatsman.                         */
  10. /*                                                                       */
  11. /*  This program was written mostly for testing  Analog Devices' g21k C  */
  12. /*  compiler for the  ADSP21000 architecture  family. While the program  */
  13. /*  works  on  Sparc and ADSP21020, it  has  NOT  been  tested with the  */
  14. /*  official test data from CCITT/ITU.                                   */
  15. /*                                                                       */
  16. /*  The program  is   distributed as  is,  WITHOUT ANY WARRANTY, EITHER  */
  17. /*  EXPLICIT OR IMPLIED.                                                 */
  18. /*                                                                       */
  19. /*************************************************************************/
  20. /* Postfilter of LD-CELP Decoder */
  21. #include "common.h"
  22. #include "prototyp.h"
  23. #include "parm.h"
  24. #include "data.h"
  25. #ifdef __ADSP21000__
  26. #include <math.h>
  27. #define ABS(X) fabsf(X)
  28. #else
  29. #define ABS(X) ((X)<0.0?(-X):(X))
  30. #endif
  31. /*  Parameters from the adapter: */
  32. #define SPORDER 10
  33. int  pitch_period = 50;
  34. real pitch_tap=0.0;
  35. real pitch_gain=1;
  36. static real
  37.     shzscale[SPORDER+1], /* Precomputed Scales for IIR coefficients */
  38.     shpscale[SPORDER+1], /* Precomputed Scales for FIR Coefficients */
  39.     shpcoef[SPORDER+1], /* Short Term Filter (Poles/IIR) Coefficients */
  40.     shzcoef[SPORDER+1], /* Short Term Filter (Zeros/FIR) Coefficients */
  41.     tiltz;
  42. static void  longterm(real[], real[]);
  43. static void shortterm(real[], real[]);
  44. /* Compute sum of absolute values of vector V */
  45. static real vec_abs(real v[])
  46. {
  47.     int i;
  48.     real r = v[0];
  49.     for(i=1; i<IDIM; i++)
  50. r+=ABS(v[i]);
  51.     return r;
  52. }
  53. void
  54. postfilter(real input[], real output[])
  55. {
  56.     int i;
  57.     static
  58.     real
  59. temp[IDIM],  /* Output of long term filter*/
  60. temp2[IDIM],  /* Input of short term filter*/
  61. new_gain, /* Gain of filtered output */
  62. input_gain,  /* Gain of input */
  63. scale; /* Scaling factor for gain preservation */
  64. static real scalefil=1.0; /* Smoother version of scale */
  65.     longterm(input, temp);
  66.     shortterm(temp, temp2);
  67.     /* Computed scale for gain preservation */
  68.     new_gain = vec_abs(temp2);
  69.     if (new_gain > 1.0)
  70.     {
  71. input_gain = vec_abs(input);
  72. scale = input_gain/new_gain;
  73.     }
  74.     else 
  75. scale = 1.0;
  76.     
  77.     /* Smooth out scale, then scale the output */
  78.     for(i=0; i<IDIM; i++) {
  79. scalefil = AGCFAC * scalefil + (1.0 - AGCFAC)*scale;
  80. output[i] = scalefil * temp2[i];
  81.     }
  82. }
  83. static void
  84. longterm(real input[], real output[])
  85. {
  86.     int i;
  87.     real out;
  88.     static real lmemory[KPMAX];
  89.     /* Add weighted pitch_period-delayed signal */
  90.     for(i=0; i<IDIM; i++) {
  91. out = input[i] + pitch_tap * lmemory[KPMAX+i-pitch_period];
  92. output[i] = pitch_gain*out;
  93.     }
  94.     
  95.     /* Shift-in input to lmemory */
  96.     for (i=0; i<KPMAX-IDIM; i++)
  97. lmemory[i] = lmemory[i+IDIM];
  98.     for(i=0; i<IDIM; i++)
  99. lmemory[KPMAX-IDIM+i] = input[i];
  100. }
  101. /*
  102.   Again, memories (shpmem, shzmem) are in reverse order, 
  103.   i.e. [0] is the oldest.
  104.  */
  105. static void
  106. shortterm(real input[], real output[])
  107. {
  108.     int k,j;
  109.     static real shpmem[SPORDER], shzmem[SPORDER];
  110.     for(k=0; k<IDIM; k++) {
  111. /* FIR Part */
  112. real in = input[k], out;
  113. out = in;
  114. for(j=SPORDER-1; j>=1; j--) {
  115.     out += shzmem[j]*shzcoef[j+1];
  116.     shzmem[j] = shzmem[j-1];
  117. }
  118. out += shzmem[0] * shzcoef[1];
  119. shzmem[0] = in;
  120. /* IIR Part */
  121. for(j=SPORDER-1; j>=1; j--) {
  122.     out -= shpmem[j]*shpcoef[j+1];
  123.     shpmem[j] = shpmem[j-1];
  124. }
  125. out -= shpmem[0] * shpcoef[1];
  126. shpmem[0] = out;
  127. output[k] = out+tiltz*shzmem[1];
  128.     }
  129. }
  130. /*********************************/
  131. /***** Postfilter Adapter ********/
  132. /*********************************/
  133. #define DECIM 4
  134. #define PMSIZE  (NPWSZ+KPMAX) /* Postfilter Memory SIZE */
  135. #define PDMSIZE (PMSIZE/DECIM)  /* Post. Decim. Memory SIZE */
  136. #define DPERMAX (KPMAX/DECIM) /* Max. Decimated Period */
  137. #define DPERMIN (KPMIN/DECIM) /* Min. Decimated Period */
  138. /* 
  139.   Using macro will make it easy to reverse the order of fil_mem elements.
  140.   Current macro realizes reverse memory.
  141.   */
  142. static real fil_mem[PMSIZE]; /* Post-Filter Memory */
  143. #define FIL_MEM(I) fil_mem[PMSIZE-1-(I)]
  144. static int extract_pitch(real[]);
  145. void
  146. psf_adapter (real frame[])
  147. {
  148.     real residue[NFRSZ];
  149.     /* Inverse Filter */
  150.   {
  151.       int i,j,k;
  152.       static real mem1[SPORDER+NFRSZ];
  153.       /** Shift in frame into mem1 **/
  154.       for(i=NFRSZ; i<SPORDER+NFRSZ; i++)
  155.   mem1[i-NFRSZ] = mem1[i];
  156.       for(i=0; i<NFRSZ; i++)
  157.   mem1[SPORDER+i] = frame[i];
  158.       
  159. #ifdef noPIPELINE
  160. {
  161.     for(k=0; k<NFRSZ; k++) {
  162. real *mem1kp = mem1+k;
  163. real
  164.     PSF_LPC_MEM *ap=a10;
  165. real
  166.     *mem1p = mem1kp,
  167.     mem1_1 = *mem1p,
  168.     a10_1 = *ap,
  169.     tmp = mem1_1;
  170. for(j=1; j<=SPORDER; j++) {
  171.     tmp -= mem1_1 * a10_1;
  172.     mem1_1 = *mem1p--;
  173.     a10_1 = *ap++;
  174.     }
  175. residue[k] = tmp-mem1_1*a10_1;
  176. mem1kp++;
  177.     }
  178. }
  179. #else
  180.       /* Un-pipelined version -- kept for reference */
  181.       for(k=0; k<NFRSZ; k++) {
  182.   real tmp = mem1[SPORDER+k];
  183.   for(j=1; j<=SPORDER; j++)
  184.       tmp -= mem1[SPORDER+k-j]*a10[j];
  185.   residue[k] = tmp;
  186.       }
  187. #endif
  188.   }
  189.      SPDEBUG(36, residue, NFRSZ);
  190.     pitch_period = extract_pitch(residue);
  191.     /** Compute Pitch Tap **/
  192.   {
  193.       int i;
  194.       real corr=0.0, corr_per=0.0;
  195. #ifdef noPIPELINE
  196.     {
  197. /** Only for REVERSED (!) fil_mem **/
  198. real
  199.     *p1 = &FIL_MEM(KPMAX),
  200.     *p2 = &FIL_MEM(KPMAX-pitch_period),
  201.     c1 = *p1--, 
  202.     c2 = *p2--;
  203. for(i=1; i<NPWSZ; i++) {
  204.     corr_per += c1 * c2; 
  205.     corr += c1 * c1;
  206.     c2 = *p2--;
  207.     c1= *p1--;
  208. }
  209. corr_per += c1 * c2;
  210. corr     += c1 * c1;
  211.     }
  212. #else
  213.       /* Un-pipelined version -- kept for reference */
  214.       for(i=0; i<NPWSZ; i++) {
  215.   corr     += FIL_MEM(KPMAX+i) * FIL_MEM(KPMAX+i);
  216.   corr_per += FIL_MEM(KPMAX+i) * FIL_MEM(KPMAX-pitch_period+i);
  217.       }
  218. #endif
  219.       if REALZEROP(corr)
  220.   pitch_tap = 0.0;
  221.       else
  222.   pitch_tap = corr_per/corr;
  223.   }
  224.     
  225.     /** Compute Long Term Coefficients **/
  226.     
  227.   {
  228.       if (pitch_tap > 1)
  229.   pitch_tap = 1.0;
  230.       if (pitch_tap < PPFTH)
  231.   pitch_tap = 0.0;
  232.       pitch_tap = PPFZCF * pitch_tap;
  233.       pitch_gain = 1.0/(1.0+pitch_tap);
  234.   }
  235.     /** Compute Short Term Coefficients **/
  236.   {
  237.       int i;
  238.       for(i=1; i<=SPORDER; i++) {
  239.   shzcoef[i] = shzscale[i]*a10[i];
  240.   shpcoef[i] = shpscale[i]*a10[i];
  241.       }
  242.       tiltz = TILTF * k10;
  243.   }
  244. }
  245. static int best_period (real buffer[], int buflen,
  246. int pmin, int pmax)
  247. {
  248.     int i, per, best_per = -1;
  249.     real best_corr = -(BIG);
  250.     for(per = pmin; per<pmax; per++) {
  251. real corr = 0.0;
  252. #ifdef noPIPELINE
  253.       {
  254.   /** Pipelining **/
  255.   real
  256.       *pb0 = buffer+pmax,
  257.       *pb1 = pb0-per,
  258.       b0 = *pb0,
  259.       b1 = *pb1;
  260.   for(i=pmax+1; i<buflen; i++) {
  261.       corr += b0 * b1;
  262.       b0 = *pb0++;
  263.       b1 = *pb1++;
  264.   }
  265.   corr += b0 * b1;
  266.       }
  267. #else
  268. for(i=pmax; i<buflen; i++)
  269.     corr += buffer[i] * buffer[i-per];
  270. #endif
  271. if (corr > best_corr) {
  272.     best_corr = corr;
  273.     best_per  = per;
  274. }     
  275.     }
  276.     return best_per;
  277. }
  278. #define DCFRSZ NFRSZ/DECIM /* size of decimated frame */
  279. static int
  280. extract_pitch(real frame[])
  281. {
  282.     int
  283. i, j, k,
  284. best_per=KPMAX,  /* Best Period (undecimated) */
  285. best_dper = KPMAX/DECIM, /* Best Decimated Period */
  286. best_old_per=KPMAX,  /* Best Old Period */
  287. permin,  /* Limits for search of best period */
  288. permax;
  289.     real
  290. best_corr=-(BIG), best_old_corr=-(BIG), tap0=0.0, tap1=0.0;
  291.     static int old_per = (KPMIN+KPMAX)>>1;
  292.     static real
  293. fil_decim_mem[PDMSIZE],
  294. fil_out_mem[NFRSZ+DECIM];
  295. #define FIL_DECIM_MEM(I) fil_decim_mem[I]
  296. #define FIL_OUT_MEM(I)   fil_out_mem[I]
  297.     
  298.     /** Shift in the frame into fil_mem **/
  299.     for(i=NFRSZ; i<PMSIZE; i++)
  300. FIL_MEM(i-NFRSZ) = FIL_MEM(i);
  301.     for(i=0; i<NFRSZ; i++)
  302. FIL_MEM(PMSIZE-NFRSZ+i) = frame[i];
  303.     /** Shift decimated filtered output */
  304.     for(i=DCFRSZ; i<PDMSIZE; i++)
  305. FIL_DECIM_MEM(i-DCFRSZ) = FIL_DECIM_MEM(i);
  306.   
  307.     /* Filter and  decimate  input */
  308.   {
  309.       int decim_phase = 0, dk;
  310.       for (k = 0, dk=0; k<NFRSZ; k++)
  311.       {
  312.   real tmp;
  313.   tmp = frame[k] - A1 * FIL_OUT_MEM(2)
  314.                  - A2 * FIL_OUT_MEM(1)
  315.                  - A3 * FIL_OUT_MEM(0);
  316.   decim_phase++;
  317.   if (decim_phase == 4) {
  318.       FIL_DECIM_MEM(PDMSIZE-DCFRSZ+dk) = 
  319.   B0 * tmp
  320. + B1 * FIL_OUT_MEM(2)
  321. + B2 * FIL_OUT_MEM(1)
  322. + B3 * FIL_OUT_MEM(0);
  323.       decim_phase = 0;
  324.       dk++;
  325.   }
  326.   FIL_OUT_MEM(0) = FIL_OUT_MEM(1);
  327.   FIL_OUT_MEM(1) = FIL_OUT_MEM(2);
  328.   FIL_OUT_MEM(2) = tmp;
  329.       }
  330.       SPDEBUG(27, fil_decim_mem+PDMSIZE-DCFRSZ, 5);
  331.   }
  332.     /* Find best Correlation in decimated domain: */
  333.     best_dper = best_period(fil_decim_mem, PDMSIZE, DPERMIN, DPERMAX);
  334.     /* Now fine-tune best correlation on undecimated  domain */
  335.     
  336.     permin = best_dper * DECIM - DECIM + 1;
  337.     permax = best_dper * DECIM + DECIM - 1;
  338.     if (permax > KPMAX)
  339. permax = KPMAX;
  340.     if (permin < KPMIN)
  341. permin = KPMIN;
  342.     
  343.   {
  344.       int per;
  345.       best_corr = -(BIG);
  346.       for(per = permin; per<=permax; per++) {
  347.   real corr = 0.0;
  348.   for(i=0,j=per;   i<NPWSZ;   i++,j++)
  349.       corr += FIL_MEM(PMSIZE-i)*FIL_MEM(PMSIZE-j);
  350.   if (corr > best_corr) {
  351.       best_corr = corr;
  352.       best_per = per;
  353.   }
  354.       }
  355.   }
  356.     
  357.     /** If we are not exceeding old period by too much, we have a real
  358.        period and not a multiple */
  359.     
  360.     permax = old_per + KPDELTA;
  361.     if (best_per <= permax)
  362. goto done;
  363.     /** Now compute best period around the old period **/
  364.     
  365.     permin = old_per - KPDELTA;
  366.     if (permin<KPMIN) permin = KPMIN;
  367.   {
  368.       int per;
  369.       best_old_corr = -(BIG);
  370.       for(per = permin; per<permax; per++) {
  371.   real corr = 0.0;
  372.   for(i=0,j=per;
  373.       j<PMSIZE;
  374.       i++,j++)
  375.       corr += FIL_MEM(i)*FIL_MEM(j);
  376.   if (corr > best_old_corr) {
  377.       best_old_corr = corr;
  378.       best_old_per = per;
  379.   }
  380.       }
  381.   }
  382.     
  383.     /***** Compute the tap ****/
  384.   {
  385.       real s0=0.0, s1=0.0;
  386.       for(i=KPMAX; i<PMSIZE; i++) {
  387.   s0 += FIL_MEM(i-best_per)     * FIL_MEM(i-best_per);
  388.   s1 += FIL_MEM(i-best_old_per) * FIL_MEM(i-best_old_per);
  389.       }
  390.       if (! REALZEROP(s0))
  391.   tap0 = best_corr/s0;
  392.       if (! REALZEROP(s1))
  393.   tap1 = best_old_corr/s1;
  394.       tap0 = CLIPP(tap0, 0.0, 1.0);
  395.       tap1 = CLIPP(tap1, 0.0, 1.0);
  396.       if (tap1 > TAPTH * tap0)
  397.   best_per = best_old_per;
  398.   }
  399.   done:
  400.     old_per = best_per;
  401.     return best_per;
  402. }
  403. void
  404. init_postfilter()
  405. {
  406.     int i;
  407.     shzscale[0] = shpscale[0] = 1.0;
  408.     for (i=1; i<=SPORDER; i++)
  409.     {
  410. shzscale[i] = SPFZCF * shzscale[i-1];
  411. shpscale[i] = SPFPCF * shpscale[i-1];
  412.     }
  413. }
  414. #ifdef PITCHTEST
  415. /* Test Pitch Extract -- only on hosts.
  416.    Build a "chirp wave" and dump expected and computed pitch,
  417.    as well as the filtered and decimated signal */
  418. #include <math.h>
  419. void
  420. main ()
  421. {
  422.     real freq0=70, slope=0.1;
  423.     int i, phase;
  424.     real freq, real_freq, frame[NFRSZ];
  425.     
  426.     sp_file_on(27);
  427.     sp_file_on(30);
  428.     sp_file_on(33);
  429.     sp_file_on(34);
  430.     sp_file_on(35);
  431.     for(i=0, phase =0, freq=freq0;
  432. i<2000;
  433. i++,phase++,freq+=slope) {
  434. if (phase == NFRSZ) {
  435.     int pitch = extract_pitch(frame);
  436.     real rpitch = (real) pitch;
  437.     real expected_pitch = 8000/freq;
  438.     phase= 0;
  439.     SPDEBUG(33, frame, NFRSZ);
  440.     SPDEBUG(34, &expected_pitch, 1);
  441.     SPDEBUG(35, &rpitch, 1);
  442. }
  443. real_freq = 2. *M_PI * freq / 8000.;
  444. frame[phase] = sin(real_freq*i);
  445.     }
  446. }
  447. #endif