lsp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /*---------------------------------------------------------------------------*\
  2. Original copyright
  3. FILE........: lsp.c
  4. AUTHOR......: David Rowe
  5. DATE CREATED: 24/2/93
  6. Heavily modified by Jean-Marc Valin (c) 2002-2006 (fixed-point,
  7. optimizations, additional functions, ...)
  8. This file contains functions for converting Linear Prediction
  9. Coefficients (LPC) to Line Spectral Pair (LSP) and back. Note that the
  10. LSP coefficients are not in radians format but in the x domain of the
  11. unit circle.
  12. Speex License:
  13. Redistribution and use in source and binary forms, with or without
  14. modification, are permitted provided that the following conditions
  15. are met:
  16. - Redistributions of source code must retain the above copyright
  17. notice, this list of conditions and the following disclaimer.
  18. - Redistributions in binary form must reproduce the above copyright
  19. notice, this list of conditions and the following disclaimer in the
  20. documentation and/or other materials provided with the distribution.
  21. - Neither the name of the Xiph.org Foundation nor the names of its
  22. contributors may be used to endorse or promote products derived from
  23. this software without specific prior written permission.
  24. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  27. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
  28. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  29. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  30. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  31. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  32. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  33. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  34. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. /*---------------------------------------------------------------------------*\
  37. Introduction to Line Spectrum Pairs (LSPs)
  38. ------------------------------------------
  39. LSPs are used to encode the LPC filter coefficients {ak} for
  40. transmission over the channel. LSPs have several properties (like
  41. less sensitivity to quantisation noise) that make them superior to
  42. direct quantisation of {ak}.
  43. A(z) is a polynomial of order lpcrdr with {ak} as the coefficients.
  44. A(z) is transformed to P(z) and Q(z) (using a substitution and some
  45. algebra), to obtain something like:
  46. A(z) = 0.5[P(z)(z+z^-1) + Q(z)(z-z^-1)] (1)
  47. As you can imagine A(z) has complex zeros all over the z-plane. P(z)
  48. and Q(z) have the very neat property of only having zeros _on_ the
  49. unit circle. So to find them we take a test point z=exp(jw) and
  50. evaluate P (exp(jw)) and Q(exp(jw)) using a grid of points between 0
  51. and pi.
  52. The zeros (roots) of P(z) also happen to alternate, which is why we
  53. swap coefficients as we find roots. So the process of finding the
  54. LSP frequencies is basically finding the roots of 5th order
  55. polynomials.
  56. The root so P(z) and Q(z) occur in symmetrical pairs at +/-w, hence
  57. the name Line Spectrum Pairs (LSPs).
  58. To convert back to ak we just evaluate (1), "clocking" an impulse
  59. thru it lpcrdr times gives us the impulse response of A(z) which is
  60. {ak}.
  61. \*---------------------------------------------------------------------------*/
  62. #ifdef HAVE_CONFIG_H
  63. #include "config.h"
  64. #endif
  65. #include <math.h>
  66. #include "lsp.h"
  67. #include "stack_alloc.h"
  68. #include "math_approx.h"
  69. #ifndef M_PI
  70. #define M_PI 3.14159265358979323846 /* pi */
  71. #endif
  72. #ifndef NULL
  73. #define NULL 0
  74. #endif
  75. #ifdef FIXED_POINT
  76. #define FREQ_SCALE 16384
  77. /*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/
  78. #define ANGLE2X(a) (SHL16(spx_cos(a),2))
  79. /*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/
  80. #define X2ANGLE(x) (spx_acos(x))
  81. #ifdef BFIN_ASM
  82. #include "lsp_bfin.h"
  83. #endif
  84. #else
  85. /*#define C1 0.99940307
  86. #define C2 -0.49558072
  87. #define C3 0.03679168*/
  88. #define FREQ_SCALE 1.
  89. #define ANGLE2X(a) (spx_cos(a))
  90. #define X2ANGLE(x) (acos(x))
  91. #endif
  92. /*---------------------------------------------------------------------------*\
  93. FUNCTION....: cheb_poly_eva()
  94. AUTHOR......: David Rowe
  95. DATE CREATED: 24/2/93
  96. This function evaluates a series of Chebyshev polynomials
  97. \*---------------------------------------------------------------------------*/
  98. #ifdef FIXED_POINT
  99. #ifndef OVERRIDE_CHEB_POLY_EVA
  100. static inline spx_word32_t cheb_poly_eva(
  101. spx_word16_t *coef, /* P or Q coefs in Q13 format */
  102. spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */
  103. int m, /* LPC order/2 */
  104. char *stack
  105. )
  106. {
  107. int i;
  108. spx_word16_t b0, b1;
  109. spx_word32_t sum;
  110. /*Prevents overflows*/
  111. if (x>16383)
  112. x = 16383;
  113. if (x<-16383)
  114. x = -16383;
  115. /* Initialise values */
  116. b1=16384;
  117. b0=x;
  118. /* Evaluate Chebyshev series formulation usin g iterative approach */
  119. sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x)));
  120. for(i=2;i<=m;i++)
  121. {
  122. spx_word16_t tmp=b0;
  123. b0 = SUB16(MULT16_16_Q13(x,b0), b1);
  124. b1 = tmp;
  125. sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0)));
  126. }
  127. return sum;
  128. }
  129. #endif
  130. #else
  131. static float cheb_poly_eva(spx_word32_t *coef, spx_word16_t x, int m, char *stack)
  132. {
  133. int k;
  134. float b0, b1, tmp;
  135. /* Initial conditions */
  136. b0=0; /* b_(m+1) */
  137. b1=0; /* b_(m+2) */
  138. x*=2;
  139. /* Calculate the b_(k) */
  140. for(k=m;k>0;k--)
  141. {
  142. tmp=b0; /* tmp holds the previous value of b0 */
  143. b0=x*b0-b1+coef[m-k]; /* b0 holds its new value based on b0 and b1 */
  144. b1=tmp; /* b1 holds the previous value of b0 */
  145. }
  146. return(-b1+.5*x*b0+coef[m]);
  147. }
  148. #endif
  149. /*---------------------------------------------------------------------------*\
  150. FUNCTION....: lpc_to_lsp()
  151. AUTHOR......: David Rowe
  152. DATE CREATED: 24/2/93
  153. This function converts LPC coefficients to LSP
  154. coefficients.
  155. \*---------------------------------------------------------------------------*/
  156. #ifdef FIXED_POINT
  157. #define SIGN_CHANGE(a,b) (((a)&0x70000000)^((b)&0x70000000)||(b==0))
  158. #else
  159. #define SIGN_CHANGE(a,b) (((a)*(b))<0.0)
  160. #endif
  161. int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack)
  162. /* float *a lpc coefficients */
  163. /* int lpcrdr order of LPC coefficients (10) */
  164. /* float *freq LSP frequencies in the x domain */
  165. /* int nb number of sub-intervals (4) */
  166. /* float delta grid spacing interval (0.02) */
  167. {
  168. spx_word16_t temp_xr,xl,xr,xm=0;
  169. spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
  170. int i,j,m,flag,k;
  171. VARDECL(spx_word32_t *Q); /* ptrs for memory allocation */
  172. VARDECL(spx_word32_t *P);
  173. VARDECL(spx_word16_t *Q16); /* ptrs for memory allocation */
  174. VARDECL(spx_word16_t *P16);
  175. spx_word32_t *px; /* ptrs of respective P'(z) & Q'(z) */
  176. spx_word32_t *qx;
  177. spx_word32_t *p;
  178. spx_word32_t *q;
  179. spx_word16_t *pt; /* ptr used for cheb_poly_eval()
  180. whether P' or Q' */
  181. int roots=0; /* DR 8/2/94: number of roots found */
  182. flag = 1; /* program is searching for a root when,
  183. 1 else has found one */
  184. m = lpcrdr/2; /* order of P'(z) & Q'(z) polynomials */
  185. /* Allocate memory space for polynomials */
  186. ALLOC(Q, (m+1), spx_word32_t);
  187. ALLOC(P, (m+1), spx_word32_t);
  188. /* determine P'(z)'s and Q'(z)'s coefficients where
  189. P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */
  190. px = P; /* initialise ptrs */
  191. qx = Q;
  192. p = px;
  193. q = qx;
  194. #ifdef FIXED_POINT
  195. *px++ = LPC_SCALING;
  196. *qx++ = LPC_SCALING;
  197. for(i=0;i<m;i++){
  198. *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++);
  199. *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++);
  200. }
  201. px = P;
  202. qx = Q;
  203. for(i=0;i<m;i++)
  204. {
  205. /*if (fabs(*px)>=32768)
  206. speex_warning_int("px", *px);
  207. if (fabs(*qx)>=32768)
  208. speex_warning_int("qx", *qx);*/
  209. *px = PSHR32(*px,2);
  210. *qx = PSHR32(*qx,2);
  211. px++;
  212. qx++;
  213. }
  214. /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */
  215. P[m] = PSHR32(P[m],3);
  216. Q[m] = PSHR32(Q[m],3);
  217. #else
  218. *px++ = LPC_SCALING;
  219. *qx++ = LPC_SCALING;
  220. for(i=0;i<m;i++){
  221. *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
  222. *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
  223. }
  224. px = P;
  225. qx = Q;
  226. for(i=0;i<m;i++){
  227. *px = 2**px;
  228. *qx = 2**qx;
  229. px++;
  230. qx++;
  231. }
  232. #endif
  233. px = P; /* re-initialise ptrs */
  234. qx = Q;
  235. /* now that we have computed P and Q convert to 16 bits to
  236. speed up cheb_poly_eval */
  237. ALLOC(P16, m+1, spx_word16_t);
  238. ALLOC(Q16, m+1, spx_word16_t);
  239. for (i=0;i<m+1;i++)
  240. {
  241. P16[i] = P[i];
  242. Q16[i] = Q[i];
  243. }
  244. /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z).
  245. Keep alternating between the two polynomials as each zero is found */
  246. xr = 0; /* initialise xr to zero */
  247. xl = FREQ_SCALE; /* start at point xl = 1 */
  248. for(j=0;j<lpcrdr;j++){
  249. if(j&1) /* determines whether P' or Q' is eval. */
  250. pt = Q16;
  251. else
  252. pt = P16;
  253. psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl */
  254. flag = 1;
  255. while(flag && (xr >= -FREQ_SCALE)){
  256. spx_word16_t dd;
  257. /* Modified by JMV to provide smaller steps around x=+-1 */
  258. #ifdef FIXED_POINT
  259. dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000)));
  260. if (psuml<512 && psuml>-512)
  261. dd = PSHR16(dd,1);
  262. #else
  263. dd=delta*(1-.9*xl*xl);
  264. if (fabs(psuml)<.2)
  265. dd *= .5;
  266. #endif
  267. xr = SUB16(xl, dd); /* interval spacing */
  268. psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x) */
  269. temp_psumr = psumr;
  270. temp_xr = xr;
  271. /* if no sign change increment xr and re-evaluate poly(xr). Repeat til
  272. sign change.
  273. if a sign change has occurred the interval is bisected and then
  274. checked again for a sign change which determines in which
  275. interval the zero lies in.
  276. If there is no sign change between poly(xm) and poly(xl) set interval
  277. between xm and xr else set interval between xl and xr and repeat till
  278. root is located within the specified limits */
  279. if(SIGN_CHANGE(psumr,psuml))
  280. {
  281. roots++;
  282. psumm=psuml;
  283. for(k=0;k<=nb;k++){
  284. #ifdef FIXED_POINT
  285. xm = ADD16(PSHR16(xl,1),PSHR16(xr,1)); /* bisect the interval */
  286. #else
  287. xm = .5*(xl+xr); /* bisect the interval */
  288. #endif
  289. psumm=cheb_poly_eva(pt,xm,m,stack);
  290. /*if(psumm*psuml>0.)*/
  291. if(!SIGN_CHANGE(psumm,psuml))
  292. {
  293. psuml=psumm;
  294. xl=xm;
  295. } else {
  296. psumr=psumm;
  297. xr=xm;
  298. }
  299. }
  300. /* once zero is found, reset initial interval to xr */
  301. freq[j] = X2ANGLE(xm);
  302. xl = xm;
  303. flag = 0; /* reset flag for next search */
  304. }
  305. else{
  306. psuml=temp_psumr;
  307. xl=temp_xr;
  308. }
  309. }
  310. }
  311. return(roots);
  312. }
  313. /*---------------------------------------------------------------------------*\
  314. FUNCTION....: lsp_to_lpc()
  315. AUTHOR......: David Rowe
  316. DATE CREATED: 24/2/93
  317. Converts LSP coefficients to LPC coefficients.
  318. \*---------------------------------------------------------------------------*/
  319. #ifdef FIXED_POINT
  320. void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
  321. /* float *freq array of LSP frequencies in the x domain */
  322. /* float *ak array of LPC coefficients */
  323. /* int lpcrdr order of LPC coefficients */
  324. {
  325. int i,j;
  326. spx_word32_t xout1,xout2,xin;
  327. spx_word32_t mult, a;
  328. VARDECL(spx_word16_t *freqn);
  329. VARDECL(spx_word32_t **xp);
  330. VARDECL(spx_word32_t *xpmem);
  331. VARDECL(spx_word32_t **xq);
  332. VARDECL(spx_word32_t *xqmem);
  333. int m = lpcrdr>>1;
  334. /*
  335. Reconstruct P(z) and Q(z) by cascading second order polynomials
  336. in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency.
  337. In the time domain this is:
  338. y(n) = x(n) - 2cos(w)x(n-1) + x(n-2)
  339. This is what the ALLOCS below are trying to do:
  340. int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP
  341. int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP
  342. These matrices store the output of each stage on each row. The
  343. final (m-th) row has the output of the final (m-th) cascaded
  344. 2nd order filter. The first row is the impulse input to the
  345. system (not written as it is known).
  346. The version below takes advantage of the fact that a lot of the
  347. outputs are zero or known, for example if we put an inpulse
  348. into the first section the "clock" it 10 times only the first 3
  349. outputs samples are non-zero (it's an FIR filter).
  350. */
  351. ALLOC(xp, (m+1), spx_word32_t*);
  352. ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
  353. ALLOC(xq, (m+1), spx_word32_t*);
  354. ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
  355. for(i=0; i<=m; i++) {
  356. xp[i] = xpmem + i*(lpcrdr+1+2);
  357. xq[i] = xqmem + i*(lpcrdr+1+2);
  358. }
  359. /* work out 2cos terms in Q14 */
  360. ALLOC(freqn, lpcrdr, spx_word16_t);
  361. for (i=0;i<lpcrdr;i++)
  362. freqn[i] = ANGLE2X(freq[i]);
  363. #define QIMP 21 /* scaling for impulse */
  364. xin = SHL32(EXTEND32(1), (QIMP-1)); /* 0.5 in QIMP format */
  365. /* first col and last non-zero values of each row are trivial */
  366. for(i=0;i<=m;i++) {
  367. xp[i][1] = 0;
  368. xp[i][2] = xin;
  369. xp[i][2+2*i] = xin;
  370. xq[i][1] = 0;
  371. xq[i][2] = xin;
  372. xq[i][2+2*i] = xin;
  373. }
  374. /* 2nd row (first output row) is trivial */
  375. xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]);
  376. xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]);
  377. xout1 = xout2 = 0;
  378. /* now generate remaining rows */
  379. for(i=1;i<m;i++) {
  380. for(j=1;j<2*(i+1)-1;j++) {
  381. mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
  382. xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]);
  383. mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
  384. xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]);
  385. }
  386. /* for last col xp[i][j+2] = xq[i][j+2] = 0 */
  387. mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
  388. xp[i+1][j+2] = SUB32(xp[i][j], mult);
  389. mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
  390. xq[i+1][j+2] = SUB32(xq[i][j], mult);
  391. }
  392. /* process last row to extra a{k} */
  393. for(j=1;j<=lpcrdr;j++) {
  394. int shift = QIMP-13;
  395. /* final filter sections */
  396. a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift);
  397. xout1 = xp[m][j+2];
  398. xout2 = xq[m][j+2];
  399. /* hard limit ak's to +/- 32767 */
  400. if (a < -32767) a = -32767;
  401. if (a > 32767) a = 32767;
  402. ak[j-1] = (short)a;
  403. }
  404. }
  405. #else
  406. void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
  407. /* float *freq array of LSP frequencies in the x domain */
  408. /* float *ak array of LPC coefficients */
  409. /* int lpcrdr order of LPC coefficients */
  410. {
  411. int i,j;
  412. float xout1,xout2,xin1,xin2;
  413. VARDECL(float *Wp);
  414. float *pw,*n1,*n2,*n3,*n4=NULL;
  415. VARDECL(float *x_freq);
  416. int m = lpcrdr>>1;
  417. ALLOC(Wp, 4*m+2, float);
  418. pw = Wp;
  419. /* initialise contents of array */
  420. for(i=0;i<=4*m+1;i++){ /* set contents of buffer to 0 */
  421. *pw++ = 0.0;
  422. }
  423. /* Set pointers up */
  424. pw = Wp;
  425. xin1 = 1.0;
  426. xin2 = 1.0;
  427. ALLOC(x_freq, lpcrdr, float);
  428. for (i=0;i<lpcrdr;i++)
  429. x_freq[i] = ANGLE2X(freq[i]);
  430. /* reconstruct P(z) and Q(z) by cascading second order
  431. polynomials in form 1 - 2xz(-1) +z(-2), where x is the
  432. LSP coefficient */
  433. for(j=0;j<=lpcrdr;j++){
  434. int i2=0;
  435. for(i=0;i<m;i++,i2+=2){
  436. n1 = pw+(i*4);
  437. n2 = n1 + 1;
  438. n3 = n2 + 1;
  439. n4 = n3 + 1;
  440. xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2;
  441. xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4;
  442. *n2 = *n1;
  443. *n4 = *n3;
  444. *n1 = xin1;
  445. *n3 = xin2;
  446. xin1 = xout1;
  447. xin2 = xout2;
  448. }
  449. xout1 = xin1 + *(n4+1);
  450. xout2 = xin2 - *(n4+2);
  451. if (j>0)
  452. ak[j-1] = (xout1 + xout2)*0.5f;
  453. *(n4+1) = xin1;
  454. *(n4+2) = xin2;
  455. xin1 = 0.0;
  456. xin2 = 0.0;
  457. }
  458. }
  459. #endif
  460. #ifdef FIXED_POINT
  461. /*Makes sure the LSPs are stable*/
  462. void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin)
  463. {
  464. int i;
  465. spx_word16_t m = margin;
  466. spx_word16_t m2 = 25736-margin;
  467. if (lsp[0]<m)
  468. lsp[0]=m;
  469. if (lsp[len-1]>m2)
  470. lsp[len-1]=m2;
  471. for (i=1;i<len-1;i++)
  472. {
  473. if (lsp[i]<lsp[i-1]+m)
  474. lsp[i]=lsp[i-1]+m;
  475. if (lsp[i]>lsp[i+1]-m)
  476. lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1);
  477. }
  478. }
  479. 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)
  480. {
  481. int i;
  482. spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes);
  483. spx_word16_t tmp2 = 16384-tmp;
  484. for (i=0;i<len;i++)
  485. {
  486. interp_lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]);
  487. }
  488. }
  489. #else
  490. /*Makes sure the LSPs are stable*/
  491. void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin)
  492. {
  493. int i;
  494. if (lsp[0]<LSP_SCALING*margin)
  495. lsp[0]=LSP_SCALING*margin;
  496. if (lsp[len-1]>LSP_SCALING*(M_PI-margin))
  497. lsp[len-1]=LSP_SCALING*(M_PI-margin);
  498. for (i=1;i<len-1;i++)
  499. {
  500. if (lsp[i]<lsp[i-1]+LSP_SCALING*margin)
  501. lsp[i]=lsp[i-1]+LSP_SCALING*margin;
  502. if (lsp[i]>lsp[i+1]-LSP_SCALING*margin)
  503. lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin);
  504. }
  505. }
  506. 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)
  507. {
  508. int i;
  509. float tmp = (1.0f + subframe)/nb_subframes;
  510. for (i=0;i<len;i++)
  511. {
  512. interp_lsp[i] = (1-tmp)*old_lsp[i] + tmp*new_lsp[i];
  513. }
  514. }
  515. #endif