ltp.c revision 98913fed6520d8849fb2e246be943e04474aefa4
1/* Copyright (C) 2002-2006 Jean-Marc Valin
2   File: ltp.c
3   Long-Term Prediction functions
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8
9   - Redistributions of source code must retain the above copyright
10   notice, this list of conditions and the following disclaimer.
11
12   - Redistributions in binary form must reproduce the above copyright
13   notice, this list of conditions and the following disclaimer in the
14   documentation and/or other materials provided with the distribution.
15
16   - Neither the name of the Xiph.org Foundation nor the names of its
17   contributors may be used to endorse or promote products derived from
18   this software without specific prior written permission.
19
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
24   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
37#include <math.h>
38#include "ltp.h"
39#include "stack_alloc.h"
40#include "filters.h"
41#include <speex/speex_bits.h>
42#include "math_approx.h"
43#include "os_support.h"
44
45#ifndef NULL
46#define NULL 0
47#endif
48
49
50#ifdef _USE_SSE
51#include "ltp_sse.h"
52#elif defined (ARM4_ASM) || defined(ARM5E_ASM)
53#include "ltp_arm4.h"
54#elif defined (BFIN_ASM)
55#include "ltp_bfin.h"
56#endif
57
58#ifndef OVERRIDE_INNER_PROD
59spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len)
60{
61   spx_word32_t sum=0;
62   len >>= 2;
63   while(len--)
64   {
65      spx_word32_t part=0;
66      part = MAC16_16(part,*x++,*y++);
67      part = MAC16_16(part,*x++,*y++);
68      part = MAC16_16(part,*x++,*y++);
69      part = MAC16_16(part,*x++,*y++);
70      /* HINT: If you had a 40-bit accumulator, you could shift only at the end */
71      sum = ADD32(sum,SHR32(part,6));
72   }
73   return sum;
74}
75#endif
76
77#ifndef OVERRIDE_PITCH_XCORR
78#if 0 /* HINT: Enable this for machines with enough registers (i.e. not x86) */
79void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack)
80{
81   int i,j;
82   for (i=0;i<nb_pitch;i+=4)
83   {
84      /* Compute correlation*/
85      /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/
86      spx_word32_t sum1=0;
87      spx_word32_t sum2=0;
88      spx_word32_t sum3=0;
89      spx_word32_t sum4=0;
90      const spx_word16_t *y = _y+i;
91      const spx_word16_t *x = _x;
92      spx_word16_t y0, y1, y2, y3;
93      /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/
94      y0=*y++;
95      y1=*y++;
96      y2=*y++;
97      y3=*y++;
98      for (j=0;j<len;j+=4)
99      {
100         spx_word32_t part1;
101         spx_word32_t part2;
102         spx_word32_t part3;
103         spx_word32_t part4;
104         part1 = MULT16_16(*x,y0);
105         part2 = MULT16_16(*x,y1);
106         part3 = MULT16_16(*x,y2);
107         part4 = MULT16_16(*x,y3);
108         x++;
109         y0=*y++;
110         part1 = MAC16_16(part1,*x,y1);
111         part2 = MAC16_16(part2,*x,y2);
112         part3 = MAC16_16(part3,*x,y3);
113         part4 = MAC16_16(part4,*x,y0);
114         x++;
115         y1=*y++;
116         part1 = MAC16_16(part1,*x,y2);
117         part2 = MAC16_16(part2,*x,y3);
118         part3 = MAC16_16(part3,*x,y0);
119         part4 = MAC16_16(part4,*x,y1);
120         x++;
121         y2=*y++;
122         part1 = MAC16_16(part1,*x,y3);
123         part2 = MAC16_16(part2,*x,y0);
124         part3 = MAC16_16(part3,*x,y1);
125         part4 = MAC16_16(part4,*x,y2);
126         x++;
127         y3=*y++;
128
129         sum1 = ADD32(sum1,SHR32(part1,6));
130         sum2 = ADD32(sum2,SHR32(part2,6));
131         sum3 = ADD32(sum3,SHR32(part3,6));
132         sum4 = ADD32(sum4,SHR32(part4,6));
133      }
134      corr[nb_pitch-1-i]=sum1;
135      corr[nb_pitch-2-i]=sum2;
136      corr[nb_pitch-3-i]=sum3;
137      corr[nb_pitch-4-i]=sum4;
138   }
139
140}
141#else
142void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack)
143{
144   int i;
145   for (i=0;i<nb_pitch;i++)
146   {
147      /* Compute correlation*/
148      corr[nb_pitch-1-i]=inner_prod(_x, _y+i, len);
149   }
150
151}
152#endif
153#endif
154
155#ifndef OVERRIDE_COMPUTE_PITCH_ERROR
156static inline spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g, spx_word16_t pitch_control)
157{
158   spx_word32_t sum = 0;
159   sum = ADD32(sum,MULT16_16(MULT16_16_16(g[0],pitch_control),C[0]));
160   sum = ADD32(sum,MULT16_16(MULT16_16_16(g[1],pitch_control),C[1]));
161   sum = ADD32(sum,MULT16_16(MULT16_16_16(g[2],pitch_control),C[2]));
162   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[1]),C[3]));
163   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[1]),C[4]));
164   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[0]),C[5]));
165   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[0]),C[6]));
166   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[1],g[1]),C[7]));
167   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[2]),C[8]));
168   return sum;
169}
170#endif
171
172#ifndef OVERRIDE_OPEN_LOOP_NBEST_PITCH
173void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack)
174{
175   int i,j,k;
176   VARDECL(spx_word32_t *best_score);
177   VARDECL(spx_word32_t *best_ener);
178   spx_word32_t e0;
179   VARDECL(spx_word32_t *corr);
180#ifdef FIXED_POINT
181   /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16)
182      arrays for (normalized) 16-bit values */
183   VARDECL(spx_word16_t *corr16);
184   VARDECL(spx_word16_t *ener16);
185   spx_word32_t *energy;
186   int cshift=0, eshift=0;
187   int scaledown = 0;
188   ALLOC(corr16, end-start+1, spx_word16_t);
189   ALLOC(ener16, end-start+1, spx_word16_t);
190   ALLOC(corr, end-start+1, spx_word32_t);
191   energy = corr;
192#else
193   /* In floating-point, we need to float arrays and no normalized copies */
194   VARDECL(spx_word32_t *energy);
195   spx_word16_t *corr16;
196   spx_word16_t *ener16;
197   ALLOC(energy, end-start+2, spx_word32_t);
198   ALLOC(corr, end-start+1, spx_word32_t);
199   corr16 = corr;
200   ener16 = energy;
201#endif
202
203   ALLOC(best_score, N, spx_word32_t);
204   ALLOC(best_ener, N, spx_word32_t);
205   for (i=0;i<N;i++)
206   {
207        best_score[i]=-1;
208        best_ener[i]=0;
209        pitch[i]=start;
210   }
211
212#ifdef FIXED_POINT
213   for (i=-end;i<len;i++)
214   {
215      if (ABS16(sw[i])>16383)
216      {
217         scaledown=1;
218         break;
219      }
220   }
221   /* If the weighted input is close to saturation, then we scale it down */
222   if (scaledown)
223   {
224      for (i=-end;i<len;i++)
225      {
226         sw[i]=SHR16(sw[i],1);
227      }
228   }
229#endif
230   energy[0]=inner_prod(sw-start, sw-start, len);
231   e0=inner_prod(sw, sw, len);
232   for (i=start;i<end;i++)
233   {
234      /* Update energy for next pitch*/
235      energy[i-start+1] = SUB32(ADD32(energy[i-start],SHR32(MULT16_16(sw[-i-1],sw[-i-1]),6)), SHR32(MULT16_16(sw[-i+len-1],sw[-i+len-1]),6));
236      if (energy[i-start+1] < 0)
237         energy[i-start+1] = 0;
238   }
239
240#ifdef FIXED_POINT
241   eshift = normalize16(energy, ener16, 32766, end-start+1);
242#endif
243
244   /* In fixed-point, this actually overrites the energy array (aliased to corr) */
245   pitch_xcorr(sw, sw-end, corr, len, end-start+1, stack);
246
247#ifdef FIXED_POINT
248   /* Normalize to 180 so we can square it and it still fits in 16 bits */
249   cshift = normalize16(corr, corr16, 180, end-start+1);
250   /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */
251   if (scaledown)
252   {
253      for (i=-end;i<len;i++)
254      {
255         sw[i]=SHL16(sw[i],1);
256      }
257   }
258#endif
259
260   /* Search for the best pitch prediction gain */
261   for (i=start;i<=end;i++)
262   {
263      spx_word16_t tmp = MULT16_16_16(corr16[i-start],corr16[i-start]);
264      /* Instead of dividing the tmp by the energy, we multiply on the other side */
265      if (MULT16_16(tmp,best_ener[N-1])>MULT16_16(best_score[N-1],ADD16(1,ener16[i-start])))
266      {
267         /* We can safely put it last and then check */
268         best_score[N-1]=tmp;
269         best_ener[N-1]=ener16[i-start]+1;
270         pitch[N-1]=i;
271         /* Check if it comes in front of others */
272         for (j=0;j<N-1;j++)
273         {
274            if (MULT16_16(tmp,best_ener[j])>MULT16_16(best_score[j],ADD16(1,ener16[i-start])))
275            {
276               for (k=N-1;k>j;k--)
277               {
278                  best_score[k]=best_score[k-1];
279                  best_ener[k]=best_ener[k-1];
280                  pitch[k]=pitch[k-1];
281               }
282               best_score[j]=tmp;
283               best_ener[j]=ener16[i-start]+1;
284               pitch[j]=i;
285               break;
286            }
287         }
288      }
289   }
290
291   /* Compute open-loop gain if necessary */
292   if (gain)
293   {
294      for (j=0;j<N;j++)
295      {
296         spx_word16_t g;
297         i=pitch[j];
298         g = DIV32(SHL32(EXTEND32(corr16[i-start]),cshift), 10+SHR32(MULT16_16(spx_sqrt(e0),spx_sqrt(SHL32(EXTEND32(ener16[i-start]),eshift))),6));
299         /* FIXME: g = max(g,corr/energy) */
300         if (g<0)
301            g = 0;
302         gain[j]=g;
303      }
304   }
305
306
307}
308#endif
309
310#ifndef OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ
311static int pitch_gain_search_3tap_vq(
312  const signed char *gain_cdbk,
313  int                gain_cdbk_size,
314  spx_word16_t      *C16,
315  spx_word16_t       max_gain
316)
317{
318  const signed char *ptr=gain_cdbk;
319  int                best_cdbk=0;
320  spx_word32_t       best_sum=-VERY_LARGE32;
321  spx_word32_t       sum=0;
322  spx_word16_t       g[3];
323  spx_word16_t       pitch_control=64;
324  spx_word16_t       gain_sum;
325  int                i;
326
327  for (i=0;i<gain_cdbk_size;i++) {
328
329    ptr = gain_cdbk+4*i;
330    g[0]=ADD16((spx_word16_t)ptr[0],32);
331    g[1]=ADD16((spx_word16_t)ptr[1],32);
332    g[2]=ADD16((spx_word16_t)ptr[2],32);
333    gain_sum = (spx_word16_t)ptr[3];
334
335    sum = compute_pitch_error(C16, g, pitch_control);
336
337    if (sum>best_sum && gain_sum<=max_gain) {
338      best_sum=sum;
339      best_cdbk=i;
340    }
341  }
342
343  return best_cdbk;
344}
345#endif
346
347/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
348static spx_word32_t pitch_gain_search_3tap(
349const spx_word16_t target[],       /* Target vector */
350const spx_coef_t ak[],          /* LPCs for this subframe */
351const spx_coef_t awk1[],        /* Weighted LPCs #1 for this subframe */
352const spx_coef_t awk2[],        /* Weighted LPCs #2 for this subframe */
353spx_sig_t exc[],                /* Excitation */
354const signed char *gain_cdbk,
355int gain_cdbk_size,
356int   pitch,                    /* Pitch value */
357int   p,                        /* Number of LPC coeffs */
358int   nsf,                      /* Number of samples in subframe */
359SpeexBits *bits,
360char *stack,
361const spx_word16_t *exc2,
362const spx_word16_t *r,
363spx_word16_t *new_target,
364int  *cdbk_index,
365int plc_tuning,
366spx_word32_t cumul_gain,
367int scaledown
368)
369{
370   int i,j;
371   VARDECL(spx_word16_t *tmp1);
372   VARDECL(spx_word16_t *e);
373   spx_word16_t *x[3];
374   spx_word32_t corr[3];
375   spx_word32_t A[3][3];
376   spx_word16_t gain[3];
377   spx_word32_t err;
378   spx_word16_t max_gain=128;
379   int          best_cdbk=0;
380
381   ALLOC(tmp1, 3*nsf, spx_word16_t);
382   ALLOC(e, nsf, spx_word16_t);
383
384   if (cumul_gain > 262144)
385      max_gain = 31;
386
387   x[0]=tmp1;
388   x[1]=tmp1+nsf;
389   x[2]=tmp1+2*nsf;
390
391   for (j=0;j<nsf;j++)
392      new_target[j] = target[j];
393
394   {
395      VARDECL(spx_mem_t *mm);
396      int pp=pitch-1;
397      ALLOC(mm, p, spx_mem_t);
398      for (j=0;j<nsf;j++)
399      {
400         if (j-pp<0)
401            e[j]=exc2[j-pp];
402         else if (j-pp-pitch<0)
403            e[j]=exc2[j-pp-pitch];
404         else
405            e[j]=0;
406      }
407#ifdef FIXED_POINT
408      /* Scale target and excitation down if needed (avoiding overflow) */
409      if (scaledown)
410      {
411         for (j=0;j<nsf;j++)
412            e[j] = SHR16(e[j],1);
413         for (j=0;j<nsf;j++)
414            new_target[j] = SHR16(new_target[j],1);
415      }
416#endif
417      for (j=0;j<p;j++)
418         mm[j] = 0;
419      iir_mem16(e, ak, e, nsf, p, mm, stack);
420      for (j=0;j<p;j++)
421         mm[j] = 0;
422      filter_mem16(e, awk1, awk2, e, nsf, p, mm, stack);
423      for (j=0;j<nsf;j++)
424         x[2][j] = e[j];
425   }
426   for (i=1;i>=0;i--)
427   {
428      spx_word16_t e0=exc2[-pitch-1+i];
429#ifdef FIXED_POINT
430      /* Scale excitation down if needed (avoiding overflow) */
431      if (scaledown)
432         e0 = SHR16(e0,1);
433#endif
434      x[i][0]=MULT16_16_Q14(r[0], e0);
435      for (j=0;j<nsf-1;j++)
436         x[i][j+1]=ADD32(x[i+1][j],MULT16_16_P14(r[j+1], e0));
437   }
438
439   for (i=0;i<3;i++)
440      corr[i]=inner_prod(x[i],new_target,nsf);
441   for (i=0;i<3;i++)
442      for (j=0;j<=i;j++)
443         A[i][j]=A[j][i]=inner_prod(x[i],x[j],nsf);
444
445   {
446      spx_word32_t C[9];
447#ifdef FIXED_POINT
448      spx_word16_t C16[9];
449#else
450      spx_word16_t *C16=C;
451#endif
452      C[0]=corr[2];
453      C[1]=corr[1];
454      C[2]=corr[0];
455      C[3]=A[1][2];
456      C[4]=A[0][1];
457      C[5]=A[0][2];
458      C[6]=A[2][2];
459      C[7]=A[1][1];
460      C[8]=A[0][0];
461
462      /*plc_tuning *= 2;*/
463      if (plc_tuning<2)
464         plc_tuning=2;
465      if (plc_tuning>30)
466         plc_tuning=30;
467#ifdef FIXED_POINT
468      C[0] = SHL32(C[0],1);
469      C[1] = SHL32(C[1],1);
470      C[2] = SHL32(C[2],1);
471      C[3] = SHL32(C[3],1);
472      C[4] = SHL32(C[4],1);
473      C[5] = SHL32(C[5],1);
474      C[6] = MAC16_32_Q15(C[6],MULT16_16_16(plc_tuning,655),C[6]);
475      C[7] = MAC16_32_Q15(C[7],MULT16_16_16(plc_tuning,655),C[7]);
476      C[8] = MAC16_32_Q15(C[8],MULT16_16_16(plc_tuning,655),C[8]);
477      normalize16(C, C16, 32767, 9);
478#else
479      C[6]*=.5*(1+.02*plc_tuning);
480      C[7]*=.5*(1+.02*plc_tuning);
481      C[8]*=.5*(1+.02*plc_tuning);
482#endif
483
484      best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain);
485
486#ifdef FIXED_POINT
487      gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4]);
488      gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+1]);
489      gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+2]);
490      /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/
491#else
492      gain[0] = 0.015625*gain_cdbk[best_cdbk*4]  + .5;
493      gain[1] = 0.015625*gain_cdbk[best_cdbk*4+1]+ .5;
494      gain[2] = 0.015625*gain_cdbk[best_cdbk*4+2]+ .5;
495#endif
496      *cdbk_index=best_cdbk;
497   }
498
499   SPEEX_MEMSET(exc, 0, nsf);
500   for (i=0;i<3;i++)
501   {
502      int j;
503      int tmp1, tmp3;
504      int pp=pitch+1-i;
505      tmp1=nsf;
506      if (tmp1>pp)
507         tmp1=pp;
508      for (j=0;j<tmp1;j++)
509         exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp]);
510      tmp3=nsf;
511      if (tmp3>pp+pitch)
512         tmp3=pp+pitch;
513      for (j=tmp1;j<tmp3;j++)
514         exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp-pitch]);
515   }
516   for (i=0;i<nsf;i++)
517   {
518      spx_word32_t tmp = ADD32(ADD32(MULT16_16(gain[0],x[2][i]),MULT16_16(gain[1],x[1][i])),
519                            MULT16_16(gain[2],x[0][i]));
520      new_target[i] = SUB16(new_target[i], EXTRACT16(PSHR32(tmp,6)));
521   }
522   err = inner_prod(new_target, new_target, nsf);
523
524   return err;
525}
526
527/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
528int pitch_search_3tap(
529spx_word16_t target[],                 /* Target vector */
530spx_word16_t *sw,
531spx_coef_t ak[],                     /* LPCs for this subframe */
532spx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
533spx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
534spx_sig_t exc[],                    /* Excitation */
535const void *par,
536int   start,                    /* Smallest pitch value allowed */
537int   end,                      /* Largest pitch value allowed */
538spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
539int   p,                        /* Number of LPC coeffs */
540int   nsf,                      /* Number of samples in subframe */
541SpeexBits *bits,
542char *stack,
543spx_word16_t *exc2,
544spx_word16_t *r,
545int complexity,
546int cdbk_offset,
547int plc_tuning,
548spx_word32_t *cumul_gain
549)
550{
551   int i;
552   int cdbk_index, pitch=0, best_gain_index=0;
553   VARDECL(spx_sig_t *best_exc);
554   VARDECL(spx_word16_t *new_target);
555   VARDECL(spx_word16_t *best_target);
556   int best_pitch=0;
557   spx_word32_t err, best_err=-1;
558   int N;
559   const ltp_params *params;
560   const signed char *gain_cdbk;
561   int   gain_cdbk_size;
562   int scaledown=0;
563
564   VARDECL(int *nbest);
565
566   params = (const ltp_params*) par;
567   gain_cdbk_size = 1<<params->gain_bits;
568   gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset;
569
570   N=complexity;
571   if (N>10)
572      N=10;
573   if (N<1)
574      N=1;
575
576   ALLOC(nbest, N, int);
577   params = (const ltp_params*) par;
578
579   if (end<start)
580   {
581      speex_bits_pack(bits, 0, params->pitch_bits);
582      speex_bits_pack(bits, 0, params->gain_bits);
583      SPEEX_MEMSET(exc, 0, nsf);
584      return start;
585   }
586
587#ifdef FIXED_POINT
588   /* Check if we need to scale everything down in the pitch search to avoid overflows */
589   for (i=0;i<nsf;i++)
590   {
591      if (ABS16(target[i])>16383)
592      {
593         scaledown=1;
594         break;
595      }
596   }
597   for (i=-end;i<nsf;i++)
598   {
599      if (ABS16(exc2[i])>16383)
600      {
601         scaledown=1;
602         break;
603      }
604   }
605#endif
606   if (N>end-start+1)
607      N=end-start+1;
608   if (end != start)
609      open_loop_nbest_pitch(sw, start, end, nsf, nbest, NULL, N, stack);
610   else
611      nbest[0] = start;
612
613   ALLOC(best_exc, nsf, spx_sig_t);
614   ALLOC(new_target, nsf, spx_word16_t);
615   ALLOC(best_target, nsf, spx_word16_t);
616
617   for (i=0;i<N;i++)
618   {
619      pitch=nbest[i];
620      SPEEX_MEMSET(exc, 0, nsf);
621      err=pitch_gain_search_3tap(target, ak, awk1, awk2, exc, gain_cdbk, gain_cdbk_size, pitch, p, nsf,
622                                 bits, stack, exc2, r, new_target, &cdbk_index, plc_tuning, *cumul_gain, scaledown);
623      if (err<best_err || best_err<0)
624      {
625         SPEEX_COPY(best_exc, exc, nsf);
626         SPEEX_COPY(best_target, new_target, nsf);
627         best_err=err;
628         best_pitch=pitch;
629         best_gain_index=cdbk_index;
630      }
631   }
632   /*printf ("pitch: %d %d\n", best_pitch, best_gain_index);*/
633   speex_bits_pack(bits, best_pitch-start, params->pitch_bits);
634   speex_bits_pack(bits, best_gain_index, params->gain_bits);
635#ifdef FIXED_POINT
636   *cumul_gain = MULT16_32_Q13(SHL16(params->gain_cdbk[4*best_gain_index+3],8), MAX32(1024,*cumul_gain));
637#else
638   *cumul_gain = 0.03125*MAX32(1024,*cumul_gain)*params->gain_cdbk[4*best_gain_index+3];
639#endif
640   /*printf ("%f\n", cumul_gain);*/
641   /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/
642   SPEEX_COPY(exc, best_exc, nsf);
643   SPEEX_COPY(target, best_target, nsf);
644#ifdef FIXED_POINT
645   /* Scale target back up if needed */
646   if (scaledown)
647   {
648      for (i=0;i<nsf;i++)
649         target[i]=SHL16(target[i],1);
650   }
651#endif
652   return pitch;
653}
654
655void pitch_unquant_3tap(
656spx_word16_t exc[],             /* Input excitation */
657spx_word32_t exc_out[],         /* Output excitation */
658int   start,                    /* Smallest pitch value allowed */
659int   end,                      /* Largest pitch value allowed */
660spx_word16_t pitch_coef,        /* Voicing (pitch) coefficient */
661const void *par,
662int   nsf,                      /* Number of samples in subframe */
663int *pitch_val,
664spx_word16_t *gain_val,
665SpeexBits *bits,
666char *stack,
667int count_lost,
668int subframe_offset,
669spx_word16_t last_pitch_gain,
670int cdbk_offset
671)
672{
673   int i;
674   int pitch;
675   int gain_index;
676   spx_word16_t gain[3];
677   const signed char *gain_cdbk;
678   int gain_cdbk_size;
679   const ltp_params *params;
680
681   params = (const ltp_params*) par;
682   gain_cdbk_size = 1<<params->gain_bits;
683   gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset;
684
685   pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits);
686   pitch += start;
687   gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits);
688   /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/
689#ifdef FIXED_POINT
690   gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4]);
691   gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+1]);
692   gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+2]);
693#else
694   gain[0] = 0.015625*gain_cdbk[gain_index*4]+.5;
695   gain[1] = 0.015625*gain_cdbk[gain_index*4+1]+.5;
696   gain[2] = 0.015625*gain_cdbk[gain_index*4+2]+.5;
697#endif
698
699   if (count_lost && pitch > subframe_offset)
700   {
701      spx_word16_t gain_sum;
702      if (1) {
703#ifdef FIXED_POINT
704         spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain,1);
705         if (tmp>62)
706            tmp=62;
707#else
708         spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain;
709         if (tmp>.95)
710            tmp=.95;
711#endif
712         gain_sum = gain_3tap_to_1tap(gain);
713
714         if (gain_sum > tmp)
715         {
716            spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp),14),gain_sum);
717            for (i=0;i<3;i++)
718               gain[i]=MULT16_16_Q14(fact,gain[i]);
719         }
720
721      }
722
723   }
724
725   *pitch_val = pitch;
726   gain_val[0]=gain[0];
727   gain_val[1]=gain[1];
728   gain_val[2]=gain[2];
729   gain[0] = SHL16(gain[0],7);
730   gain[1] = SHL16(gain[1],7);
731   gain[2] = SHL16(gain[2],7);
732   SPEEX_MEMSET(exc_out, 0, nsf);
733   for (i=0;i<3;i++)
734   {
735      int j;
736      int tmp1, tmp3;
737      int pp=pitch+1-i;
738      tmp1=nsf;
739      if (tmp1>pp)
740         tmp1=pp;
741      for (j=0;j<tmp1;j++)
742         exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp]);
743      tmp3=nsf;
744      if (tmp3>pp+pitch)
745         tmp3=pp+pitch;
746      for (j=tmp1;j<tmp3;j++)
747         exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp-pitch]);
748   }
749   /*for (i=0;i<nsf;i++)
750   exc[i]=PSHR32(exc32[i],13);*/
751}
752
753
754/** Forced pitch delay and gain */
755int forced_pitch_quant(
756spx_word16_t target[],                 /* Target vector */
757spx_word16_t *sw,
758spx_coef_t ak[],                     /* LPCs for this subframe */
759spx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
760spx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
761spx_sig_t exc[],                    /* Excitation */
762const void *par,
763int   start,                    /* Smallest pitch value allowed */
764int   end,                      /* Largest pitch value allowed */
765spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
766int   p,                        /* Number of LPC coeffs */
767int   nsf,                      /* Number of samples in subframe */
768SpeexBits *bits,
769char *stack,
770spx_word16_t *exc2,
771spx_word16_t *r,
772int complexity,
773int cdbk_offset,
774int plc_tuning,
775spx_word32_t *cumul_gain
776)
777{
778   int i;
779   VARDECL(spx_word16_t *res);
780   ALLOC(res, nsf, spx_word16_t);
781#ifdef FIXED_POINT
782   if (pitch_coef>63)
783      pitch_coef=63;
784#else
785   if (pitch_coef>.99)
786      pitch_coef=.99;
787#endif
788   for (i=0;i<nsf&&i<start;i++)
789   {
790      exc[i]=MULT16_16(SHL16(pitch_coef, 7),exc2[i-start]);
791   }
792   for (;i<nsf;i++)
793   {
794      exc[i]=MULT16_32_Q15(SHL16(pitch_coef, 9),exc[i-start]);
795   }
796   for (i=0;i<nsf;i++)
797      res[i] = EXTRACT16(PSHR32(exc[i], SIG_SHIFT-1));
798   syn_percep_zero16(res, ak, awk1, awk2, res, nsf, p, stack);
799   for (i=0;i<nsf;i++)
800      target[i]=EXTRACT16(SATURATE(SUB32(EXTEND32(target[i]),EXTEND32(res[i])),32700));
801   return start;
802}
803
804/** Unquantize forced pitch delay and gain */
805void forced_pitch_unquant(
806spx_word16_t exc[],             /* Input excitation */
807spx_word32_t exc_out[],         /* Output excitation */
808int   start,                    /* Smallest pitch value allowed */
809int   end,                      /* Largest pitch value allowed */
810spx_word16_t pitch_coef,        /* Voicing (pitch) coefficient */
811const void *par,
812int   nsf,                      /* Number of samples in subframe */
813int *pitch_val,
814spx_word16_t *gain_val,
815SpeexBits *bits,
816char *stack,
817int count_lost,
818int subframe_offset,
819spx_word16_t last_pitch_gain,
820int cdbk_offset
821)
822{
823   int i;
824#ifdef FIXED_POINT
825   if (pitch_coef>63)
826      pitch_coef=63;
827#else
828   if (pitch_coef>.99)
829      pitch_coef=.99;
830#endif
831   for (i=0;i<nsf;i++)
832   {
833      exc_out[i]=MULT16_16(exc[i-start],SHL16(pitch_coef,7));
834      exc[i] = EXTRACT16(PSHR32(exc_out[i],13));
835   }
836   *pitch_val = start;
837   gain_val[0]=gain_val[2]=0;
838   gain_val[1] = pitch_coef;
839}
840