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 352010 : static void setnoiseLevelMemory_fx( Word16 f, Word16 *new_noiseEstimate_e, Word16 *noiseLevelMemory_e, Word16 *noiseLevelMemory, Word16 *currLevelIndex )
19 : {
20 352010 : noiseLevelMemory[*currLevelIndex] = f;
21 352010 : move16();
22 352010 : noiseLevelMemory_e[*currLevelIndex] = *new_noiseEstimate_e;
23 352010 : move16();
24 352010 : }
25 :
26 :
27 : /* PLC: [Common: Fade-out]
28 : * PLC: and for PLC fade out */
29 :
30 352010 : 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 352010 : aOpt_e = 0;
48 352010 : move16();
49 :
50 :
51 : BASOP_SATURATE_WARNING_OFF_EVS
52 352010 : IF( LT_16( shl_sat( currentFrameLevel, currentFrameLevel_e ), PLC_MIN_CNG_LEV ) )
53 : {
54 : BASOP_SATURATE_WARNING_ON_EVS
55 67948 : currentFrameLevel = PLC_MIN_CNG_LEV; /*Q15*/
56 67948 : move16();
57 67948 : currentFrameLevel_e = 0;
58 67948 : move16();
59 : }
60 : BASOP_SATURATE_WARNING_ON_EVS
61 :
62 : /* compute optimal factor aOpt for recursive smoothing of frame minima */
63 352010 : tmp2 = BASOP_Util_Add_MantExp( *lastFrameLevel, *lastFrameLevel_e, negate( *noiseEstimate ), noiseEstimate_e, &tmp );
64 352010 : IF( tmp >= 0 )
65 : {
66 : /* aOpt = *noiseEstimate / *lastFrameLevel; */
67 290335 : aOpt = BASOP_Util_Divide1616_Scale( *noiseEstimate, *lastFrameLevel, &aOpt_e ); /*Q16-aOpt_e*/
68 290335 : aOpt_e = add( aOpt_e, sub( noiseEstimate_e, *lastFrameLevel_e ) );
69 : }
70 : ELSE
71 : {
72 : /* aOpt = *lastFrameLevel / *noiseEstimate; */
73 61675 : aOpt = BASOP_Util_Divide1616_Scale( *lastFrameLevel, *noiseEstimate, &aOpt_e ); /*Q16-aOpt_e*/
74 61675 : aOpt_e = add( aOpt_e, sub( *lastFrameLevel_e, noiseEstimate_e ) );
75 : }
76 352010 : aOpt = mult_r( aOpt, aOpt ); /* Q15 */
77 352010 : aOpt_e = shl( aOpt_e, 1 );
78 352010 : if ( aOpt == 0 )
79 : {
80 0 : aOpt_e = 0;
81 0 : move16();
82 : }
83 :
84 352010 : *lastFrameLevel = currentFrameLevel; /*Qx*/
85 352010 : move16();
86 352010 : *lastFrameLevel_e = currentFrameLevel_e;
87 352010 : move16();
88 :
89 : /* recursively compute smoothed frame minima using optimal factor aOpt */
90 352010 : tmp = *currLevelIndex;
91 352010 : move16();
92 352010 : if ( tmp == 0 )
93 : {
94 13902 : tmp = PLC_MIN_STAT_BUFF_SIZE; /*Q0*/
95 13902 : 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 352010 : tmp32 = L_mult( aOpt, noiseLevelMemory[sub( tmp, 1 )] ); /*Q_tmp32 = aOpt_e + noiseLevelMemory_e[tmp - 1]*/
102 352010 : tmp_e = tmp;
103 352010 : move16();
104 :
105 :
106 352010 : tmp2 = BASOP_Util_Add_MantExp( aOpt, aOpt_e, negate( 32768 / 2 ), 1, &tmp );
107 352010 : tmp = mult_r( tmp, currentFrameLevel ); /*Q_tmp = tmp2 + currentFrameLevel_e*/
108 352010 : tmp2 = add( tmp2, currentFrameLevel_e );
109 :
110 352010 : if ( tmp == 0 )
111 : {
112 73220 : tmp2 = 0;
113 73220 : move16();
114 : }
115 :
116 352010 : *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 352010 : move16();
118 :
119 352010 : assert( f >= 0 );
120 :
121 : /* if current frame min is a new local min, set index to current index */
122 352010 : p = *noiseLevelIndex; /*Q0*/
123 352010 : move16();
124 352010 : tmp2 = BASOP_Util_Add_MantExp( noiseLevelMemory[p], noiseLevelMemory_e[p], negate( f ), *new_noiseEstimate_e, &tmp );
125 352010 : IF( tmp >= 0 )
126 : {
127 :
128 : /*rescale noiseLevelMemory*/
129 :
130 88357 : setnoiseLevelMemory_fx( f, new_noiseEstimate_e, noiseLevelMemory_e, noiseLevelMemory, currLevelIndex );
131 88357 : p = *currLevelIndex; /*Q0*/
132 88357 : move16();
133 : }
134 : ELSE
135 : {
136 263653 : 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 263653 : IF( NE_16( p, *currLevelIndex ) )
140 : {
141 250343 : f = noiseLevelMemory[p]; /* min is still in memory, so return it Qx*/
142 250343 : move16();
143 250343 : *new_noiseEstimate_e = noiseLevelMemory_e[p];
144 250343 : move16();
145 : }
146 : ELSE
147 : {
148 : /* p == currLevelIndex; min was removed from memory, re-search min */
149 678810 : FOR( i = 0; i < PLC_MIN_STAT_BUFF_SIZE; i++ )
150 : {
151 665500 : tmp2 = BASOP_Util_Add_MantExp( noiseLevelMemory[p], noiseLevelMemory_e[p], negate( noiseLevelMemory[i] ), noiseLevelMemory_e[i], &tmp );
152 665500 : if ( tmp > 0 )
153 : {
154 46801 : p = i;
155 46801 : move16();
156 : }
157 : }
158 13310 : f = noiseLevelMemory[p]; /*Qx*/
159 13310 : move16();
160 13310 : *new_noiseEstimate_e = noiseLevelMemory_e[p];
161 13310 : move16();
162 : }
163 : }
164 :
165 : /* update local-minimum-value index and current circular-buffer index */
166 352010 : *noiseLevelIndex = p; /*Q0*/
167 352010 : move16();
168 352010 : p = add( *currLevelIndex, 1 );
169 352010 : *currLevelIndex = add( *currLevelIndex, 1 ); /*Q0*/
170 352010 : move16();
171 352010 : if ( EQ_16( *currLevelIndex, PLC_MIN_STAT_BUFF_SIZE ) )
172 : {
173 5560 : *currLevelIndex = 0;
174 5560 : move16();
175 : }
176 :
177 352010 : *noiseEstimate = f; /*Qx*/
178 352010 : move16();
179 352010 : }
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 4802 : 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 4802 : levelSynDeemphSub = L_deposit_l( 0 );
213 4802 : levelSynDeemph = L_deposit_l( 0 );
214 4802 : tmp = 0;
215 4802 : move16();
216 4802 : Q_h1 = 9; /*synthesis scaling for */
217 4802 : move16();
218 :
219 : /*calculate headroom for dotproduct*/
220 4802 : Hr16 = sub( 15, norm_s( lenLpcExc ) ); /*Q0*/
221 :
222 4802 : 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 4802 : tmp16 = shr( 32768 / 2, sub( Hr16, 1 ) ); /*Q15*/
226 :
227 : /*moved from inside loop, before synthesis*/
228 4802 : h1Init[0] = mult_r( h1Init[0], tmp16 ); /*Q15*/
229 4802 : move16();
230 :
231 9604 : FOR( loop = 0; loop < numLoops; loop++ )
232 : {
233 4802 : set16_fx( h1, 0, lenLpcExc );
234 4802 : set16_fx( mem, 0, lpcorder );
235 :
236 4802 : Copy( h1Init, h1, 1 ); /*Q15*/
237 : /*h1 will be scaled down, Q_h1 */
238 4802 : E_UTIL_synthesis( Q_h1, A, h1, h1, lenLpcExc, mem, 0, lpcorder );
239 4802 : deemph_fx( h1, preemph_fac, lenLpcExc, &tmp );
240 4802 : A += ( M + 1 );
241 :
242 : /* gain introduced by synthesis+deemphasis */
243 : /*levelSynDeemphSub = (float)sqrt(dot_product( h1, h1, lenLpcExc));*/
244 4802 : levelSynDeemphSub = Dot_product12_offs( h1, h1, lenLpcExc, &s16, 0 ); /*Q31 - s16*/
245 4802 : s16 = sub( shl( add( Q_h1, Hr16 ), 1 ), sub( 30, s16 ) );
246 :
247 4802 : 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 4802 : tmp16 = 32767 /*1.0f Q15*/;
252 4802 : move16();
253 :
254 4802 : if ( GT_16( numLoops, 1 ) )
255 : {
256 0 : tmp16 = div_s( 1, numLoops ); /*Q15*/
257 : }
258 :
259 4802 : levelSynDeemph = L_add( levelSynDeemph, L_shl( Mpy_32_16_1( levelSynDeemphSub, tmp16 ), sub( s16, 10 ) ) ); /*10Q21*/
260 : }
261 4802 : s16 = norm_l( levelSynDeemph );
262 4802 : levelSynDeemph = L_shl( levelSynDeemph, s16 ); /*Q31*/
263 4802 : *Exp = sub( 10, s16 ); /*Set exponent in order to transform returnvalue to Q15*/
264 4802 : move16();
265 :
266 4802 : 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 2392 : 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 2392 : IF( GT_16( last_good, UNVOICED_TRANSITION ) )
355 : {
356 2643744 : FOR( i = 0; i < L_buffer; i++ )
357 : {
358 2641352 : exc2[i] = round_fx( L_sub( Dot_product( &exc2[i], hp_filt, l_fir_fer ), 1 ) ); /*Qx*/
359 2641352 : move16();
360 : }
361 : }
362 2392 : }
363 :
364 : /*----------------------------------------------------------------------------------*
365 : * PLC: [Common: mode decision]
366 : * PLC: Decide which Concealment to use. Update pitch lags if needed
367 : *----------------------------------------------------------------------------------*/
368 13448 : Word16 GetPLCModeDecision_ivas_fx(
369 : Decoder_State *st /* i/o: decoder memory state pointer */
370 : )
371 : {
372 : Word16 /*int*/ core;
373 13448 : Word16 numIndices = 0;
374 : TCX_DEC_HANDLE hTcxDec;
375 :
376 13448 : hTcxDec = st->hTcxDec;
377 :
378 13448 : 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 13448 : st->plc_use_future_lag = 0;
389 13448 : move16();
390 13448 : test();
391 13448 : test();
392 13448 : 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 10380 : st->plc_use_future_lag = 1;
396 10380 : move16();
397 : }
398 :
399 13448 : 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 13448 : core = ACELP_CORE;
416 13448 : move16();
417 13448 : if ( GT_16( st->nbLostCmpt, 1 ) )
418 : {
419 6159 : core = st->last_core_bfi; /*Q0*/
420 6159 : move16();
421 : }
422 13448 : IF( EQ_16( st->nbLostCmpt, 1 ) )
423 : {
424 7289 : st->tonal_mdct_plc_active = 0;
425 7289 : move16();
426 7289 : test();
427 7289 : test();
428 7289 : test();
429 7289 : 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 7289 : test();
432 7289 : test();
433 7289 : test();
434 7289 : test();
435 7289 : test();
436 7289 : test();
437 7289 : test();
438 7289 : 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 1856 : {
444 : Word32 pitch;
445 :
446 1856 : pitch = L_deposit_h( 0 );
447 1856 : if ( hTcxDec->tcxltp_last_gain_unmodified > 0 )
448 : {
449 450 : pitch = L_add( st->old_fpitch, 0 ); /*Q16*/
450 : }
451 :
452 1856 : 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 1856 : test();
455 1856 : test();
456 1856 : test();
457 1856 : test();
458 1856 : test();
459 1856 : test();
460 1856 : test();
461 1856 : 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 384 : core = TCX_20_CORE;
464 384 : move16();
465 384 : st->tonal_mdct_plc_active = 1;
466 384 : move16();
467 : }
468 1472 : ELSE IF( LE_16( st->last_good, UNVOICED_TRANSITION ) || LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) )
469 : {
470 1357 : core = TCX_20_CORE;
471 1357 : move16();
472 : }
473 : }
474 5433 : ELSE IF( st->last_core != ACELP_CORE )
475 : {
476 5433 : test();
477 5433 : if ( LE_16( st->last_good, UNVOICED_TRANSITION ) || LE_16( hTcxDec->tcxltp_last_gain_unmodified, 13107 /*0.4f Q15*/ ) )
478 : {
479 3124 : core = st->last_core;
480 3124 : move16();
481 : }
482 : }
483 : }
484 : }
485 : }
486 13448 : 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 : }
|