Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 :
6 : #include <stdint.h>
7 : #include "options.h"
8 : #include "prot_fx.h"
9 : #include "basop_util.h"
10 : #include <assert.h>
11 : #include "ivas_prot_fx.h"
12 :
13 :
14 : /* static void setnoiseLevelMemory_fx()
15 : *
16 : * Helper function - updates buffer for minimumStatistics_fx function
17 : */
18 351787 : static void setnoiseLevelMemory_fx( Word16 f, Word16 *new_noiseEstimate_e, Word16 *noiseLevelMemory_e, Word16 *noiseLevelMemory, Word16 *currLevelIndex )
19 : {
20 351787 : noiseLevelMemory[*currLevelIndex] = f;
21 351787 : move16();
22 351787 : noiseLevelMemory_e[*currLevelIndex] = *new_noiseEstimate_e;
23 351787 : move16();
24 351787 : }
25 :
26 :
27 : /* PLC: [Common: Fade-out]
28 : * PLC: and for PLC fade out */
29 :
30 351787 : void minimumStatistics_fx(
31 : Word16 *noiseLevelMemory, /* Qx, internal state */
32 : Word16 *noiseLevelIndex, /* Q0, internal state */
33 : Word16 *currLevelIndex, /* Q0, internal state (circular buffer) */
34 : Word16 *noiseEstimate, /* Qx, previous estimate of background noise */
35 : Word16 *lastFrameLevel, /* Qx, level of the last frame */
36 : Word16 currentFrameLevel, /* Qx, level of the current frame */
37 : Word16 *noiseLevelMemory_e, /* scaling factor for noiseLevelMemory */
38 : Word16 const noiseEstimate_e, /* exponent of noiseEstimate */
39 : Word16 *new_noiseEstimate_e, /* new exponent of noise Estimate*/
40 : Word16 *const lastFrameLevel_e, /* exponent of lastFrameLevel */
41 : Word16 currentFrameLevel_e ) /* exponent of currentFrameLevel */
42 : {
43 : Word16 aOpt, aOpt_e;
44 : Word16 f, p, i;
45 : Word16 tmp, tmp2, tmp_e;
46 : Word32 tmp32;
47 : #ifndef ISSUE_1866_replace_overflow_libdec
48 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
49 : Flag Overflow = 0;
50 : move16();
51 : #endif
52 : #endif
53 351787 : aOpt_e = 0;
54 351787 : move16();
55 :
56 :
57 : BASOP_SATURATE_WARNING_OFF_EVS
58 : #ifdef ISSUE_1866_replace_overflow_libdec
59 351787 : IF( LT_16( shl_sat( currentFrameLevel, currentFrameLevel_e ), PLC_MIN_CNG_LEV ) )
60 : #else
61 : IF( LT_16( shl_o( currentFrameLevel, currentFrameLevel_e, &Overflow ), PLC_MIN_CNG_LEV ) )
62 : #endif
63 : {
64 : BASOP_SATURATE_WARNING_ON_EVS
65 68001 : currentFrameLevel = PLC_MIN_CNG_LEV; /*Q15*/
66 68001 : move16();
67 68001 : currentFrameLevel_e = 0;
68 68001 : move16();
69 : }
70 : BASOP_SATURATE_WARNING_ON_EVS
71 :
72 : /* compute optimal factor aOpt for recursive smoothing of frame minima */
73 351787 : tmp2 = BASOP_Util_Add_MantExp( *lastFrameLevel, *lastFrameLevel_e, negate( *noiseEstimate ), noiseEstimate_e, &tmp );
74 351787 : IF( tmp >= 0 )
75 : {
76 : /* aOpt = *noiseEstimate / *lastFrameLevel; */
77 290119 : aOpt = BASOP_Util_Divide1616_Scale( *noiseEstimate, *lastFrameLevel, &aOpt_e ); /*Q16-aOpt_e*/
78 290119 : aOpt_e = add( aOpt_e, sub( noiseEstimate_e, *lastFrameLevel_e ) );
79 : }
80 : ELSE
81 : {
82 : /* aOpt = *lastFrameLevel / *noiseEstimate; */
83 61668 : aOpt = BASOP_Util_Divide1616_Scale( *lastFrameLevel, *noiseEstimate, &aOpt_e ); /*Q16-aOpt_e*/
84 61668 : aOpt_e = add( aOpt_e, sub( *lastFrameLevel_e, noiseEstimate_e ) );
85 : }
86 351787 : aOpt = mult_r( aOpt, aOpt ); /* Q15 */
87 351787 : aOpt_e = shl( aOpt_e, 1 );
88 351787 : if ( aOpt == 0 )
89 : {
90 0 : aOpt_e = 0;
91 0 : move16();
92 : }
93 :
94 351787 : *lastFrameLevel = currentFrameLevel; /*Qx*/
95 351787 : move16();
96 351787 : *lastFrameLevel_e = currentFrameLevel_e;
97 351787 : move16();
98 :
99 : /* recursively compute smoothed frame minima using optimal factor aOpt */
100 351787 : tmp = *currLevelIndex;
101 351787 : move16();
102 351787 : if ( tmp == 0 )
103 : {
104 13904 : tmp = PLC_MIN_STAT_BUFF_SIZE; /*Q0*/
105 13904 : move16();
106 : }
107 : /*f = msu_r(L_mult(aOpt, noiseLevelMemory[sub(tmp, 1)]), add(aOpt, 0x8000), currentFrameLevel);*/
108 : /*f = (aOpt * noiseLevelMemory[tmp-1]) - (currentFrameLevel * (aOpt-1))*/
109 : /*tmp32*/ /*tmp*/
110 :
111 351787 : tmp32 = L_mult( aOpt, noiseLevelMemory[sub( tmp, 1 )] ); /*Q_tmp32 = aOpt_e + noiseLevelMemory_e[tmp - 1]*/
112 351787 : tmp_e = tmp;
113 351787 : move16();
114 :
115 :
116 351787 : tmp2 = BASOP_Util_Add_MantExp( aOpt, aOpt_e, negate( 32768 / 2 ), 1, &tmp );
117 351787 : tmp = mult_r( tmp, currentFrameLevel ); /*Q_tmp = tmp2 + currentFrameLevel_e*/
118 351787 : tmp2 = add( tmp2, currentFrameLevel_e );
119 :
120 351787 : if ( tmp == 0 )
121 : {
122 73248 : tmp2 = 0;
123 73248 : move16();
124 : }
125 :
126 351787 : *new_noiseEstimate_e = BASOP_Util_Add_MantExp( round_fx( tmp32 ), add( aOpt_e, noiseLevelMemory_e[sub( tmp_e, 1 )] ), negate( s_max( tmp, -32767 ) /*to avoid negate(-32768)*/ ), tmp2, &f );
127 351787 : move16();
128 :
129 351787 : assert( f >= 0 );
130 :
131 : /* if current frame min is a new local min, set index to current index */
132 351787 : p = *noiseLevelIndex; /*Q0*/
133 351787 : move16();
134 351787 : tmp2 = BASOP_Util_Add_MantExp( noiseLevelMemory[p], noiseLevelMemory_e[p], negate( f ), *new_noiseEstimate_e, &tmp );
135 351787 : IF( tmp >= 0 )
136 : {
137 :
138 : /*rescale noiseLevelMemory*/
139 :
140 88371 : setnoiseLevelMemory_fx( f, new_noiseEstimate_e, noiseLevelMemory_e, noiseLevelMemory, currLevelIndex );
141 88371 : p = *currLevelIndex; /*Q0*/
142 88371 : move16();
143 : }
144 : ELSE
145 : {
146 263416 : setnoiseLevelMemory_fx( f, new_noiseEstimate_e, noiseLevelMemory_e, noiseLevelMemory, currLevelIndex );
147 :
148 : /* current min is not a new min, so check if min must be re-searched */
149 263416 : IF( NE_16( p, *currLevelIndex ) )
150 : {
151 250296 : f = noiseLevelMemory[p]; /* min is still in memory, so return it Qx*/
152 250296 : move16();
153 250296 : *new_noiseEstimate_e = noiseLevelMemory_e[p];
154 250296 : move16();
155 : }
156 : ELSE
157 : {
158 : /* p == currLevelIndex; min was removed from memory, re-search min */
159 669120 : FOR( i = 0; i < PLC_MIN_STAT_BUFF_SIZE; i++ )
160 : {
161 656000 : tmp2 = BASOP_Util_Add_MantExp( noiseLevelMemory[p], noiseLevelMemory_e[p], negate( noiseLevelMemory[i] ), noiseLevelMemory_e[i], &tmp );
162 656000 : if ( tmp > 0 )
163 : {
164 45865 : p = i;
165 45865 : move16();
166 : }
167 : }
168 13120 : f = noiseLevelMemory[p]; /*Qx*/
169 13120 : move16();
170 13120 : *new_noiseEstimate_e = noiseLevelMemory_e[p];
171 13120 : move16();
172 : }
173 : }
174 :
175 : /* update local-minimum-value index and current circular-buffer index */
176 351787 : *noiseLevelIndex = p; /*Q0*/
177 351787 : move16();
178 351787 : p = add( *currLevelIndex, 1 );
179 351787 : *currLevelIndex = add( *currLevelIndex, 1 ); /*Q0*/
180 351787 : move16();
181 351787 : if ( EQ_16( *currLevelIndex, PLC_MIN_STAT_BUFF_SIZE ) )
182 : {
183 5548 : *currLevelIndex = 0;
184 5548 : move16();
185 : }
186 :
187 351787 : *noiseEstimate = f; /*Qx*/
188 351787 : move16();
189 351787 : }
190 :
191 : /*----------------------------------------------------------------------*
192 : * PLC: [ACELP: Fade-out]
193 : * PLC: getLevelSynDeemph_fx: derives on frame or subframe basis the level
194 : * of LPC synthesis and deeemphasis based on the given input
195 : *----------------------------------------------------------------------*/
196 4652 : Word16 getLevelSynDeemph_fx( /*10Q5*/
197 : Word16 h1Init[],
198 : /* i: input value or vector to be processed */ /* Q15 */
199 : Word16 const A[],
200 : /* i: LPC coefficients */ /* Qx */
201 : Word16 const lpcorder,
202 : /* i: LPC order */ /* Q0 */
203 : Word16 const lenLpcExc,
204 : /* i: length of the LPC excitation buffer */ /* Q0 */
205 : Word16 const preemph_fac,
206 : /* i: preemphasis factor */ /* Q15 */
207 : Word16 const numLoops,
208 : /* i: number of loops */ /* Q0 */
209 : Word16 *Exp /* o: exponent of return value Q15 */
210 : )
211 : {
212 : Word32 levelSynDeemphSub;
213 : Word32 levelSynDeemph;
214 : Word16 h1[L_FRAME_PLUS / 4]; /*Q15*/
215 : Word16 mem[M];
216 : Word16 tmp;
217 : Word16 loop;
218 : Word16 s16, tmp16, Hr16;
219 : Word16 Q_h1;
220 :
221 :
222 4652 : levelSynDeemphSub = L_deposit_l( 0 );
223 4652 : levelSynDeemph = L_deposit_l( 0 );
224 4652 : tmp = 0;
225 4652 : move16();
226 4652 : Q_h1 = 9; /*synthesis scaling for */
227 4652 : move16();
228 :
229 : /*calculate headroom for dotproduct*/
230 4652 : Hr16 = sub( 15, norm_s( lenLpcExc ) ); /*Q0*/
231 :
232 4652 : Q_h1 = s_max( sub( Q_h1, Hr16 ), 0 ); /*compensate synthesis scaling with Headroom as much as possible to retain as much precision as possible*/
233 :
234 : /*Factor to be multiplied in order to calculate dotproduct with headroom*/
235 4652 : tmp16 = shr( 32768 / 2, sub( Hr16, 1 ) ); /*Q15*/
236 :
237 : /*moved from inside loop, before synthesis*/
238 4652 : h1Init[0] = mult_r( h1Init[0], tmp16 ); /*Q15*/
239 4652 : move16();
240 :
241 9304 : FOR( loop = 0; loop < numLoops; loop++ )
242 : {
243 4652 : set16_fx( h1, 0, lenLpcExc );
244 4652 : set16_fx( mem, 0, lpcorder );
245 :
246 4652 : Copy( h1Init, h1, 1 ); /*Q15*/
247 : /*h1 will be scaled down, Q_h1 */
248 4652 : E_UTIL_synthesis( Q_h1, A, h1, h1, lenLpcExc, mem, 0, lpcorder );
249 4652 : deemph_fx( h1, preemph_fac, lenLpcExc, &tmp );
250 4652 : A += ( M + 1 );
251 :
252 : /* gain introduced by synthesis+deemphasis */
253 : /*levelSynDeemphSub = (float)sqrt(dot_product( h1, h1, lenLpcExc));*/
254 4652 : levelSynDeemphSub = Dot_product12_offs( h1, h1, lenLpcExc, &s16, 0 ); /*Q31 - s16*/
255 4652 : s16 = sub( shl( add( Q_h1, Hr16 ), 1 ), sub( 30, s16 ) );
256 :
257 4652 : levelSynDeemphSub = Sqrt32( levelSynDeemphSub, &s16 ); /*Q31 - s16*/
258 :
259 : /* mean of the above across all subframes -- moved outta loop*/
260 : /*levelSynDeemph += (1.0/(float)numLoops) * levelSynDeemphSub;*/
261 4652 : tmp16 = 32767 /*1.0f Q15*/;
262 4652 : move16();
263 :
264 4652 : if ( GT_16( numLoops, 1 ) )
265 : {
266 0 : tmp16 = div_s( 1, numLoops ); /*Q15*/
267 : }
268 :
269 4652 : levelSynDeemph = L_add( levelSynDeemph, L_shl( Mpy_32_16_1( levelSynDeemphSub, tmp16 ), sub( s16, 10 ) ) ); /*10Q21*/
270 : }
271 4652 : s16 = norm_l( levelSynDeemph );
272 4652 : levelSynDeemph = L_shl( levelSynDeemph, s16 ); /*Q31*/
273 4652 : *Exp = sub( 10, s16 ); /*Set exponent in order to transform returnvalue to Q15*/
274 4652 : move16();
275 :
276 4652 : return round_fx_sat( levelSynDeemph ); /*Q15*/
277 : }
278 :
279 : /* BASOP version: up to date with rev 7422 */
280 0 : void genPlcFiltBWAdap_fx(
281 : const Word32 sr_core, /* i : core sampling rate Q0*/
282 : Word16 *lpFiltAdapt, /* o : filter coefficients for filtering codebooks in case of flc Q15*/
283 : const Word16 type, /* i : type of filter, either 0 : lowpass or 1 : highpass Q0*/
284 : const Word16 alpha /* i : fade out factor [0 1) used decrease filter tilt Q15*/
285 : )
286 : {
287 : Word16 a, b, exp;
288 :
289 :
290 0 : assert( type == 0 || type == 1 );
291 :
292 0 : IF( EQ_32( sr_core, INT_FS_16k ) )
293 : {
294 0 : IF( type == 0 )
295 : {
296 0 : *lpFiltAdapt++ = 7282 /* 0.4000f/(2.f*0.4000f+1.f) Q15*/;
297 0 : move16();
298 0 : *lpFiltAdapt++ = 18204 /* 1.f/(2.f*0.4000f+1.f) Q15*/;
299 0 : move16();
300 0 : *lpFiltAdapt = 7282 /* 0.4000f/(2.f*0.4000f+1.f) Q15*/;
301 0 : move16();
302 : }
303 : ELSE
304 : {
305 0 : a = mult_r( 13107 /*0.4000f Q15*/, alpha ); /*Q15*/
306 0 : exp = 0;
307 0 : move16();
308 0 : b = Inv16( add( a, 16384 /*0.5f Q15*/ ), &exp ); /*Q15 - exp*/
309 0 : b = shr( b, sub( 1, exp ) ); /*Q15*/
310 0 : a = negate( mult_r( a, b ) ); /*Q15*/
311 0 : *lpFiltAdapt++ = a; /*Q15*/
312 0 : move16();
313 0 : *lpFiltAdapt++ = b; /*Q15*/
314 0 : move16();
315 0 : *lpFiltAdapt = a; /*Q15*/
316 0 : move16();
317 : }
318 : }
319 : ELSE /*sr_core = INT_FS_12k8 */
320 : {
321 0 : IF( type == 0 )
322 : {
323 0 : *lpFiltAdapt++ = 5899 /* 0.2813f/(2.f*0.2813f+1.f) Q15*/;
324 0 : move16();
325 0 : *lpFiltAdapt++ = 20970 /* 1.f/(2.f*0.2813f+1.f) Q15*/;
326 0 : move16();
327 0 : *lpFiltAdapt = 5899 /* 0.2813f/(2.f*0.2813f+1.f) Q15*/;
328 0 : move16();
329 : }
330 : ELSE
331 : {
332 0 : a = mult_r( 9218 /*0.2813f Q15*/, alpha ); /*Q15*/
333 0 : exp = 0;
334 0 : move16();
335 0 : b = Inv16( add( a, 16384 /*0.5f Q15*/ ), &exp ); /*Q15 - exp*/
336 0 : b = shr( b, sub( 1, exp ) ); /*Q15*/
337 0 : a = negate( mult_r( a, b ) ); /*Q15*/
338 0 : *lpFiltAdapt++ = a; /*Q15*/
339 0 : move16();
340 0 : *lpFiltAdapt++ = b; /*Q15*/
341 0 : move16();
342 0 : *lpFiltAdapt = a; /*Q15*/
343 0 : move16();
344 : }
345 : }
346 0 : }
347 :
348 :
349 : /*-----------------------------------------------------------------*
350 : * PLC: [ACELP: general]
351 : * PLC: high pass filtering
352 : *-----------------------------------------------------------------*/
353 : /*VERSIONINFO: This port is up to date with trunk rev. 32434*/
354 2360 : void highPassFiltering_fx(
355 : const Word16 last_good, /* i: short last classification type Q0*/
356 : const Word16 L_buffer, /* i: int buffer length Q0*/
357 : Word16 exc2[], /* i/o: Qx unvoiced excitation before the high pass filtering */
358 : const Word16 hp_filt[], /* i: Q15 high pass filter coefficients */
359 : const Word16 l_fir_fer ) /* i: high pass filter length Q0*/
360 :
361 : {
362 : Word16 i; /*int*/
363 :
364 2360 : IF( GT_16( last_good, UNVOICED_TRANSITION ) )
365 : {
366 2593440 : FOR( i = 0; i < L_buffer; i++ )
367 : {
368 2591080 : exc2[i] = round_fx( L_sub( Dot_product( &exc2[i], hp_filt, l_fir_fer ), 1 ) ); /*Qx*/
369 2591080 : move16();
370 : }
371 : }
372 2360 : }
373 :
374 : /*----------------------------------------------------------------------------------*
375 : * PLC: [Common: mode decision]
376 : * PLC: Decide which Concealment to use. Update pitch lags if needed
377 : *----------------------------------------------------------------------------------*/
378 13326 : Word16 GetPLCModeDecision_ivas_fx(
379 : Decoder_State *st /* i/o: decoder memory state pointer */
380 : )
381 : {
382 : Word16 /*int*/ core;
383 13326 : Word16 numIndices = 0;
384 : TCX_DEC_HANDLE hTcxDec;
385 :
386 13326 : hTcxDec = st->hTcxDec;
387 :
388 13326 : IF( EQ_16( st->flagGuidedAcelp, 1 ) )
389 : {
390 0 : st->old_pitch_buf_fx[( st->nb_subfr * 2 )] = L_deposit_h( st->guidedT0 ); /*Q16*/
391 0 : move32();
392 0 : st->old_pitch_buf_fx[( ( st->nb_subfr * 2 ) + 1 )] = L_deposit_h( st->guidedT0 ); /*Q16*/
393 0 : move32();
394 0 : st->mem_pitch_gain[0] = st->mem_pitch_gain[1] = 16384 /*1.f Q14*/; /*Q14*/
395 0 : move16();
396 0 : move16();
397 : }
398 13326 : st->plc_use_future_lag = 0;
399 13326 : move16();
400 13326 : test();
401 13326 : test();
402 13326 : if ( ( st->last_core > ACELP_CORE && hTcxDec->tcxltp_last_gain_unmodified != 0 ) || ( EQ_16( st->flagGuidedAcelp, 1 ) ) )
403 : {
404 : /* no updates needed here, because already updated in last good frame */
405 10580 : st->plc_use_future_lag = 1;
406 10580 : move16();
407 : }
408 :
409 13326 : IF( EQ_16( st->last_core, -1 ) )
410 : {
411 0 : core = TCX_20_CORE;
412 0 : move16();
413 0 : st->last_core = ACELP_CORE;
414 0 : move16();
415 0 : if ( st->Opt_AMR_WB )
416 : {
417 0 : core = ACELP_CORE;
418 0 : move16();
419 : }
420 0 : st->tonal_mdct_plc_active = 0;
421 0 : move16();
422 : }
423 : ELSE
424 : {
425 13326 : core = ACELP_CORE;
426 13326 : move16();
427 13326 : if ( GT_16( st->nbLostCmpt, 1 ) )
428 : {
429 6193 : core = st->last_core_bfi; /*Q0*/
430 6193 : move16();
431 : }
432 13326 : IF( EQ_16( st->nbLostCmpt, 1 ) )
433 : {
434 7133 : st->tonal_mdct_plc_active = 0;
435 7133 : move16();
436 7133 : test();
437 7133 : test();
438 7133 : test();
439 7133 : IF( !( st->rf_flag && st->use_partial_copy && ( EQ_16( st->rf_frame_type, RF_TCXTD1 ) || EQ_16( st->rf_frame_type, RF_TCXTD2 ) ) ) )
440 : {
441 7133 : test();
442 7133 : test();
443 7133 : test();
444 7133 : test();
445 7133 : test();
446 7133 : test();
447 7133 : test();
448 7133 : IF( ( st->hTonalMDCTConc != NULL && EQ_16( st->last_core, TCX_20_CORE ) ) && ( EQ_16( st->second_last_core, TCX_20_CORE ) ) && ( ( LE_32( st->old_fpitch, L_deposit_h( shr( st->L_frame, 1 ) ) ) ) || ( LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) ) )
449 : /* it is fine to call the detection even if no ltp information
450 : is available, meaning that st->old_fpitch ==
451 : st->tcxltp_second_last_pitch == st->L_frame */
452 : && ( EQ_32( st->old_fpitch, hTcxDec->tcxltp_second_last_pitch ) ) && !st->last_tns_active && !st->second_last_tns_active )
453 1673 : {
454 : Word32 pitch;
455 :
456 1673 : pitch = L_deposit_h( 0 );
457 1673 : if ( hTcxDec->tcxltp_last_gain_unmodified > 0 )
458 : {
459 436 : pitch = L_add( st->old_fpitch, 0 ); /*Q16*/
460 : }
461 :
462 1673 : TonalMDCTConceal_Detect_ivas_fx( st->hTonalMDCTConc, pitch, &numIndices, ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ? &( st->hTcxCfg->psychParamsTCX20 ) : st->hTcxCfg->psychParamsCurrent ), st->element_mode );
463 :
464 1673 : test();
465 1673 : test();
466 1673 : test();
467 1673 : test();
468 1673 : test();
469 1673 : test();
470 1673 : test();
471 1673 : IF( ( GT_16( numIndices, 10 ) ) || ( ( GT_16( numIndices, 5 ) ) && ( LT_32( L_abs( L_sub( hTcxDec->tcxltp_third_last_pitch, hTcxDec->tcxltp_second_last_pitch ) ), 32768l /*0.5f Q16*/ ) ) ) || ( ( numIndices > 0 ) && ( ( LE_16( st->last_good, UNVOICED_TRANSITION ) ) || ( LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) ) ) && ( LT_32( L_abs( L_sub( hTcxDec->tcxltp_third_last_pitch, hTcxDec->tcxltp_second_last_pitch ) ), 32768l /*0.5f Q16*/ ) ) ) )
472 : {
473 369 : core = TCX_20_CORE;
474 369 : move16();
475 369 : st->tonal_mdct_plc_active = 1;
476 369 : move16();
477 : }
478 1304 : ELSE IF( LE_16( st->last_good, UNVOICED_TRANSITION ) || LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) )
479 : {
480 1195 : core = TCX_20_CORE;
481 1195 : move16();
482 : }
483 : }
484 5460 : ELSE IF( st->last_core != ACELP_CORE )
485 : {
486 5460 : test();
487 5460 : if ( LE_16( st->last_good, UNVOICED_TRANSITION ) || LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) )
488 : {
489 3178 : core = st->last_core;
490 3178 : move16();
491 : }
492 : }
493 : }
494 : }
495 : }
496 13326 : return core; /*Q0*/
497 : }
498 :
499 0 : Word16 GetPLCModeDecision_fx(
500 : Decoder_State *st /* i/o: decoder memory state pointer */
501 : )
502 : {
503 : Word16 /*int*/ core;
504 : Word16 numIndices;
505 : TCX_DEC_HANDLE hTcxDec;
506 :
507 0 : numIndices = 0;
508 0 : move16();
509 :
510 0 : hTcxDec = st->hTcxDec;
511 :
512 :
513 0 : IF( EQ_16( st->flagGuidedAcelp, 1 ) )
514 : {
515 0 : st->old_pitch_buf_fx[( st->nb_subfr * 2 )] = L_deposit_h( st->guidedT0 ); /*Q16*/
516 0 : move32();
517 0 : st->old_pitch_buf_fx[( ( st->nb_subfr * 2 ) + 1 )] = L_deposit_h( st->guidedT0 ); /*Q16*/
518 0 : move32();
519 0 : st->mem_pitch_gain[0] = st->mem_pitch_gain[1] = 16384 /*1.f Q14*/; /*Q14*/
520 0 : move16();
521 0 : move16();
522 : }
523 0 : st->plc_use_future_lag = 0;
524 0 : move16();
525 0 : test();
526 0 : test();
527 0 : if ( ( st->last_core > ACELP_CORE && hTcxDec->tcxltp_last_gain_unmodified != 0 ) || ( EQ_16( st->flagGuidedAcelp, 1 ) ) )
528 : {
529 : /* no updates needed here, because already updated in last good frame */
530 0 : st->plc_use_future_lag = 1;
531 0 : move16();
532 : }
533 :
534 0 : IF( EQ_16( st->last_core, -1 ) )
535 : {
536 0 : core = TCX_20_CORE;
537 0 : move16();
538 0 : st->last_core = ACELP_CORE;
539 0 : move16();
540 0 : if ( st->Opt_AMR_WB )
541 : {
542 0 : core = ACELP_CORE;
543 0 : move16();
544 : }
545 0 : st->tonal_mdct_plc_active = 0;
546 0 : move16();
547 : }
548 : ELSE
549 : {
550 0 : core = ACELP_CORE;
551 0 : move16();
552 0 : if ( GT_16( st->nbLostCmpt, 1 ) )
553 : {
554 0 : core = st->last_core_bfi;
555 0 : move16();
556 : }
557 :
558 0 : IF( EQ_16( st->nbLostCmpt, 1 ) )
559 : {
560 0 : st->tonal_mdct_plc_active = 0;
561 0 : move16();
562 0 : test();
563 0 : test();
564 0 : test();
565 0 : IF( !( st->rf_flag && st->use_partial_copy && ( EQ_16( st->rf_frame_type, RF_TCXTD1 ) || EQ_16( st->rf_frame_type, RF_TCXTD2 ) ) ) )
566 : {
567 0 : test();
568 0 : test();
569 0 : test();
570 0 : test();
571 0 : test();
572 0 : test();
573 0 : IF( ( st->hTonalMDCTConc != NULL && EQ_16( st->last_core, TCX_20_CORE ) ) && ( EQ_16( st->second_last_core, TCX_20_CORE ) ) && ( ( LE_32( st->old_fpitch, L_deposit_h( shr( st->L_frame, 1 ) ) ) ) || ( LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) ) )
574 : /* it is fine to call the detection even if no ltp information
575 : is available, meaning that st->old_fpitch ==
576 : st->tcxltp_second_last_pitch == st->L_frame */
577 : && ( EQ_32( st->old_fpitch, hTcxDec->tcxltp_second_last_pitch ) ) && !st->last_tns_active && !st->second_last_tns_active )
578 0 : {
579 : Word32 pitch;
580 :
581 :
582 0 : pitch = L_deposit_h( 0 );
583 0 : if ( hTcxDec->tcxltp_last_gain_unmodified > 0 )
584 : {
585 0 : pitch = L_add( st->old_fpitch, 0 ); /*Q16*/
586 : }
587 :
588 0 : TonalMDCTConceal_Detect( st->hTonalMDCTConc, pitch, &numIndices, st->element_mode );
589 :
590 0 : test();
591 0 : test();
592 0 : test();
593 0 : test();
594 0 : test();
595 0 : test();
596 0 : test();
597 0 : IF( ( GT_16( numIndices, 10 ) ) || ( ( GT_16( numIndices, 5 ) ) && ( LT_32( L_abs( L_sub( hTcxDec->tcxltp_third_last_pitch, hTcxDec->tcxltp_second_last_pitch ) ), 32768l /*0.5f Q16*/ ) ) ) || ( ( numIndices > 0 ) && ( ( LE_16( st->last_good, UNVOICED_TRANSITION ) ) || ( LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) ) ) && ( LT_32( L_abs( L_sub( hTcxDec->tcxltp_third_last_pitch, hTcxDec->tcxltp_second_last_pitch ) ), 32768l /*0.5f Q16*/ ) ) ) )
598 : {
599 0 : core = TCX_20_CORE;
600 0 : move16();
601 0 : st->tonal_mdct_plc_active = 1;
602 0 : move16();
603 : }
604 0 : ELSE IF( LE_16( st->last_good, UNVOICED_TRANSITION ) || LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) )
605 : {
606 0 : core = TCX_20_CORE;
607 0 : move16();
608 : }
609 : }
610 0 : ELSE IF( st->last_core != ACELP_CORE )
611 : {
612 0 : test();
613 0 : if ( LE_16( st->last_good, UNVOICED_TRANSITION ) || LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) )
614 : {
615 0 : core = st->last_core;
616 0 : move16();
617 : }
618 : }
619 : }
620 : }
621 : }
622 0 : return core;
623 : }
|