Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : //#include "prot_fx.h" /* Function prototypes */
8 : #include "basop_util.h"
9 : #include "prot_fx.h" /* Function prototypes */
10 : #include "prot_fx_enc.h" /* Function prototypes */
11 :
12 : /*-------------------------------------------------------------------*
13 : * Local constants
14 : *-------------------------------------------------------------------*/
15 :
16 : #define GAIN_PIT_MAX 19661
17 :
18 :
19 : /*-------------------------------------------------------------------*
20 : * Local function prototypes
21 : *-------------------------------------------------------------------*/
22 :
23 : static Word16 adpt_enr_fx( const Word16 codec_mode, const Word16 *exc, const Word16 *h1, Word16 *y1, const Word16 L_subfr, Word16 *gain, Word16 *g_corr, const Word16 clip_gain, const Word16 *xn, Word16 *xn2, Word16 *exp_ener, Word16 use_prev_sf_pit_gain );
24 :
25 : /*-------------------------------------------------------------------*
26 : * function lp_filt_exc_enc_fx()
27 : *
28 : * Low-pass filtering of the adaptive excitation
29 : * Innovation target construction
30 : * Gain quantization limitation
31 : *-------------------------------------------------------------------*/
32 :
33 6156 : Word16 lp_filt_exc_enc_fx(
34 : const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */
35 : const Word16 coder_type, /* i : coding type Q0 */
36 : const Word16 i_subfr, /* i : subframe index Q0 */
37 : Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */
38 : const Word16 *h1, /* i : weighted filter input response Q(14+shift) */
39 : const Word16 *xn, /* i : target vector Q_new-1+shift */
40 : Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */
41 : Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */
42 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */
43 : const Word16 L_frame, /* i : frame size Q0 */
44 : Word16 *g_corr, /* o : ACELP correlation values mant/exp */
45 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */
46 : Word16 *gain_pit, /* o : adaptive excitation gain Q14 */
47 : Word16 *lp_flag /* i/o: mode selection Q0 */
48 : )
49 : {
50 : Word16 gain1, gain2, g_corr2[4], exc_tmp[5 * L_SUBFR], xn2_tmp[5 * L_SUBFR];
51 : Word16 y1_tmp[5 * L_SUBFR];
52 : Word16 select, i, exp_ener, exp_ener1;
53 : Word16 wtmp, wtmp1;
54 : Word32 Ltmp;
55 :
56 6156 : Word16 use_prev_sf_pit_gain = 0; // Q0
57 6156 : move16();
58 :
59 6156 : gain1 = 0;
60 6156 : move16();
61 6156 : gain2 = 0;
62 6156 : move16();
63 :
64 : /*----------------------------------------------------------------*
65 : * Find the target energy if the adaptive exc. is not filtered
66 : *----------------------------------------------------------------*/
67 6156 : test();
68 6156 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, 100 ) )
69 : {
70 0 : use_prev_sf_pit_gain = 1; // Q0
71 0 : move16();
72 : }
73 6156 : exp_ener = 0;
74 6156 : move16();
75 6156 : wtmp = 0;
76 6156 : move16();
77 6156 : test();
78 6156 : IF( EQ_16( *lp_flag, FULL_BAND ) || EQ_16( *lp_flag, NORMAL_OPERATION ) )
79 : {
80 6156 : wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); // exp_ener
81 6156 : move16();
82 : }
83 :
84 : /*----------------------------------------------------------------*
85 : * Filter the adaptive excitation
86 : * Find the target energy if the adapt. exc. is filtered
87 : *----------------------------------------------------------------*/
88 :
89 6156 : exp_ener1 = 0;
90 6156 : move16();
91 6156 : wtmp1 = 0;
92 6156 : move16();
93 6156 : test();
94 6156 : IF( ( ( *lp_flag == LOW_PASS ) ) || ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) )
95 : {
96 6142 : test();
97 6142 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( L_frame, L_FRAME16k ) )
98 : {
99 0 : FOR( i = 0; i < L_subfr; i++ )
100 : {
101 0 : Ltmp = L_mult( 6881, exc[i - 1 + i_subfr] ); /* constants in Q15 */
102 0 : Ltmp = L_mac( Ltmp, 19005, exc[i + i_subfr] );
103 0 : Ltmp = L_mac( Ltmp, 6881, exc[i + 1 + i_subfr] );
104 0 : exc_tmp[i] = round_fx( Ltmp );
105 0 : move16();
106 : }
107 : }
108 : ELSE
109 : {
110 399230 : FOR( i = 0; i < L_subfr; i++ )
111 : {
112 393088 : Ltmp = L_mult( 5898, exc[i - 1 + i_subfr] ); /* constants in Q15 */
113 393088 : Ltmp = L_mac( Ltmp, 20972, exc[i + i_subfr] );
114 393088 : Ltmp = L_mac( Ltmp, 5898, exc[i + 1 + i_subfr] );
115 393088 : exc_tmp[i] = round_fx( Ltmp );
116 393088 : move16();
117 : }
118 : }
119 :
120 6142 : wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, &gain2, g_corr2, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); // exp_ener1
121 : }
122 :
123 6156 : if ( LT_16( exp_ener, exp_ener1 ) )
124 : {
125 72 : wtmp = shr( wtmp, 1 ); // exp_ener + 1
126 : }
127 :
128 6156 : if ( GT_16( exp_ener, exp_ener1 ) )
129 : {
130 374 : wtmp1 = shr( wtmp1, 1 ); // exp_ener1 + 1
131 : }
132 :
133 : /*-----------------------------------------------------------------*
134 : * use the best prediction (minimize quadratic error)
135 : *-----------------------------------------------------------------*/
136 :
137 6156 : test();
138 6156 : test();
139 6156 : IF( ( ( LT_16( wtmp1, wtmp ) ) && ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) ) || ( ( *lp_flag == LOW_PASS ) ) )
140 : {
141 : /* use the LP filter for pitch excitation prediction */
142 4523 : select = LOW_PASS;
143 4523 : move16();
144 4523 : Copy( exc_tmp, &exc[i_subfr], L_subfr ); // Q_new
145 4523 : Copy( y1_tmp, y1, L_subfr ); // Q_new-1+shift
146 4523 : Copy( xn2_tmp, xn2, L_subfr ); // Q_new-1+shift
147 :
148 4523 : IF( use_prev_sf_pit_gain == 0 )
149 : {
150 4523 : *gain_pit = gain2; // Q14
151 4523 : move16();
152 4523 : g_corr[0] = g_corr2[0];
153 4523 : move16();
154 4523 : g_corr[1] = g_corr2[1];
155 4523 : move16();
156 4523 : g_corr[2] = g_corr2[2];
157 4523 : move16();
158 4523 : g_corr[3] = g_corr2[3];
159 4523 : move16();
160 : }
161 : }
162 : ELSE
163 : {
164 : /* no LP filter used for pitch excitation prediction */
165 1633 : select = FULL_BAND;
166 1633 : move16();
167 1633 : IF( use_prev_sf_pit_gain == 0 )
168 : {
169 1633 : *gain_pit = gain1; // Q14
170 1633 : move16();
171 : }
172 : }
173 :
174 6156 : return select;
175 : }
176 :
177 589952 : Word16 lp_filt_exc_enc_ivas_fx(
178 : const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */
179 : const Word16 coder_type, /* i : coding type Q0 */
180 : const Word16 i_subfr, /* i : subframe index Q0 */
181 : Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */
182 : const Word16 *h1, /* i : weighted filter input response Q(15) */
183 : const Word16 *xn, /* i : target vector Q_new-1+shift */
184 : Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */
185 : Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */
186 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */
187 : const Word16 L_frame, /* i : frame size Q0 */
188 : Word16 *g_corr, /* o : ACELP correlation values mant/exp */
189 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */
190 : Word16 *gain_pit, /* o : adaptive excitation gain Q14 */
191 : Word16 *lp_flag /* i/o: mode selection Q0 */
192 : )
193 : {
194 : Word16 gain1, gain2, g_corr2[4], exc_tmp[5 * L_SUBFR], xn2_tmp[5 * L_SUBFR];
195 : Word16 y1_tmp[5 * L_SUBFR];
196 : Word16 select, i, exp_ener, exp_ener1;
197 : Word16 wtmp, wtmp1;
198 : Word32 Ltmp;
199 :
200 589952 : Word16 use_prev_sf_pit_gain = 0; // Q0
201 589952 : move16();
202 :
203 589952 : gain1 = 0;
204 589952 : move16();
205 589952 : gain2 = 0;
206 589952 : move16();
207 :
208 : /*----------------------------------------------------------------*
209 : * Find the target energy if the adaptive exc. is not filtered
210 : *----------------------------------------------------------------*/
211 589952 : test();
212 589952 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, 100 ) )
213 : {
214 0 : use_prev_sf_pit_gain = 1; // Q0
215 0 : move16();
216 : }
217 589952 : exp_ener = 0;
218 589952 : move16();
219 589952 : wtmp = 0;
220 589952 : move16();
221 589952 : test();
222 589952 : IF( EQ_16( *lp_flag, FULL_BAND ) || EQ_16( *lp_flag, NORMAL_OPERATION ) )
223 : {
224 549111 : IF( EQ_16( use_prev_sf_pit_gain, 1 ) )
225 : {
226 0 : wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, gain_pit, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); // exp_ener
227 : }
228 : ELSE
229 : {
230 549111 : wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); // exp_ener
231 : }
232 : }
233 :
234 : /*----------------------------------------------------------------*
235 : * Filter the adaptive excitation
236 : * Find the target energy if the adapt. exc. is filtered
237 : *----------------------------------------------------------------*/
238 :
239 589952 : exp_ener1 = 0;
240 589952 : move16();
241 589952 : wtmp1 = 0;
242 589952 : move16();
243 589952 : test();
244 589952 : IF( ( ( *lp_flag == LOW_PASS ) ) || ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) )
245 : {
246 530488 : test();
247 530488 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( L_frame, L_FRAME16k ) )
248 : {
249 0 : FOR( i = 0; i < L_subfr; i++ )
250 : {
251 0 : Ltmp = L_mult( 6881, exc[i - 1 + i_subfr] ); /* constants in Q15 */
252 0 : Ltmp = L_mac( Ltmp, 19005, exc[i + i_subfr] );
253 0 : Ltmp = L_mac( Ltmp, 6881, exc[i + 1 + i_subfr] );
254 0 : exc_tmp[i] = round_fx( Ltmp );
255 0 : move16();
256 : }
257 : }
258 : ELSE
259 : {
260 34481720 : FOR( i = 0; i < L_subfr; i++ )
261 : {
262 33951232 : Ltmp = L_mult( 5898, exc[i - 1 + i_subfr] ); /* constants in Q15 */
263 33951232 : Ltmp = L_mac( Ltmp, 20972, exc[i + i_subfr] );
264 33951232 : Ltmp = L_mac( Ltmp, 5898, exc[i + 1 + i_subfr] );
265 33951232 : exc_tmp[i] = round_fx( Ltmp );
266 33951232 : move16();
267 : }
268 : }
269 530488 : IF( EQ_16( use_prev_sf_pit_gain, 1 ) )
270 : {
271 0 : wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, gain_pit, g_corr2, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); // exp_ener1
272 : }
273 : ELSE
274 : {
275 530488 : wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, &gain2, g_corr2, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); // exp_ener1
276 : }
277 : }
278 :
279 589952 : if ( LT_16( exp_ener, exp_ener1 ) )
280 : {
281 46132 : wtmp = shr( wtmp, 1 );
282 : }
283 :
284 589952 : if ( GT_16( exp_ener, exp_ener1 ) )
285 : {
286 76727 : wtmp1 = shr( wtmp1, 1 );
287 : }
288 :
289 : /*-----------------------------------------------------------------*
290 : * use the best prediction (minimize quadratic error)
291 : *-----------------------------------------------------------------*/
292 :
293 589952 : test();
294 589952 : test();
295 589952 : IF( ( ( LT_16( wtmp1, wtmp ) ) && ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) ) || ( ( *lp_flag == LOW_PASS ) ) )
296 : {
297 : /* use the LP filter for pitch excitation prediction */
298 369514 : select = LOW_PASS;
299 369514 : move16();
300 369514 : Copy( exc_tmp, &exc[i_subfr], L_subfr ); // Q_new
301 369514 : Copy( y1_tmp, y1, L_subfr ); // Q_new-1+shift
302 369514 : Copy( xn2_tmp, xn2, L_subfr ); // Q_new-1+shift
303 :
304 369514 : IF( use_prev_sf_pit_gain == 0 )
305 : {
306 369514 : *gain_pit = gain2; // Q14
307 369514 : move16();
308 369514 : g_corr[0] = g_corr2[0];
309 369514 : move16();
310 369514 : g_corr[1] = g_corr2[1];
311 369514 : move16();
312 369514 : g_corr[2] = g_corr2[2];
313 369514 : move16();
314 369514 : g_corr[3] = g_corr2[3];
315 369514 : move16();
316 : }
317 : }
318 : ELSE
319 : {
320 : /* no LP filter used for pitch excitation prediction */
321 220438 : select = FULL_BAND;
322 220438 : move16();
323 220438 : IF( use_prev_sf_pit_gain == 0 )
324 : {
325 220438 : *gain_pit = gain1; // Q14
326 220438 : move16();
327 : }
328 : }
329 :
330 589952 : return select;
331 : }
332 :
333 : /*-------------------------------------------------------------------*
334 : * adpt_enr_fx()
335 : *
336 : * Find adaptive excitation energy
337 : * This serves to decide about the filtering of the adaptive excitation
338 : *-------------------------------------------------------------------*/
339 :
340 1091897 : static Word16 adpt_enr_fx( /* o : adaptive excitation energy mant */
341 : const Word16 codec_mode, /* i : MODE1 or MODE2 */
342 : const Word16 *exc, /* i : excitation vector Q_new */
343 : const Word16 *h1, /* i : impuls response Q15 */
344 : Word16 *y1, /* o : zero-memory filtered adpt. excitation 12 bits */
345 : const Word16 L_subfr, /* i : vector length */
346 : Word16 *gain, /* o : subframe adaptive gain Q14 */
347 : Word16 *g_corr, /* o : correlations for adptive gain mant/exp*/
348 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */
349 : const Word16 *xn, /* i : adaptive codebook target 12 bits Q_new-1+shift*/
350 : Word16 *xn2, /* o : algebraic codebook target 12 bits Q_new-1+shift*/
351 : Word16 *exp_ener /* o : adaptive excitation energy exp */
352 : ,
353 : Word16 use_prev_sf_pit_gain /* i : flag to use prev sf pitch gain or not */
354 : )
355 : {
356 : Word16 ener, i;
357 : Word16 exc_tmp[L_FRAME16k], xn_tmp[L_FRAME16k];
358 : Word32 Ltmp;
359 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL /* Critical Overflow */
360 1091897 : Flag Overflow = 0;
361 : #endif
362 :
363 1091897 : Overflow = 0;
364 1091897 : move16();
365 1091897 : Overflow =
366 1091897 : conv_fx( exc, h1, y1, L_subfr );
367 :
368 1091897 : IF( use_prev_sf_pit_gain == 0 )
369 : {
370 1091897 : *gain = corr_xy1_fx( xn, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
371 1091897 : move16();
372 :
373 1091897 : test();
374 1091897 : IF( GT_16( L_subfr, L_SUBFR ) && Overflow )
375 : {
376 44482 : FOR( i = 0; i < L_subfr; i++ )
377 : {
378 44224 : exc_tmp[i] = mult( exc[i], 8192 /*0.25.Q15*/ ); // Q_new
379 44224 : move16();
380 44224 : xn_tmp[i] = mult( xn[i], 8192 /*0.25.Q15*/ ); // Q_new
381 44224 : move16();
382 : }
383 258 : Overflow = 0;
384 :
385 258 : conv_fx( exc_tmp, h1, y1, L_subfr );
386 258 : *gain = corr_xy1_fx( xn_tmp, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
387 258 : move16();
388 : }
389 :
390 : /* clip gain, if necessary to avoid problems at decoder */
391 1091897 : test();
392 1091897 : if ( EQ_16( clip_gain, 1 ) && GT_16( *gain, 15565 ) ) /* constant in Q14 */
393 : {
394 4251 : *gain = 15565; // 0.95.Q14
395 4251 : move16();
396 : }
397 :
398 1091897 : test();
399 1091897 : IF( EQ_16( clip_gain, 2 ) && GT_16( *gain, 10650 ) ) // 0.65.Q14
400 : {
401 2927 : *gain = 10650; // 0.65.Q14
402 2927 : move16();
403 : }
404 : }
405 :
406 : /* find energy of new target xn2[] */
407 1091897 : updt_tar_fx( xn, xn2, y1, *gain, L_subfr );
408 :
409 1091897 : IF( GT_16( L_subfr, L_SUBFR ) )
410 : {
411 : /* could possibly happen in GSC */
412 15046 : Ltmp = Calc_Energy_Autoscaled( xn2, 0, L_subfr, exp_ener );
413 15046 : i = norm_l( Ltmp );
414 15046 : ener = extract_h( L_shl( Ltmp, i ) ); // exp_ener
415 15046 : i = sub( 31, i );
416 15046 : *exp_ener = sub( i, *exp_ener );
417 15046 : move16();
418 : }
419 : ELSE
420 : {
421 1076851 : ener = extract_h( Dot_product12( xn2, xn2, L_SUBFR, exp_ener ) ); // Q15
422 : }
423 :
424 1091897 : return ener;
425 : }
426 :
427 : /*-------------------------------------------------------------------*
428 : * corr_xy1()
429 : *
430 : * Find the correlations between the target xn[] and the filtered adaptive
431 : * codebook excitation y1[]. ( <y1,y1> and -2<xn,y1> )
432 : *-------------------------------------------------------------------*/
433 :
434 1167461 : Word16 corr_xy1_fx( /* o : pitch gain (0..GAIN_PIT_MAX) */
435 : const Word16 xn_1[], /* i : target signal Q_new*/
436 : const Word16 y1_1[], /* i : filtered adaptive codebook excitation 12 bits*/
437 : Word16 g_corr[], /* o : correlations <y1,y1> and -2<xn,y1> mant/exp*/
438 : const Word16 L_subfr, /* i : vector length */
439 : const Word16 norm_flag /* i : flag for constraining pitch contribution */
440 : ,
441 : Flag *Overflow_out /* o : propagating the Overflow flag to upper level */
442 : )
443 : {
444 : Word16 i;
445 : Word16 tmp, xx, xy, yy, exp_xy, exp_xx, exp_yy, exp_div, gain, gain_p_snr;
446 : Word32 Ltmp1, Ltmp2;
447 : Word16 xn[L_FRAME16k], y1[L_FRAME16k];
448 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
449 1167461 : Flag Overflow = 0;
450 : #endif
451 :
452 : /*----------------------------------------------------------------*
453 : * Find the ACELP correlations and the pitch gain
454 : *----------------------------------------------------------------*/
455 :
456 : /* Compute scalar product <y1[],y1[]> */
457 1167461 : Copy( xn_1, xn, L_subfr ); // Q_new
458 1167461 : Copy( y1_1, y1, L_subfr );
459 1167461 : Overflow = 0;
460 1167461 : move16();
461 1167461 : Ltmp1 = Dot_product12_o( y1, y1, L_subfr, &exp_yy, &Overflow );
462 1167461 : *Overflow_out |= Overflow;
463 1167461 : move16();
464 1167461 : IF( Overflow )
465 : {
466 82008 : FOR( i = 0; i < L_subfr; i++ )
467 : {
468 80896 : xn[i] = mult_r( xn_1[i], 4096 /*0.125.Q15*/ ); // Q-new
469 80896 : move16();
470 80896 : y1[i] = mult_r( y1_1[i], 4096 /*0.125.Q15*/ );
471 80896 : move16();
472 : }
473 :
474 1112 : Ltmp1 = Dot_product12( y1, y1, L_subfr, &exp_yy );
475 1112 : exp_yy = add( exp_yy, 6 );
476 1112 : yy = extract_h( Ltmp1 );
477 :
478 : /* Compute scalar product <xn[],y1[]> */
479 1112 : Ltmp2 = Dot_product12( xn, y1, L_subfr, &exp_xy );
480 1112 : xy = extract_h( Ltmp2 );
481 1112 : exp_xy = add( exp_xy, 6 );
482 :
483 1112 : g_corr[0] = yy;
484 1112 : move16();
485 1112 : g_corr[1] = exp_yy;
486 1112 : move16();
487 : /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function */
488 1112 : g_corr[2] = xy;
489 1112 : move16();
490 1112 : g_corr[3] = exp_xy;
491 1112 : move16();
492 : }
493 : ELSE
494 : {
495 1166349 : yy = extract_h( Ltmp1 ); // exp_yy
496 : /* Ltmp1 = L_shr(Ltmp1, sub(30, exp_yy));*/
497 :
498 : /* Compute scalar product <xn[],y1[]> */
499 1166349 : Ltmp2 = Dot_product12_o( xn, y1, L_subfr, &exp_xy, &Overflow );
500 1166349 : *Overflow_out |= Overflow;
501 1166349 : move16();
502 1166349 : xy = extract_h( Ltmp2 );
503 : /* Ltmp2 = L_shr(Ltmp2, sub(30, exp_xy));*/
504 :
505 1166349 : g_corr[0] = yy;
506 1166349 : move16();
507 1166349 : g_corr[1] = exp_yy;
508 1166349 : move16();
509 : /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function*/
510 1166349 : g_corr[2] = xy; // exp_xy
511 1166349 : move16();
512 1166349 : g_corr[3] = exp_xy;
513 1166349 : move16();
514 : }
515 :
516 : /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */
517 1167461 : test();
518 1167461 : IF( xy >= 0 && NE_16( s_or( yy, xy ), 16384 ) )
519 : {
520 : /* compute gain = xy/yy */
521 1114458 : xy = shr( xy, 1 ); /* be sure that xy < yy */
522 1114458 : gain = div_s( xy, yy ); // Q15
523 1114458 : i = sub( exp_xy, exp_yy );
524 1114458 : gain = shl_o( gain, i, &Overflow ); /* saturation can occur here */
525 1114458 : *Overflow_out |= Overflow;
526 1114458 : move16();
527 :
528 1114458 : gain = s_max( gain, 0 );
529 1114458 : gain = s_min( gain, GAIN_PIT_MAX ); /* 1.2 in Q14 */
530 : }
531 : ELSE
532 : {
533 53003 : gain = 0;
534 53003 : move16();
535 : }
536 :
537 : /* Limit the energy of pitch contribution */
538 1167461 : IF( norm_flag )
539 : {
540 : /*that part of code seems never used*/
541 : /* Compute scalar product <xn[],xn[]> */
542 0 : xx = round_fx( Dot_product12_offs( xn, xn, L_subfr, &exp_xx, 1 ) );
543 :
544 : /* gain_p_snr = sqrt(<xn,xn>/<y1,y1>) */
545 0 : tmp = BASOP_Util_Divide1616_Scale( xx, yy, &exp_div );
546 0 : exp_xx = add( sub( exp_xx, exp_yy ), exp_div );
547 0 : tmp = Sqrt16( tmp, &exp_xx ); // exp_xx
548 :
549 : /* Note: shl works as shl or shr. */
550 0 : exp_xx = sub( exp_xx, 1 );
551 : BASOP_SATURATE_WARNING_OFF_EVS
552 0 : gain_p_snr = round_fx_sat( L_shl_sat( Mpy_32_16_1( 1717986944l /*ACELP_GAINS_CONST Q31*/, tmp ), exp_xx ) );
553 : BASOP_SATURATE_WARNING_ON_EVS
554 :
555 0 : gain = s_min( gain, gain_p_snr ); // Q14
556 : }
557 :
558 1167461 : return gain; // Q14
559 : }
|