⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc_lib.c

📁 2400bps MELP语音编解码源程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
    for(i=2; i <= p; i++)
    {
	y1[1] = L_deposit_h(r[i]);
	L_temp = L_deposit_h(r[i]);
	
        for(j=1; j < i; j++)
        {  
	    y1[j+1] = L_add(y2[j], L_mpy_ls(L_temp, k[j]));    L_data_move();
	    L_temp = L_add (L_temp, L_mpy_ls(y2[j], k[j]));
	    y2[j] = y1[j];    L_data_move();
	}

        /* k[i] = -temp/y2[i]; */
        if (L_temp > y2[i]) {
	  for (j = i; j <= p; j++)
	    k[j] = 0;
#if (PRINT)
	  printf("\nERROR: numerator bigger than denominator in lpc_schr\n");
	  printf("Reflection coefficients used in frame %d:\n",frames);
	  for (i = 1; i <= p; i++) {
	    printf(" %5.8f ",(float)k[i]/(1<<15));
	  }
	  printf("\n");
#endif
	  break;
	}

	shift = norm_l(y2[i]);
	n_temp = abs_s(extract_h(L_shl(L_temp,shift)));    data_move();
	n_y2 = abs_s(extract_h(L_shl(y2[i],shift)));    data_move();

	k[i] = divide_s(n_temp,n_y2);    data_move();
	/* increment complexity for if statement */
	L_logic(); compare_zero();
	if ((L_temp ^ y2[i]) >= 0)
	{
	    k[i] = negate(k[i]);    data_move();
	}

	y2[i+1] = L_add(y2[i], L_mpy_ls(L_temp, k[i]));    L_data_move();
	y2[i] = y1[i];    L_data_move();
	
	alphap = mult(alphap,sub(ONE_Q15,mult(k[i],k[i])));    data_move();
    }
    
    if (a != NULL)
    {
	lpc_refl2pred(k,a,p);	
    }

    if (k_tmp == NULL) 
	MEM_FREE(FREE,k);

    MEM_FREE(FREE,y2);
    MEM_FREE(FREE,y1);
    
    return(alphap);   /* alphap in Q15 */
} /* LPC_SCHR */


/* LPC_REFL2PRED
      get predictor coefficients from the reflection coeffs
   Synopsis: lpc_refl2pred(k,a,p)

      Input:
         k- the reflection coeffs
         p- the predictor order
      Output:
         a- the predictor coefficients
   Reference:  Markel and Gray, Linear Prediction of Speech

   Q values:
   k - Q15
   a - Q12
*/

Shortword lpc_refl2pred(Shortword *k,Shortword *a,Shortword p)
{
    Shortword i,j;
    Shortword *a1;

    MEM_ALLOC(MALLOC,a1,p+1,Shortword);

    for(i=1; i <= p; i++)
    {
        /* refl to a recursion */
        a[i] = shift_r(k[i],-3);      /* a in Q12 */    data_move();
        for(j=1; j < i; j++) {
	  a1[j] = a[j];    data_move();
	}
        for(j=1; j < i; j++) {
            a[j] = add(a1[j],mult(k[i],a1[i-j]));    data_move();
	}
    }

    MEM_FREE(FREE,a1);
    return((Shortword)0);
} /* LPC_REFL2PRED */


/* minimum LSP separation-- a global variable */
Shortword lsp_delta = 0;

/* LPC_PRED2LSP
      get LSP coeffs from the predictor coeffs
      Input:
         a- the predictor coefficients
         p- the predictor order
      Output:
         w- the lsp coefficients

      This function uses a DFT to evaluate the P and Q polynomials,
      and is hard-coded to work only for 10th order LPC.

   Q values:
   a - Q12
   w - Q15
*/
static void lsp_to_freq(Shortword lsp[], Shortword w[], Shortword order);

#define LPC_ORD 10

Shortword lpc_pred2lsp(Shortword *a,Shortword *w,Shortword p)
{
    Shortword i,j;
    Shortword p_cof[LPC_ORD+1], q_cof[LPC_ORD+1],
              p_freq[LPC_ORD+1], q_freq[LPC_ORD+1];
    Longword L_p_cof[LPC_ORD+1], L_q_cof[LPC_ORD+1];
    Longword L_ai,L_api,L_temp;

    /* Generate P' and Q' polynomials   */
    L_p_cof[0] = (Longword)ONE_Q26;
    L_q_cof[0] = (Longword)ONE_Q26;
    for ( i = 1; i <= p; i++ ) {
        /* temp = sub(a[i],a[p+1-i]); */     /* temp in Q12 */
        L_ai = L_shr(L_deposit_h(a[i]),2);     L_data_move();
	L_api = L_shr(L_deposit_h(a[p+1-i]),2);     L_data_move();
	L_temp = L_sub(L_ai,L_api);       /* L_temp in Q26 */
        L_p_cof[i] = L_add(L_temp,L_p_cof[i-1]);      /* L_p_cof in Q26 */
	/* temp = add(a[i],a[p+1-i]); */
	L_temp = L_add(L_ai,L_api);
        L_q_cof[i] = L_sub(L_temp,L_q_cof[i-1]);      /* L_q_cof in Q26 */
    }

    /* Convert p_cof and q_cof to short */
    for ( i = 0; i <= p; i++ ) {
      p_cof[i] = round(L_p_cof[i]);     /* p_cof in Q10 */
      q_cof[i] = round(L_q_cof[i]);     /* q_cof in Q10 */
    }

    /* Find root frequencies of LSP polynomials */
    lsp_to_freq(p_cof,p_freq,p);
    lsp_to_freq(q_cof,q_freq,p);

    /* Combine frequencies into single array    */
    w[0] = 0;
    j = 1;
    for (i = 0; i < (shr(p,1)); i++) {
        w[j++] = q_freq[i];      data_move();
        w[j++] = p_freq[i];      data_move();
    }

    return((Shortword)0);

} /* LPC_PRED2LSP */

/*                                                              */
/*      Subroutine LSP_TO_FREQ: Calculate Line Spectrum Pair    */
/*      root frequencies from LSP polynomial.                   */
/*                                                              */
/* Q values:
   lsp - Q10
   w - Q15 
*/
#define DFTLENGTH       512
#define DFTLENGTH_D2    (DFTLENGTH/2)
#define DFTLENGTH_D4    (DFTLENGTH/4)

static void lsp_to_freq(Shortword lsp[], Shortword w[], Shortword p)

{
    Shortword i;
    Shortword p2, count, prev_less, j;
    static Shortword firstcall = 1;
    Longword mag0, mag1, mag2;
    Shortword s_mag0, s_mag1, s_mag2;
    Shortword *p_cos, *p_endlsp, *p_lsp, *p_begcos, *p_endcos;
    Shortword temp1, temp2;
    Longword L_temp1, L_temp2;
    static Shortword lsp_cos[DFTLENGTH];    /* cosine table */
    static Shortword default_w, default_w0;
    static Shortword cos_tab[129] =
    { 
        32767, 32766, 32758, 32746, 32729, 32706, 32679, 32647, 32610,
        32568, 32522, 32470, 32413, 32352, 32286, 32214, 32138, 32058,
        31972, 31881, 31786, 31686, 31581, 31471, 31357, 31238, 31114,
        30986, 30853, 30715, 30572, 30425, 30274, 30118, 29957, 29792,
        29622, 29448, 29269, 29086, 28899, 28707, 28511, 28311, 28106,
        27897, 27684, 27467, 27246, 27020, 26791, 26557, 26320, 26078,
        25833, 25583, 25330, 25073, 24812, 24548, 24279, 24008, 23732,
        23453, 23170, 22884, 22595, 22302, 22006, 21706, 21403, 21097,
        20788, 20475, 20160, 19841, 19520, 19195, 18868, 18538, 18205,
        17869, 17531, 17190, 16846, 16500, 16151, 15800, 15447, 15091,
        14733, 14373, 14010, 13646, 13279, 12910, 12540, 12167, 11793,
        11417, 11039, 10660, 10279,  9896,  9512,  9127,  8740,  8351,
        7962,   7571,  7180,  6787,  6393,  5998,  5602,  5205,  4808,
        4410,   4011,  3612,  3212,  2811,  2411,  2009,  1608,  1206,
        804,     402,     0
    };

    if (firstcall) {
        /* Initialization: fill cosine table */
        firstcall = 0;

	/* for (i = 0; i < DFTLENGTH; i++ )
	     lsp_cos[i] = cos(i*(TWOPI / DFTLENGTH)); */
	for (i = 0; i < DFTLENGTH_D4; i++) {
	  lsp_cos[i] = cos_tab[i];
	  lsp_cos[i+DFTLENGTH_D4] = -cos_tab[DFTLENGTH_D4-i];
	  lsp_cos[i+2*DFTLENGTH_D4] = -cos_tab[i];
	  lsp_cos[i+3*DFTLENGTH_D4] = cos_tab[DFTLENGTH_D4-i];
	}

	/* compute default values for w[] */
	/* (1./p2) in Q15 */
	default_w = divide_s(ONE_Q11,shl(p,10));
	/* w[0] = (0.5/p2) in Q15 */
	default_w0 = shr(default_w,1);
    }

    prev_less = 1;
    mag0 = (Longword)0x7fffffff;      L_data_move();
    mag1 = (Longword)0x7fffffff;      L_data_move();
    s_mag0 = (Shortword)0x7fff;      data_move();
    s_mag1 = (Shortword)0x7fff;      data_move();
    p2 = shr(p,1);      /* p/2 */
    count = 0;      data_move();
    p_begcos = &lsp_cos[0];
    p_endcos = &lsp_cos[DFTLENGTH-1];
    p_endlsp = &lsp[p2];

    /*  Search all frequencies for minima of Pc(w) */
    for (i = 0; i <= DFTLENGTH_D2; i++ ) {
        p_lsp = p_endlsp;
        p_cos = p_begcos++;
	/* mag2 = 0.5 * *(p_lsp--); */
	mag2 = L_mult(*(p_lsp--),(Shortword)X05_Q14);     /* mag2 in Q25 */
        for (j = p2 - 1; j >= 0; j-- ) {
	    L_temp1 = L_shr(L_mult(*(p_lsp--),*(p_cos)),1);
            mag2 = L_add(mag2,L_temp1);
	    complexity -= 4;    /* this can be done with MAC on TMS320C5x */
            p_cos += i;
            if (p_cos > p_endcos)
                p_cos -= DFTLENGTH;
        }
	s_mag2 = extract_h(mag2);
        mag2 = L_abs(mag2);

	L_compare_nonzero();
        if (mag2 < mag1) {
	    prev_less = 1;      data_move();
	}
        else {
            if (prev_less) {
	      /* check for sign change */
	      logic();    compare_zero();
	      if ((s_mag0 ^ s_mag2) < 0) {
		/* Minimum frequency found */
		/*w[count] = i - 1 + (0.5 *
		             (mag0 - mag2) / (mag0 + mag2 - 2*mag1) );
			     w[count] *= (2. / DFTLENGTH) ;*/
		L_temp1 = L_shr(L_sub(mag0,mag2),1);
		L_temp2 = L_sub(mag0,L_shl(mag1,1));
		L_temp2 = L_add(L_temp2,mag2);
		temp1 = L_divider2(L_temp1,L_temp2,0,0);  /* temp1 in Q15 */
		temp1 = shr(temp1,9);    /* Q6 */
		temp2 = sub(i,1);
		temp1 = add(shl(temp2,6),temp1);
		w[count] = divide_s(temp1,shl(DFTLENGTH,5));      data_move();
		count = add(count,1);
	      }
	    }
	    prev_less = 0;      data_move();
        }
        mag0 = mag1;      L_data_move();
        mag1 = mag2;      L_data_move();
	s_mag0 = s_mag1;      data_move();
	s_mag1 = s_mag2;      data_move();

    }
    
    /*  Verify that all roots were found                */
    if (count != p2) {
#if (PRINT)
        printf("ERROR: couldn't find LSP frequencies in frame %d.\n",frames);
        printf(" Found were ");
        for (i = 0; i < count; i++) 
            printf(" %10.4f ",(float)w[i]/(1<<15));
        printf("\n");
#endif
        /* use default values */
        w[0] = default_w0;
        for (i = 1; i < p2; i++) {
            w[i] = w[i-1] + default_w;
        }
    }
} /* LSP_TO_FREQ */
#undef  DFTLENGTH
#undef  DFTLENGTH_D2
#undef  DFTLENGTH_D4


/* LPC_PRED2REFL
      get refl coeffs from the predictor coeffs
      Input:
         a- the predictor coefficients
         p- the predictor order
      Output:
         k- the reflection coefficients
      Returns:
         energy - energy of residual signal
   Reference:  Markel and Gray, Linear Prediction of Speech

   Q values:
   *a - Q12
   *k - Q15
   energy - Q15
*/

Shortword lpc_pred2refl(Shortword *a,Shortword *k,Shortword p)
{
    Shortword *b,*b1, e;
    Shortword energy = ONE_Q15;
    Shortword i,j;
    Shortword shift;
    Shortword temp, n_temp, n_e;

    MEM_ALLOC(MALLOC,b,p+1,Shortword);
    MEM_ALLOC(MALLOC,b1,p+1,Shortword);

    /* equate temporary variables (b = a) */
    for(i=1; i <= p; i++) {
      b[i] = a[i];      data_move();
    }

    /* compute reflection coefficients */
    for(i=p; i > 0; i--)
    {
        k[i] = shl(b[i],3);     /* Q12 -> Q15 */
        e = sub(ONE_Q15,mult(k[i],k[i]));
        energy = mult(energy,e);
        for(j=1; j < i; j++) {
            b1[j] = b[j];      data_move();
	}

        for(j=1; j < i; j++) {
	    /* b[j] = (b1[j] - k[i]*b1[i-j])/e; */
	    temp = mult(k[i],b1[i-j]);    /* temp in Q12 */
	    temp = sub(b1[j],temp);

	    /* check signs of temp and e before division */
	    n_temp = abs_s(temp);
	    n_e = abs_s(e);
	    shift = norm_s(n_e);
	    n_e = shl(n_e,shift);
	    if (n_temp > n_e) {
	      n_temp = shr(n_temp,1);
	      shift = add(shift,1);
	    }
	    b[j] = shl(divide_s(n_temp,n_e),shift);    /* b[j] in Q12 */

	    if ((temp ^ e) < 0)
	      b[j] = negate(b[j]);
	}
    }

    MEM_FREE(FREE,b1);
    MEM_FREE(FREE,b);
    return(energy);
} /* LPC_PRED2REFL */


/* LPC_LSP2PRED
      get predictor coefficients from the LSPs
   Synopsis: lpc_lsp2pred(w,a,p)
      Input:
         w- the LSPs
         p- the predictor order
      Output:
         a- the predictor coefficients
   Reference:  Kabal and Ramachandran
*/
/* Q values:
   w - Q15
   a - Q12
   f - Q25
   c - Q14 */

Shortword lpc_lsp2pred(Shortword *w,Shortword *a,Shortword p)
{
    Shortword i,j,k,p2;
    Shortword c[2];
    Longword **f;
    Longword L_temp;

    /* ensure minimum separation and sort */
    (void)lpc_clmp(w,lsp_delta,p);

    /* p2 = p/2 */
    p2 = shr(p,1);     data_move();

    MEM_2ALLOC(MALLOC,f,2,p2+1,Longword);

    /* f is Q25 */
    f[0][0] = f[1][0] = (Longword)ONE_Q25;    L_data_move();    L_data_move();

    /* -2.0*cos((double)w[1]*M_PI) */
    f[0][1] = L_shr(L_deposit_h(negate(cos_fxp(w[1]))),5);  L_data_move();
    f[1][1] = L_shr(L_deposit_h(negate(cos_fxp(w[2]))),5);  L_data_move();

    k = 3;

    for(i=2; i <= p2; i++)
      { 
        /* c is Q14 */
        /* multiply by 2 is considered as Q15->Q14 */
        c[0] = negate(cos_fxp(w[k++]));    data_move();
        c[1] = negate(cos_fxp(w[k++]));    data_move();
       
        f[0][i] = f[0][i-2];    L_data_move();
        f[1][i] = f[1][i-2];    L_data_move();

        for(j=i; j >= 2; j--)
          {
	    /* f[0][j] += c[0]*f[0][j-1]+f[0][j-2] */
	    L_temp = L_mpy_ls(f[0][j-1],c[0]);
	    L_temp = L_add(L_shl(L_temp,1),f[0][j-2]);
            f[0][j] = L_add(f[0][j],L_temp);    L_data_move();

            /* f[1][j] += c[1]*f[1][j-1]+f[1][j-2] */
	    L_temp = L_mpy_ls(f[1][j-1],c[1]);
	    L_temp = L_add(L_shl(L_temp,1),f[1][j-2]);
            f[1][j] = L_add(f[1][j],L_temp);    L_data_move();
          }

        f[0][1] = L_add(f[0][1],L_shl(L_mpy_ls(f[0][0],c[0]),1));
        f[1][1] = L_add(f[1][1],L_shl(L_mpy_ls(f[1][0],c[1]),1));
      }

    for(i=p2; i > 0; i--)
      {
        /* short f (f is a Q14) */
        f[0][i] = L_add(f[0][i],f[0][i-1]);
        f[1][i] = L_sub(f[1][i],f[1][i-1]);

        /* a is Q12 */
        /* a[i] = 0.50*(f[0][i]+f[1][i]) */
	/* a[p+1-i] = 0.50*(f[0][i]-f[1][i]) */
	/* Q25 -> Q27 -> Q12 */
        a[i] = extract_h(L_shl(L_add(f[0][i],f[1][i]),2));
        a[p+1-i] = extract_h(L_shl(L_sub(f[0][i],f[1][i]),2));
    }

    MEM_2FREE(FREE,f);
    return((Shortword)0);
} /* LPC_LSP2PRED */


/*
    Name: lpc_syn- LPC synthesis filter.
    Aliases: lpc_synthesis
    Description:
        LPC all-pole synthesis filter

        for j = 0 to n-1
            y[j] = x[j] - sum(k=1 to p) y[j-k] a[k]

    Inputs:
        x- input vector (n samples, x[0..n-1])
        a- lpc vector (order p, a[1..p])
        p- order of lpc filter
        n- number of elements in vector which is to be filtered
        y[-p..-1]- filter memory (past outputs)
    Outputs:
        y- output vector (n samples, y[0..n-1])
    Returns: NULL
    Includes:
        spbstd.h
        lpc.h

    Systems and Info. Science Lab
    Copyright (c) 1995 by Texas Instruments, Inc.  All rights reserved.

*/

Shortword lpc_syn(Shortword *x,Shortword *y,Shortword *a,Shortword p,
		  Shortword n)
{
    Shortword i,j;
    Longword accum;

    for(j=0; j < n; j++) {
        accum = L_shr(L_deposit_h(x[j]),3);
	for(i=p; i > 0; i--)
	    accum = L_msu(accum,y[j-i],a[i]);
	/* Round off output */
	accum = L_shl(accum,3);
	y[j] = round(accum);
    }
    return((Shortword)0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -