134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*---------------------------------------------------------------------------*\ 234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)Original copyright 334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FILE........: lsp.c 434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) AUTHOR......: David Rowe 534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DATE CREATED: 24/2/93 634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)Heavily modified by Jean-Marc Valin (c) 2002-2006 (fixed-point, 834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) optimizations, additional functions, ...) 934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 1034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) This file contains functions for converting Linear Prediction 1134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Coefficients (LPC) to Line Spectral Pair (LSP) and back. Note that the 1234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LSP coefficients are not in radians format but in the x domain of the 1334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) unit circle. 1434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 1534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Speex License: 1634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 1734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Redistribution and use in source and binary forms, with or without 1834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) modification, are permitted provided that the following conditions 1934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) are met: 2034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 2134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) - Redistributions of source code must retain the above copyright 2234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) notice, this list of conditions and the following disclaimer. 2334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 2434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) - Redistributions in binary form must reproduce the above copyright 2534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) notice, this list of conditions and the following disclaimer in the 2634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) documentation and/or other materials provided with the distribution. 2734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 2834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) - Neither the name of the Xiph.org Foundation nor the names of its 2934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) contributors may be used to endorse or promote products derived from 3034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) this software without specific prior written permission. 3134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 3234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 3634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 3734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 3834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 4034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 4134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 4234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)*/ 4434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 4534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*---------------------------------------------------------------------------*\ 4634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 4734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Introduction to Line Spectrum Pairs (LSPs) 4834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ------------------------------------------ 4934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 5034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LSPs are used to encode the LPC filter coefficients {ak} for 5134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) transmission over the channel. LSPs have several properties (like 5234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) less sensitivity to quantisation noise) that make them superior to 5334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) direct quantisation of {ak}. 5434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 5534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) A(z) is a polynomial of order lpcrdr with {ak} as the coefficients. 5634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 5734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) A(z) is transformed to P(z) and Q(z) (using a substitution and some 5834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) algebra), to obtain something like: 5934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 6034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) A(z) = 0.5[P(z)(z+z^-1) + Q(z)(z-z^-1)] (1) 6134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 6234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) As you can imagine A(z) has complex zeros all over the z-plane. P(z) 6334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) and Q(z) have the very neat property of only having zeros _on_ the 6434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) unit circle. So to find them we take a test point z=exp(jw) and 6534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) evaluate P (exp(jw)) and Q(exp(jw)) using a grid of points between 0 6634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) and pi. 6734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 6834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) The zeros (roots) of P(z) also happen to alternate, which is why we 6934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) swap coefficients as we find roots. So the process of finding the 7034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LSP frequencies is basically finding the roots of 5th order 7134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) polynomials. 7234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 7334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) The root so P(z) and Q(z) occur in symmetrical pairs at +/-w, hence 7434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) the name Line Spectrum Pairs (LSPs). 7534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 7634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) To convert back to ak we just evaluate (1), "clocking" an impulse 7734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) thru it lpcrdr times gives us the impulse response of A(z) which is 7834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) {ak}. 7934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 8034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)\*---------------------------------------------------------------------------*/ 8134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 8234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef HAVE_CONFIG_H 8334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "config.h" 8434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 8534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 8634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include <math.h> 8734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "lsp.h" 8834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "stack_alloc.h" 8934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "math_approx.h" 9034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 9134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifndef M_PI 9234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define M_PI 3.14159265358979323846 /* pi */ 9334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 9434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 9534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifndef NULL 9634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define NULL 0 9734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 9834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 9934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 10034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 10134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define FREQ_SCALE 16384 10234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 10334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/ 10434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define ANGLE2X(a) (SHL16(spx_cos(a),2)) 10534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 10634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/ 10734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define X2ANGLE(x) (spx_acos(x)) 10834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 10934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef BFIN_ASM 11034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "lsp_bfin.h" 11134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 11234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 11334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 11434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 11534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*#define C1 0.99940307 11634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define C2 -0.49558072 11734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define C3 0.03679168*/ 11834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 11934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define FREQ_SCALE 1. 12034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define ANGLE2X(a) (spx_cos(a)) 12134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define X2ANGLE(x) (acos(x)) 12234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 12334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 12434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 12534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 12634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*---------------------------------------------------------------------------*\ 12734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 12834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FUNCTION....: cheb_poly_eva() 12934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 13034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) AUTHOR......: David Rowe 13134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DATE CREATED: 24/2/93 13234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 13334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) This function evaluates a series of Chebyshev polynomials 13434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 13534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)\*---------------------------------------------------------------------------*/ 13634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 13734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 13834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 13934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifndef OVERRIDE_CHEB_POLY_EVA 14034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)static inline spx_word32_t cheb_poly_eva( 14134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t *coef, /* P or Q coefs in Q13 format */ 14234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */ 14334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int m, /* LPC order/2 */ 14434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) char *stack 14534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)) 14634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 14734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i; 14834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t b0, b1; 14934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t sum; 15034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 15134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /*Prevents overflows*/ 15234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (x>16383) 15334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) x = 16383; 15434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (x<-16383) 15534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) x = -16383; 15634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 15734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Initialise values */ 15834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b1=16384; 15934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b0=x; 16034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 16134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Evaluate Chebyshev series formulation usin g iterative approach */ 16234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x))); 16334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=2;i<=m;i++) 16434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 16534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t tmp=b0; 16634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b0 = SUB16(MULT16_16_Q13(x,b0), b1); 16734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b1 = tmp; 16834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0))); 16934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 17034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 17134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return sum; 17234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 17334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 17434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 17534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 17634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 17734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)static float cheb_poly_eva(spx_word32_t *coef, spx_word16_t x, int m, char *stack) 17834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 17934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int k; 18034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) float b0, b1, tmp; 18134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 18234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Initial conditions */ 18334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b0=0; /* b_(m+1) */ 18434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b1=0; /* b_(m+2) */ 18534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 18634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) x*=2; 18734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 18834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Calculate the b_(k) */ 18934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(k=m;k>0;k--) 19034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 19134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) tmp=b0; /* tmp holds the previous value of b0 */ 19234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b0=x*b0-b1+coef[m-k]; /* b0 holds its new value based on b0 and b1 */ 19334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) b1=tmp; /* b1 holds the previous value of b0 */ 19434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 19534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 19634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return(-b1+.5*x*b0+coef[m]); 19734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 19834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 19934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 20034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*---------------------------------------------------------------------------*\ 20134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 20234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FUNCTION....: lpc_to_lsp() 20334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 20434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) AUTHOR......: David Rowe 20534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DATE CREATED: 24/2/93 20634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 20734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) This function converts LPC coefficients to LSP 20834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) coefficients. 20934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 21034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)\*---------------------------------------------------------------------------*/ 21134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 21234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 21334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define SIGN_CHANGE(a,b) (((a)&0x70000000)^((b)&0x70000000)||(b==0)) 21434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 21534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#define SIGN_CHANGE(a,b) (((a)*(b))<0.0) 21634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 21734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 21834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 21934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack) 22034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float *a lpc coefficients */ 22134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* int lpcrdr order of LPC coefficients (10) */ 22234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float *freq LSP frequencies in the x domain */ 22334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* int nb number of sub-intervals (4) */ 22434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float delta grid spacing interval (0.02) */ 22534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 22634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 22734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 22834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t temp_xr,xl,xr,xm=0; 22934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/; 23034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i,j,m,flag,k; 23134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word32_t *Q); /* ptrs for memory allocation */ 23234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word32_t *P); 23334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word16_t *Q16); /* ptrs for memory allocation */ 23434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word16_t *P16); 23534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t *px; /* ptrs of respective P'(z) & Q'(z) */ 23634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t *qx; 23734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t *p; 23834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t *q; 23934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t *pt; /* ptr used for cheb_poly_eval() 24034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) whether P' or Q' */ 24134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int roots=0; /* DR 8/2/94: number of roots found */ 24234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) flag = 1; /* program is searching for a root when, 24334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 1 else has found one */ 24434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) m = lpcrdr/2; /* order of P'(z) & Q'(z) polynomials */ 24534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 24634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Allocate memory space for polynomials */ 24734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(Q, (m+1), spx_word32_t); 24834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(P, (m+1), spx_word32_t); 24934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 25034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* determine P'(z)'s and Q'(z)'s coefficients where 25134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */ 25234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 25334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) px = P; /* initialise ptrs */ 25434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) qx = Q; 25534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) p = px; 25634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) q = qx; 25734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 25834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 25934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *px++ = LPC_SCALING; 26034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *qx++ = LPC_SCALING; 26134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<m;i++){ 26234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++); 26334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++); 26434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 26534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) px = P; 26634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) qx = Q; 26734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<m;i++) 26834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 26934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /*if (fabs(*px)>=32768) 27034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) speex_warning_int("px", *px); 27134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (fabs(*qx)>=32768) 27234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) speex_warning_int("qx", *qx);*/ 27334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *px = PSHR32(*px,2); 27434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *qx = PSHR32(*qx,2); 27534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) px++; 27634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) qx++; 27734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 27834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */ 27934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) P[m] = PSHR32(P[m],3); 28034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Q[m] = PSHR32(Q[m],3); 28134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 28234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *px++ = LPC_SCALING; 28334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *qx++ = LPC_SCALING; 28434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<m;i++){ 28534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *px++ = (a[i]+a[lpcrdr-1-i]) - *p++; 28634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++; 28734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 28834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) px = P; 28934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) qx = Q; 29034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<m;i++){ 29134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *px = 2**px; 29234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *qx = 2**qx; 29334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) px++; 29434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) qx++; 29534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 29634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 29734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 29834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) px = P; /* re-initialise ptrs */ 29934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) qx = Q; 30034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 30134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* now that we have computed P and Q convert to 16 bits to 30234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) speed up cheb_poly_eval */ 30334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 30434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(P16, m+1, spx_word16_t); 30534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(Q16, m+1, spx_word16_t); 30634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 30734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=0;i<m+1;i++) 30834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 30934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) P16[i] = P[i]; 31034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Q16[i] = Q[i]; 31134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 31234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 31334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z). 31434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Keep alternating between the two polynomials as each zero is found */ 31534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 31634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xr = 0; /* initialise xr to zero */ 31734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xl = FREQ_SCALE; /* start at point xl = 1 */ 31834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 31934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(j=0;j<lpcrdr;j++){ 32034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if(j&1) /* determines whether P' or Q' is eval. */ 32134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) pt = Q16; 32234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) else 32334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) pt = P16; 32434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 32534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl */ 32634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) flag = 1; 32734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) while(flag && (xr >= -FREQ_SCALE)){ 32834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t dd; 32934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Modified by JMV to provide smaller steps around x=+-1 */ 33034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 33134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000))); 33234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (psuml<512 && psuml>-512) 33334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) dd = PSHR16(dd,1); 33434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 33534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) dd=delta*(1-.9*xl*xl); 33634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (fabs(psuml)<.2) 33734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) dd *= .5; 33834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 33934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xr = SUB16(xl, dd); /* interval spacing */ 34034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x) */ 34134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) temp_psumr = psumr; 34234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) temp_xr = xr; 34334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 34434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* if no sign change increment xr and re-evaluate poly(xr). Repeat til 34534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) sign change. 34634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if a sign change has occurred the interval is bisected and then 34734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) checked again for a sign change which determines in which 34834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) interval the zero lies in. 34934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) If there is no sign change between poly(xm) and poly(xl) set interval 35034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) between xm and xr else set interval between xl and xr and repeat till 35134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) root is located within the specified limits */ 35234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 35334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if(SIGN_CHANGE(psumr,psuml)) 35434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 35534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) roots++; 35634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 35734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psumm=psuml; 35834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(k=0;k<=nb;k++){ 35934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 36034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xm = ADD16(PSHR16(xl,1),PSHR16(xr,1)); /* bisect the interval */ 36134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 36234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xm = .5*(xl+xr); /* bisect the interval */ 36334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 36434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psumm=cheb_poly_eva(pt,xm,m,stack); 36534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /*if(psumm*psuml>0.)*/ 36634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if(!SIGN_CHANGE(psumm,psuml)) 36734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 36834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psuml=psumm; 36934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xl=xm; 37034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } else { 37134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psumr=psumm; 37234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xr=xm; 37334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 37434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 37534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 37634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* once zero is found, reset initial interval to xr */ 37734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) freq[j] = X2ANGLE(xm); 37834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xl = xm; 37934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) flag = 0; /* reset flag for next search */ 38034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 38134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) else{ 38234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) psuml=temp_psumr; 38334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xl=temp_xr; 38434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 38534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 38634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 38734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return(roots); 38834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 38934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*---------------------------------------------------------------------------*\ 39134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FUNCTION....: lsp_to_lpc() 39334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) AUTHOR......: David Rowe 39534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DATE CREATED: 24/2/93 39634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Converts LSP coefficients to LPC coefficients. 39834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)\*---------------------------------------------------------------------------*/ 40034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 40134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 40234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 40334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack) 40434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float *freq array of LSP frequencies in the x domain */ 40534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float *ak array of LPC coefficients */ 40634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* int lpcrdr order of LPC coefficients */ 40734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 40834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i,j; 40934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t xout1,xout2,xin; 41034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word32_t mult, a; 41134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word16_t *freqn); 41234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word32_t **xp); 41334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word32_t *xpmem); 41434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word32_t **xq); 41534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(spx_word32_t *xqmem); 41634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int m = lpcrdr>>1; 41734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 41834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* 41934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 42034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) Reconstruct P(z) and Q(z) by cascading second order polynomials 42134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency. 42234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) In the time domain this is: 42334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 42434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) y(n) = x(n) - 2cos(w)x(n-1) + x(n-2) 42534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 42634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) This is what the ALLOCS below are trying to do: 42734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 42834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP 42934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP 43034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 43134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) These matrices store the output of each stage on each row. The 43234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) final (m-th) row has the output of the final (m-th) cascaded 43334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 2nd order filter. The first row is the impulse input to the 43434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) system (not written as it is known). 43534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 43634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) The version below takes advantage of the fact that a lot of the 43734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) outputs are zero or known, for example if we put an inpulse 43834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) into the first section the "clock" it 10 times only the first 3 43934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) outputs samples are non-zero (it's an FIR filter). 44034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) */ 44134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 44234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(xp, (m+1), spx_word32_t*); 44334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t); 44434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 44534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(xq, (m+1), spx_word32_t*); 44634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t); 44734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 44834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0; i<=m; i++) { 44934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[i] = xpmem + i*(lpcrdr+1+2); 45034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[i] = xqmem + i*(lpcrdr+1+2); 45134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 45234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 45334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* work out 2cos terms in Q14 */ 45434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 45534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(freqn, lpcrdr, spx_word16_t); 45634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=0;i<lpcrdr;i++) 45734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) freqn[i] = ANGLE2X(freq[i]); 45834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 45934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) #define QIMP 21 /* scaling for impulse */ 46034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 46134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin = SHL32(EXTEND32(1), (QIMP-1)); /* 0.5 in QIMP format */ 46234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 46334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* first col and last non-zero values of each row are trivial */ 46434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 46534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<=m;i++) { 46634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[i][1] = 0; 46734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[i][2] = xin; 46834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[i][2+2*i] = xin; 46934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[i][1] = 0; 47034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[i][2] = xin; 47134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[i][2+2*i] = xin; 47234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 47334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 47434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* 2nd row (first output row) is trivial */ 47534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 47634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]); 47734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]); 47834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 47934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout1 = xout2 = 0; 48034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 48134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* now generate remaining rows */ 48234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 48334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=1;i<m;i++) { 48434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 48534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(j=1;j<2*(i+1)-1;j++) { 48634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]); 48734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]); 48834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]); 48934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]); 49034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 49134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 49234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* for last col xp[i][j+2] = xq[i][j+2] = 0 */ 49334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 49434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]); 49534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xp[i+1][j+2] = SUB32(xp[i][j], mult); 49634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]); 49734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xq[i+1][j+2] = SUB32(xq[i][j], mult); 49834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 49934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 50034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* process last row to extra a{k} */ 50134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 50234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(j=1;j<=lpcrdr;j++) { 50334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int shift = QIMP-13; 50434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 50534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* final filter sections */ 50634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift); 50734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout1 = xp[m][j+2]; 50834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout2 = xq[m][j+2]; 50934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 51034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* hard limit ak's to +/- 32767 */ 51134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 51234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (a < -32767) a = -32767; 51334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (a > 32767) a = 32767; 51434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ak[j-1] = (short)a; 51534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 51634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 51734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 51834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 51934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 52034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 52134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 52234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack) 52334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float *freq array of LSP frequencies in the x domain */ 52434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* float *ak array of LPC coefficients */ 52534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/* int lpcrdr order of LPC coefficients */ 52634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 52734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 52834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 52934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i,j; 53034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) float xout1,xout2,xin1,xin2; 53134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(float *Wp); 53234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) float *pw,*n1,*n2,*n3,*n4=NULL; 53334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VARDECL(float *x_freq); 53434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int m = lpcrdr>>1; 53534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 53634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(Wp, 4*m+2, float); 53734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) pw = Wp; 53834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 53934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* initialise contents of array */ 54034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 54134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<=4*m+1;i++){ /* set contents of buffer to 0 */ 54234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *pw++ = 0.0; 54334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 54434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 54534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* Set pointers up */ 54634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 54734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) pw = Wp; 54834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin1 = 1.0; 54934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin2 = 1.0; 55034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 55134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ALLOC(x_freq, lpcrdr, float); 55234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=0;i<lpcrdr;i++) 55334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) x_freq[i] = ANGLE2X(freq[i]); 55434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 55534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) /* reconstruct P(z) and Q(z) by cascading second order 55634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) polynomials in form 1 - 2xz(-1) +z(-2), where x is the 55734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LSP coefficient */ 55834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 55934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(j=0;j<=lpcrdr;j++){ 56034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i2=0; 56134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for(i=0;i<m;i++,i2+=2){ 56234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) n1 = pw+(i*4); 56334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) n2 = n1 + 1; 56434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) n3 = n2 + 1; 56534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) n4 = n3 + 1; 56634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2; 56734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4; 56834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *n2 = *n1; 56934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *n4 = *n3; 57034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *n1 = xin1; 57134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *n3 = xin2; 57234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin1 = xout1; 57334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin2 = xout2; 57434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 57534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout1 = xin1 + *(n4+1); 57634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xout2 = xin2 - *(n4+2); 57734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (j>0) 57834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ak[j-1] = (xout1 + xout2)*0.5f; 57934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *(n4+1) = xin1; 58034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) *(n4+2) = xin2; 58134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 58234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin1 = 0.0; 58334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) xin2 = 0.0; 58434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 58534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 58634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 58734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 58834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 58934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 59034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#ifdef FIXED_POINT 59134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 59234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*Makes sure the LSPs are stable*/ 59334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin) 59434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 59534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i; 59634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t m = margin; 59734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t m2 = 25736-margin; 59834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 59934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[0]<m) 60034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[0]=m; 60134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[len-1]>m2) 60234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[len-1]=m2; 60334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=1;i<len-1;i++) 60434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 60534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[i]<lsp[i-1]+m) 60634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[i]=lsp[i-1]+m; 60734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 60834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[i]>lsp[i+1]-m) 60934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); 61034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 61134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 61234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 61334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 61434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes) 61534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 61634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i; 61734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); 61834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) spx_word16_t tmp2 = 16384-tmp; 61934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=0;i<len;i++) 62034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 62134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) interp_lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]); 62234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 62334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 62434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 62534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#else 62634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 62734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/*Makes sure the LSPs are stable*/ 62834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin) 62934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 63034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i; 63134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[0]<LSP_SCALING*margin) 63234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[0]=LSP_SCALING*margin; 63334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[len-1]>LSP_SCALING*(M_PI-margin)) 63434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[len-1]=LSP_SCALING*(M_PI-margin); 63534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=1;i<len-1;i++) 63634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 63734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[i]<lsp[i-1]+LSP_SCALING*margin) 63834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[i]=lsp[i-1]+LSP_SCALING*margin; 63934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 64034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (lsp[i]>lsp[i+1]-LSP_SCALING*margin) 64134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin); 64234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 64334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 64434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 64534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 64634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes) 64734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles){ 64834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int i; 64934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) float tmp = (1.0f + subframe)/nb_subframes; 65034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (i=0;i<len;i++) 65134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) { 65234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) interp_lsp[i] = (1-tmp)*old_lsp[i] + tmp*new_lsp[i]; 65334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 65434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 65534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 65634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 657