lpc_lib.c
资源名称:melpfix.rar [点击查看]
上传用户:cxx_68
上传日期:2021-02-21
资源大小:161k
文件大小:29k
源码类别:
语音压缩
开发平台:
Visual C++
- /*
- 2.4 kbps MELP Proposed Federal Standard speech coder
- Fixed-point C code, version 1.0
- Copyright (c) 1998, Texas Instruments, Inc.
- Texas Instruments has intellectual property rights on the MELP
- algorithm. The Texas Instruments contact for licensing issues for
- commercial and non-government use is William Gordon, Director,
- Government Contracts, Texas Instruments Incorporated, Semiconductor
- Group (phone 972 480 7442).
- The fixed-point version of the voice codec Mixed Excitation Linear
- Prediction (MELP) is based on specifications on the C-language software
- simulation contained in GSM 06.06 which is protected by copyright and
- is the property of the European Telecommunications Standards Institute
- (ETSI). This standard is available from the ETSI publication office
- tel. +33 (0)4 92 94 42 58. ETSI has granted a license to United States
- Department of Defense to use the C-language software simulation contained
- in GSM 06.06 for the purposes of the development of a fixed-point
- version of the voice codec Mixed Excitation Linear Prediction (MELP).
- Requests for authorization to make other use of the GSM 06.06 or
- otherwise distribute or modify them need to be addressed to the ETSI
- Secretariat fax: +33 493 65 47 16.
- */
- /*
- lpc_lib.c: LPC subroutines.
- */
- /* compiler include files */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "spbstd.h"
- #include "mathhalf.h"
- #include "mathdp31.h"
- #include "math_lib.h"
- #include "wmops.h"
- #include "mat.h"
- #include "lpc.h"
- #include "constant.h"
- extern int complexity;
- extern Shortword frames;
- extern FILE *fp_outdat;
- #define PRINT 1
- #define ALMOST_ONE_Q14 16382 /* ((1<<14)-2) */
- /* Lag window coefficients */
- Shortword lagw_cof[10] = {
- 32756,32721,32663,32582,32478,32351,32201,32030,31837,31622};
- /*
- LPC_ACOR
- Compute autocorrelations based on windowed speech frame
- Synopsis: lpc_acor(s,window,r,hf_correction,lag_win,p,nx)
- Input:
- input- input vector (npts samples, s[0..npts-1])
- win_cof- window vector (npts samples, s[0..npts-1])
- hf_correction- high frequency correction value
- lag_win- lag window value (for bandwidth expansion
- factor is BeqT, where T is the sampling rate)
- NOT used in this function
- order- order of lpc filter
- npts- number of elements in window
- Output:
- r- output autocorrelation vector (order+1 samples, r[0..order])
- Q values:
- input - Q0
- win_cof - Q15
- hf_correction - Q15
- */
- void lpc_acor(Shortword input[],Shortword win_cof[],
- Shortword r[],Shortword hf_correction,
- Shortword lag_win,Shortword order,Shortword npts)
- {
- Shortword i,j;
- Longword L_temp;
- Shortword *inputw;
- Shortword norm_var, scale_fact, temp;
- /* window optimized for speed and readability
- does windowing and autocorrelation sequentially
- and in the usual manner
- */
- MEM_ALLOC(MALLOC,inputw,npts,Shortword);
- if (win_cof) {
- for(i=0; i < npts; i++) {
- inputw[i] = mult(win_cof[i],shr(input[i],4)); data_move();
- }
- }
- else {
- v_equ_shr(inputw,input,4,npts);
- }
- /* Find scaling factor */
- L_temp = L_v_magsq(inputw,npts,0,1);
- compare_zero();
- if (L_temp) {
- norm_var = norm_l(L_temp);
- norm_var = sub(4,shr(norm_var,1));
- if (norm_var < 0)
- norm_var = 0;
- }
- else
- norm_var = 0;
- /* increment complexity for if statement */
- compare_zero();
- if (win_cof) {
- for(i=0; i < npts; i++) {
- inputw[i] = shr(mult(win_cof[i],input[i]),norm_var); data_move();
- }
- }
- else
- v_equ_shr(inputw,input,norm_var,npts);
- /* Compute r[0] */
- L_temp = L_v_magsq(inputw,npts,0,1);
- compare_zero();
- if (L_temp > 0) {
- /* normalize with 1 bit of headroom */
- norm_var = norm_l(L_temp);
- norm_var = sub(norm_var,1);
- L_temp = L_shl(L_temp,norm_var);
- /* High frequency correction */
- L_temp = L_add(L_temp,L_mpy_ls(L_temp,hf_correction));
- /* normalize result */
- temp = norm_s(extract_h(L_temp));
- L_temp = L_shl(L_temp,temp);
- norm_var = add(norm_var,temp);
- r[0] = round(L_temp);
- /* Multiply by 1/r[0] for full normalization */
- scale_fact = divide_s(ALMOST_ONE_Q14,r[0]);
- L_temp = L_shl(L_mpy_ls(L_temp,scale_fact),1);
- r[0] = round(L_temp);
- }
- else {
- norm_var = 0; data_move();
- r[0] = ONE_Q15; /* 1 in Q15 */ data_move();
- scale_fact = 0; data_move();
- }
- /* Compute remaining autocorrelation terms */
- for(j=1; j <= order; j++)
- {
- L_temp = 0; data_move();
- for(i=j; i < npts; i++) {
- L_temp = L_mac(L_temp,inputw[i],inputw[i-j]);
- }
- L_temp = L_shl(L_temp,norm_var);
- /* Scaling */
- L_temp = L_shl(L_mpy_ls(L_temp,scale_fact),1);
- /* Lag windowing */
- L_temp = L_mpy_ls(L_temp,lagw_cof[j-1]);
- r[j] = round(L_temp);
- }
- MEM_FREE(FREE,inputw);
- } /* lpc_acor */
- /*
- Name: lpc_aejw- Compute square of A(z) evaluated at exp(jw)
- Description:
- Compute the magnitude squared of the z-transform of
- A(z) = 1+a(1)z^-1 + ... +a(p)z^-p
- evaluated at z=exp(jw)
- Inputs:
- a- LPC filter (a[0] is undefined, a[1..p])
- w- radian frequency
- p- predictor order
- Returns:
- |A(exp(jw))|^2
- See_Also: cos(3), sin(3)
- Includes:
- spbstd.h
- lpc.h
- Systems and Info. Science Lab
- Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.
- */
- /* Q values
- --------
- a - Q12
- w - Q15
- return - Q19
- */
- /* lower limit of return value to prevent overflow of weighting function */
- #define LOW_LIMIT 54
- Longword lpc_aejw(Shortword *a,Shortword w, Shortword p)
- {
- Shortword i;
- Shortword c_re,c_im;
- Shortword cs,sn,temp;
- Shortword temp1,temp2;
- Longword L_temp;
- if (p==0)
- return((Longword)ONE_Q19);
- /* use horners method
- A(exp(jw)) = 1+ e(-jw)[a(1)+e(-jw)[a(2)+e(-jw)[a(3)+..
- ...[a(p-1)+e(-jw)a(p)]]]]
- */
- cs = cos_fxp(w); data_move(); /* temp in Q15 */
- sn = negate(sin_fxp(w)); data_move(); /* temp in Q15 */
- c_re = shr(mult(cs,a[p]),3); data_move(); /* -> Q9 */
- c_im = shr(mult(sn,a[p]),3); data_move(); /* -> Q9 */
- for(i=p-1; i > 0; i--)
- {
- /* add a[i] */
- temp = shr(a[i],3);
- c_re = add(c_re,temp); data_move();
- /* multiply by exp(-jw) */
- temp=c_im;
- temp1 = mult(cs,temp); data_move(); /* temp1 in Q9 */
- temp2 = mult(sn,c_re); data_move(); /* temp2 in Q9 */
- c_im = add(temp1, temp2); data_move();
- temp1 = mult(cs,c_re); data_move(); /* temp1 in Q9 */
- temp2 = mult(sn,temp); data_move(); /* temp2 in Q9 */
- c_re = sub(temp1,temp2); data_move();
- }
- /* add one */
- c_re = add(c_re, ONE_Q9); data_move();
- /* L_temp in Q19 */
- L_temp = L_add(L_mult(c_re,c_re),L_mult(c_im,c_im));
- if (L_temp<LOW_LIMIT)
- L_temp=(Longword)LOW_LIMIT;
- return(L_temp);
- } /* LPC_AEJW */
- #undef LOW_LIMIT
- /*
- Name: lpc_bwex- Move the zeros of A(z) toward the origin.
- Aliases: lpc_bw_expand
- Description:
- Expand the zeros of the LPC filter by gamma, which
- moves each zero radially into the origin.
- <nf>
- for j = 1 to p
- aw[j] = a[j]*gamma^j
- </nf>
- (Can also be used to perform an exponential windowing procedure).
- Inputs:
- a- lpc vector (order p, a[1..p])
- gamma- the bandwidth expansion factor
- p- order of lpc filter
- Outputs:
- aw- the bandwidth expanded LPC filter
- Returns: NULL
- See_Also: lpc_lagw(3l)
- Includes:
- spbstd.h
- lpc.h
- Systems and Info. Science Lab
- Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.
- Q values:
- *a,*aw - Q12
- gamma - Q15
- gk - Q15
- */
- Shortword lpc_bwex(Shortword *a, Shortword *aw, Shortword gamma, Shortword p)
- {
- Shortword i;
- Shortword gk;
- gk = gamma; data_move();
- for(i=1; i <= p; i++) {
- aw[i] = mult(a[i],gk);
- gk = mult(gk,gamma);
- }
- return((Shortword)0);
- }
- /*
- Name: lpc_clmp- Sort and ensure minimum separation in LSPs.
- Aliases: lpc_clamp
- Description:
- Ensure that all LSPs are ordered and separated
- by at least delta. The algorithm isn't guarenteed
- to work, so it prints an error message when it fails
- to sort the LSPs properly.
- Inputs:
- w- lsp vector (order p, w[1..p])
- delta- the clamping factor
- p- order of lpc filter
- Outputs:
- w- the sorted and clamped lsps
- Returns: NULL
- See_Also:
- Includes:
- spbstd.h
- lpc.h
- Bugs:
- Currently only supports 10 loops, which is too
- complex and perhaps unneccesary.
- Systems and Info. Science Lab
- Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.
- */
- /* Q values:
- w - Q15
- delta - Q15 */
- #define MAX_LOOPS 10
- Shortword lpc_clmp(Shortword *w, Shortword delta, Shortword p)
- {
- Shortword i,j,unsorted;
- Shortword temp,d,step1,step2;
- /* sort the LSPs for 10 loops */
- for (j=0,unsorted=TRUE; unsorted && (j < MAX_LOOPS); j++)
- {
- for(i=1,unsorted=FALSE; i < p; i++)
- if (w[i] > w[i+1])
- {
- temp = w[i+1];
- w[i+1] = w[i];
- w[i] = temp;
- unsorted = TRUE;
- }
- }
- /* ensure minimum separation */
- if (!unsorted)
- {
- for(j=0; j < MAX_LOOPS; j++)
- {
- for(i=1; i < p; i++)
- {
- /* increment complexity for if statement */
- compare_nonzero();
- d = sub(w[i+1],w[i]); data_move();
- if (d < delta)
- {
- data_move(); data_move();
- step1 = step2 = shr(sub(delta,d),1);
- /* increment complexity for if statement */
- compare_nonzero(); compare_nonzero();
- if (i==1 && (w[i] < delta)) {
- step1 = shr(w[i],1); data_move();
- }
- else {
- /* increment complexity for if statement */
- compare_nonzero();
- if (i > 1)
- {
- /* increment complexity for if statement */
- compare_nonzero();
- temp = sub(w[i],w[i-1]);
- if (temp < delta) {
- step1 = 0; data_move();
- }
- else {
- /* increment complexity for if statement */
- compare_nonzero(); compare_nonzero();
- if (temp < shl(delta,1)) {
- step1 = shr(sub(temp,delta),1);
- }
- }
- }
- }
- /* increment complexity for if statement */
- compare_nonzero(); compare_nonzero();
- if (i==(p-1) && (w[i+1] > sub(ONE_Q15,delta))) {
- step2 = shr(sub(ONE_Q15,w[i+1]),1); data_move();
- }
- else {
- /* increment complexity for if statement */
- compare_nonzero();
- if (i < (p-1))
- {
- /* increment complexity for if statement */
- compare_nonzero();
- temp = sub(w[i+2],w[i+1]);
- if (temp < delta) {
- step2 = 0; data_move();
- }
- else {
- /* increment complexity for if statement */
- compare_nonzero();
- if (temp < shl(delta,1)) {
- step2 = shr(sub(temp,delta),1);
- }
- }
- }
- }
- w[i] = sub(w[i],step1); data_move();
- w[i+1] = add(w[i+1],step2); data_move();
- }
- }
- }
- }
- /* Debug: check if the minimum separation rule was met */
- temp = mult(32440,delta); /* temp = 0.99*delta */
- for(j=1; j < p; j++)
- if ((w[j+1]-w[j]) < temp)
- (void)fprintf(stderr,"%s: LSPs not separated by enough (line %d)n",
- __FILE__,__LINE__);
- if (unsorted)
- (void)fprintf(stderr,"%s: Fxp LSPs still unsorted (line %d)n",
- __FILE__,__LINE__);
- return((Shortword)0);
- } /* LPC_CLMP */
- /*
- Name: lpc_schr- Schur recursion (autocorrelations to refl coef)
- Aliases: lpc_schur
- Description:
- Compute reflection coefficients from autocorrelations
- based on schur recursion. Will also compute predictor
- parameters by calling lpc_refl2pred(3l) if necessary.
- Inputs:
- r- autocorrelation vector (r[0..p]).
- p- order of lpc filter.
- Outputs:
- a- predictor parameters (can be NULL)
- k_tmp- reflection coefficients (can be NULL)
- Returns:
- alphap- the minimum residual energy
- Includes:
- spbstd.h
- lpc.h
- See_Also:
- lpc_refl2pred(3l) in lpc.h or lpc(3l)
- Q values:
- r - Q0
- a - Q12
- k_tmp - Q15
- */
- Shortword lpc_schr(Shortword *r, Shortword *a, Shortword *k_tmp, Shortword p)
- {
- Shortword i,j;
- Shortword shift,alphap,*k;
- Longword L_temp, *y1, *y2;
- Shortword n_temp,n_y2,nr1,nr0;
- MEM_ALLOC(MALLOC,y1,p+2,Longword);
- MEM_ALLOC(MALLOC,y2,p+2,Longword);
- if (k_tmp == NULL)
- MEM_ALLOC(MALLOC,k,p+1,Shortword);
- else
- k = k_tmp;
- nr1 = abs_s(r[1]); data_move();
- nr0 = abs_s(r[0]); data_move();
- k[1] = divide_s(nr1,nr0); data_move();
- /* increment complexity for if statement */
- logic(); compare_zero();
- /* if (((r[1] < 0) && (r[0] < 0)) || ((r[1] > 0) && (r[0] > 0))) */
- if ((r[1] ^ r[0]) >= 0)
- {
- k[1] = negate(k[1]); data_move();
- }
- alphap = mult(r[0],sub(ONE_Q15,mult(k[1],k[1]))); data_move();
- y2[1] = L_deposit_h(r[1]);
- y2[2] = L_add(L_deposit_h(r[0]),L_mult(k[1],r[1]));
- 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_schrn");
- 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);
- }