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"
6 : #include "prot_fx.h"
7 : #include "basop_util.h"
8 : #include "rom_dec.h"
9 : #include "rom_com.h"
10 : #include "cnst.h"
11 : #define FORMAT_POST_FILT_G1 24576 /*0.75f Q15*/ /*0.75f*/ /*denominator 0.9,0.75,0.15,0.9*/
12 : #define FORMAT_POST_FILT_G2 22938 /*0.7f Q15*/ /*0.7f*/ /*numerator 0.75,0.7,0.1,0.7*/
13 : #define FORMAT_POST_FILT_G1_MAX 26214 /*0.8f Q15*/ /*for low bit-rates on clean speech*/
14 : #define FORMAT_POST_FILT_G1_MIN 24576 /*0.75f Q15*/ /*for high bit-rates on clean speech and noisy speech*/
15 :
16 : /*--------------------------------------------------------------------------
17 : * Local function prototypes
18 : *--------------------------------------------------------------------------*/
19 :
20 : static void Dec_postfilt_fx( PFSTAT_HANDLE hPFstat, const Word16 t0, const Word16 *signal_ptr, const Word16 *coeff, Word16 *sig_out, const Word16 gamma1, const Word16 gamma2, const Word16 Gain_factor, const Word16 disable_hpf );
21 :
22 : static void pst_ltp_fx( Word16 t0, Word16 *ptr_sig_in, Word16 *ptr_sig_pst0, Word16 gain_factor );
23 :
24 : static void search_del_fx( Word16 t0, Word16 *ptr_sig_in, Word16 *ltpdel, Word16 *phase, Word16 *num_gltp, Word16 *den_gltp, Word16 *sh_num_gltp, Word16 *sh_den_gltp, Word16 *y_up, Word16 *off_yup );
25 :
26 : static void filt_plt_fx( Word16 *s_in, Word16 *s_ltp, Word16 *s_out, Word16 gain_plt );
27 :
28 : static void compute_ltp_l_fx( Word16 *s_in, Word16 ltpdel, Word16 phase, Word16 *y_up, Word16 *num, Word16 *den, Word16 *sh_num, Word16 *sh_den );
29 :
30 : static Word16 select_ltp_fx( Word16 num1, Word16 den1, Word16 sh_num1, Word16 sh_den1, Word16 num2, Word16 den2, Word16 sh_num2, Word16 sh_den2 );
31 :
32 : static void calc_st_filt_local_fx( Word16 *apond2, Word16 *apond1, Word16 *parcor0, Word16 *sig_ltp_ptr, Word16 *mem_zero );
33 :
34 : static void modify_pst_param_fx( const Word16 lp_noise, Word16 *g1, Word16 *g2, const Word16 coder_type, Word16 *gain_factor );
35 :
36 : static void Dec_formant_postfilt_fx( PFSTAT_HANDLE hPFstat, Word16 *signal_ptr, Word16 *coeff, Word16 *sig_out, Word16 gamma1, Word16 gamma2 );
37 :
38 : static void calc_st_filt_ivas_fx( Word16 *apond2, Word16 *apond1, Word16 *parcor0, Word16 *sig_ltp_ptr, Word16 *mem_zero, const Word16 extl );
39 :
40 :
41 : /*--------------------------------------------------------------------------
42 : * Init_post_filter_fx
43 : *
44 : * post filter initialization
45 : *--------------------------------------------------------------------------*/
46 3256 : void Init_post_filter_fx(
47 : PFSTAT_HANDLE hPFstat /* i : core decoder parameters */
48 : )
49 : {
50 : /* It is off by default */
51 3256 : hPFstat->on = 0;
52 3256 : move16();
53 : /* Reset */
54 3256 : hPFstat->reset = 0;
55 3256 : move16();
56 : /* Initialize arrays and pointers */
57 3256 : set16_fx( hPFstat->mem_pf_in, 0, L_SUBFR );
58 :
59 : /* res2 = A(gamma2) residual */
60 3256 : set16_fx( hPFstat->mem_res2, 0, DECMEM_RES2 );
61 :
62 : /* 1/A(gamma1) memory */
63 3256 : set16_fx( hPFstat->mem_stp, 0, L_SUBFR );
64 :
65 : /* null memory to compute i.r. of A(gamma2)/A(gamma1) */
66 3256 : set16_fx( hPFstat->mem_zero, 0, M );
67 :
68 : /* for gain adjustment */
69 3256 : hPFstat->gain_prec = 16384; /*Q14*/
70 3256 : move16();
71 :
72 3256 : return;
73 : }
74 :
75 : /*--------------------------------------------------------------------------
76 : * NB_post_filt:
77 : *
78 : * Main routine to perform post filtering on NB synthesis
79 : *--------------------------------------------------------------------------*/
80 2076 : void nb_post_filt_fx(
81 : const Word16 L_frame, /* i : frame length */
82 : PFSTAT_HANDLE hPFstat, /* i : core decoder parameters */
83 : Word16 *psf_lp_noise, /* i : Long term noise Q8 */
84 : const Word16 tmp_noise, /* i : noise energy Q0 */
85 : Word16 *Synth, /* i : 12k8 synthesis Qsyn */
86 : const Word16 *Aq, /* i : LP filter coefficient Q12 */
87 : const Word16 *Pitch_buf, /* i : Fractionnal subframe pitch buffer Q0 */
88 : const Word16 coder_type, /* i : coder_type */
89 : const Word16 BER_detect, /* i : BER detect flag */
90 : const Word16 disable_hpf /* i : flag to diabled HPF */
91 : )
92 : {
93 : Word16 i, j, Post_G1, Post_G2, Gain_factor;
94 : Word16 T0_first, *Pf_in;
95 : const Word16 *p_Aq;
96 : Word16 pf_in_buffer[M + L_FRAME16k];
97 :
98 2076 : IF( BER_detect == 0 )
99 : {
100 : /* update long-term background noise energy during inactive frames */
101 2076 : IF( EQ_16( coder_type, INACTIVE ) )
102 : {
103 0 : *psf_lp_noise = round_fx( L_mac( L_mult( 31130 /*0.95.Q15*/, *psf_lp_noise ), 26214 /*0.05 Q19*/, shl( tmp_noise, 4 ) ) ); /*Q8*Q15 + Q19*Q4 -> Q8 */
104 : }
105 : }
106 :
107 2076 : modify_pst_param_fx( *psf_lp_noise, &Post_G1, &Post_G2, coder_type, &Gain_factor );
108 :
109 2076 : IF( hPFstat->reset )
110 : {
111 2076 : set16_fx( hPFstat->mem_res2, 0, DECMEM_RES2 );
112 2076 : Copy( &Synth[L_frame - L_SYN_MEM], hPFstat->mem_pf_in, L_SYN_MEM ); // Qsyn
113 2076 : Copy( &Synth[L_frame - L_SYN_MEM], hPFstat->mem_stp, L_SYN_MEM );
114 2076 : hPFstat->gain_prec = 16384; // 1.Q14
115 2076 : move16();
116 2076 : hPFstat->reset = 0;
117 2076 : move16();
118 2076 : return;
119 : }
120 0 : Pf_in = &pf_in_buffer[M];
121 0 : Copy( hPFstat->mem_pf_in + L_SYN_MEM - M, &Pf_in[-M], M ); // Qsyn
122 0 : Copy( Synth, Pf_in, L_frame ); // Qsyn
123 0 : Copy( &Synth[L_frame - L_SYN_MEM], hPFstat->mem_pf_in, L_SYN_MEM );
124 : /* deactivation of the post filter in case of AUDIO because it causes problems to singing sequences */
125 0 : IF( EQ_16( coder_type, AUDIO ) )
126 : {
127 0 : Post_G1 = 32767;
128 0 : move16();
129 0 : Post_G2 = 32767;
130 0 : move16();
131 0 : Gain_factor = 32767;
132 0 : move16();
133 : }
134 :
135 :
136 : /* run the post filter */
137 0 : p_Aq = Aq; // Q12
138 0 : move16();
139 0 : j = 0;
140 0 : move16();
141 0 : FOR( i = 0; i < L_frame; i += L_SUBFR )
142 : {
143 0 : T0_first = Pitch_buf[j]; // Q0
144 0 : move16();
145 0 : Dec_postfilt_fx( hPFstat, T0_first, &Pf_in[i], p_Aq, &Synth[i], Post_G1, Post_G2, Gain_factor, disable_hpf );
146 :
147 0 : p_Aq += ( M + 1 );
148 0 : j = add( j, 1 );
149 : }
150 :
151 :
152 0 : return;
153 : }
154 :
155 : /*----------------------------------------------------------------------------
156 : * Dec_postfilt()
157 : *
158 : * Post - adaptive postfilter main function
159 : * Short term postfilter :
160 : * Hst(z) = Hst0(z) Hst1(z)
161 : * Hst0(z) = 1/g0 A(gamma2)(z) / A(gamma1)(z)
162 : * if {hi} = i.r. filter A(gamma2)/A(gamma1) (truncated)
163 : * g0 = SUM(|hi|) if > 1
164 : * g0 = 1. else
165 : * Hst1(z) = 1/(1 - |mu|) (1 + mu z-1)
166 : * with mu = k1 * gamma3
167 : * k1 = 1st parcor calculated on {hi}
168 : * gamma3 = gamma3_minus if k1<0, gamma3_plus if k1>0
169 : * Long term postfilter :
170 : * harmonic postfilter : H0(z) = gl * (1 + b * z-p)
171 : * b = gamma_g * gain_ltp
172 : * gl = 1 / 1 + b
173 : * computation of delay p on A(gamma2)(z) s(z)
174 : * sub optimal search
175 : * 1. search around 1st subframe delay (3 integer values)
176 : * 2. search around best integer with fract. delays (1/8)
177 : *----------------------------------------------------------------------------*/
178 0 : static void Dec_postfilt_fx(
179 : PFSTAT_HANDLE hPFstat, /* i : core decoder parameters */
180 : const Word16 t0, /* i : pitch delay given by coder Q0 */
181 : const Word16 *signal_ptr, /* i : input signal (pointer to current subframe Q0 */
182 : const Word16 *coeff, /* i : LPC coefficients for current subframe Q12 */
183 : Word16 *sig_out, /* o : postfiltered output Q15*/
184 : const Word16 gamma1, /* i : short term postfilt. den. weighting factor Q15*/
185 : const Word16 gamma2, /* i : short term postfilt. num. weighting factor Q15*/
186 : const Word16 Gain_factor, /* i : Gain Factor (Q15) */
187 : const Word16 disable_hpf )
188 : {
189 : /* Local variables and arrays */
190 : Word16 apond1[M + 1]; /* s.t. denominator coeff. Q12*/
191 : Word16 apond2[LONG_H_ST]; // Q12
192 : Word16 sig_ltp[L_SUBFR + 1]; /* H0 output signal */
193 : Word16 res2[SIZ_RES2]; // Q0
194 :
195 : Word16 *sig_ltp_ptr;
196 : Word16 *res2_ptr;
197 : Word16 *ptr_mem_stp;
198 :
199 : Word16 parcor0; // Q15
200 :
201 :
202 : /* Init pointers and restore memories */
203 0 : res2_ptr = res2 + DECMEM_RES2;
204 0 : ptr_mem_stp = hPFstat->mem_stp + L_SYN_MEM - 1;
205 0 : Copy( hPFstat->mem_res2, res2, DECMEM_RES2 );
206 :
207 : /* Compute weighted LPC coefficients */
208 0 : weight_a_fx( coeff, apond1, gamma1, M );
209 0 : weight_a_fx( coeff, apond2, gamma2, M );
210 0 : set16_fx( &apond2[M + 1], 0, LONG_H_ST - ( M + 1 ) );
211 :
212 : /* Compute A(gamma2) residual */
213 0 : Residu3_fx( apond2, signal_ptr, res2_ptr, L_SUBFR, 1 );
214 :
215 : /* Harmonic filtering */
216 0 : sig_ltp_ptr = sig_ltp + 1;
217 :
218 0 : IF( disable_hpf == 0 )
219 : {
220 0 : pst_ltp_fx( t0, res2_ptr, sig_ltp_ptr, Gain_factor );
221 : }
222 : ELSE
223 : {
224 0 : Copy( res2_ptr, sig_ltp_ptr, L_SUBFR );
225 : }
226 :
227 : /* Save last output of 1/A(gamma1) */
228 : /* (from preceding subframe) */
229 0 : sig_ltp[0] = *ptr_mem_stp;
230 0 : move16();
231 :
232 : /* Controls short term pst filter gain and compute parcor0 */
233 0 : calc_st_filt_local_fx( apond2, apond1, &parcor0, sig_ltp_ptr, hPFstat->mem_zero );
234 :
235 0 : E_UTIL_synthesis( 1, apond1, sig_ltp_ptr, sig_ltp_ptr, L_SUBFR, hPFstat->mem_stp + L_SYN_MEM - M, 0, M );
236 0 : Copy( sig_ltp_ptr + L_SUBFR - L_SYN_MEM, hPFstat->mem_stp, L_SYN_MEM );
237 :
238 : /* Tilt filtering */
239 0 : Filt_mu_fx( sig_ltp, sig_out, parcor0, L_SUBFR );
240 :
241 : /* Gain control */
242 0 : scale_st_fx( signal_ptr, sig_out, &hPFstat->gain_prec, L_SUBFR );
243 :
244 : /* Update for next subframe */
245 0 : Copy( &res2[L_SUBFR], hPFstat->mem_res2, DECMEM_RES2 );
246 :
247 :
248 0 : return;
249 : }
250 :
251 : /*--------------------------------------------------------------------------
252 : * formant_post_filt_fx:
253 : *
254 : * Main routine to perform formant post filtering
255 : *--------------------------------------------------------------------------*/
256 :
257 258774 : void formant_post_filt_fx(
258 : PFSTAT_HANDLE hPFstat, /* i : core decoder parameters */
259 : Word16 *synth_in, /* i : 12k8 synthesis */
260 : Word16 *Aq, /* i : LP filter coefficient Q12 */
261 : Word16 *synth_out, /* i/o: input signal */
262 : const Word16 L_frame, /* i : frame length */
263 : const Word32 lp_noise, /* (i) : background noise energy (15Q16) */
264 : const Word32 brate, /* (i) : bit-rate */
265 : const Word16 off_flag /* i : off flag */
266 : )
267 : {
268 : Word16 i_subfr;
269 : Word16 *p_Aq;
270 : Word16 post_G1, post_G2;
271 :
272 : /*default parameter for noisy speech and high bit-rates*/
273 258774 : IF( EQ_16( L_frame, L_FRAME ) )
274 : {
275 126131 : post_G2 = 22938 /*0.7f Q15*/;
276 126131 : move16();
277 126131 : IF( LT_32( lp_noise, LP_NOISE_THRESH ) )
278 : {
279 : /*Clean speech*/
280 106288 : IF( LT_32( brate, ACELP_13k20 ) )
281 : {
282 : /*Low rates*/
283 :
284 69531 : post_G1 = 26214 /*0.8f Q15*/;
285 69531 : move16();
286 : }
287 36757 : ELSE IF( LT_32( brate, ACELP_24k40 ) )
288 : {
289 : /*Low rates*/
290 :
291 36757 : post_G1 = 24576 /*0.75f Q15*/;
292 36757 : move16();
293 : }
294 : ELSE
295 : {
296 0 : post_G1 = 23593 /*0.72f Q15*/;
297 0 : move16();
298 : }
299 : }
300 : ELSE /*Noisy speech*/
301 : {
302 19843 : post_G1 = 22938 /*0.7f Q15*/;
303 19843 : move16();
304 19843 : if ( LT_32( brate, ACELP_15k85 ) )
305 : {
306 : /*Low rates*/
307 18565 : post_G1 = 24576 /*0.75f Q15*/;
308 18565 : move16();
309 : }
310 : }
311 : }
312 : ELSE
313 : {
314 132643 : post_G2 = 24904 /*0.76f Q15*/;
315 132643 : move16();
316 132643 : test();
317 132643 : IF( GE_32( lp_noise, LP_NOISE_THRESH ) )
318 : {
319 16151 : post_G1 = 24904 /*0.76f Q15*/;
320 : }
321 116492 : ELSE IF( EQ_32( brate, ACELP_13k20 ) )
322 : {
323 0 : post_G1 = 26870 /*0.82f Q15*/;
324 0 : move16();
325 : }
326 116492 : ELSE IF( EQ_32( brate, ACELP_16k40 ) )
327 : {
328 190 : post_G1 = 26214 /*0.80f Q15*/;
329 190 : move16();
330 : }
331 116302 : ELSE IF( EQ_32( brate, ACELP_24k40 ) || EQ_32( brate, ACELP_32k ) )
332 : {
333 1454 : post_G1 = 25559 /*0.78f Q15*/;
334 1454 : move16();
335 : }
336 : ELSE
337 : {
338 114848 : post_G1 = 24904 /*0.76f Q15*/;
339 114848 : move16();
340 : }
341 : }
342 :
343 : /* Switch off post-filter */
344 258774 : if ( off_flag != 0 )
345 : {
346 0 : post_G1 = post_G2;
347 0 : move16();
348 : }
349 :
350 : /* Reset post filter */
351 258774 : IF( hPFstat->reset != 0 )
352 : {
353 108110 : post_G1 = MAX16B;
354 108110 : move16();
355 108110 : post_G2 = MAX16B;
356 108110 : move16();
357 108110 : hPFstat->reset = 0;
358 108110 : move16();
359 108110 : Copy( &synth_in[L_frame - L_SYN_MEM], hPFstat->mem_pf_in, L_SYN_MEM );
360 108110 : Copy( &synth_in[L_frame - L_SYN_MEM], hPFstat->mem_stp, L_SYN_MEM );
361 108110 : hPFstat->gain_prec = 16384; // 1.Q14
362 108110 : move16();
363 108110 : Copy( synth_in, synth_out, L_frame );
364 :
365 108110 : return;
366 : }
367 :
368 : /* input memory*/
369 150664 : Copy( hPFstat->mem_pf_in, synth_in - L_SYN_MEM, L_SYN_MEM );
370 150664 : Copy( &synth_in[L_frame - L_SYN_MEM], hPFstat->mem_pf_in, L_SYN_MEM );
371 :
372 150664 : move16();
373 150664 : p_Aq = Aq; // Q12
374 823504 : FOR( i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR )
375 : {
376 672840 : Dec_formant_postfilt_fx( hPFstat, &synth_in[i_subfr], p_Aq, &synth_out[i_subfr], post_G1, post_G2 );
377 672840 : p_Aq += ( M + 1 );
378 : }
379 :
380 150664 : return;
381 : }
382 :
383 :
384 : /*----------------------------------------------------------------------------
385 : * Dec_formant_postfilt_fx()
386 : *
387 : * Post - adaptive postfilter main function
388 : * Short term postfilter :
389 : * Hst(z) = Hst0(z) Hst1(z)
390 : * Hst0(z) = 1/g0 A(gamma2)(z) / A(gamma1)(z)
391 : * if {hi} = i.r. filter A(gamma2)/A(gamma1) (truncated)
392 : * g0 = SUM(|hi|) if > 1
393 : * g0 = 1. else
394 : * Hst1(z) = 1/(1 - |mu|) (1 + mu z-1)
395 : * with mu = k1 * gamma3
396 : * k1 = 1st parcor calculated on {hi}
397 : * gamma3 = gamma3_minus if k1<0, gamma3_plus if k1>0
398 : *----------------------------------------------------------------------------*/
399 :
400 672840 : static void Dec_formant_postfilt_fx(
401 : PFSTAT_HANDLE hPFstat, /* i : core decoder parameters */
402 : Word16 *signal_ptr, /* i : input signal (pointer to current subframe Q14*/
403 : Word16 *coeff, /* i : LPC coefficients for current subframe Q12 */
404 : Word16 *sig_out, /* o : postfiltered output */
405 : Word16 gamma1, /* i : short term postfilt. den. weighting factor Q15*/
406 : Word16 gamma2 /* i : short term postfilt. num. weighting factor Q15*/
407 : )
408 : {
409 : /* Local variables and arrays */
410 : Word16 apond1[M + 1]; /* s.t. denominator coeff. Q12*/
411 : Word16 apond2[LONG_H_ST]; // Q12
412 : Word16 res2[L_SUBFR]; // Q14
413 : Word16 resynth[L_SUBFR + 1]; // Qy
414 : Word16 parcor0; // Q15
415 : Word16 i, max;
416 : Word16 scale_down;
417 :
418 : /* Compute weighted LPC coefficients */
419 672840 : weight_a_fx( coeff, apond1, gamma1, M );
420 672840 : weight_a_fx( coeff, apond2, gamma2, M );
421 672840 : set16_fx( &apond2[M + 1], 0, LONG_H_ST - ( M + 1 ) );
422 :
423 672840 : max = abs_s( signal_ptr[0] ); // Q14
424 43061760 : FOR( i = 1; i < L_SUBFR; i++ )
425 : {
426 42388920 : max = s_max( max, abs_s( signal_ptr[i] ) );
427 : }
428 672840 : scale_down = 0;
429 672840 : move16();
430 672840 : if ( GT_16( max, 16384 /*1.Q14*/ ) )
431 : {
432 646 : scale_down = 1;
433 646 : move16();
434 : }
435 :
436 : /* Compute A(gamma2) residual */
437 672840 : IF( !scale_down )
438 : {
439 672194 : Residu3_fx( apond2, signal_ptr, res2, L_SUBFR, 1 );
440 : }
441 : ELSE
442 : {
443 646 : Residu3_fx( apond2, signal_ptr, res2, L_SUBFR, 0 );
444 646 : Scale_sig( hPFstat->mem_stp, L_SYN_MEM, -1 );
445 : }
446 :
447 : /* Controls short term pst filter gain and compute parcor0 */
448 672840 : calc_st_filt_ivas_fx( apond2, apond1, &parcor0, res2, hPFstat->mem_zero, -1 );
449 :
450 : /* 1/A(gamma1) filtering, mem_stp is updated */
451 672840 : resynth[0] = *( hPFstat->mem_stp + sub( L_SYN_MEM, 1 ) );
452 672840 : move16();
453 :
454 672840 : E_UTIL_synthesis( 1, apond1, res2, &( resynth[1] ), L_SUBFR, hPFstat->mem_stp + L_SYN_MEM - M, 0, M );
455 :
456 672840 : IF( !scale_down )
457 : {
458 672194 : Copy( &( resynth[1] ) + L_SUBFR - L_SYN_MEM, hPFstat->mem_stp, L_SYN_MEM );
459 : }
460 : ELSE
461 : {
462 646 : Copy_Scale_sig( &( resynth[1] ) + L_SUBFR - L_SYN_MEM, hPFstat->mem_stp, L_SYN_MEM, 1 );
463 : }
464 :
465 : /* Tilt filtering */
466 672840 : Filt_mu_ivas_fx( resynth, sig_out, parcor0, L_SUBFR, -1 );
467 672840 : IF( scale_down )
468 : {
469 646 : Scale_sig( sig_out, L_SUBFR, 1 );
470 : }
471 :
472 : /* Gain control */
473 672840 : scale_st_fx( signal_ptr, sig_out, &hPFstat->gain_prec, L_SUBFR );
474 :
475 :
476 672840 : return;
477 : }
478 :
479 : /*------------------------------------------------------------------------------------
480 : * modify_pst_param()
481 : *
482 : * Modify gamma1 and gamma2 values in function of the long term noise level
483 : *-----------------------------------------------------------------------------------*/
484 :
485 2076 : static void modify_pst_param_fx(
486 : const Word16 lp_noise, /* i : Long term noise energy Q8 */
487 : Word16 *g1, /* o : Gamma1 used in post filter Q15 */
488 : Word16 *g2, /* o : Gamma1 used in post filter Q15 */
489 : const Word16 coder_type, /* i : Vad information decoded in UV frame */
490 : Word16 *gain_factor /* o : Gain factor applied in post filtering Q15 */
491 : )
492 : {
493 : Word16 tmp;
494 : Word16 lp_noiseQ12;
495 : Word32 L_tmp;
496 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
497 2076 : Flag Overflow = 0;
498 2076 : move16();
499 : #endif
500 :
501 :
502 2076 : test();
503 2076 : IF( NE_16( coder_type, INACTIVE ) && LT_16( lp_noise, LP_NOISE_THR_FX ) )
504 : {
505 2076 : lp_noiseQ12 = shl_o( lp_noise, 4, &Overflow ); /* to go from Q8 to Q12 */
506 :
507 : /* ftmp = lp_noise*BG1_FX + CG1_FX */
508 2076 : tmp = mac_r( CG1_FX * 65536L, lp_noiseQ12, BG1_FX * 8 ); /* x8 to go from Q12 to Q15 */
509 2076 : tmp = s_min( tmp, POST_G1_FX );
510 2076 : tmp = s_max( tmp, GAMMA1_PST12K_MIN_FX );
511 :
512 2076 : *g1 = tmp;
513 2076 : move16();
514 :
515 : /* ftmp = lp_noise*BG2_FX + CG2_FX */
516 2076 : L_tmp = L_mac0( CG2_FX / 2 * 65536L, lp_noiseQ12, BG2_FX * 8 ); /* L_mac0 and /2 to go from Q12 to Q14 */
517 : /* we go to Q30 to avoid overflow CG2_FX*/
518 :
519 2076 : L_tmp = L_min( L_tmp, POST_G2_FX * 65536L / 2 ); /* /2 because L_tmp is Q30 */
520 2076 : L_tmp = L_max( L_tmp, GAMMA2_PST12K_MIN_FX * 65536L / 2 );
521 :
522 2076 : *g2 = extract_h( L_shl( L_tmp, 1 ) ); /* Q30=>Q31=>Q15 */
523 : }
524 : ELSE
525 : {
526 0 : *g1 = GAMMA1_PST12K_NOIS_FX;
527 0 : move16();
528 0 : *g2 = GAMMA2_PST12K_NOIS_FX;
529 0 : move16();
530 : }
531 :
532 : /* Set gain_factor of the harmonic filtering*/
533 : /* ftmp = (lp_noise - K_LP_NOISE)*C_LP_NOISE_FX */
534 2076 : L_tmp = L_mac( -CK_LP_NOISE_FX, lp_noise, C_LP_NOISE_FX ); /* tmp is in Q24 (from Q8) */
535 :
536 2076 : L_tmp = L_min( L_tmp, 64 * 65536L ); /* 0.25 in Q24 */
537 2076 : L_tmp = L_max( L_tmp, 0 );
538 :
539 2076 : *gain_factor = extract_h( L_shl( L_tmp, 7 ) ); /* Q24=>Q31=>Q15 */
540 :
541 :
542 2076 : return;
543 : }
544 :
545 : /*----------------------------------------------------------------------------
546 : * pst_ltp_fx
547 : *
548 : * Perform harmonic postfilter
549 : *----------------------------------------------------------------------------*/
550 0 : static void pst_ltp_fx(
551 : Word16 t0, /* i : pitch delay given by coder Q0 */
552 : Word16 *ptr_sig_in, /* i : postfilter i filter (residu2) Qx */
553 : Word16 *ptr_sig_pst0, /* o : harmonic postfilter o Qx */
554 : Word16 gain_factor /* i : Gain Factor (Q15) */
555 : )
556 : {
557 : Word32 L_temp;
558 :
559 : Word16 y_up[SIZ_Y_UP];
560 : Word16 sig_cadr[SIZ_RES2];
561 :
562 : Word16 *ptr_y_up;
563 : Word16 *ptr_sig;
564 : Word16 *ptr_sig_cadr;
565 :
566 : Word16 i;
567 : Word16 temp;
568 : Word16 ltpdel, phase;
569 : Word16 num_gltp, den_gltp;
570 : Word16 num2_gltp, den2_gltp;
571 : Word16 sh_num, sh_den;
572 : Word16 sh_num2, sh_den2;
573 : Word16 gain_plt;
574 : Word16 off_yup;
575 : Word16 nb_sh_sig;
576 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
577 0 : Flag Overflow = 0;
578 0 : move16();
579 : #endif
580 :
581 :
582 : /* i signal justified on 13 bits */
583 0 : ptr_sig = ptr_sig_in - DECMEM_RES2; // Qx
584 0 : nb_sh_sig = getScaleFactor16( ptr_sig, DECMEM_RES2 + L_SUBFR );
585 0 : nb_sh_sig = sub( 3, nb_sh_sig );
586 :
587 0 : FOR( i = 0; i < DECMEM_RES2 + L_SUBFR; i++ )
588 : {
589 : /* nb_sh_sig may be >0, <0 or =0 */
590 0 : sig_cadr[i] = shr( ptr_sig[i], nb_sh_sig );
591 0 : move16();
592 : }
593 0 : ptr_sig_cadr = sig_cadr + DECMEM_RES2;
594 :
595 : /* Sub optimal delay search */
596 0 : search_del_fx( t0, ptr_sig_cadr, <pdel, &phase, &num_gltp, &den_gltp, &sh_num, &sh_den, y_up, &off_yup );
597 :
598 :
599 0 : IF( num_gltp == 0 )
600 : {
601 0 : Copy( ptr_sig_in, ptr_sig_pst0, L_SUBFR );
602 : }
603 : ELSE
604 : {
605 0 : IF( phase == 0 )
606 : {
607 0 : ptr_y_up = ptr_sig_in - ltpdel; // Qx
608 : }
609 : ELSE
610 : {
611 : /* Filtering with long filter */
612 0 : compute_ltp_l_fx( ptr_sig_cadr, ltpdel, phase, ptr_sig_pst0, &num2_gltp, &den2_gltp, &sh_num2, &sh_den2 );
613 :
614 :
615 0 : IF( EQ_16( select_ltp_fx( num_gltp, den_gltp, sh_num, sh_den, num2_gltp, den2_gltp, sh_num2, sh_den2 ), 1 ) )
616 : {
617 : /* select short filter */
618 0 : temp = sub( phase, 1 );
619 0 : L_temp = L_mult0( temp, L_SUBFR + 1 );
620 0 : temp = extract_l( L_temp );
621 0 : temp = add( temp, off_yup );
622 :
623 : /* ptr_y_up = y_up + (phase-1) * (L_SUBFR+1) + off_yup */
624 0 : ptr_y_up = y_up + temp;
625 : }
626 : ELSE
627 : {
628 : /* select long filter */
629 0 : num_gltp = num2_gltp;
630 0 : move16();
631 0 : den_gltp = den2_gltp;
632 0 : move16();
633 0 : sh_num = sh_num2;
634 0 : move16();
635 0 : sh_den = sh_den2;
636 0 : move16();
637 0 : ptr_y_up = ptr_sig_pst0;
638 : }
639 :
640 : /* rescale y_up */
641 0 : FOR( i = 0; i < L_SUBFR; i++ )
642 : {
643 : /* nb_sh_sig may be >0, <0 or =0 */
644 0 : ptr_y_up[i] = shl_sat( ptr_y_up[i], nb_sh_sig );
645 0 : move16();
646 : }
647 : }
648 :
649 0 : temp = sub( sh_num, sh_den );
650 0 : IF( temp >= 0 )
651 : {
652 0 : den_gltp = shr( den_gltp, temp );
653 : }
654 : ELSE
655 : {
656 0 : num_gltp = shl( num_gltp, temp ); /* >> (-temp) */
657 : }
658 0 : IF( GE_16( num_gltp, den_gltp ) )
659 : {
660 : /* beta bounded to 1 */
661 0 : gain_plt = MIN_GPLT_FX;
662 0 : move16();
663 : }
664 : ELSE
665 : {
666 : /* GAMMA_G = 0.5 */
667 : /* gain_plt = den_gltp x 2**15 / (den_gltp + 0.5 num_gltp) */
668 : /* shift 1 bit to avoid overflows in add */
669 0 : num_gltp = shr( num_gltp, 2 );
670 0 : den_gltp = shr( den_gltp, 1 );
671 0 : temp = add( den_gltp, num_gltp );
672 0 : gain_plt = div_s( den_gltp, temp ); /* Q15 */
673 : }
674 :
675 : /* decrease gain in noisy condition */
676 : /* gain_plt += (1.0f-gain_plt) * gain_factor */
677 : /* gain_plt = gain_plt + gain_factor - gain_plt*gain_factor */
678 0 : gain_plt = msu_ro( L_msu( L_deposit_h( gain_plt ), gain_plt, gain_factor ), -32768, gain_factor, &Overflow ); // Q15
679 :
680 : /** filtering by H0(z) = harmonic filter **/
681 0 : filt_plt_fx( ptr_sig_in, ptr_y_up, ptr_sig_pst0, gain_plt );
682 : }
683 0 : }
684 :
685 : /*----------------------------------------------------------------------------
686 : * search_del_fx:
687 : *
688 : * Computes best (shortest) integer LTP delay + fine search
689 : *---------------------------------------------------------------------------*/
690 0 : static void search_del_fx(
691 : Word16 t0, /* i : pitch delay given by coder Q0 */
692 : Word16 *ptr_sig_in, /* i : i signal (with delay line) */
693 : Word16 *ltpdel, /* o : delay = *ltpdel - *phase / f_up */
694 : Word16 *phase, /* o : phase */
695 : Word16 *num_gltp, /* o : 16 bits numerator of LTP gain Q(sh_num_gltp) */
696 : Word16 *den_gltp, /* o : 16 bits denominator of LTP gain Q(sh_den_gltp) */
697 : Word16 *sh_num_gltp, /* o : justification for num_gltp */
698 : Word16 *sh_den_gltp, /* o : justification for den_gltp */
699 : Word16 *y_up, /* o : LT delayed signal if fract. delay */
700 : Word16 *off_yup /* o : offset in y_up */
701 : )
702 : {
703 : Word32 L_den0[F_UP_PST - 1];
704 : Word32 L_den1[F_UP_PST - 1];
705 :
706 : Word32 *ptr_L_den0, *ptr_L_den1;
707 :
708 : Word32 L_num_int, L_den_int, L_den_max;
709 : Word32 L_temp0, L_temp1;
710 : Word32 L_acc;
711 : Word32 L_temp;
712 :
713 : const Word16 *ptr_h;
714 : Word16 *ptr_sig_past, *ptr_sig_past0;
715 : Word16 *ptr1, *ptr_y_up;
716 :
717 : Word16 i, n;
718 : Word16 num /*Q(sh_num)*/, den0 /*Q(sh_den)*/, den1 /*Q(sh_den)*/;
719 : Word16 den_max, num_max;
720 : Word32 L_numsq_max;
721 : Word16 ener; // Q(sh_ener)
722 : Word16 sh_num, sh_den, sh_ener;
723 : Word16 i_max, lambda, phi, phi_max, ioff;
724 : Word16 temp;
725 :
726 :
727 : /*-------------------------------------
728 : * Computes energy of current signal
729 : *-------------------------------------*/
730 :
731 0 : L_acc = L_mult( ptr_sig_in[0], ptr_sig_in[0] );
732 0 : FOR( i = 1; i < L_SUBFR; i++ )
733 : {
734 0 : L_acc = L_mac_sat( L_acc, ptr_sig_in[i], ptr_sig_in[i] );
735 : }
736 0 : IF( L_acc == 0 )
737 : {
738 0 : *num_gltp = 0;
739 0 : move16();
740 0 : *den_gltp = 1;
741 0 : move16();
742 0 : *ltpdel = 0;
743 0 : move16();
744 0 : *phase = 0;
745 0 : move16();
746 :
747 0 : return;
748 : }
749 0 : sh_ener = sub( 16, norm_l( L_acc ) );
750 : /* save energy for final decision */
751 0 : sh_ener = s_max( 0, sh_ener );
752 0 : ener = extract_l( L_shr( L_acc, sh_ener ) );
753 :
754 : /*-------------------------------------
755 : * Selects best of 3 integer delays
756 : * Maximum of 3 numerators around t0
757 : *-------------------------------------*/
758 0 : lambda = sub( t0, 1 );
759 0 : ptr_sig_past = ptr_sig_in - lambda;
760 0 : L_num_int = L_deposit_l( -1 );
761 :
762 : /* initialization used only to suppress Microsoft Visual C++ warnings */
763 0 : i_max = (Word16) 0;
764 0 : move16();
765 :
766 0 : FOR( i = 0; i < 3; i++ )
767 : {
768 0 : L_acc = L_mult( ptr_sig_in[0], ptr_sig_past[0] );
769 0 : FOR( n = 1; n < L_SUBFR; n++ )
770 : {
771 0 : L_acc = L_mac_sat( L_acc, ptr_sig_in[n], ptr_sig_past[n] );
772 : }
773 :
774 :
775 0 : L_acc = L_max( L_acc, 0 );
776 0 : L_temp = L_sub_sat( L_acc, L_num_int );
777 0 : if ( L_temp > 0L )
778 : {
779 0 : i_max = (Word16) i;
780 0 : move16();
781 : }
782 0 : L_num_int = L_max( L_num_int, L_acc );
783 0 : ptr_sig_past--;
784 : }
785 :
786 0 : IF( L_num_int == 0 )
787 : {
788 0 : *num_gltp = 0;
789 0 : move16();
790 0 : *den_gltp = 1;
791 0 : move16();
792 0 : *ltpdel = 0;
793 0 : move16();
794 0 : *phase = 0;
795 0 : move16();
796 :
797 0 : return;
798 : }
799 :
800 : /* Compute den for i_max */
801 0 : lambda = add( lambda, (Word16) i_max );
802 0 : ptr_sig_past = ptr_sig_in - lambda;
803 0 : temp = *ptr_sig_past++;
804 0 : move16();
805 0 : L_acc = L_mult( temp, temp );
806 0 : FOR( i = 1; i < L_SUBFR; i++ )
807 : {
808 0 : temp = *ptr_sig_past++;
809 0 : move16();
810 0 : L_acc = L_mac_sat( L_acc, temp, temp );
811 : }
812 0 : IF( L_acc == 0L )
813 : {
814 0 : *num_gltp = 0;
815 0 : move16();
816 0 : *den_gltp = 1;
817 0 : move16();
818 0 : *ltpdel = 0;
819 0 : move16();
820 0 : *phase = 0;
821 0 : move16();
822 :
823 0 : return;
824 : }
825 0 : L_den_int = L_acc; /* sets to 'L_acc' in 1 clock */
826 0 : move32();
827 :
828 : /*----------------------------------
829 : * Select best phase around lambda
830 : *----------------------------------
831 : * Compute y_up & denominators
832 : *----------------------------------*/
833 :
834 0 : ptr_y_up = y_up;
835 0 : L_den_max = L_den_int; /* sets to 'L_acc' in 1 clock */
836 0 : move32();
837 0 : ptr_L_den0 = L_den0;
838 0 : ptr_L_den1 = L_den1;
839 0 : ptr_h = tab_hup_s_fx;
840 0 : temp = sub( lambda, LH_UP_S - 1 );
841 0 : ptr_sig_past0 = ptr_sig_in - temp;
842 :
843 : /* Loop on phase */
844 0 : FOR( phi = 1; phi < F_UP_PST; phi++ )
845 : {
846 : /* Compute y_up for lambda+1 - phi/F_UP_PST */
847 : /* and lambda - phi/F_UP_PST */
848 :
849 0 : ptr_sig_past = ptr_sig_past0;
850 0 : FOR( n = 0; n <= L_SUBFR; n++ )
851 : {
852 0 : ptr1 = ptr_sig_past++;
853 :
854 0 : L_acc = L_mult( ptr_h[0], ptr1[0] );
855 0 : FOR( i = 1; i < LH2_S; i++ )
856 : {
857 0 : L_acc = L_mac( L_acc, ptr_h[i], ptr1[-i] );
858 : }
859 0 : ptr_y_up[n] = round_fx( L_acc );
860 : }
861 :
862 : /* compute den0 (lambda+1) and den1 (lambda) */
863 :
864 : /* part common to den0 and den1 */
865 0 : L_acc = L_mult( ptr_y_up[1], ptr_y_up[1] );
866 0 : FOR( n = 2; n < L_SUBFR; n++ )
867 : {
868 0 : L_acc = L_mac_sat( L_acc, ptr_y_up[n], ptr_y_up[n] );
869 : }
870 0 : L_temp0 = L_acc; /* sets to 'L_acc' in 1 clock (saved for den1) */
871 0 : move32();
872 :
873 : /* den0 */
874 0 : L_acc = L_mac_sat( L_acc, ptr_y_up[0], ptr_y_up[0] );
875 0 : *ptr_L_den0 = L_acc;
876 0 : move32();
877 :
878 : /* den1 */
879 0 : L_acc = L_mac_sat( L_temp0, ptr_y_up[L_SUBFR], ptr_y_up[L_SUBFR] );
880 0 : *ptr_L_den1 = L_acc;
881 0 : move32();
882 :
883 0 : IF( GT_16( abs_s( ptr_y_up[0] ), abs_s( ptr_y_up[L_SUBFR] ) ) )
884 : {
885 0 : L_den_max = L_max( *ptr_L_den0, L_den_max );
886 : }
887 : ELSE
888 : {
889 0 : L_den_max = L_max( *ptr_L_den1, L_den_max );
890 : }
891 0 : ptr_L_den0++;
892 0 : ptr_L_den1++;
893 0 : ptr_y_up += ( L_SUBFR + 1 );
894 0 : ptr_h += LH2_S;
895 : }
896 :
897 0 : IF( L_den_max == 0 )
898 : {
899 0 : *num_gltp = 0;
900 0 : move16();
901 0 : *den_gltp = 1;
902 0 : move16();
903 0 : *ltpdel = 0;
904 0 : move16();
905 0 : *phase = 0;
906 0 : move16();
907 :
908 0 : return;
909 : }
910 :
911 0 : sh_den = sub( 16, norm_l( L_den_max ) );
912 : /* if sh_den <= 0 : dynamic between current frame */
913 : /* and delay line too high */
914 0 : IF( sh_den <= 0 )
915 : {
916 0 : *num_gltp = 0;
917 0 : move16();
918 0 : *den_gltp = 1;
919 0 : move16();
920 0 : *ltpdel = 0;
921 0 : move16();
922 0 : *phase = 0;
923 0 : move16();
924 :
925 0 : return;
926 : }
927 :
928 : /* search sh_num to justify correlations */
929 : /* sh_num = Max(sh_den, sh_ener) */
930 0 : sh_num = sh_ener;
931 0 : move16();
932 0 : if ( GE_16( sh_den, sh_ener ) )
933 : {
934 0 : sh_num = sh_den;
935 0 : move16();
936 : }
937 :
938 : /* Computation of the numerators */
939 : /* and selection of best num*num/den */
940 : /* for non null phases */
941 :
942 : /* Initialize with null phase */
943 0 : L_acc = L_shr( L_den_int, sh_den ); /* sh_den > 0 */
944 0 : den_max = extract_l( L_acc );
945 0 : L_acc = L_shr( L_num_int, sh_num ); /* sh_num > 0 */
946 0 : num_max = extract_l( L_acc );
947 0 : L_numsq_max = L_mult( num_max, num_max );
948 :
949 0 : phi_max = 0;
950 0 : move16();
951 0 : ioff = 1;
952 0 : move16();
953 :
954 0 : ptr_L_den0 = L_den0;
955 0 : ptr_L_den1 = L_den1;
956 0 : ptr_y_up = y_up;
957 :
958 :
959 : /* if den_max = 0 : will be selected and declared unvoiced */
960 : /* if num!=0 & den=0 : will be selected and declared unvoiced */
961 : /* degenerated seldom cases, switch off LT is OK */
962 :
963 : /* Loop on phase */
964 0 : FOR( phi = 1; phi < F_UP_PST; phi++ )
965 : {
966 : /* compute num for lambda+1 - phi/F_UP_PST */
967 0 : L_acc = L_mult( ptr_sig_in[0], ptr_y_up[0] );
968 0 : FOR( n = 1; n < L_SUBFR; n++ )
969 : {
970 0 : L_acc = L_mac_sat( L_acc, ptr_sig_in[n], ptr_y_up[n] );
971 : }
972 0 : L_acc = L_shr( L_acc, sh_num ); /* sh_num > 0 */
973 0 : L_acc = L_max( 0, L_acc );
974 0 : num = extract_l( L_acc );
975 :
976 : /* selection if num**2/den0 max */
977 0 : L_temp1 = L_mult( num, num );
978 0 : L_temp0 = Mpy_32_16_1( L_temp1, den_max );
979 0 : L_acc = L_add( *ptr_L_den0++, 0 );
980 0 : L_acc = L_shr( L_acc, sh_den ); /* sh_den > 0 */
981 0 : den0 = extract_l( L_acc );
982 0 : L_temp = Msub_32_16( L_temp0, L_numsq_max, den0 );
983 0 : IF( L_temp > 0L )
984 : {
985 0 : num_max = num;
986 0 : move16();
987 0 : L_numsq_max = L_temp1; /* sets to 'L_temp1' in 1 clock */
988 0 : move32();
989 0 : den_max = den0;
990 0 : move16();
991 0 : ioff = 0;
992 0 : move16();
993 0 : phi_max = phi;
994 0 : move16();
995 : }
996 :
997 : /* compute num for lambda - phi/F_UP_PST */
998 0 : ptr_y_up++;
999 :
1000 0 : L_acc = L_mult( ptr_sig_in[0], ptr_y_up[0] );
1001 0 : FOR( n = 1; n < L_SUBFR; n++ )
1002 : {
1003 0 : L_acc = L_mac_sat( L_acc, ptr_sig_in[n], ptr_y_up[n] );
1004 : }
1005 0 : L_acc = L_shr( L_acc, sh_num ); /* sh_num > 0 */
1006 0 : L_acc = L_max( 0, L_acc );
1007 0 : num = extract_l( L_acc );
1008 :
1009 : /* selection if num**2/den1 max */
1010 0 : L_temp1 = L_mult( num, num );
1011 0 : L_temp0 = Mpy_32_16_1( L_temp1, den_max );
1012 0 : L_acc = L_add( *ptr_L_den1++, 0 );
1013 0 : L_acc = L_shr( L_acc, sh_den ); /* sh_den > 0 */
1014 0 : den1 = extract_l( L_acc );
1015 0 : L_temp = Msub_32_16( L_temp0, L_numsq_max, den1 );
1016 0 : IF( L_temp > 0L )
1017 : {
1018 0 : num_max = num;
1019 0 : move16();
1020 0 : L_numsq_max = L_temp1; /* sets to 'L_temp1' in 1 clock */
1021 0 : move32();
1022 0 : den_max = den1;
1023 0 : move16();
1024 0 : ioff = 1;
1025 0 : move16();
1026 0 : phi_max = phi;
1027 0 : move16();
1028 : }
1029 :
1030 0 : ptr_y_up += L_SUBFR;
1031 : }
1032 :
1033 : /*---------------------------------------------------
1034 : * test if normalized crit0[iopt] > THRESHCRIT
1035 : *--------------------------------------------------*/
1036 0 : test();
1037 0 : IF( num_max == 0 || LE_16( den_max, 1 ) )
1038 : {
1039 0 : *num_gltp = 0;
1040 0 : move16();
1041 0 : *den_gltp = 1;
1042 0 : move16();
1043 0 : *ltpdel = 0;
1044 0 : move16();
1045 0 : *phase = 0;
1046 0 : move16();
1047 :
1048 0 : return;
1049 : }
1050 :
1051 : /* compare num**2 */
1052 : /* to ener * den * 0.5 */
1053 : /* (THRESHCRIT = 0.5) */
1054 0 : L_temp1 = L_mult( den_max, ener );
1055 :
1056 : /* temp = 2 * sh_num - sh_den - sh_ener + 1 */
1057 : /* 16 bits with no overflows */
1058 0 : temp = shl( sh_num, 1 );
1059 0 : temp = sub( temp, sh_den );
1060 0 : temp = sub( temp, sh_ener );
1061 0 : temp = add( temp, 1 );
1062 0 : IF( temp < 0 )
1063 : {
1064 0 : temp = negate( temp ); /* no overflow */
1065 0 : L_numsq_max = L_shr( L_numsq_max, temp );
1066 : }
1067 : ELSE
1068 : {
1069 0 : IF( temp > 0 )
1070 : {
1071 0 : L_temp1 = L_shr( L_temp1, temp );
1072 : }
1073 : }
1074 0 : L_temp = L_sub( L_numsq_max, L_temp1 );
1075 0 : IF( L_temp >= 0L )
1076 : {
1077 0 : temp = add( lambda, 1 );
1078 0 : *ltpdel = sub( temp, ioff );
1079 0 : *off_yup = ioff;
1080 0 : move16();
1081 0 : *phase = phi_max;
1082 0 : move16();
1083 0 : *num_gltp = num_max;
1084 0 : move16();
1085 0 : *den_gltp = den_max;
1086 0 : move16();
1087 0 : *sh_den_gltp = sh_den;
1088 0 : move16();
1089 0 : *sh_num_gltp = sh_num;
1090 0 : move16();
1091 : }
1092 : ELSE
1093 : {
1094 0 : *num_gltp = 0;
1095 0 : move16();
1096 0 : *den_gltp = 1;
1097 0 : move16();
1098 0 : *ltpdel = 0;
1099 0 : move16();
1100 0 : *phase = 0;
1101 0 : move16();
1102 : }
1103 :
1104 :
1105 0 : return;
1106 : }
1107 :
1108 : /*----------------------------------------------------------------------------
1109 : * filt_plt_fx:
1110 : *
1111 : * Perform long term postfilter
1112 : *----------------------------------------------------------------------------*/
1113 0 : static void filt_plt_fx(
1114 : Word16 *s_in, /* i : i signal with past Qx */
1115 : Word16 *s_ltp, /* i : filtered signal with gain 1 Qx*/
1116 : Word16 *s_out, /* o : signal Qx */
1117 : Word16 gain_plt /* i : filter gain Q15 */
1118 : )
1119 : {
1120 :
1121 : /* Local variables */
1122 : Word32 L_acc;
1123 :
1124 : Word16 n;
1125 : Word16 gain_plt_1;
1126 :
1127 :
1128 0 : gain_plt_1 = sub( 32767, gain_plt ); // Q15
1129 0 : gain_plt_1 = add( gain_plt_1, 1 ); /* 2**15 (1 - g) */
1130 :
1131 0 : FOR( n = 0; n < L_SUBFR; n++ )
1132 : {
1133 : /* s_out(n) = gain_plt x s_in(n) + gain_plt_1 x s_ltp(n) */
1134 0 : L_acc = L_mult( gain_plt, s_in[n] ); // Qx + Q15 + 1
1135 0 : s_out[n] = mac_r( L_acc, gain_plt_1, s_ltp[n] ); // Qx
1136 0 : move16(); /* no overflow */
1137 : }
1138 :
1139 :
1140 0 : return;
1141 : }
1142 :
1143 :
1144 : /*----------------------------------------------------------------------------
1145 : * compute_ltp_l_fx :
1146 : *
1147 : * compute delayed signal, num & den of gain for fractional delay
1148 : * with long interpolation filter
1149 : *----------------------------------------------------------------------------*/
1150 0 : static void compute_ltp_l_fx(
1151 : Word16 *s_in, /* i/o: signal with past */
1152 : Word16 ltpdel, /* i : delay factor */
1153 : Word16 phase, /* i : phase factor */
1154 : Word16 *y_up, /* i : delayed signal */
1155 : Word16 *num, /* i : numerator of LTP gain Q(sh_num) */
1156 : Word16 *den, /* i : denominator of LTP gain Q(sh_den) */
1157 : Word16 *sh_num, /* i : justification factor of num */
1158 : Word16 *sh_den /* i : justification factor of den */
1159 : )
1160 : {
1161 : Word32 L_acc;
1162 : Word16 *ptr2;
1163 : const Word16 *ptr_h;
1164 : Word16 n, i;
1165 : Word16 temp;
1166 :
1167 0 : temp = sub( phase, 1 );
1168 0 : temp = shl( temp, L2_LH2_L );
1169 0 : ptr_h = tab_hup_l_fx + temp; /* tab_hup_l_fx + LH2_L * (phase-1) */ // Q15
1170 :
1171 0 : temp = sub( LH_UP_L, ltpdel );
1172 0 : ptr2 = s_in + temp;
1173 :
1174 : /* Compute y_up */
1175 0 : FOR( n = 0; n < L_SUBFR; n++ )
1176 : {
1177 0 : L_acc = L_mult( ptr_h[0], *ptr2-- );
1178 :
1179 0 : FOR( i = 1; i < LH2_L; i++ )
1180 : {
1181 0 : L_acc = L_mac( L_acc, ptr_h[i], *ptr2-- );
1182 : }
1183 0 : y_up[n] = round_fx( L_acc );
1184 0 : ptr2 += LH2_L_P1;
1185 : }
1186 :
1187 : /* Compute num */
1188 0 : L_acc = L_mult( y_up[0], s_in[0] );
1189 0 : FOR( n = 1; n < L_SUBFR; n++ )
1190 : {
1191 0 : L_acc = L_mac( L_acc, y_up[n], s_in[n] );
1192 : }
1193 0 : IF( L_acc < 0L )
1194 : {
1195 0 : *num = 0;
1196 0 : move16();
1197 0 : *sh_num = 0;
1198 0 : move16();
1199 : }
1200 : ELSE
1201 : {
1202 0 : temp = sub( 16, norm_l( L_acc ) );
1203 0 : temp = s_max( temp, 0 );
1204 0 : L_acc = L_shr( L_acc, temp ); /* with temp >= 0 */
1205 0 : *num = extract_l( L_acc );
1206 0 : *sh_num = temp;
1207 0 : move16();
1208 0 : move16();
1209 : }
1210 :
1211 : /* Compute den */
1212 0 : L_acc = L_mult( y_up[0], y_up[0] );
1213 0 : FOR( n = 1; n < L_SUBFR; n++ )
1214 : {
1215 0 : L_acc = L_mac_sat( L_acc, y_up[n], y_up[n] );
1216 : }
1217 0 : temp = sub( 16, norm_l( L_acc ) );
1218 0 : temp = s_max( temp, 0 );
1219 0 : L_acc = L_shr( L_acc, temp ); /* with temp >= 0 */
1220 0 : *den = extract_l( L_acc );
1221 0 : *sh_den = temp;
1222 0 : move16();
1223 0 : move16();
1224 :
1225 :
1226 0 : return;
1227 : }
1228 :
1229 : /*----------------------------------------------------------------------------
1230 : * select_ltp_fx:
1231 : *
1232 : * selects best of (gain1, gain2)
1233 : * with gain1 = num1 * 2** sh_num1 / den1 * 2** sh_den1
1234 : * and gain2 = num2 * 2** sh_num2 / den2 * 2** sh_den2
1235 : *----------------------------------------------------------------------------*/
1236 0 : static Word16 select_ltp_fx( /* o : 1 = 1st gain, 2 = 2nd gain */
1237 : Word16 num1, /* i : numerator of gain1 Q(sh_num1) */
1238 : Word16 den1, /* i : denominator of gain1 Q(sh_den1) */
1239 : Word16 sh_num1, /* i : just. factor for num1 */
1240 : Word16 sh_den1, /* i : just. factor for den1 */
1241 : Word16 num2, /* i : numerator of gain2 Q(sh_num2) */
1242 : Word16 den2, /* i : denominator of gain2 Q(sh_den2) */
1243 : Word16 sh_num2, /* i : just. factor for num2 */
1244 : Word16 sh_den2 /* i : just. factor for den2 */
1245 : )
1246 : {
1247 : Word32 L_temp1, L_temp2;
1248 : Word32 L_temp;
1249 :
1250 : Word16 temp1, temp2;
1251 :
1252 :
1253 0 : IF( den2 == 0 )
1254 : {
1255 0 : return 1;
1256 : }
1257 :
1258 : /* compares criteria = num**2/den */
1259 0 : L_temp1 = L_mult( num1, num1 );
1260 0 : L_temp1 = Mpy_32_16_1( L_temp1, den2 );
1261 :
1262 0 : L_temp2 = L_mult( num2, num2 );
1263 0 : L_temp2 = Mpy_32_16_1( L_temp2, den1 );
1264 :
1265 : /* temp1 = sh_den2 + 2 * sh_num1 */
1266 0 : temp1 = shl( sh_num1, 1 );
1267 0 : temp1 = add( temp1, sh_den2 );
1268 : /* temp2 = sh_den1 + 2 * sh_num2; */
1269 0 : temp2 = shl( sh_num2, 1 );
1270 0 : temp2 = add( temp2, sh_den1 );
1271 :
1272 0 : temp2 = sub( temp2, temp1 );
1273 0 : IF( temp2 > 0 )
1274 : {
1275 0 : L_temp1 = L_shr( L_temp1, temp2 ); /* temp2 > 0 */
1276 : }
1277 0 : IF( temp2 < 0 )
1278 : {
1279 0 : L_temp2 = L_shl( L_temp2, temp2 ); /* temp2 < 0 */
1280 : }
1281 :
1282 0 : L_temp = L_sub( L_temp2, L_temp1 );
1283 0 : temp1 = 1;
1284 0 : move16();
1285 0 : if ( L_temp > 0L )
1286 : {
1287 0 : temp1 = 2;
1288 0 : move16();
1289 : }
1290 :
1291 0 : return temp1;
1292 : }
1293 :
1294 : /*----------------------------------------------------------------------------
1295 : * calc_st_filt_local_fx
1296 : *
1297 : * computes impulse response of A(gamma2) / A(gamma1)
1298 : * controls gain : computation of energy impulse response as
1299 : * SUMn (abs (h[n])) and computes parcor0
1300 : *---------------------------------------------------------------------------- */
1301 0 : static void calc_st_filt_local_fx(
1302 : Word16 *apond2, /* i : coefficients of numerator Q12 */
1303 : Word16 *apond1, /* i : coefficients of denominator Q12 */
1304 : Word16 *parcor0, /* o : 1st parcor calcul. on composed filter Q15*/
1305 : Word16 *sig_ltp_ptr, /* i/o: i of 1/A(gamma1) : scaled by 1/g0 Qx */
1306 : Word16 *mem_zero /* i : All zero memory */
1307 : )
1308 : {
1309 : Word32 L_g0;
1310 :
1311 : Word16 h[LONG_H_ST];
1312 :
1313 : Word16 g0, temp;
1314 : Word16 i;
1315 :
1316 :
1317 0 : temp = sub( 2, norm_s( apond2[0] ) );
1318 :
1319 : /* compute i.r. of composed filter apond2 / apond1 */
1320 0 : E_UTIL_synthesis( temp, apond1, apond2, h, LONG_H_ST, mem_zero, 0, M );
1321 :
1322 : /* compute 1st parcor */
1323 0 : Calc_rc0_h( h, parcor0 );
1324 :
1325 : /* compute g0 */
1326 0 : L_g0 = L_mult0( 1, abs_s( h[0] ) ); // Q12
1327 0 : FOR( i = 1; i < LONG_H_ST; i++ )
1328 : {
1329 0 : L_g0 = L_mac0( L_g0, 1, abs_s( h[i] ) ); // Q12
1330 : }
1331 0 : g0 = extract_h( L_shl( L_g0, 14 ) ); // Q10
1332 :
1333 : /* Scale signal i of 1/A(gamma1) */
1334 0 : IF( GT_16( g0, 1024 ) ) /*1024 = 1.Q10*/
1335 : {
1336 0 : temp = div_s( 1024, g0 ); /* temp => Q15 / gain0 */ /*1024 = 1.Q10*/
1337 0 : FOR( i = 0; i < L_SUBFR; i++ )
1338 : {
1339 0 : sig_ltp_ptr[i] = mult_r( sig_ltp_ptr[i], temp ); // Qx
1340 0 : move16();
1341 : }
1342 : }
1343 :
1344 :
1345 0 : return;
1346 : }
1347 :
1348 672840 : static void calc_st_filt_ivas_fx(
1349 : Word16 *apond2, /* i : coefficients of numerator Q12 */
1350 : Word16 *apond1, /* i : coefficients of denominator Q12 */
1351 : Word16 *parcor0, /* o : 1st parcor calcul. on composed filter Q15 */
1352 : Word16 *sig_ltp_ptr, /* i/o: i of 1/A(gamma1) : scaled by 1/g0 Qx*/
1353 : Word16 *mem_zero, /* i : All zero memory */
1354 : const Word16 extl /* i : extension layer info */
1355 : )
1356 : {
1357 : Word32 L_g0;
1358 :
1359 : Word16 h[LONG_H_ST]; // Q12
1360 :
1361 : Word16 g0, temp;
1362 : Word16 i;
1363 :
1364 :
1365 672840 : temp = sub( 2, norm_s( apond2[0] ) );
1366 :
1367 : /* compute i.r. of composed filter apond2 / apond1 */
1368 672840 : IF( EQ_16( extl, SWB_TBE ) )
1369 : {
1370 0 : E_UTIL_synthesis( temp, apond1, apond2, h, LONG_H_ST, mem_zero, 0, LPC_SHB_ORDER );
1371 : }
1372 : ELSE
1373 : {
1374 672840 : E_UTIL_synthesis( temp, apond1, apond2, h, LONG_H_ST, mem_zero, 0, M );
1375 : }
1376 :
1377 : /* compute 1st parcor */
1378 672840 : Calc_rc0_h( h, parcor0 );
1379 :
1380 : /* compute g0 */
1381 672840 : L_g0 = L_mult0( 1, abs_s( h[0] ) ); // Q12
1382 13456800 : FOR( i = 1; i < LONG_H_ST; i++ )
1383 : {
1384 12783960 : L_g0 = L_mac0( L_g0, 1, abs_s( h[i] ) ); // Q12
1385 : }
1386 672840 : g0 = extract_h( L_shl( L_g0, 14 ) ); // Q10
1387 :
1388 : /* Scale signal i of 1/A(gamma1) */
1389 672840 : IF( GT_16( g0, 1024 ) ) /*1024 = 1.Q10*/
1390 : {
1391 323043 : temp = div_s( 1024, g0 ); /* temp => Q15 / gain0 */ /*1024 = 1.Q10*/
1392 20997795 : FOR( i = 0; i < L_SUBFR; i++ )
1393 : {
1394 20674752 : sig_ltp_ptr[i] = mult_r( sig_ltp_ptr[i], temp ); // Qx
1395 20674752 : move16();
1396 : }
1397 : }
1398 :
1399 :
1400 672840 : return;
1401 : }
1402 : /*----------------------------------------------------------------------------
1403 : * filt_mu
1404 : *
1405 : * tilt filtering with : (1 + mu z-1) * (1/1-|mu|)
1406 : * computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1])
1407 : *---------------------------------------------------------------------------*/
1408 0 : void Filt_mu_fx(
1409 : Word16 *sig_in, /* i : signal (beginning at sample -1) */
1410 : Word16 *sig_out, /* o : signal with tilt */
1411 : Word16 parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */
1412 : Word16 L_subfr /* i : the length of subframe */
1413 : )
1414 : {
1415 : Word32 L_acc, L_temp, L_fact;
1416 :
1417 : Word16 *ptrs;
1418 :
1419 : Word16 n;
1420 : Word16 mu, mu2, ga, temp;
1421 : Word16 fact, sh_fact;
1422 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1423 0 : Flag Overflow = 0;
1424 0 : move16();
1425 : #endif
1426 :
1427 :
1428 0 : IF( parcor0 > 0 )
1429 : {
1430 0 : mu = mult_r( parcor0, GAMMA3_PLUS_FX ); // Q15
1431 : /* GAMMA3_PLUS_FX < 0.5 */
1432 0 : sh_fact = 14;
1433 0 : move16(); /* sh_fact */
1434 0 : fact = (Word16) 0x4000;
1435 0 : move16(); /* Q(sh_fact) */
1436 0 : L_fact = (Word32) L_deposit_l( 0x2000 ); /* fact >> 1 */
1437 : }
1438 : ELSE
1439 : {
1440 0 : mu = mult_r( parcor0, GAMMA3_MINUS_FX ); // Q15
1441 : /* GAMMA3_MINUS_FX < 0.9375 */
1442 0 : sh_fact = 11;
1443 0 : move16(); /* sh_fact */
1444 0 : fact = (Word16) 0x0800;
1445 0 : move16(); /* Q(sh_fact) */
1446 0 : L_fact = (Word32) L_deposit_l( 0x0400 ); /* fact >> 1 */
1447 : }
1448 :
1449 0 : temp = sub( 1, abs_s( mu ) );
1450 : BASOP_SATURATE_WARNING_OFF_EVS;
1451 0 : mu2 = add_o( 32767, temp, &Overflow ); /* Q15 (1 - |mu|) */
1452 : BASOP_SATURATE_WARNING_ON_EVS;
1453 0 : ga = div_s( fact, mu2 ); /* Q(sh_fact) / (1 - |mu|) */
1454 :
1455 0 : ptrs = sig_in; /* points on sig_in(-1) */
1456 :
1457 0 : sh_fact = sub( sh_fact, 16 ); /* to remove the saturate(), should shl by 16 before rounding */
1458 :
1459 0 : FOR( n = 0; n < L_subfr; n++ )
1460 : {
1461 0 : L_acc = L_mult0( mu, *ptrs++ );
1462 0 : L_temp = L_mac( L_acc, 16384, *ptrs ); /* sig_in(n) * 2**15 */
1463 :
1464 0 : L_temp = Madd_32_16( L_fact, L_temp, ga );
1465 0 : L_temp = L_shr_sat( L_temp, sh_fact ); /* mult. temp x ga */
1466 : BASOP_SATURATE_WARNING_OFF_EVS;
1467 : /*sig_out[n] = saturate(L_temp); move16();*/
1468 0 : sig_out[n] = round_fx_sat( L_temp );
1469 0 : move16();
1470 : BASOP_SATURATE_WARNING_ON_EVS;
1471 : }
1472 :
1473 :
1474 0 : return;
1475 : }
1476 :
1477 672840 : void Filt_mu_ivas_fx(
1478 : Word16 *sig_in, /* i : signal (beginning at sample -1) */
1479 : Word16 *sig_out, /* o : signal with tilt */
1480 : Word16 parcor0, /* i : parcor0 (mu = parcor0 * gamma3) Q15 */
1481 : Word16 L_subfr, /* i : the length of subframe */
1482 : const Word16 extl )
1483 : {
1484 : Word32 L_acc, L_temp, L_fact;
1485 :
1486 : Word16 *ptrs;
1487 :
1488 : Word16 n;
1489 : Word16 mu, mu2, ga, temp;
1490 : Word16 fact, sh_fact;
1491 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1492 672840 : Flag Overflow = 0;
1493 672840 : move16();
1494 : #endif
1495 :
1496 672840 : IF( EQ_16( extl, SWB_TBE ) )
1497 : {
1498 0 : IF( parcor0 > 0 )
1499 : {
1500 0 : mu = mult_r( parcor0, GAMMA3_PLUS_WB_FX ); // Q15
1501 : /* GAMMA3_PLUS_FX < 0.5 */
1502 0 : sh_fact = 14;
1503 0 : move16(); /* sh_fact */
1504 0 : fact = (Word16) 0x4000;
1505 0 : move16(); /* Q(sh_fact) */
1506 0 : L_fact = L_deposit_l( 0x2000 ); /* fact >> 1 */
1507 : }
1508 : ELSE
1509 : {
1510 0 : mu = mult_r( parcor0, GAMMA3_MINUS_WB_FX ); // Q15
1511 : /* GAMMA3_MINUS_FX < 0.9375 */
1512 0 : sh_fact = 11;
1513 0 : move16(); /* sh_fact */
1514 0 : fact = (Word16) 0x0800;
1515 0 : move16(); /* Q(sh_fact) */
1516 0 : L_fact = L_deposit_l( 0x0400 ); /* fact >> 1 */
1517 : }
1518 : }
1519 : ELSE
1520 : {
1521 672840 : IF( parcor0 > 0 )
1522 : {
1523 49148 : mu = mult_r( parcor0, GAMMA3_PLUS_FX ); // Q15
1524 : /* GAMMA3_PLUS_FX < 0.5 */
1525 49148 : sh_fact = 14;
1526 49148 : move16(); /* sh_fact */
1527 49148 : fact = (Word16) 0x4000;
1528 49148 : move16(); /* Q(sh_fact) */
1529 49148 : L_fact = L_deposit_l( 0x2000 ); /* fact >> 1 */
1530 : }
1531 : ELSE
1532 : {
1533 623692 : mu = mult_r( parcor0, GAMMA3_MINUS_FX ); // Q15
1534 : /* GAMMA3_MINUS_FX < 0.9375 */
1535 623692 : sh_fact = 11;
1536 623692 : move16(); /* sh_fact */
1537 623692 : fact = (Word16) 0x0800;
1538 623692 : move16(); /* Q(sh_fact) */
1539 623692 : L_fact = L_deposit_l( 0x0400 ); /* fact >> 1 */
1540 : }
1541 : }
1542 :
1543 672840 : temp = sub( 1, abs_s( mu ) );
1544 : BASOP_SATURATE_WARNING_OFF_EVS;
1545 672840 : mu2 = add_o( 32767, temp, &Overflow ); /* Q15 (1 - |mu|) */
1546 : BASOP_SATURATE_WARNING_ON_EVS;
1547 672840 : ga = div_s( fact, mu2 ); /* Q(sh_fact) / (1 - |mu|) */
1548 :
1549 672840 : ptrs = sig_in; /* points on sig_in(-1) */
1550 :
1551 672840 : sh_fact = sub( sh_fact, 16 ); /* to remove the saturate(), should shl by 16 before rounding */
1552 :
1553 43734600 : FOR( n = 0; n < L_subfr; n++ )
1554 : {
1555 43061760 : L_acc = L_mult0( mu, *ptrs++ );
1556 43061760 : L_temp = L_mac( L_acc, 16384, *ptrs ); /* sig_in(n) * 2**15 */
1557 :
1558 43061760 : L_temp = Madd_32_16( L_fact, L_temp, ga );
1559 43061760 : L_temp = L_shr( L_temp, sh_fact ); /* mult. temp x ga */
1560 :
1561 : BASOP_SATURATE_WARNING_OFF_EVS;
1562 : /*sig_out[n] = saturate(L_temp); move16();*/
1563 43061760 : sig_out[n] = round_fx_sat( L_temp );
1564 : BASOP_SATURATE_WARNING_ON_EVS;
1565 : }
1566 :
1567 :
1568 672840 : return;
1569 : }
1570 : /*----------------------------------------------------------------------------
1571 : * scale_st_fx()
1572 : *
1573 : * control of the subframe gain
1574 : * gain[n] = AGC_FAC_FX * gain[n-1] + (1 - AGC_FAC_FX) g_in/g_out
1575 : *---------------------------------------------------------------------------*/
1576 674040 : void scale_st_fx(
1577 : const Word16 *sig_in, /* i : postfilter i signal Qx */
1578 : Word16 *sig_out, /* i/o: postfilter o signal Qx */
1579 : Word16 *gain_prec, /* i/o: last value of gain for subframe Q14*/
1580 : Word16 L_subfr )
1581 : {
1582 : Word32 L_acc, L_temp;
1583 :
1584 : Word16 i;
1585 : Word16 scal_in, scal_out;
1586 : Word16 s_g_in, s_g_out, temp, sh_g0, g0;
1587 674040 : Word16 gain = 0;
1588 :
1589 :
1590 : /* compute i gain */
1591 674040 : L_acc = L_deposit_l( 0 );
1592 43812600 : FOR( i = 0; i < L_subfr; i++ )
1593 : {
1594 43138560 : IF( sig_in[i] > 0 )
1595 : {
1596 21400781 : L_acc = L_mac0( L_acc, 1, sig_in[i] );
1597 : }
1598 43138560 : IF( sig_in[i] < 0 )
1599 : {
1600 21309704 : L_acc = L_msu0( L_acc, 1, sig_in[i] );
1601 : }
1602 : }
1603 :
1604 674040 : g0 = 0;
1605 674040 : move16();
1606 674040 : IF( L_acc != 0L )
1607 : {
1608 670864 : scal_in = norm_l( L_acc );
1609 670864 : L_acc = L_shl( L_acc, scal_in );
1610 670864 : s_g_in = extract_h( L_acc ); /* normalized */
1611 :
1612 : /* Compute o gain */
1613 : {
1614 670864 : Word64 acc64 = 0;
1615 43606160 : FOR( i = 0; i < L_subfr; i++ )
1616 : {
1617 42935296 : acc64 = W_mac0_16_16( acc64, 1, abs_s( sig_out[i] ) );
1618 : }
1619 670864 : L_acc = W_sat_l( acc64 );
1620 : }
1621 670864 : IF( L_acc == 0L )
1622 : {
1623 919 : *gain_prec = 0;
1624 919 : move16();
1625 :
1626 919 : return;
1627 : }
1628 669945 : scal_out = norm_l( L_acc );
1629 669945 : L_acc = L_shl( L_acc, scal_out );
1630 669945 : s_g_out = extract_h( L_acc ); /* normalized */
1631 :
1632 669945 : sh_g0 = add( scal_in, 1 );
1633 669945 : sh_g0 = sub( sh_g0, scal_out ); /* scal_in - scal_out + 1 */
1634 669945 : IF( LT_16( s_g_in, s_g_out ) )
1635 : {
1636 210714 : g0 = div_s( s_g_in, s_g_out ); /* s_g_in/s_g_out in Q15 */
1637 : }
1638 : ELSE
1639 : {
1640 459231 : temp = sub( s_g_in, s_g_out ); /* sufficient since normalized */
1641 459231 : g0 = shr( div_s( temp, s_g_out ), 1 );
1642 459231 : g0 = add( g0, (Word16) 0x4000 ); /* s_g_in/s_g_out in Q14 */
1643 459231 : sh_g0 = sub( sh_g0, 1 );
1644 : }
1645 : /* L_gain_in/L_gain_out in Q14 */
1646 : /* overflows if L_gain_in > 2 * L_gain_out */
1647 669945 : g0 = shr_sat( g0, sh_g0 ); /* sh_g0 may be >0, <0, or =0 */
1648 669945 : g0 = mult_r( g0, AGC_FAC1_FX ); /* L_gain_in/L_gain_out * AGC_FAC1_FX */
1649 : }
1650 :
1651 : /* gain(n) = AGC_FAC gain(n-1) + AGC_FAC1 gain_in/gain_out */
1652 : /* sig_out(n) = gain(n) sig_out(n) */
1653 673121 : gain = *gain_prec;
1654 673121 : move16();
1655 43752865 : FOR( i = 0; i < L_subfr; i++ )
1656 : {
1657 43079744 : temp = mult_r( AGC_FAC_FX, gain );
1658 43079744 : gain = add( temp, g0 ); /* in Q14 */
1659 43079744 : L_temp = L_mult( gain, sig_out[i] );
1660 43079744 : L_temp = L_shl_sat( L_temp, 1 );
1661 43079744 : sig_out[i] = round_fx_sat( L_temp );
1662 43079744 : move16();
1663 : }
1664 673121 : *gain_prec = gain;
1665 673121 : move16();
1666 :
1667 :
1668 673121 : return;
1669 : }
1670 :
1671 : /*----------------------------------------------------------------------------
1672 : * blend_subfr2_fx()
1673 : *
1674 : *
1675 : *---------------------------------------------------------------------------*/
1676 :
1677 1200 : void blend_subfr2_fx(
1678 : Word16 *sigIn1, // Qx
1679 : Word16 *sigIn2, // Qx
1680 : Word16 *sigOut // Qx
1681 : )
1682 : {
1683 1200 : Word16 fac1 = 32768 - 512; // 1.Q15 - ( 1.Q15 / L_SUBFR );
1684 1200 : Word16 fac2 = 0 + 512; // 0.Q15 + ( 1.Q15 / L_SUBFR );
1685 1200 : Word16 step = 1024; // 1.Q15 / ( L_SUBFR / 2 );
1686 : Word16 i;
1687 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1688 1200 : Flag Overflow = 0;
1689 1200 : move16();
1690 : #endif
1691 1200 : move16();
1692 1200 : move16();
1693 1200 : move16();
1694 39600 : FOR( i = 0; i < L_SUBFR / 2; i++ )
1695 : {
1696 38400 : sigOut[i] = mac_ro( L_mult_o( fac1, sigIn1[i], &Overflow ), fac2, sigIn2[i], &Overflow ); // Qx
1697 38400 : fac1 = sub_o( fac1, step, &Overflow );
1698 38400 : fac2 = add_o( fac2, step, &Overflow );
1699 38400 : move16();
1700 : }
1701 :
1702 1200 : return;
1703 : }
|