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