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