| /* |
| ** Copyright 2003-2010, VisualOn, Inc. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| /*********************************************************************** |
| * File: levinson.c * |
| * * |
| * Description:LEVINSON-DURBIN algorithm in double precision * |
| * * |
| ************************************************************************/ |
| /*---------------------------------------------------------------------------* |
| * LEVINSON.C * |
| *---------------------------------------------------------------------------* |
| * * |
| * LEVINSON-DURBIN algorithm in double precision * |
| * * |
| * * |
| * Algorithm * |
| * * |
| * R[i] autocorrelations. * |
| * A[i] filter coefficients. * |
| * K reflection coefficients. * |
| * Alpha prediction gain. * |
| * * |
| * Initialization: * |
| * A[0] = 1 * |
| * K = -R[1]/R[0] * |
| * A[1] = K * |
| * Alpha = R[0] * (1-K**2] * |
| * * |
| * Do for i = 2 to M * |
| * * |
| * S = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] * |
| * * |
| * K = -S / Alpha * |
| * * |
| * An[j] = A[j] + K*A[i-j] for j=1 to i-1 * |
| * where An[i] = new A[i] * |
| * An[i]=K * |
| * * |
| * Alpha=Alpha * (1-K**2) * |
| * * |
| * END * |
| * * |
| * Remarks on the dynamics of the calculations. * |
| * * |
| * The numbers used are in double precision in the following format : * |
| * A = AH <<16 + AL<<1. AH and AL are 16 bit signed integers. * |
| * Since the LSB's also contain a sign bit, this format does not * |
| * correspond to standard 32 bit integers. We use this format since * |
| * it allows fast execution of multiplications and divisions. * |
| * * |
| * "DPF" will refer to this special format in the following text. * |
| * See oper_32b.c * |
| * * |
| * The R[i] were normalized in routine AUTO (hence, R[i] < 1.0). * |
| * The K[i] and Alpha are theoretically < 1.0. * |
| * The A[i], for a sampling frequency of 8 kHz, are in practice * |
| * always inferior to 16.0. * |
| * * |
| * These characteristics allow straigthforward fixed-point * |
| * implementation. We choose to represent the parameters as * |
| * follows : * |
| * * |
| * R[i] Q31 +- .99.. * |
| * K[i] Q31 +- .99.. * |
| * Alpha Normalized -> mantissa in Q31 plus exponent * |
| * A[i] Q27 +- 15.999.. * |
| * * |
| * The additions are performed in 32 bit. For the summation used * |
| * to calculate the K[i], we multiply numbers in Q31 by numbers * |
| * in Q27, with the result of the multiplications in Q27, * |
| * resulting in a dynamic of +- 16. This is sufficient to avoid * |
| * overflow, since the final result of the summation is * |
| * necessarily < 1.0 as both the K[i] and Alpha are * |
| * theoretically < 1.0. * |
| *___________________________________________________________________________*/ |
| #include "typedef.h" |
| #include "basic_op.h" |
| #include "oper_32b.h" |
| #include "acelp.h" |
| |
| #define M 16 |
| #define NC (M/2) |
| |
| void Init_Levinson( |
| Word16 * mem /* output :static memory (18 words) */ |
| ) |
| { |
| Set_zero(mem, 18); /* old_A[0..M-1] = 0, old_rc[0..1] = 0 */ |
| return; |
| } |
| |
| |
| void Levinson( |
| Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */ |
| Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */ |
| Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */ |
| Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */ |
| Word16 * mem /* (i/o) :static memory (18 words) */ |
| ) |
| { |
| Word32 i, j; |
| Word16 hi, lo; |
| Word16 Kh, Kl; /* reflection coefficient; hi and lo */ |
| Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent */ |
| Word16 Ah[M + 1], Al[M + 1]; /* LPC coef. in double prec. */ |
| Word16 Anh[M + 1], Anl[M + 1]; /* LPC coef.for next iteration in double prec. */ |
| Word32 t0, t1, t2; /* temporary variable */ |
| Word16 *old_A, *old_rc; |
| |
| /* Last A(z) for case of unstable filter */ |
| old_A = mem; |
| old_rc = mem + M; |
| |
| /* K = A[1] = -R[1] / R[0] */ |
| |
| t1 = ((Rh[1] << 16) + (Rl[1] << 1)); /* R[1] in Q31 */ |
| t2 = L_abs(t1); /* abs R[1] */ |
| t0 = Div_32(t2, Rh[0], Rl[0]); /* R[1]/R[0] in Q31 */ |
| if (t1 > 0) |
| t0 = -t0; /* -R[1]/R[0] */ |
| |
| Kh = t0 >> 16; |
| Kl = (t0 & 0xffff)>>1; |
| rc[0] = Kh; |
| t0 = (t0 >> 4); /* A[1] in Q27 */ |
| |
| Ah[1] = t0 >> 16; |
| Al[1] = (t0 & 0xffff)>>1; |
| |
| /* Alpha = R[0] * (1-K**2) */ |
| t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */ |
| t0 = L_abs(t0); /* Some case <0 !! */ |
| t0 = vo_L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */ |
| |
| hi = t0 >> 16; |
| lo = (t0 & 0xffff)>>1; |
| |
| t0 = Mpy_32(Rh[0], Rl[0], hi, lo); /* Alpha in Q31 */ |
| |
| /* Normalize Alpha */ |
| alp_exp = norm_l(t0); |
| t0 = (t0 << alp_exp); |
| |
| alp_h = t0 >> 16; |
| alp_l = (t0 & 0xffff)>>1; |
| /*--------------------------------------* |
| * ITERATIONS I=2 to M * |
| *--------------------------------------*/ |
| for (i = 2; i <= M; i++) |
| { |
| /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] */ |
| t0 = 0; |
| for (j = 1; j < i; j++) |
| t0 = vo_L_add(t0, Mpy_32(Rh[j], Rl[j], Ah[i - j], Al[i - j])); |
| |
| t0 = t0 << 4; /* result in Q27 -> convert to Q31 */ |
| /* No overflow possible */ |
| t1 = ((Rh[i] << 16) + (Rl[i] << 1)); |
| t0 = vo_L_add(t0, t1); /* add R[i] in Q31 */ |
| |
| /* K = -t0 / Alpha */ |
| t1 = L_abs(t0); |
| t2 = Div_32(t1, alp_h, alp_l); /* abs(t0)/Alpha */ |
| if (t0 > 0) |
| t2 = -t2; /* K =-t0/Alpha */ |
| t2 = (t2 << alp_exp); /* denormalize; compare to Alpha */ |
| |
| Kh = t2 >> 16; |
| Kl = (t2 & 0xffff)>>1; |
| |
| rc[i - 1] = Kh; |
| /* Test for unstable filter. If unstable keep old A(z) */ |
| if (abs_s(Kh) > 32750) |
| { |
| A[0] = 4096; /* Ai[0] not stored (always 1.0) */ |
| for (j = 0; j < M; j++) |
| { |
| A[j + 1] = old_A[j]; |
| } |
| rc[0] = old_rc[0]; /* only two rc coefficients are needed */ |
| rc[1] = old_rc[1]; |
| return; |
| } |
| /*------------------------------------------* |
| * Compute new LPC coeff. -> An[i] * |
| * An[j]= A[j] + K*A[i-j] , j=1 to i-1 * |
| * An[i]= K * |
| *------------------------------------------*/ |
| for (j = 1; j < i; j++) |
| { |
| t0 = Mpy_32(Kh, Kl, Ah[i - j], Al[i - j]); |
| t0 = vo_L_add(t0, ((Ah[j] << 16) + (Al[j] << 1))); |
| Anh[j] = t0 >> 16; |
| Anl[j] = (t0 & 0xffff)>>1; |
| } |
| t2 = (t2 >> 4); /* t2 = K in Q31 ->convert to Q27 */ |
| |
| VO_L_Extract(t2, &Anh[i], &Anl[i]); /* An[i] in Q27 */ |
| |
| /* Alpha = Alpha * (1-K**2) */ |
| t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */ |
| t0 = L_abs(t0); /* Some case <0 !! */ |
| t0 = vo_L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */ |
| hi = t0 >> 16; |
| lo = (t0 & 0xffff)>>1; |
| t0 = Mpy_32(alp_h, alp_l, hi, lo); /* Alpha in Q31 */ |
| |
| /* Normalize Alpha */ |
| j = norm_l(t0); |
| t0 = (t0 << j); |
| alp_h = t0 >> 16; |
| alp_l = (t0 & 0xffff)>>1; |
| alp_exp += j; /* Add normalization to alp_exp */ |
| |
| /* A[j] = An[j] */ |
| for (j = 1; j <= i; j++) |
| { |
| Ah[j] = Anh[j]; |
| Al[j] = Anl[j]; |
| } |
| } |
| /* Truncate A[i] in Q27 to Q12 with rounding */ |
| A[0] = 4096; |
| for (i = 1; i <= M; i++) |
| { |
| t0 = (Ah[i] << 16) + (Al[i] << 1); |
| old_A[i - 1] = A[i] = vo_round((t0 << 1)); |
| } |
| old_rc[0] = rc[0]; |
| old_rc[1] = rc[1]; |
| |
| return; |
| } |
| |
| |
| |