void _celt_lpc( opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */ const opus_val32 *ac, /* in: [0...p] autocorrelation values */ int p ) { int i, j; opus_val32 r; opus_val32 error = ac[0]; #ifdef OPUS_FIXED_POINT opus_val32 lpc[LPC_ORDER]; #else float *lpc = _lpc; #endif for (i = 0; i < p; i++) lpc[i] = 0; if (ac[0] != 0) { for (i = 0; i < p; i++) { /* Sum up this iteration's reflection coefficient */ opus_val32 rr = 0; for (j = 0; j < i; j++) rr += MULT32_32_Q31(lpc[j],ac[i - j]); rr += SHR32(ac[i + 1],3); r = -frac_div32(SHL32(rr,3), error); /* Update LPC coefficients and total error */ lpc[i] = SHR32(r,3); for (j = 0; j < (i+1)>>1; j++) { opus_val32 tmp1, tmp2; tmp1 = lpc[j]; tmp2 = lpc[i-1-j]; lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2); lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1); } error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error); /* Bail out once we get 30 dB gain */ #ifdef OPUS_FIXED_POINT if (error<SHR32(ac[0],10)) break; #else if (error<.001f*ac[0]) break; #endif } } #ifdef OPUS_FIXED_POINT for (i=0;i<p;i++) _lpc[i] = ROUND16(lpc[i],16); #endif }
void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t *residualEnergy) { /*********************************************************************************/ /* Compute the LP Coefficient using Levinson-Durbin algo spec 3.2.2 */ /*********************************************************************************/ /* start a iteration i=2, init values as after iteration i=1 : */ /* a[0] = 1 */ /* a[1] = -r1/r0 */ /* E = r0(1 - a[1]^2) */ /* */ /* iterations i = 2..10 */ /* sum = r[i] + ∑ a[j]*r[i-j] with j = 1..i-1 (a[0] is always 1) */ /* a[i] = -sum/E */ /* iterations j = 1..i-1 */ /* a[j] += a[i]*a{i-1}[i-j] use a{i-1}: from previous iteration */ /* E *=(1-a[i]^2) */ /* */ /* r in Q31 (normalised) stored in array autoCorrelationCoefficients */ /* E in Q31 (can't be > 1) */ /* sum in Q27 (sum can't be > 1 but intermediate accumulation can) */ /* a in Q4.27 with full range possible */ /* Note: during iteration, current a[i] is in Q31 (can't be >1) and is */ /* set to Q27 at the end of current iteration */ /* */ /*********************************************************************************/ word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* to compute a[]*/ word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */ word32_t E = 0; /* in Q31 */ word32_t sum = 0; /* in Q27 */ int i,j; /* init */ LPCoefficients[0] = ONE_IN_Q27; LPCoefficients[1] = -DIV32_32_Q27(autoCorrelationCoefficients[1], autoCorrelationCoefficients[0]); /* result in Q27(but<1) */ reflectionCoefficients[0] = SHL(LPCoefficients[1],4); /* k[0] is -r1/r0 in Q31 */ /* E = r0(1 - a[1]^2) in Q31 */ E = MULT32_32_Q31(autoCorrelationCoefficients[0], SUB32(ONE_IN_Q31, MULT32_32_Q23(LPCoefficients[1], LPCoefficients[1]))); /* LPCoefficient[1] is in Q27, using a Q23 operation will result in a Q31 variable */ for (i=2; i<NB_LSP_COEFF+1; i++) { /* update the previousIterationLPCoefficients needed for this one */ for (j=1; j<i; j++) { previousIterationLPCoefficients[j] = LPCoefficients[j]; } /* sum = r[i] + ∑ a[j]*r[i-j] with j = 1..i-1 (a[0] is always 1) */ sum = 0; for (j=1; j<i; j++) { sum = MAC32_32_Q31(sum, LPCoefficients[j], autoCorrelationCoefficients[i-j]);/* LPCoefficients in Q27, autoCorrelation in Q31 -> result in Q27 -> sum in Q27 */ } sum = ADD32(SHL(sum, 4), autoCorrelationCoefficients[i]); /* set sum in Q31 and add r[0] */ /* a[i] = -sum/E */ LPCoefficients[i] = -DIV32_32_Q31(sum,E); /* LPCoefficient of current iteration is in Q31 for now, it will be set to Q27 at the end of this iteration */ reflectionCoefficients[i-1] = LPCoefficients[i]; /* k[1] is needed by VAD others by RFC3389 RTP payload for Comfort Noise spectral information encoding */ /* iterations j = 1..i-1 */ /* a[j] += a[i]*a[i-j] */ for (j=1; j<i; j++) { LPCoefficients[j] = MAC32_32_Q31(LPCoefficients[j], LPCoefficients[i], previousIterationLPCoefficients[i-j]); /*LPCoefficients in Q27 except for LPCoefficients[i] in Q31 */ } /* E *=(1-a[i]^2) */ E = MULT32_32_Q31(E, SUB32(ONE_IN_Q31, MULT32_32_Q31(LPCoefficients[i], LPCoefficients[i]))); /* all in Q31 */ /* set LPCoefficients[i] from Q31 to Q27 */ LPCoefficients[i] = SHR(LPCoefficients[i], 4); } *residualEnergy = E; /* convert with rounding the LP Coefficients form Q27 to Q12, ignore first coefficient which is always 1 */ for (i=0; i<NB_LSP_COEFF; i++) { LPCoefficientsQ12[i] = (word16_t)SATURATE(PSHR(LPCoefficients[i+1], 15), MAXINT16); } }