applied symbian related config and casting diffs from Colin Ward
[speexdsp.git] / libspeex / ltp.c
1 /* Copyright (C) 2002 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
44 #include <stdio.h>
45
46 #ifdef _USE_SSE
47 #include "ltp_sse.h"
48 #else
49 static spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len)
50 {
51    int i;
52    spx_word32_t sum=0;
53    for (i=0;i<len;i+=4)
54    {
55       spx_word32_t part=0;
56       part = MAC16_16(part,x[i],y[i]);
57       part = MAC16_16(part,x[i+1],y[i+1]);
58       part = MAC16_16(part,x[i+2],y[i+2]);
59       part = MAC16_16(part,x[i+3],y[i+3]);
60       sum = ADD32(sum,SHR(part,6));
61    }
62    return sum;
63 }
64
65 static void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack)
66 {
67    int i;
68    for (i=0;i<nb_pitch;i++)
69    {
70       /* Compute correlation*/
71       corr[nb_pitch-1-i]=inner_prod(_x, _y+i, len);
72    }
73
74 }
75
76 #endif
77
78 void open_loop_nbest_pitch(spx_sig_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack)
79 {
80    int i,j,k;
81    spx_word32_t *best_score;
82    spx_word32_t e0;
83    spx_word32_t *corr, *energy;
84    spx_word32_t *score;
85    spx_word16_t *swn;
86
87    best_score = PUSH(stack,N, spx_word32_t);
88    corr = PUSH(stack,end-start+1, spx_word32_t);
89    energy = PUSH(stack,end-start+2, spx_word32_t);
90    score = PUSH(stack,end-start+1, spx_word32_t);
91
92 #ifdef FIXED_POINT
93    swn = PUSH(stack, end+len, spx_word16_t);
94    normalize16(sw-end, swn, 16384, end+len);
95    swn += end;
96 #else
97    swn = sw;
98 #endif
99
100    for (i=0;i<N;i++)
101    {
102         best_score[i]=-1;
103         gain[i]=0;
104         pitch[i]=start;
105    }
106
107
108    energy[0]=inner_prod(swn-start, swn-start, len);
109    e0=inner_prod(swn, swn, len);
110    for (i=start;i<=end;i++)
111    {
112       /* Update energy for next pitch*/
113       energy[i-start+1] = energy[i-start] + SHR(MULT16_16(swn[-i-1],swn[-i-1]),6) - SHR(MULT16_16(swn[-i+len-1],swn[-i+len-1]),6);
114    }
115    for (i=start;i<=end;i++)
116    {
117       corr[i-start]=0;
118       score[i-start]=0;
119    }
120
121    pitch_xcorr(swn, swn-end, corr, len, end-start+1, stack);
122
123 #ifdef FIXED_POINT
124    {
125       spx_word16_t *corr16;
126       spx_word16_t *ener16;
127       corr16 = PUSH(stack, end-start+1, spx_word16_t);
128       ener16 = PUSH(stack, end-start+1, spx_word16_t);
129       normalize16(corr, corr16, 16384, end-start+1);
130       normalize16(energy, ener16, 16384, end-start+1);
131
132       for (i=start;i<=end;i++)
133       {
134          spx_word16_t g;
135          spx_word32_t tmp;
136          tmp = corr16[i-start];
137          if (SHR(corr16[i-start],4)>ener16[i-start])
138             tmp = SHL((spx_word32_t)ener16[i-start],14);
139          else if (-SHR(corr16[i-start],4)>ener16[i-start])
140             tmp = -SHL((spx_word32_t)ener16[i-start],14);
141          else
142             tmp = SHL(tmp,10);
143          g = DIV32_16(tmp, 8+ener16[i-start]);
144          score[i-start] = MULT16_16(corr16[i-start],g);
145       }
146    }
147 #else
148    for (i=start;i<=end;i++)
149    {
150       float g = corr[i-start]/(1+energy[i-start]);
151       if (g>16)
152          g = 16;
153       else if (g<-16)
154          g = -16;
155       score[i-start] = g*corr[i-start];
156    }
157 #endif
158
159    /* Extract best scores */
160    for (i=start;i<=end;i++)
161    {
162       if (score[i-start]>best_score[N-1])
163       {
164          for (j=0;j<N;j++)
165          {
166             if (score[i-start] > best_score[j])
167             {
168                for (k=N-1;k>j;k--)
169                {
170                   best_score[k]=best_score[k-1];
171                   pitch[k]=pitch[k-1];
172                }
173                best_score[j]=score[i-start];
174                pitch[j]=i;
175                break;
176             }
177          }
178       }
179    }
180
181    /* Compute open-loop gain */
182    for (j=0;j<N;j++)
183    {
184       spx_word16_t g;
185       i=pitch[j];
186       g = DIV32(corr[i-start], 10+SHR(MULT16_16(spx_sqrt(e0),spx_sqrt(energy[i-start])),6));
187       /* FIXME: g = max(g,corr/energy) */
188       if (g<0)
189          g = 0;
190       gain[j]=g;
191    }
192 }
193
194
195 /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
196 static spx_word64_t pitch_gain_search_3tap(
197 spx_sig_t target[],                 /* Target vector */
198 spx_coef_t ak[],                     /* LPCs for this subframe */
199 spx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
200 spx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
201 spx_sig_t exc[],                    /* Excitation */
202 const void *par,
203 int   pitch,                    /* Pitch value */
204 int   p,                        /* Number of LPC coeffs */
205 int   nsf,                      /* Number of samples in subframe */
206 SpeexBits *bits,
207 char *stack,
208 spx_sig_t *exc2,
209 spx_sig_t *r,
210 int  *cdbk_index,
211 int cdbk_offset
212 )
213 {
214    int i,j;
215    spx_sig_t *tmp, *tmp2;
216    spx_sig_t *x[3];
217    spx_sig_t *e[3];
218    spx_word32_t corr[3];
219    spx_word32_t A[3][3];
220    int   gain_cdbk_size;
221    const signed char *gain_cdbk;
222    spx_word16_t gain[3];
223    spx_word64_t err;
224
225    ltp_params *params;
226    params = (ltp_params*) par;
227    gain_cdbk_size = 1<<params->gain_bits;
228    gain_cdbk = params->gain_cdbk + 3*gain_cdbk_size*cdbk_offset;
229    tmp = PUSH(stack, 3*nsf, spx_sig_t);
230    tmp2 = PUSH(stack, 3*nsf, spx_sig_t);
231
232    x[0]=tmp;
233    x[1]=tmp+nsf;
234    x[2]=tmp+2*nsf;
235
236    e[0]=tmp2;
237    e[1]=tmp2+nsf;
238    e[2]=tmp2+2*nsf;
239    for (i=2;i>=0;i--)
240    {
241       int pp=pitch+1-i;
242       for (j=0;j<nsf;j++)
243       {
244          if (j-pp<0)
245             e[i][j]=exc2[j-pp];
246          else if (j-pp-pitch<0)
247             e[i][j]=exc2[j-pp-pitch];
248          else
249             e[i][j]=0;
250       }
251
252       if (i==2)
253          syn_percep_zero(e[i], ak, awk1, awk2, x[i], nsf, p, stack);
254       else {
255          for (j=0;j<nsf-1;j++)
256             x[i][j+1]=x[i+1][j];
257          x[i][0]=0;
258          for (j=0;j<nsf;j++)
259          {
260             x[i][j]=ADD32(x[i][j],SHL(MULT16_32_Q15(r[j], e[i][0]),1));
261          }
262       }
263    }
264
265 #ifdef FIXED_POINT
266    {
267       /* If using fixed-point, we need to normalize the signals first */
268       spx_word16_t *y[3];
269       spx_word16_t *t;
270
271       spx_sig_t max_val=1;
272       int sig_shift;
273       
274       y[0] = PUSH(stack, nsf, spx_word16_t);
275       y[1] = PUSH(stack, nsf, spx_word16_t);
276       y[2] = PUSH(stack, nsf, spx_word16_t);
277       t = PUSH(stack, nsf, spx_word16_t);
278       for (j=0;j<3;j++)
279       {
280          for (i=0;i<nsf;i++)
281          {
282             spx_sig_t tmp = x[j][i];
283             if (tmp<0)
284                tmp = -tmp;
285             if (tmp > max_val)
286                max_val = tmp;
287          }
288       }
289       for (i=0;i<nsf;i++)
290       {
291          spx_sig_t tmp = target[i];
292          if (tmp<0)
293             tmp = -tmp;
294          if (tmp > max_val)
295             max_val = tmp;
296       }
297
298       sig_shift=0;
299       while (max_val>16384)
300       {
301          sig_shift++;
302          max_val >>= 1;
303       }
304
305       for (j=0;j<3;j++)
306       {
307          for (i=0;i<nsf;i++)
308          {
309             y[j][i] = SHR(x[j][i],sig_shift);
310          }
311       }     
312       for (i=0;i<nsf;i++)
313       {
314          t[i] = SHR(target[i],sig_shift);
315       }
316
317       for (i=0;i<3;i++)
318          corr[i]=inner_prod(y[i],t,nsf);
319       
320       for (i=0;i<3;i++)
321          for (j=0;j<=i;j++)
322             A[i][j]=A[j][i]=inner_prod(y[i],y[j],nsf);
323    }
324 #else
325    {
326       for (i=0;i<3;i++)
327          corr[i]=inner_prod(x[i],target,nsf);
328       
329       for (i=0;i<3;i++)
330          for (j=0;j<=i;j++)
331             A[i][j]=A[j][i]=inner_prod(x[i],x[j],nsf);
332    }
333 #endif
334
335    {
336       spx_word32_t C[9];
337       const signed char *ptr=gain_cdbk;
338       int best_cdbk=0;
339       spx_word32_t best_sum=0;
340       C[0]=corr[2];
341       C[1]=corr[1];
342       C[2]=corr[0];
343       C[3]=A[1][2];
344       C[4]=A[0][1];
345       C[5]=A[0][2];
346       C[6]=A[2][2];
347       C[7]=A[1][1];
348       C[8]=A[0][0];
349 #ifndef FIXED_POINT
350       C[6]*=.5;
351       C[7]*=.5;
352       C[8]*=.5;
353 #endif
354       for (i=0;i<gain_cdbk_size;i++)
355       {
356          spx_word32_t sum=0;
357          spx_word16_t g0,g1,g2;
358          ptr = gain_cdbk+3*i;
359          g0=ptr[0]+32;
360          g1=ptr[1]+32;
361          g2=ptr[2]+32;
362
363          sum = ADD32(sum,MULT16_32_Q14(MULT16_16_16(g0,64),C[0]));
364          sum = ADD32(sum,MULT16_32_Q14(MULT16_16_16(g1,64),C[1]));
365          sum = ADD32(sum,MULT16_32_Q14(MULT16_16_16(g2,64),C[2]));
366          sum = SUB32(sum,MULT16_32_Q14(MULT16_16_16(g0,g1),C[3]));
367          sum = SUB32(sum,MULT16_32_Q14(MULT16_16_16(g2,g1),C[4]));
368          sum = SUB32(sum,MULT16_32_Q14(MULT16_16_16(g2,g0),C[5]));
369          sum = SUB32(sum,MULT16_32_Q15(MULT16_16_16(g0,g0),C[6]));
370          sum = SUB32(sum,MULT16_32_Q15(MULT16_16_16(g1,g1),C[7]));
371          sum = SUB32(sum,MULT16_32_Q15(MULT16_16_16(g2,g2),C[8]));
372
373          /* We could force "safe" pitch values to handle packet loss better */
374
375          if (sum>best_sum || i==0)
376          {
377             best_sum=sum;
378             best_cdbk=i;
379          }
380       }
381 #ifdef FIXED_POINT
382       gain[0] = 32+(spx_word16_t)gain_cdbk[best_cdbk*3];
383       gain[1] = 32+(spx_word16_t)gain_cdbk[best_cdbk*3+1];
384       gain[2] = 32+(spx_word16_t)gain_cdbk[best_cdbk*3+2];
385 #else
386       gain[0] = 0.015625*gain_cdbk[best_cdbk*3]  + .5;
387       gain[1] = 0.015625*gain_cdbk[best_cdbk*3+1]+ .5;
388       gain[2] = 0.015625*gain_cdbk[best_cdbk*3+2]+ .5;
389 #endif
390       *cdbk_index=best_cdbk;
391    }
392
393 #ifdef FIXED_POINT
394    for (i=0;i<nsf;i++)
395      exc[i]=SHL(MULT16_32_Q15(SHL(gain[0],7),e[2][i])+MULT16_32_Q15(SHL(gain[1],7),e[1][i])+MULT16_32_Q15(SHL(gain[2],7),e[0][i]),2);
396    
397    err=0;
398    for (i=0;i<nsf;i++)
399    {
400       spx_sig_t perr=target[i]-SHL((MULT16_32_Q15(SHL(gain[0],7),x[2][i])+MULT16_32_Q15(SHL(gain[1],7),x[1][i])+MULT16_32_Q15(SHL(gain[2],7),x[0][i])),2);
401       spx_word16_t perr2 = PSHR(perr,15);
402       err = ADD64(err,MULT16_16(perr2,perr2));
403       
404    }
405 #else
406    for (i=0;i<nsf;i++)
407       exc[i]=gain[0]*e[2][i]+gain[1]*e[1][i]+gain[2]*e[0][i];
408    
409    err=0;
410    for (i=0;i<nsf;i++)
411       err+=(target[i]-gain[2]*x[0][i]-gain[1]*x[1][i]-gain[0]*x[2][i])
412       * (target[i]-gain[2]*x[0][i]-gain[1]*x[1][i]-gain[0]*x[2][i]);
413 #endif
414
415    return err;
416 }
417
418
419 /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
420 int pitch_search_3tap(
421 spx_sig_t target[],                 /* Target vector */
422 spx_sig_t *sw,
423 spx_coef_t ak[],                     /* LPCs for this subframe */
424 spx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
425 spx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
426 spx_sig_t exc[],                    /* Excitation */
427 const void *par,
428 int   start,                    /* Smallest pitch value allowed */
429 int   end,                      /* Largest pitch value allowed */
430 spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
431 int   p,                        /* Number of LPC coeffs */
432 int   nsf,                      /* Number of samples in subframe */
433 SpeexBits *bits,
434 char *stack,
435 spx_sig_t *exc2,
436 spx_sig_t *r,
437 int complexity,
438 int cdbk_offset
439 )
440 {
441    int i,j;
442    int cdbk_index, pitch=0, best_gain_index=0;
443    spx_sig_t *best_exc;
444    int best_pitch=0;
445    spx_word64_t err, best_err=-1;
446    int N;
447    ltp_params *params;
448    int *nbest;
449    spx_word16_t *gains;
450
451    N=complexity;
452    if (N>10)
453       N=10;
454
455    nbest=PUSH(stack, N, int);
456    gains = PUSH(stack, N, spx_word16_t);
457    params = (ltp_params*) par;
458
459    if (N==0 || end<start)
460    {
461       speex_bits_pack(bits, 0, params->pitch_bits);
462       speex_bits_pack(bits, 0, params->gain_bits);
463       for (i=0;i<nsf;i++)
464          exc[i]=0;
465       return start;
466    }
467    
468    best_exc=PUSH(stack,nsf, spx_sig_t);
469    
470    if (N>end-start+1)
471       N=end-start+1;
472    open_loop_nbest_pitch(sw, start, end, nsf, nbest, gains, N, stack);
473    for (i=0;i<N;i++)
474    {
475       pitch=nbest[i];
476       for (j=0;j<nsf;j++)
477          exc[j]=0;
478       err=pitch_gain_search_3tap(target, ak, awk1, awk2, exc, par, pitch, p, nsf,
479                                  bits, stack, exc2, r, &cdbk_index, cdbk_offset);
480       if (err<best_err || best_err<0)
481       {
482          for (j=0;j<nsf;j++)
483             best_exc[j]=exc[j];
484          best_err=err;
485          best_pitch=pitch;
486          best_gain_index=cdbk_index;
487       }
488    }
489    
490    /*printf ("pitch: %d %d\n", best_pitch, best_gain_index);*/
491    speex_bits_pack(bits, best_pitch-start, params->pitch_bits);
492    speex_bits_pack(bits, best_gain_index, params->gain_bits);
493    /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/
494    for (i=0;i<nsf;i++)
495       exc[i]=best_exc[i];
496
497    return pitch;
498 }
499
500 void pitch_unquant_3tap(
501 spx_sig_t exc[],                    /* Excitation */
502 int   start,                    /* Smallest pitch value allowed */
503 int   end,                      /* Largest pitch value allowed */
504 spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
505 const void *par,
506 int   nsf,                      /* Number of samples in subframe */
507 int *pitch_val,
508 spx_word16_t *gain_val,
509 SpeexBits *bits,
510 char *stack,
511 int count_lost,
512 int subframe_offset,
513 spx_word16_t last_pitch_gain,
514 int cdbk_offset
515 )
516 {
517    int i;
518    int pitch;
519    int gain_index;
520    spx_word16_t gain[3];
521    const signed char *gain_cdbk;
522    int gain_cdbk_size;
523    ltp_params *params;
524
525    params = (ltp_params*) par;
526    gain_cdbk_size = 1<<params->gain_bits;
527    gain_cdbk = params->gain_cdbk + 3*gain_cdbk_size*cdbk_offset;
528
529    pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits);
530    pitch += start;
531    gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits);
532    /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/
533 #ifdef FIXED_POINT
534    gain[0] = 32+(spx_word16_t)gain_cdbk[gain_index*3];
535    gain[1] = 32+(spx_word16_t)gain_cdbk[gain_index*3+1];
536    gain[2] = 32+(spx_word16_t)gain_cdbk[gain_index*3+2];
537 #else
538    gain[0] = 0.015625*gain_cdbk[gain_index*3]+.5;
539    gain[1] = 0.015625*gain_cdbk[gain_index*3+1]+.5;
540    gain[2] = 0.015625*gain_cdbk[gain_index*3+2]+.5;
541 #endif
542
543    if (count_lost && pitch > subframe_offset)
544    {
545       float gain_sum;
546       if (1) {
547          float tmp = count_lost < 4 ? GAIN_SCALING_1*last_pitch_gain : 0.4 * GAIN_SCALING_1 * last_pitch_gain;
548          if (tmp>.95)
549             tmp=.95;
550          gain_sum = GAIN_SCALING_1*gain_3tap_to_1tap(gain);
551
552          if (gain_sum > tmp) {
553             float fact = tmp/gain_sum;
554             for (i=0;i<3;i++)
555                gain[i]*=fact;
556
557          }
558
559       }
560
561    }
562
563    *pitch_val = pitch;
564    gain_val[0]=gain[0];
565    gain_val[1]=gain[1];
566    gain_val[2]=gain[2];
567
568    {
569       spx_sig_t *e[3];
570       spx_sig_t *tmp2;
571       tmp2=PUSH(stack, 3*nsf, spx_sig_t);
572       e[0]=tmp2;
573       e[1]=tmp2+nsf;
574       e[2]=tmp2+2*nsf;
575       
576       for (i=0;i<3;i++)
577       {
578          int j;
579          int pp=pitch+1-i;
580 #if 0
581          for (j=0;j<nsf;j++)
582          {
583             if (j-pp<0)
584                e[i][j]=exc[j-pp];
585             else if (j-pp-pitch<0)
586                e[i][j]=exc[j-pp-pitch];
587             else
588                e[i][j]=0;
589          }
590 #else
591          {
592             int tmp1, tmp3;
593             tmp1=nsf;
594             if (tmp1>pp)
595                tmp1=pp;
596             for (j=0;j<tmp1;j++)
597                e[i][j]=exc[j-pp];
598             tmp3=nsf;
599             if (tmp3>pp+pitch)
600                tmp3=pp+pitch;
601             for (j=tmp1;j<tmp3;j++)
602                e[i][j]=exc[j-pp-pitch];
603             for (j=tmp3;j<nsf;j++)
604                e[i][j]=0;
605          }
606 #endif
607       }
608
609 #ifdef FIXED_POINT
610       {
611          for (i=0;i<nsf;i++)
612             exc[i]=SHL(MULT16_32_Q15(SHL(gain[0],7),e[2][i])+MULT16_32_Q15(SHL(gain[1],7),e[1][i])+MULT16_32_Q15(SHL(gain[2],7),e[0][i]),2);
613       }
614 #else
615       for (i=0;i<nsf;i++)
616          exc[i]=gain[0]*e[2][i]+gain[1]*e[1][i]+gain[2]*e[0][i];
617 #endif
618    }
619 }
620
621
622 /** Forced pitch delay and gain */
623 int forced_pitch_quant(
624 spx_sig_t target[],                 /* Target vector */
625 spx_sig_t *sw,
626 spx_coef_t ak[],                     /* LPCs for this subframe */
627 spx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
628 spx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
629 spx_sig_t exc[],                    /* Excitation */
630 const void *par,
631 int   start,                    /* Smallest pitch value allowed */
632 int   end,                      /* Largest pitch value allowed */
633 spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
634 int   p,                        /* Number of LPC coeffs */
635 int   nsf,                      /* Number of samples in subframe */
636 SpeexBits *bits,
637 char *stack,
638 spx_sig_t *exc2,
639 spx_sig_t *r,
640 int complexity,
641 int cdbk_offset
642 )
643 {
644    int i;
645    float coef = GAIN_SCALING_1*pitch_coef;
646    if (coef>.99)
647       coef=.99;
648    for (i=0;i<nsf;i++)
649    {
650       exc[i]=exc[i-start]*coef;
651    }
652    return start;
653 }
654
655 /** Unquantize forced pitch delay and gain */
656 void forced_pitch_unquant(
657 spx_sig_t exc[],                    /* Excitation */
658 int   start,                    /* Smallest pitch value allowed */
659 int   end,                      /* Largest pitch value allowed */
660 spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
661 const void *par,
662 int   nsf,                      /* Number of samples in subframe */
663 int *pitch_val,
664 spx_word16_t *gain_val,
665 SpeexBits *bits,
666 char *stack,
667 int count_lost,
668 int subframe_offset,
669 spx_word16_t last_pitch_gain,
670 int cdbk_offset
671 )
672 {
673    int i;
674    float coef = GAIN_SCALING_1*pitch_coef;
675    if (coef>.99)
676       coef=.99;
677    for (i=0;i<nsf;i++)
678    {
679       exc[i]=exc[i-start]*coef;
680    }
681    *pitch_val = start;
682    gain_val[0]=gain_val[2]=0;
683    gain_val[1] = pitch_coef;
684 }