1 /* Copyright (C) 2002-2006 Jean-Marc Valin
3 Long-Term Prediction functions
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "config-speex.h"
39 #include "stack_alloc.h"
41 #include "speex/speex_bits.h"
42 #include "math_approx.h"
43 #include "os_support.h"
52 #elif defined (ARM4_ASM) || defined(ARM5E_ASM)
54 #elif defined (COLDFIRE_ASM)
55 #define OVERRIDE_INNER_PROD
56 #elif defined (BFIN_ASM)
60 #ifndef OVERRIDE_INNER_PROD
61 spx_word32_t
inner_prod(const spx_word16_t
*x
, const spx_word16_t
*y
, int len
)
68 part
= MAC16_16(part
,*x
++,*y
++);
69 part
= MAC16_16(part
,*x
++,*y
++);
70 part
= MAC16_16(part
,*x
++,*y
++);
71 part
= MAC16_16(part
,*x
++,*y
++);
72 /* HINT: If you had a 40-bit accumulator, you could shift only at the end */
73 sum
= ADD32(sum
,SHR32(part
,6));
79 #ifndef SPEEX_DISABLE_ENCODER
80 #ifndef OVERRIDE_PITCH_XCORR
81 #if 0 /* HINT: Enable this for machines with enough registers (i.e. not x86) */
82 void pitch_xcorr(const spx_word16_t
*_x
, const spx_word16_t
*_y
, spx_word32_t
*corr
, int len
, int nb_pitch
, char *stack
)
85 for (i
=0;i
<nb_pitch
;i
+=4)
87 /* Compute correlation*/
88 /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/
93 const spx_word16_t
*y
= _y
+i
;
94 const spx_word16_t
*x
= _x
;
95 spx_word16_t y0
, y1
, y2
, y3
;
96 /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/
107 part1
= MULT16_16(*x
,y0
);
108 part2
= MULT16_16(*x
,y1
);
109 part3
= MULT16_16(*x
,y2
);
110 part4
= MULT16_16(*x
,y3
);
113 part1
= MAC16_16(part1
,*x
,y1
);
114 part2
= MAC16_16(part2
,*x
,y2
);
115 part3
= MAC16_16(part3
,*x
,y3
);
116 part4
= MAC16_16(part4
,*x
,y0
);
119 part1
= MAC16_16(part1
,*x
,y2
);
120 part2
= MAC16_16(part2
,*x
,y3
);
121 part3
= MAC16_16(part3
,*x
,y0
);
122 part4
= MAC16_16(part4
,*x
,y1
);
125 part1
= MAC16_16(part1
,*x
,y3
);
126 part2
= MAC16_16(part2
,*x
,y0
);
127 part3
= MAC16_16(part3
,*x
,y1
);
128 part4
= MAC16_16(part4
,*x
,y2
);
132 sum1
= ADD32(sum1
,SHR32(part1
,6));
133 sum2
= ADD32(sum2
,SHR32(part2
,6));
134 sum3
= ADD32(sum3
,SHR32(part3
,6));
135 sum4
= ADD32(sum4
,SHR32(part4
,6));
137 corr
[nb_pitch
-1-i
]=sum1
;
138 corr
[nb_pitch
-2-i
]=sum2
;
139 corr
[nb_pitch
-3-i
]=sum3
;
140 corr
[nb_pitch
-4-i
]=sum4
;
145 void pitch_xcorr(const spx_word16_t
*_x
, const spx_word16_t
*_y
, spx_word32_t
*corr
, int len
, int nb_pitch
, char *stack
)
148 for (i
=0;i
<nb_pitch
;i
++)
150 /* Compute correlation*/
151 corr
[nb_pitch
-1-i
]=inner_prod(_x
, _y
+i
, len
);
158 #ifndef OVERRIDE_COMPUTE_PITCH_ERROR
159 static inline spx_word32_t
compute_pitch_error(spx_word16_t
*C
, spx_word16_t
*g
, spx_word16_t pitch_control
)
161 spx_word32_t sum
= 0;
162 sum
= ADD32(sum
,MULT16_16(MULT16_16_16(g
[0],pitch_control
),C
[0]));
163 sum
= ADD32(sum
,MULT16_16(MULT16_16_16(g
[1],pitch_control
),C
[1]));
164 sum
= ADD32(sum
,MULT16_16(MULT16_16_16(g
[2],pitch_control
),C
[2]));
165 sum
= SUB32(sum
,MULT16_16(MULT16_16_16(g
[0],g
[1]),C
[3]));
166 sum
= SUB32(sum
,MULT16_16(MULT16_16_16(g
[2],g
[1]),C
[4]));
167 sum
= SUB32(sum
,MULT16_16(MULT16_16_16(g
[2],g
[0]),C
[5]));
168 sum
= SUB32(sum
,MULT16_16(MULT16_16_16(g
[0],g
[0]),C
[6]));
169 sum
= SUB32(sum
,MULT16_16(MULT16_16_16(g
[1],g
[1]),C
[7]));
170 sum
= SUB32(sum
,MULT16_16(MULT16_16_16(g
[2],g
[2]),C
[8]));
175 #ifndef OVERRIDE_OPEN_LOOP_NBEST_PITCH
176 void open_loop_nbest_pitch(spx_word16_t
*sw
, int start
, int end
, int len
, int *pitch
, spx_word16_t
*gain
, int N
, char *stack
)
179 VARDECL(spx_word32_t
*best_score
);
180 VARDECL(spx_word32_t
*best_ener
);
182 VARDECL(spx_word32_t
*corr
);
184 /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16)
185 arrays for (normalized) 16-bit values */
186 VARDECL(spx_word16_t
*corr16
);
187 VARDECL(spx_word16_t
*ener16
);
188 spx_word32_t
*energy
;
189 int cshift
=0, eshift
=0;
191 ALLOC(corr16
, end
-start
+1, spx_word16_t
);
192 ALLOC(ener16
, end
-start
+1, spx_word16_t
);
193 ALLOC(corr
, end
-start
+1, spx_word32_t
);
196 /* In floating-point, we need to float arrays and no normalized copies */
197 VARDECL(spx_word32_t
*energy
);
198 spx_word16_t
*corr16
;
199 spx_word16_t
*ener16
;
200 ALLOC(energy
, end
-start
+2, spx_word32_t
);
201 ALLOC(corr
, end
-start
+1, spx_word32_t
);
206 ALLOC(best_score
, N
, spx_word32_t
);
207 ALLOC(best_ener
, N
, spx_word32_t
);
216 for (i
=-end
;i
<len
;i
++)
218 if (ABS16(sw
[i
])>16383)
224 /* If the weighted input is close to saturation, then we scale it down */
227 for (i
=-end
;i
<len
;i
++)
229 sw
[i
]=SHR16(sw
[i
],1);
233 energy
[0]=inner_prod(sw
-start
, sw
-start
, len
);
234 e0
=inner_prod(sw
, sw
, len
);
235 for (i
=start
;i
<end
;i
++)
237 /* Update energy for next pitch*/
238 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));
239 if (energy
[i
-start
+1] < 0)
240 energy
[i
-start
+1] = 0;
244 eshift
= normalize16(energy
, ener16
, 32766, end
-start
+1);
247 /* In fixed-point, this actually overrites the energy array (aliased to corr) */
248 pitch_xcorr(sw
, sw
-end
, corr
, len
, end
-start
+1, stack
);
251 /* Normalize to 180 so we can square it and it still fits in 16 bits */
252 cshift
= normalize16(corr
, corr16
, 180, end
-start
+1);
253 /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */
256 for (i
=-end
;i
<len
;i
++)
258 sw
[i
]=SHL16(sw
[i
],1);
263 /* Search for the best pitch prediction gain */
264 for (i
=start
;i
<=end
;i
++)
266 spx_word16_t tmp
= MULT16_16_16(corr16
[i
-start
],corr16
[i
-start
]);
267 /* Instead of dividing the tmp by the energy, we multiply on the other side */
268 if (MULT16_16(tmp
,best_ener
[N
-1])>MULT16_16(best_score
[N
-1],ADD16(1,ener16
[i
-start
])))
270 /* We can safely put it last and then check */
272 best_ener
[N
-1]=ener16
[i
-start
]+1;
274 /* Check if it comes in front of others */
277 if (MULT16_16(tmp
,best_ener
[j
])>MULT16_16(best_score
[j
],ADD16(1,ener16
[i
-start
])))
281 best_score
[k
]=best_score
[k
-1];
282 best_ener
[k
]=best_ener
[k
-1];
286 best_ener
[j
]=ener16
[i
-start
]+1;
294 /* Compute open-loop gain if necessary */
301 g
= DIV32(SHL32(EXTEND32(corr16
[i
-start
]),cshift
), 10+SHR32(MULT16_16(spx_sqrt(e0
),spx_sqrt(SHL32(EXTEND32(ener16
[i
-start
]),eshift
))),6));
302 /* FIXME: g = max(g,corr/energy) */
313 #ifndef OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ
314 static int pitch_gain_search_3tap_vq(
315 const signed char *gain_cdbk
,
318 spx_word16_t max_gain
321 const signed char *ptr
=gain_cdbk
;
323 spx_word32_t best_sum
=-VERY_LARGE32
;
326 spx_word16_t pitch_control
=64;
327 spx_word16_t gain_sum
;
330 for (i
=0;i
<gain_cdbk_size
;i
++) {
333 g
[0]=ADD16((spx_word16_t
)ptr
[0],32);
334 g
[1]=ADD16((spx_word16_t
)ptr
[1],32);
335 g
[2]=ADD16((spx_word16_t
)ptr
[2],32);
336 gain_sum
= (spx_word16_t
)ptr
[3];
338 sum
= compute_pitch_error(C16
, g
, pitch_control
);
340 if (sum
>best_sum
&& gain_sum
<=max_gain
) {
350 /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
351 static spx_word32_t
pitch_gain_search_3tap(
352 const spx_word16_t target
[], /* Target vector */
353 const spx_coef_t ak
[], /* LPCs for this subframe */
354 const spx_coef_t awk1
[], /* Weighted LPCs #1 for this subframe */
355 const spx_coef_t awk2
[], /* Weighted LPCs #2 for this subframe */
356 spx_sig_t exc
[], /* Excitation */
357 const signed char *gain_cdbk
,
359 int pitch
, /* Pitch value */
360 int p
, /* Number of LPC coeffs */
361 int nsf
, /* Number of samples in subframe */
364 const spx_word16_t
*exc2
,
365 const spx_word16_t
*r
,
366 spx_word16_t
*new_target
,
369 spx_word32_t cumul_gain
,
374 VARDECL(spx_word16_t
*tmp1
);
375 VARDECL(spx_word16_t
*e
);
377 spx_word32_t corr
[3];
378 spx_word32_t A
[3][3];
379 spx_word16_t gain
[3];
381 spx_word16_t max_gain
=128;
384 ALLOC(tmp1
, 3*nsf
, spx_word16_t
);
385 ALLOC(e
, nsf
, spx_word16_t
);
387 if (cumul_gain
> 262144)
395 new_target
[j
] = target
[j
];
398 VARDECL(spx_mem_t
*mm
);
400 ALLOC(mm
, p
, spx_mem_t
);
405 else if (j
-pp
-pitch
<0)
406 e
[j
]=exc2
[j
-pp
-pitch
];
411 /* Scale target and excitation down if needed (avoiding overflow) */
415 e
[j
] = SHR16(e
[j
],1);
417 new_target
[j
] = SHR16(new_target
[j
],1);
422 iir_mem16(e
, ak
, e
, nsf
, p
, mm
, stack
);
425 filter_mem16(e
, awk1
, awk2
, e
, nsf
, p
, mm
, stack
);
431 spx_word16_t e0
=exc2
[-pitch
-1+i
];
433 /* Scale excitation down if needed (avoiding overflow) */
437 x
[i
][0]=MULT16_16_Q14(r
[0], e0
);
438 for (j
=0;j
<nsf
-1;j
++)
439 x
[i
][j
+1]=ADD32(x
[i
+1][j
],MULT16_16_P14(r
[j
+1], e0
));
443 corr
[i
]=inner_prod(x
[i
],new_target
,nsf
);
446 A
[i
][j
]=A
[j
][i
]=inner_prod(x
[i
],x
[j
],nsf
);
471 C
[0] = SHL32(C
[0],1);
472 C
[1] = SHL32(C
[1],1);
473 C
[2] = SHL32(C
[2],1);
474 C
[3] = SHL32(C
[3],1);
475 C
[4] = SHL32(C
[4],1);
476 C
[5] = SHL32(C
[5],1);
477 C
[6] = MAC16_32_Q15(C
[6],MULT16_16_16(plc_tuning
,655),C
[6]);
478 C
[7] = MAC16_32_Q15(C
[7],MULT16_16_16(plc_tuning
,655),C
[7]);
479 C
[8] = MAC16_32_Q15(C
[8],MULT16_16_16(plc_tuning
,655),C
[8]);
480 normalize16(C
, C16
, 32767, 9);
482 C
[6]*=.5*(1+.02*plc_tuning
);
483 C
[7]*=.5*(1+.02*plc_tuning
);
484 C
[8]*=.5*(1+.02*plc_tuning
);
487 best_cdbk
= pitch_gain_search_3tap_vq(gain_cdbk
, gain_cdbk_size
, C16
, max_gain
);
490 gain
[0] = ADD16(32,(spx_word16_t
)gain_cdbk
[best_cdbk
*4]);
491 gain
[1] = ADD16(32,(spx_word16_t
)gain_cdbk
[best_cdbk
*4+1]);
492 gain
[2] = ADD16(32,(spx_word16_t
)gain_cdbk
[best_cdbk
*4+2]);
493 /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/
495 gain
[0] = 0.015625*gain_cdbk
[best_cdbk
*4] + .5;
496 gain
[1] = 0.015625*gain_cdbk
[best_cdbk
*4+1]+ .5;
497 gain
[2] = 0.015625*gain_cdbk
[best_cdbk
*4+2]+ .5;
499 *cdbk_index
=best_cdbk
;
502 SPEEX_MEMSET(exc
, 0, nsf
);
512 exc
[j
]=MAC16_16(exc
[j
],SHL16(gain
[2-i
],7),exc2
[j
-pp
]);
516 for (j
=tmp1
;j
<tmp3
;j
++)
517 exc
[j
]=MAC16_16(exc
[j
],SHL16(gain
[2-i
],7),exc2
[j
-pp
-pitch
]);
521 spx_word32_t tmp
= ADD32(ADD32(MULT16_16(gain
[0],x
[2][i
]),MULT16_16(gain
[1],x
[1][i
])),
522 MULT16_16(gain
[2],x
[0][i
]));
523 new_target
[i
] = SUB16(new_target
[i
], EXTRACT16(PSHR32(tmp
,6)));
525 err
= inner_prod(new_target
, new_target
, nsf
);
530 /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
531 int pitch_search_3tap(
532 spx_word16_t target
[], /* Target vector */
534 spx_coef_t ak
[], /* LPCs for this subframe */
535 spx_coef_t awk1
[], /* Weighted LPCs #1 for this subframe */
536 spx_coef_t awk2
[], /* Weighted LPCs #2 for this subframe */
537 spx_sig_t exc
[], /* Excitation */
539 int start
, /* Smallest pitch value allowed */
540 int end
, /* Largest pitch value allowed */
541 spx_word16_t pitch_coef
, /* Voicing (pitch) coefficient */
542 int p
, /* Number of LPC coeffs */
543 int nsf
, /* Number of samples in subframe */
551 spx_word32_t
*cumul_gain
555 int cdbk_index
, pitch
=0, best_gain_index
=0;
556 VARDECL(spx_sig_t
*best_exc
);
557 VARDECL(spx_word16_t
*new_target
);
558 VARDECL(spx_word16_t
*best_target
);
560 spx_word32_t err
, best_err
=-1;
562 const ltp_params
*params
;
563 const signed char *gain_cdbk
;
569 params
= (const ltp_params
*) par
;
570 gain_cdbk_size
= 1<<params
->gain_bits
;
571 gain_cdbk
= params
->gain_cdbk
+ 4*gain_cdbk_size
*cdbk_offset
;
579 ALLOC(nbest
, N
, int);
580 params
= (const ltp_params
*) par
;
584 speex_bits_pack(bits
, 0, params
->pitch_bits
);
585 speex_bits_pack(bits
, 0, params
->gain_bits
);
586 SPEEX_MEMSET(exc
, 0, nsf
);
591 /* Check if we need to scale everything down in the pitch search to avoid overflows */
594 if (ABS16(target
[i
])>16383)
600 for (i
=-end
;i
<nsf
;i
++)
602 if (ABS16(exc2
[i
])>16383)
612 open_loop_nbest_pitch(sw
, start
, end
, nsf
, nbest
, NULL
, N
, stack
);
616 ALLOC(best_exc
, nsf
, spx_sig_t
);
617 ALLOC(new_target
, nsf
, spx_word16_t
);
618 ALLOC(best_target
, nsf
, spx_word16_t
);
623 SPEEX_MEMSET(exc
, 0, nsf
);
624 err
=pitch_gain_search_3tap(target
, ak
, awk1
, awk2
, exc
, gain_cdbk
, gain_cdbk_size
, pitch
, p
, nsf
,
625 bits
, stack
, exc2
, r
, new_target
, &cdbk_index
, plc_tuning
, *cumul_gain
, scaledown
);
626 if (err
<best_err
|| best_err
<0)
628 SPEEX_COPY(best_exc
, exc
, nsf
);
629 SPEEX_COPY(best_target
, new_target
, nsf
);
632 best_gain_index
=cdbk_index
;
635 /*printf ("pitch: %d %d\n", best_pitch, best_gain_index);*/
636 speex_bits_pack(bits
, best_pitch
-start
, params
->pitch_bits
);
637 speex_bits_pack(bits
, best_gain_index
, params
->gain_bits
);
639 *cumul_gain
= MULT16_32_Q13(SHL16(params
->gain_cdbk
[4*best_gain_index
+3],8), MAX32(1024,*cumul_gain
));
641 *cumul_gain
= 0.03125*MAX32(1024,*cumul_gain
)*params
->gain_cdbk
[4*best_gain_index
+3];
643 /*printf ("%f\n", cumul_gain);*/
644 /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/
645 SPEEX_COPY(exc
, best_exc
, nsf
);
646 SPEEX_COPY(target
, best_target
, nsf
);
648 /* Scale target back up if needed */
652 target
[i
]=SHL16(target
[i
],1);
657 #endif /* SPEEX_DISABLE_ENCODER */
659 void pitch_unquant_3tap(
660 spx_word16_t exc
[], /* Input excitation */
661 spx_word32_t exc_out
[], /* Output excitation */
662 int start
, /* Smallest pitch value allowed */
663 int end
, /* Largest pitch value allowed */
664 spx_word16_t pitch_coef
, /* Voicing (pitch) coefficient */
666 int nsf
, /* Number of samples in subframe */
668 spx_word16_t
*gain_val
,
673 spx_word16_t last_pitch_gain
,
683 spx_word16_t gain
[3];
684 const signed char *gain_cdbk
;
686 const ltp_params
*params
;
688 params
= (const ltp_params
*) par
;
689 gain_cdbk_size
= 1<<params
->gain_bits
;
690 gain_cdbk
= params
->gain_cdbk
+ 4*gain_cdbk_size
*cdbk_offset
;
692 pitch
= speex_bits_unpack_unsigned(bits
, params
->pitch_bits
);
694 gain_index
= speex_bits_unpack_unsigned(bits
, params
->gain_bits
);
695 /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/
697 gain
[0] = ADD16(32,(spx_word16_t
)gain_cdbk
[gain_index
*4]);
698 gain
[1] = ADD16(32,(spx_word16_t
)gain_cdbk
[gain_index
*4+1]);
699 gain
[2] = ADD16(32,(spx_word16_t
)gain_cdbk
[gain_index
*4+2]);
701 gain
[0] = 0.015625*gain_cdbk
[gain_index
*4]+.5;
702 gain
[1] = 0.015625*gain_cdbk
[gain_index
*4+1]+.5;
703 gain
[2] = 0.015625*gain_cdbk
[gain_index
*4+2]+.5;
706 if (count_lost
&& pitch
> subframe_offset
)
708 spx_word16_t gain_sum
;
711 spx_word16_t tmp
= count_lost
< 4 ? last_pitch_gain
: SHR16(last_pitch_gain
,1);
715 spx_word16_t tmp
= count_lost
< 4 ? last_pitch_gain
: 0.5 * last_pitch_gain
;
719 gain_sum
= gain_3tap_to_1tap(gain
);
723 spx_word16_t fact
= DIV32_16(SHL32(EXTEND32(tmp
),14),gain_sum
);
725 gain
[i
]=MULT16_16_Q14(fact
,gain
[i
]);
736 gain
[0] = SHL16(gain
[0],7);
737 gain
[1] = SHL16(gain
[1],7);
738 gain
[2] = SHL16(gain
[2],7);
739 SPEEX_MEMSET(exc_out
, 0, nsf
);
749 exc_out
[j
]=MAC16_16(exc_out
[j
],gain
[2-i
],exc
[j
-pp
]);
753 for (j
=tmp1
;j
<tmp3
;j
++)
754 exc_out
[j
]=MAC16_16(exc_out
[j
],gain
[2-i
],exc
[j
-pp
-pitch
]);
756 /*for (i=0;i<nsf;i++)
757 exc[i]=PSHR32(exc32[i],13);*/
761 #ifndef SPEEX_DISABLE_ENCODER
762 /** Forced pitch delay and gain */
763 int forced_pitch_quant(
764 spx_word16_t target
[], /* Target vector */
766 spx_coef_t ak
[], /* LPCs for this subframe */
767 spx_coef_t awk1
[], /* Weighted LPCs #1 for this subframe */
768 spx_coef_t awk2
[], /* Weighted LPCs #2 for this subframe */
769 spx_sig_t exc
[], /* Excitation */
771 int start
, /* Smallest pitch value allowed */
772 int end
, /* Largest pitch value allowed */
773 spx_word16_t pitch_coef
, /* Voicing (pitch) coefficient */
774 int p
, /* Number of LPC coeffs */
775 int nsf
, /* Number of samples in subframe */
783 spx_word32_t
*cumul_gain
787 VARDECL(spx_word16_t
*res
);
788 ALLOC(res
, nsf
, spx_word16_t
);
796 for (i
=0;i
<nsf
&&i
<start
;i
++)
798 exc
[i
]=MULT16_16(SHL16(pitch_coef
, 7),exc2
[i
-start
]);
802 exc
[i
]=MULT16_32_Q15(SHL16(pitch_coef
, 9),exc
[i
-start
]);
805 res
[i
] = EXTRACT16(PSHR32(exc
[i
], SIG_SHIFT
-1));
806 syn_percep_zero16(res
, ak
, awk1
, awk2
, res
, nsf
, p
, stack
);
808 target
[i
]=EXTRACT16(SATURATE(SUB32(EXTEND32(target
[i
]),EXTEND32(res
[i
])),32700));
811 #endif /* SPEEX_DISABLE_ENCODER */
813 /** Unquantize forced pitch delay and gain */
814 void forced_pitch_unquant(
815 spx_word16_t exc
[], /* Input excitation */
816 spx_word32_t exc_out
[], /* Output excitation */
817 int start
, /* Smallest pitch value allowed */
818 int end
, /* Largest pitch value allowed */
819 spx_word16_t pitch_coef
, /* Voicing (pitch) coefficient */
821 int nsf
, /* Number of samples in subframe */
823 spx_word16_t
*gain_val
,
828 spx_word16_t last_pitch_gain
,
837 (void)subframe_offset
;
838 (void)last_pitch_gain
;
850 exc_out
[i
]=MULT16_16(exc
[i
-start
],SHL16(pitch_coef
,7));
851 exc
[i
] = EXTRACT16(PSHR32(exc_out
[i
],13));
854 gain_val
[0]=gain_val
[2]=0;
855 gain_val
[1] = pitch_coef
;