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 :
9 : /*-------------------------------------------------------------------*
10 : * Local constants
11 : *-------------------------------------------------------------------*/
12 : #define AGC_FX 32113 /* 0.98f */
13 : #define SCLSYN_LAMBDA ( 9830 /*0.3f Q15*/ )
14 :
15 : /*========================================================================*/
16 : /* FUNCTION : FEC_scale_syn_fx() */
17 : /*------------------------------------------------------------------------*/
18 : /* PURPOSE : Smooth the speech energy evolution when */
19 : /* recovering after a BAD frame */
20 : /*------------------------------------------------------------------------*/
21 : /* INPUT ARGUMENTS : */
22 : /* _ (Word16) L_frame : length of the frame */
23 : /* _ (Word16) *update_flg : indication about resynthesis */
24 : /* _ (Word16) st_fx->clas_dec: frame classification */
25 : /* _ (Word16) last_good : last good frame classification */
26 : /* _ (Word16[]) synth : synthesized speech at Fs = 12k8 Hz Q_syn */
27 : /* _ (Word16[]) pitch : pitch values for each subframe Q0 */
28 : /* _ (Word32) L_enr_old :energy at the end of previous frame Q0 */
29 : /* _ (Word16) L_enr_q : transmitted energy for current frame Q0 */
30 : /* _ (Word16) coder_type : coder type */
31 : /* _ (Word16) st_fx->prev_bfi_fx: previous frame BFI */
32 : /* _ (Word16) st_fx->last_core_brate_fx: previous frame core bitrate */
33 : /* _ (Word16[]) mem_tmp : temp. initial synthesis filter states Q_syn */
34 : /* _ (Word16) Q_exc : quantized LSPs from frame end */
35 : /* _ (Word16) Q_syn : quantized LSPs from frame end */
36 : /*------------------------------------------------------------------------*/
37 : /* INPUT/OUTPUT ARGUMENTS : */
38 : /* _ (Word16[]) exc : excitation signal without enhancement Q_exc */
39 : /* _ (Word16[]) exc2 : excitation signal with enhancement Q_exc */
40 : /* _ (Word16[]) Aq : LP filter coefs (can be modified if BR) Q12 */
41 : /*------------------------------------------------------------------------*/
42 : /* OUTPUT ARGUMENTS : */
43 : /*------------------------------------------------------------------------*/
44 :
45 : /* _ (Word16[]) st_fx->mem_syn2 : initial synthesis filter states Q_syn */
46 : /* _ (Word16) st_fx->old_enr_LP : LP filter E of last Q5 */
47 : /* good voiced frame */
48 : /*------------------------------------------------------------------------*/
49 : /* RETURN ARGUMENTS : */
50 : /* _ None */
51 : /*========================================================================*/
52 :
53 140736 : void FEC_scale_syn_fx(
54 : const Word16 L_frame, /* i : length of the frame */
55 : Word16 *update_flg, /* o: flag indicating re-synthesis after scaling*/
56 : Word16 clas, /* i/o: frame classification */
57 : const Word16 last_good, /* i: last good frame classification */
58 : Word16 *synth, /* i/o: synthesized speech at Fs = 12k8 Hz Q_syn*/
59 : const Word16 *pitch, /* i: pitch values for each subframe Q0*/
60 : Word32 L_enr_old, /* i: energy at the end of previous frame */
61 : Word32 L_enr_q, /* i: transmitted energy for current frame */
62 : const Word16 coder_type, /* i: coder type */
63 : const Word16 LSF_Q_prediction, /* i : LSF prediction mode */
64 : Word16 *scaling_flag, /* i/o: flag to indicate energy control of syn */
65 : Word32 *lp_ener_FEC_av, /* i/o: averaged voiced signal energy Q0*/
66 : Word32 *lp_ener_FEC_max, /* i/o: averaged voiced signal energy Q0*/
67 : const Word16 bfi, /* i: current frame BFI */
68 : const Word32 total_brate, /* i: total bitrate */
69 : const Word16 prev_bfi, /* i: previous frame BFI */
70 : const Word32 last_core_brate, /* i: previous frame core bitrate */
71 : Word16 *exc, /* i/o: excitation signal without enhancement */
72 : Word16 *exc2, /* i/o: excitation signal with enhancement */
73 : Word16 Aq[], /* i/o: LP filter coefs (can be modified if BR) Q12*/
74 : Word16 *old_enr_LP, /* i/o: LP filter E of last good voiced frame Q3*/
75 : const Word16 *mem_tmp, /* i: temp. initial synthesis filter states Q_syn*/
76 : Word16 *mem_syn, /* o: initial synthesis filter states Q_syn*/
77 : Word16 Q_exc,
78 : Word16 Q_syn,
79 : const Word16 element_mode, /* i : element mode */
80 : const Word16 avoid_lpc_burst_on_recovery, /* i : if true the excitation energy is limited if LP has big gain */
81 : const Word16 force_scaling /* i: force scaling */
82 : )
83 : {
84 : Word16 i;
85 : Word32 L_enr1, L_enr2;
86 : Word16 gain1, gain2, enr_LP;
87 : Word16 tmp, tmp2, exp, exp2;
88 : Word16 tmp3;
89 : Word32 L_tmp;
90 : Word16 scaling;
91 : Word32 ener_max, L_enr2_av, L_ener2_max;
92 : Word16 h1[L_FRAME / 2], tilt, pitch_dist, mean_pitch;
93 : Word16 k;
94 : Word32 L_mean_pitch;
95 :
96 140736 : enr_LP = 0;
97 140736 : move16();
98 140736 : gain2 = 0;
99 140736 : move16();
100 140736 : gain1 = 0;
101 140736 : move16();
102 140736 : *update_flg = 0;
103 140736 : move16();
104 140736 : L_enr_old = L_max( 1, L_enr_old ); /* to avoid division by zero (*L_enr_old is always >= 0) */
105 140736 : scaling = 16384;
106 140736 : move16(); /* Q14*/
107 :
108 : /*-----------------------------------------------------------------*
109 : * Find the synthesis filter impulse response on voiced
110 : *-----------------------------------------------------------------*/
111 140736 : test();
112 140736 : IF( GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) )
113 : {
114 81681 : IF( EQ_16( L_frame, L_FRAME ) )
115 : {
116 44333 : enr_LP = Enr_1_Az_fx( Aq + ( NB_SUBFR - 1 ) * ( M + 1 ), L_SUBFR );
117 : }
118 : ELSE /* L_frame == L_FRAME16k */
119 : {
120 37348 : enr_LP = Enr_1_Az_fx( Aq + ( NB_SUBFR16k - 1 ) * ( M + 1 ), L_SUBFR ); /*Q3*/
121 : }
122 : }
123 :
124 : /*-----------------------------------------------------------------*
125 : * Define when to scale the synthesis
126 : *-----------------------------------------------------------------*/
127 :
128 140736 : IF( bfi )
129 : {
130 0 : *scaling_flag = 1;
131 0 : move16(); /* Always check synthesis on bad frames */
132 : }
133 140736 : ELSE IF( prev_bfi )
134 : {
135 1602 : test();
136 1602 : IF( ( EQ_16( LSF_Q_prediction, AUTO_REGRESSIVE ) ) || ( EQ_16( LSF_Q_prediction, MOVING_AVERAGE ) ) )
137 : {
138 1344 : *scaling_flag = 2;
139 1344 : move16(); /* Decoded LSFs affected */
140 : }
141 258 : ELSE IF( NE_16( coder_type, TRANSITION ) )
142 : {
143 102 : *scaling_flag = 1;
144 102 : move16(); /* SN, but not TC mode - LSF still affected by the interpolation */
145 : }
146 : ELSE
147 : {
148 156 : *scaling_flag = 0;
149 156 : move16(); /* LSF still possibly affected due to interpolation */
150 : }
151 1602 : scaling = 24576; /*1.5 Q14*/
152 1602 : move16();
153 : }
154 : ELSE
155 : {
156 139134 : test();
157 139134 : IF( ( EQ_16( LSF_Q_prediction, AUTO_REGRESSIVE ) ) && ( EQ_16( *scaling_flag, 2 ) ) )
158 : {
159 550 : *scaling_flag = 2;
160 550 : move16(); /* Continue with energy control till the end of AR prediction */
161 : }
162 138584 : ELSE IF( *scaling_flag > 0 )
163 : {
164 1996 : ( *scaling_flag ) = sub( *scaling_flag, 1 ); /* If scaling flag was equal to 2, add one control frame to account for the LSF interpolation */
165 1996 : move16();
166 : }
167 139134 : scaling = 32767; /*2.0 Q14*/
168 139134 : move16();
169 : }
170 :
171 : /*-----------------------------------------------------------------*
172 : * Find the energy/gain at the end of the frame
173 : *-----------------------------------------------------------------*/
174 :
175 140736 : tmp = sub( 3, getScaleFactor16( synth, L_frame ) );
176 :
177 140736 : test();
178 140736 : IF( tmp > 0 && GT_16( element_mode, EVS_MONO ) )
179 3804 : {
180 : Word16 synth_tmp[L_FRAME16k];
181 3804 : Copy_Scale_sig( synth, synth_tmp, L_frame, -tmp ); // Q_synth - tmp
182 3804 : frame_ener_fx( L_frame, clas, synth_tmp, pitch[L_frame / L_SUBFR - 1], &L_enr2 /*Q0*/, 1, sub( Q_syn, tmp ), 3, 0 );
183 : }
184 : ELSE
185 : {
186 136932 : frame_ener_fx( L_frame, clas, synth, pitch[L_frame / L_SUBFR - 1], &L_enr2 /*Q0*/, 1, Q_syn, 3, 0 );
187 : }
188 :
189 140736 : test();
190 140736 : test();
191 140736 : IF( bfi || ( EQ_32( total_brate, ACELP_7k20 ) ) || ( EQ_32( total_brate, ACELP_8k00 ) ) )
192 : {
193 : /* previous frame erased and no TC frame */
194 55 : IF( *scaling_flag > 0 )
195 : {
196 : /*enr2 += 0.01f;*/
197 0 : L_enr2 = L_max( L_enr2, 1 ); /* L_enr2 is in Q0 */
198 :
199 0 : IF( bfi ) /* In all bad frames, limit the gain to 1 */
200 : {
201 : /* gain2 = (float)sqrt( enr_old / enr2 );*/
202 0 : L_tmp = Sqrt_Ratio32( L_enr_old, 0, L_enr2, 0, &exp2 );
203 0 : gain2 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */
204 :
205 : /*if( gain2 > 1.0f )gain2 = 1.0f;*/
206 0 : gain2 = s_min( gain2, 16384 /*1.0f in Q14*/ ); /*Q14*/
207 :
208 : /* find the energy/gain at the beginning of the frame */
209 0 : frame_ener_fx( L_frame, clas, synth, pitch[0], &L_enr1 /*Q0*/, 1, Q_syn, 3, 0 );
210 :
211 : /*enr1 += 0.1f;*/
212 0 : L_enr1 = L_max( L_enr1, 1 ); /* L_enr2 is in Q0 */
213 :
214 : /*gain1 = (float)sqrt( enr_old / enr1 );*/
215 0 : L_tmp = Sqrt_Ratio32( L_enr_old, 0, L_enr1, 0, &exp2 );
216 0 : gain1 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */
217 :
218 : /*if( gain1 > 1.0f )gain1 = 1.0f;*/
219 0 : gain1 = s_min( gain1, 16384 /*1.0f in Q14*/ ); /*Q14*/
220 : }
221 : ELSE /* good frame */
222 : {
223 0 : IF( L_enr_q == 0 ) /* If E info (FEC protection bits) is not available in the bitstream */
224 : {
225 0 : L_enr_q = L_enr2; /*Q0*/
226 0 : set16_fx( h1, 0, L_FRAME / 2 );
227 0 : h1[0] = 1024; /*1.0F in Q10*/
228 0 : move16();
229 : /*syn_filt( Aq+(3*(M+1)), M, h1, h1, L_FRAME/2, h1+(M+1), 0 );*/
230 0 : E_UTIL_synthesis( 1, Aq + ( 3 * ( M + 1 ) ), h1, h1, L_FRAME / 2, h1 + ( M + 1 ), 0, M );
231 :
232 : /*Compute tilt */
233 : /*rr0 = dotp( h1, h1, L_FRAME/2-1 ) + 0.1f;*/
234 : /*rr1 = dotp( h1, h1+1, L_FRAME/2-1 );*/
235 : /*tilt = rr1 / rr0;*/
236 0 : tilt = extract_h( L_shl_sat( get_gain( h1 + 1, h1, L_FRAME / 2 - 1 ), 15 ) ); /*Q15*/
237 0 : pitch_dist = 0;
238 0 : move16();
239 0 : L_mean_pitch = L_mult( pitch[0], 8192 ); /*Q14*/
240 0 : FOR( k = 0; k < ( NB_SUBFR - 1 ); k++ )
241 : {
242 0 : pitch_dist = add( pitch_dist, abs_s( sub( pitch[k + 1], pitch[k] ) ) ); /*Q0*/
243 0 : L_mean_pitch = L_mac( L_mean_pitch, pitch[k + 1], 8192 ); /*Q14*/
244 : }
245 : /*pitch_dist /= (float)(NB_SUBFR-1); */
246 0 : pitch_dist = mult_r( shl( pitch_dist, 4 ), 10923 /*1/(float)(NB_SUBFR-1) in Q15*/ ); /*Q4*/
247 : /*mean_pitch /= (float)(NB_SUBFR);*/
248 0 : mean_pitch = extract_h( L_shl( L_mean_pitch, 4 ) ); /*Q4*/
249 :
250 :
251 0 : test();
252 0 : test();
253 0 : test();
254 0 : test();
255 0 : test();
256 0 : test();
257 0 : IF( ( GT_16( tilt, 22938 ) ) && /* HF resonnant filter */
258 : ( ( GT_16( pitch_dist, 8 << 4 ) ) || ( LT_16( mean_pitch, PIT_MIN << 4 ) ) ) && /* pitch unstable or very short */
259 : ( ( prev_bfi ) || ( ( EQ_16( coder_type, GENERIC ) ) && ( EQ_16( LSF_Q_prediction, AUTO_REGRESSIVE ) ) ) ) )
260 : {
261 : /*if( enr_q > scaling * enr_old ){enr_q = scaling * enr_old;}*/
262 0 : L_enr_q = L_min( L_enr_q, L_shl_sat( Mult_32_16( L_enr_old, scaling ), 1 ) ); /* scaling in Q14*/
263 : }
264 : ELSE
265 : {
266 0 : ener_max = *lp_ener_FEC_max; /*Q0*/
267 0 : move32();
268 0 : test();
269 0 : if ( EQ_16( clas, VOICED_TRANSITION ) || ( GE_16( clas, INACTIVE_CLAS ) ) )
270 : {
271 0 : ener_max = *lp_ener_FEC_av; /*Q0*/
272 0 : move32();
273 : }
274 : /*if( enr_old > ener_max )ener_max = enr_old;*/
275 0 : ener_max = L_max( ener_max, L_enr_old );
276 :
277 : /*if( enr_q > scaling * ener_max ){enr_q = scaling * ener_max;}*/
278 0 : L_enr_q = L_min( L_enr_q, L_shl_sat( Mult_32_16( ener_max, scaling ), 1 ) ); /* scaling in Q14*/
279 : }
280 : }
281 : /*gain2 = (float)sqrt( enr_q / enr2 );*/
282 0 : L_enr_q = L_max( L_enr_q, 1 ); /* L_enr2 is in Q0 */
283 0 : L_tmp = Sqrt_Ratio32( L_enr_q, 0, L_enr2, 0, &exp2 );
284 0 : gain2 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */
285 :
286 : /*-----------------------------------------------------------------*
287 : * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s)
288 : *-----------------------------------------------------------------*/
289 :
290 0 : test();
291 0 : test();
292 0 : test();
293 0 : test();
294 0 : test();
295 0 : test();
296 0 : IF( ( ( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && ( clas == UNVOICED_CLAS || EQ_16( clas, INACTIVE_CLAS ) ) ) ||
297 : EQ_32( last_core_brate, SID_1k75 ) || EQ_32( last_core_brate, SID_2k40 ) || last_core_brate == FRAME_NO_DATA ) &&
298 : prev_bfi )
299 : {
300 : /* voiced -> unvoiced signal transition */
301 : /* CNG -> active signal transition */
302 0 : gain1 = gain2; /*Q14*/
303 0 : move16();
304 : }
305 : ELSE
306 : {
307 : /* find the energy at the beginning of the frame */
308 0 : frame_ener_fx( L_frame, clas, synth, pitch[0], &L_enr1 /*Q0*/, 1, Q_syn, 3, 0 );
309 :
310 : /*enr1 += 0.1f;*/
311 0 : L_enr1 = L_max( L_enr1, 1 ); /* L_enr1 is in Q0 */
312 :
313 : /*gain1 = (float)sqrt( enr_old / enr1 );*/
314 0 : L_tmp = Sqrt_Ratio32( L_enr_old, 0, L_enr1, 0, &exp2 );
315 0 : gain1 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */
316 :
317 : /*if( gain1 > 1.2f )gain1 = 1.2f;*/
318 : /* prevent clipping */
319 0 : gain1 = s_min( gain1, 19661 /*1.2F in Q14*/ );
320 :
321 : /* prevent amplifying the unvoiced or inactive part of the frame in case an offset is followed by an onset */
322 0 : test();
323 0 : test();
324 0 : if ( EQ_16( clas, ONSET ) && GT_16( gain1, gain2 ) && prev_bfi )
325 : {
326 0 : gain1 = gain2; /*Q14*/
327 0 : move16();
328 : }
329 : }
330 :
331 0 : L_enr2 = L_enr_q; /*Q0*/
332 0 : move32(); /* Set the end frame energy to the scaled energy, to be used in the lp_ener_FEC */
333 : }
334 :
335 : /*------------------------------------------------------------------------------*
336 : * Smooth the energy evolution by exponentially evolving from gain1 to gain2
337 : *------------------------------------------------------------------------------*/
338 :
339 : /*gain2 *= ( 1.0f - AGC );*/
340 0 : L_tmp = L_mult( gain2, (Word16) ( 32768 /*Q15*/ - AGC_FX ) );
341 0 : FOR( i = 0; i < L_frame; i++ )
342 : {
343 : /*gain1 = gain1 * AGC + gain2;*/
344 0 : gain1 = mac_r( L_tmp, gain1, AGC_FX ); /* in Q14 */
345 : /*exc[i] *= gain1;*/
346 0 : exc[i] = mac_r( L_mult( exc[i], gain1 ), exc[i], gain1 );
347 0 : move16();
348 : /*exc2[i] *= gain1;*/
349 0 : exc2[i] = mac_r_sat( L_mult( exc2[i], gain1 ), exc2[i], gain1 );
350 0 : move16();
351 : }
352 : /* smoothing is done in excitation domain, so redo synthesis */
353 0 : Copy( mem_tmp, mem_syn, M ); /* Q_syn */
354 0 : syn_12k8_fx( L_frame, Aq, exc2, synth, mem_syn, 1, Q_exc, Q_syn );
355 0 : *update_flg = 1;
356 0 : move16();
357 : }
358 : }
359 : ELSE
360 : {
361 : /* previous frame erased and no TC frame */
362 140681 : test();
363 140681 : IF( prev_bfi && NE_16( coder_type, TRANSITION ) )
364 : {
365 1446 : IF( L_enr_q == 0 )
366 : {
367 488 : L_enr_q = L_max( 1, L_enr2 ); /* sets to 'L_enr2' in 1 clock */
368 488 : set16_fx( h1, 0, L_FRAME / 2 );
369 488 : h1[0] = 1024; /*1.0f in Q10*/
370 488 : move16();
371 : /*syn_filt( Aq+(3*(M+1)), M, h1, h1, L_FRAME/2, h1+(M+1), 0 );*/
372 488 : E_UTIL_synthesis( 1, Aq + ( 3 * ( M + 1 ) ), h1, h1, L_FRAME / 2, h1 + ( M + 1 ), 0, M );
373 : /*Compute tilt */
374 : /*rr0 = dotp( h1, h1, L_FRAME/2-1 ) + 0.1f;*/
375 : /*rr1 = dotp( h1, h1+1, L_FRAME/2-1 );*/
376 : /*tilt = rr1 / rr0;*/
377 488 : tilt = extract_h( L_shl_sat( get_gain( h1 + 1, h1, L_FRAME / 2 - 1 ), 15 ) ); /*Q15*/
378 488 : test();
379 488 : test();
380 488 : test();
381 488 : test();
382 488 : test();
383 488 : test();
384 488 : test();
385 488 : test();
386 488 : IF( ( ( ( EQ_32( total_brate, ACELP_13k20 ) ) || ( EQ_32( total_brate, ACELP_12k85 ) ) || ( EQ_32( total_brate, ACELP_12k15 ) ) || ( EQ_32( total_brate, ACELP_11k60 ) ) ||
387 : ( EQ_32( total_brate, ACELP_9k60 ) ) ) &&
388 : ( GT_16( tilt, 22938 ) ) && /* HF resonnant filter */
389 : ( ( ( clas == UNVOICED_CLAS ) ) || ( EQ_16( clas, INACTIVE_CLAS ) ) ) ) ) /* unvoiced classification */
390 : {
391 : /*if( enr_q > scaling * enr_old )enr_q = scaling * enr_old;*/
392 0 : L_enr_q = L_min( L_enr_q, L_shl_sat( Mult_32_16( L_enr_old, scaling ), 1 ) ); /* scaling in Q14*/
393 : }
394 488 : ELSE IF( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) )
395 : {
396 : /* Voiced-voiced recovery */
397 262 : test();
398 262 : IF( *old_enr_LP != 0 && GT_16( enr_LP, shl_sat( *old_enr_LP, 1 ) ) )
399 : {
400 : /* enr_q /= enr_LP */
401 12 : exp = norm_l( L_enr_q );
402 12 : tmp = extract_h( L_shl( L_enr_q, exp ) );
403 :
404 12 : exp2 = norm_s( enr_LP );
405 12 : tmp2 = shl( enr_LP, exp2 );
406 :
407 12 : exp = sub( exp2, exp );
408 :
409 12 : tmp3 = sub( tmp, tmp2 );
410 12 : IF( tmp3 > 0 )
411 : {
412 4 : tmp = shr( tmp, 1 );
413 4 : exp = add( exp, 1 );
414 : }
415 12 : tmp = div_s( tmp, tmp2 ); /*Q15*/
416 :
417 : /* L_enr_q *= 2 * *old_enr_LP */
418 12 : L_enr_q = L_shl( L_mult( tmp, shl( *old_enr_LP, 1 ) ), exp ); /*Q0*/
419 : }
420 :
421 : ELSE
422 : {
423 250 : test();
424 250 : IF( avoid_lpc_burst_on_recovery && GT_16( enr_LP, 160 /*20.0f in Q3*/ ) )
425 : {
426 3 : exp = norm_s( enr_LP );
427 3 : tmp = shl( enr_LP, exp );
428 :
429 3 : exp2 = 7;
430 3 : move16();
431 3 : tmp2 = 160 << 7; /* 160 = 20.0f in Q3 */
432 3 : move16();
433 3 : exp = sub( exp2, exp );
434 :
435 3 : IF( GT_16( tmp, tmp2 ) )
436 : {
437 3 : tmp = shr( tmp, 1 );
438 3 : exp = add( exp, 1 );
439 : }
440 3 : tmp = div_s( tmp, tmp2 ); /* tmp*2^exp = enr_LP/20.0 */
441 3 : L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* L_tmp*2^exp = sqrt(20.0/enr_LP) */
442 3 : L_enr_q = L_shl( Mpy_32_32( L_enr_q, L_tmp ), exp ); /*Q0*/
443 : }
444 : }
445 : }
446 :
447 488 : test();
448 488 : test();
449 488 : test();
450 488 : test();
451 488 : IF( ( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) || force_scaling )
452 : {
453 :
454 262 : IF( GT_32( L_enr_q, L_enr_old ) ) /* Prevent energy to increase on voiced */
455 : {
456 97 : L_enr_q = L_add( Mpy_32_16_1( L_enr_old, 32767 - SCLSYN_LAMBDA ), Mpy_32_16_1( L_enr_q, SCLSYN_LAMBDA ) ); /*Q0*/
457 : }
458 : }
459 : }
460 :
461 1446 : L_enr_q = L_max( 1, L_enr_q );
462 :
463 : /* gain2 = (float)sqrt( enr_q / enr2 );*/
464 1446 : exp = norm_l( L_enr_q );
465 1446 : tmp = extract_h( L_shl( L_enr_q, exp ) );
466 :
467 1446 : exp2 = norm_l( L_enr2 );
468 1446 : tmp2 = extract_h( L_shl( L_enr2, exp2 ) );
469 :
470 1446 : exp2 = sub( exp, exp2 ); /* Denormalize and substract */
471 :
472 1446 : tmp3 = sub( tmp2, tmp );
473 1446 : IF( tmp3 > 0 )
474 : {
475 139 : tmp2 = shr( tmp2, 1 );
476 139 : exp2 = add( exp2, 1 );
477 : }
478 :
479 1446 : tmp = div_s( tmp2, tmp );
480 :
481 1446 : L_tmp = L_deposit_h( tmp );
482 1446 : L_tmp = Isqrt_lc( L_tmp, &exp2 );
483 1446 : gain2 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */
484 : /*-----------------------------------------------------------------*
485 : * Clipping of the smoothing gain at the frame end
486 : *-----------------------------------------------------------------*/
487 :
488 1446 : gain2 = s_min( gain2, 19661 /*1.2f in Q14*/ ); /* Gain modification clipping */
489 1446 : if ( LT_32( L_enr_q, 2 ) )
490 : {
491 21 : gain2 = s_min( gain2, 16384 /*1.0f in Q14*/ ); /* Gain modification clipping */
492 : }
493 :
494 : /*-----------------------------------------------------------------*
495 : * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s)
496 : *-----------------------------------------------------------------*/
497 :
498 1446 : test();
499 1446 : test();
500 1446 : test();
501 1446 : test();
502 1446 : test();
503 1446 : test();
504 1446 : IF( EQ_16( clas, SIN_ONSET ) ) /* slow increase */
505 : {
506 19 : gain1 = shr( gain2, 1 );
507 : }
508 : /*------------------------------------------------------------*
509 : * voiced->unvoiced transition recovery
510 : *------------------------------------------------------------*/
511 1427 : ELSE IF( ( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && ( clas == UNVOICED_CLAS || EQ_16( clas, INACTIVE_CLAS ) ) ) || /* voiced->unvoiced transition recovery */
512 : EQ_32( last_core_brate, SID_1k75 ) || EQ_32( last_core_brate, SID_2k40 ) || last_core_brate == FRAME_NO_DATA ) /* CNG -> active signal transition */
513 : {
514 90 : gain1 = gain2; /*Q14*/
515 90 : move16();
516 : }
517 : ELSE
518 : {
519 : /*--------------------------------------------------------*
520 : * Find the energy at the beginning of the frame
521 : *--------------------------------------------------------*/
522 1337 : tmp = frame_ener_fx( L_frame, clas, synth, pitch[0], &L_enr1, 0, Q_syn, 3, 0 );
523 :
524 : /*gain1 = (float)sqrt( enr_old / enr1 );*/
525 1337 : exp = norm_l( L_enr_old );
526 1337 : tmp = extract_h( L_shl( L_enr_old, exp ) );
527 1337 : exp2 = norm_l( L_enr1 );
528 1337 : tmp2 = extract_h( L_shl( L_enr1, exp2 ) );
529 :
530 1337 : exp2 = sub( exp, exp2 ); /* Denormalize and substract */
531 :
532 1337 : tmp3 = sub( tmp2, tmp );
533 :
534 1337 : IF( tmp3 > 0 )
535 : {
536 655 : tmp2 = shr( tmp2, 1 );
537 655 : exp2 = add( exp2, 1 );
538 : }
539 :
540 1337 : tmp = div_s( tmp2, tmp );
541 :
542 1337 : L_tmp = L_deposit_h( tmp );
543 1337 : L_tmp = Isqrt_lc( L_tmp, &exp2 );
544 1337 : gain1 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */
545 : /* exp2 is always <= 1 */
546 :
547 1337 : gain1 = s_min( gain1, 19661 /*1.2f in Q14*/ ); /*Q14*/
548 :
549 1337 : test();
550 1337 : test();
551 1337 : if ( avoid_lpc_burst_on_recovery && ( GT_16( enr_LP, 160 ) ) && ( LE_16( enr_LP, shl_sat( *old_enr_LP, 1 ) ) ) )
552 : {
553 4 : gain1 = s_min( gain1, 16384 /*1.0f in Q14*/ ); /*Q14*/
554 : }
555 :
556 : /*--------------------------------------------------------*
557 : * Prevent a catastrophy in case of offset followed by onset
558 : *--------------------------------------------------------*/
559 1337 : test();
560 1337 : if ( ( EQ_16( clas, ONSET ) ) && ( GT_16( gain1, gain2 ) ) )
561 : {
562 5 : gain1 = gain2; /*Q14*/
563 5 : move16();
564 : }
565 : }
566 : /*-----------------------------------------------------------------*
567 : * Smooth the energy evolution by exponentially evolving from
568 : * gain1 to gain2
569 : *-----------------------------------------------------------------*/
570 :
571 1446 : L_tmp = L_mult( gain2, (Word16) ( 32768 /*Q15*/ - AGC_FX ) );
572 :
573 434278 : FOR( i = 0; i < L_frame; i++ )
574 : {
575 432832 : gain1 = mac_r( L_tmp, gain1, AGC_FX ); /* in Q14 */
576 432832 : exc[i] = mac_r_sat( L_mult_sat( exc[i], gain1 ), exc[i], gain1 );
577 432832 : move16();
578 432832 : exc2[i] = mac_r_sat( L_mult_sat( exc2[i], gain1 ), exc2[i], gain1 );
579 432832 : move16();
580 : }
581 :
582 1446 : Copy( mem_tmp, mem_syn, M ); /* Q_syn */
583 1446 : syn_12k8_fx( L_frame, Aq, exc2, synth, mem_syn, 1, Q_exc, Q_syn );
584 1446 : *update_flg = 1;
585 1446 : move16();
586 : }
587 : }
588 : /*-----------------------------------------------------------------*
589 : * Update low-pass filtered energy for voiced frames
590 : *-----------------------------------------------------------------*/
591 :
592 140736 : test();
593 140736 : test();
594 140736 : IF( !bfi && ( GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) )
595 : {
596 81681 : IF( EQ_16( clas, VOICED_TRANSITION ) )
597 : {
598 5822 : L_enr2_av = L_enr2; /*Q0*/
599 5822 : move32();
600 5822 : frame_ener_fx( L_frame, VOICED_CLAS, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_ener2_max /*Q0*/, 1, Q_syn, 3, 0 );
601 : }
602 : ELSE
603 : {
604 75859 : L_ener2_max = L_enr2; /*Q0*/
605 75859 : move32();
606 75859 : frame_ener_fx( L_frame, UNVOICED_CLAS, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_enr2_av /*Q0*/, 1, Q_syn, 3, 0 );
607 : }
608 :
609 : /**lp_ener_FEC_av = 0.2f * enr2_av + 0.8f * *lp_ener_FEC_av; move32();*/
610 81681 : *lp_ener_FEC_av = Madd_32_16( Mult_32_16( *lp_ener_FEC_av, 31130 /*0.95F in Q15*/ ), L_enr2_av, 1638 /*0.05 in Q15*/ );
611 81681 : move32();
612 : /**lp_ener_FEC_max = 0.2f * enr2_max + 0.8f * *lp_ener_FEC_max; move32();*/
613 81681 : *lp_ener_FEC_max = Madd_32_16( Mult_32_16( *lp_ener_FEC_max, 31130 /*0.95F in Q15*/ ), L_ener2_max, 1638 /*0.05 in Q15*/ );
614 81681 : move32();
615 : }
616 :
617 : /*-----------------------------------------------------------------*
618 : * Update the LP filter energy for voiced frames
619 : *-----------------------------------------------------------------*/
620 140736 : test();
621 140736 : if ( GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) )
622 : {
623 81681 : *old_enr_LP = enr_LP; /*Q3*/
624 81681 : move16();
625 : }
626 :
627 140736 : return;
628 : }
|