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 "cnst.h"
9 : #include "prot_fx.h" /* Function prototypes */
10 : #include "prot_fx_enc.h" /* Function prototypes */
11 : #include "stat_enc.h"
12 : #include "basop_util.h"
13 :
14 :
15 : /*-------------------------------------------------------------------*
16 : * coderLookAheadInnovation()
17 : *
18 : *
19 : *-------------------------------------------------------------------*/
20 315 : static void coderLookAheadInnovation(
21 : Word16 A_3Q12[], /* input: coefficients NxAz[M+1] Q12*/
22 : Word16 *pT, /* out: pitch Q0*/
23 : PLC_ENC_EVS_HANDLE st, /* i/o: coder memory state */
24 : Word16 *speechLookAhead_Qx, /* i: input speech in Q(st->Qold) */
25 : Word16 *old_exc, /* i: input excitation in Q(st->Qold) */
26 : Word16 L_frame )
27 : {
28 : Word16 i;
29 : Word16 prev_pitch, T0_fx;
30 : Word16 *exc_Qx, exc_buf_Qx[L_EXC_MEM + 2 * L_SUBFR + 8];
31 315 : Word32 mantissa_max = -0x7fffffffL;
32 315 : Word16 subfr_len = 0;
33 315 : Word16 search_range = 9;
34 : Word16 exc_max;
35 : Word16 exc_sh;
36 : Word32 ps, alp, alp_ini;
37 : Word32 alp_s1, alp_s2;
38 : Word16 k;
39 : Word16 ps_e, alp_e;
40 : Word32 max_ps, max_ps_tmp;
41 : Word16 max_ps_e;
42 : Word16 tmp_loop;
43 315 : move32();
44 315 : move16();
45 315 : move16();
46 : #ifndef ISSUE_1867_replace_overflow_libenc
47 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
48 : Flag Overflow = 0;
49 : move32();
50 : #endif
51 : #endif
52 :
53 :
54 : /* Debug init (not instrumented) */
55 315 : T0_fx = -3000;
56 315 : move16();
57 315 : subfr_len = shl( L_SUBFR, 1 ); /* 2*L_SUBFR */
58 315 : if ( GT_16( L_FRAME16k, L_frame ) )
59 : {
60 0 : subfr_len = add( L_SUBFR, 48 ); /* 1.75*L_SUBFR */
61 : }
62 315 : set16_fx( exc_buf_Qx, 0, L_EXC_MEM + 2 * L_SUBFR + 8 );
63 :
64 : /*------------------------------------------------------------------------*
65 : * - BASOP specific initialization. *
66 : *------------------------------------------------------------------------*/
67 : /* initialization */
68 315 : exc_Qx = exc_buf_Qx + L_EXC_MEM + 8; /* Q(st->Qold) */
69 103635 : FOR( i = 0; i < L_EXC_MEM + 8; i++ )
70 : {
71 103320 : exc_buf_Qx[i] = old_exc[i]; /* Q(st->Qold) */
72 103320 : move16();
73 : }
74 :
75 :
76 : /*------------------------------------------------------------------------*
77 : * - Get residual signal and target at lookahead part. *
78 : *------------------------------------------------------------------------*/
79 : /* find LP residual signal for look-ahead part */
80 315 : getLookAheadResSig( speechLookAhead_Qx, A_3Q12, exc_Qx, L_frame, 2 );
81 315 : Scale_sig( exc_Qx, subfr_len, 1 ); /* Q(st->Qold) + 1 */
82 :
83 : /* find target signals */
84 315 : prev_pitch = st->T0_4th; /* Q0 */
85 315 : move16();
86 : /* find best candidate of pitch lag */
87 315 : T0_fx = st->T0_4th; /* Q0 */
88 315 : move16();
89 315 : mantissa_max = -0x7fffffffL; /* Q15 */
90 315 : move32();
91 315 : max_ps = -0x7fffffffL; /* Q15 */
92 315 : move32();
93 315 : max_ps_e = 16;
94 315 : move16();
95 :
96 : /*find maximum*/
97 315 : exc_max = 0;
98 315 : move16();
99 315 : tmp_loop = s_min( -prev_pitch + search_range + subfr_len, 0 ); /* Q0 */
100 29486 : FOR( i = -prev_pitch - search_range; i < tmp_loop; i++ )
101 : {
102 29171 : exc_max = s_max( exc_Qx[i], exc_max ); /* Q(st->Qold) + 1 */
103 : }
104 40635 : FOR( i = 0; i < subfr_len; i++ )
105 : {
106 40320 : exc_max = s_max( exc_max, exc_Qx[i] ); /* Q(st->Qold) + 1 */
107 : }
108 : /*calculate scaling factor for optimal precision and assure no overflow in dotproduct*/
109 315 : exc_sh = sub( 15, norm_s( sub( subfr_len, 1 ) ) ); /*ceil(ld(subfr_len))*/
110 315 : exc_sh = s_max( sub( exc_sh, norm_s( s_max( abs_s( exc_max ), 1 ) ) ), 0 );
111 315 : exc_sh = shr( add( exc_sh, 1 ), 1 );
112 :
113 : /*scale buffer only where its needed*/
114 315 : tmp_loop = s_min( -prev_pitch + search_range + subfr_len, 0 ); /* Q0 */
115 29486 : FOR( i = -prev_pitch - search_range; i < tmp_loop; i++ )
116 : {
117 29171 : exc_Qx[i] = shr( exc_Qx[i], exc_sh ); /* Q(st->Qold) + 1 */
118 29171 : move16();
119 : }
120 40635 : FOR( i = 0; i < subfr_len; i++ )
121 : {
122 40320 : exc_Qx[i] = shr( exc_Qx[i], exc_sh ); /* Q(st->Qold) + 1 */
123 40320 : move16();
124 : }
125 :
126 : /*Calculate "big" dotproduct from buffer, including search range*/
127 315 : alp_ini = L_deposit_l( 0 );
128 315 : move16();
129 46305 : FOR( i = -prev_pitch - search_range; i < -prev_pitch + search_range + subfr_len; i++ )
130 : {
131 45990 : alp_ini = L_mac( alp_ini, exc_Qx[i], exc_Qx[i] ); /* 2*(Q(st->Qold) + 1) + 1 */
132 : }
133 :
134 5985 : FOR( i = -search_range; i < search_range; i++ )
135 : {
136 5670 : test();
137 5670 : IF( GT_16( add( prev_pitch, i ), st->pit_max ) || LT_16( add( prev_pitch, i ), st->pit_min ) )
138 : {
139 36 : CONTINUE;
140 : }
141 5634 : ps = L_deposit_l( 0 );
142 5634 : alp_s1 = L_deposit_l( 0 );
143 5634 : alp_s2 = L_deposit_l( 0 );
144 :
145 726786 : FOR( k = 0; k < subfr_len; k++ )
146 : {
147 721152 : ps = L_mac( ps, exc_Qx[k], exc_Qx[k - prev_pitch - i] ); /* 2*(Q(st->Qold) + 1) + 1 */
148 : }
149 :
150 : /*calculate "small" dotproducts in order to subtract them from the "bigger" one*/
151 58908 : FOR( k = -( ( prev_pitch + search_range ) ); k < -prev_pitch - i; k++ )
152 : {
153 53274 : alp_s1 = L_mac( alp_s1, exc_Qx[k], exc_Qx[k] ); /* 2*(Q(st->Qold) + 1) + 1 */
154 : }
155 5634 : tmp_loop = sub( add( search_range, subfr_len ), prev_pitch );
156 53772 : FOR( k = +subfr_len - i - prev_pitch; k < tmp_loop; k++ )
157 : {
158 48138 : alp_s2 = L_mac( alp_s2, exc_Qx[k], exc_Qx[k] ); /* 2*(Q(st->Qold) + 1) + 1 */
159 : }
160 5634 : alp = L_sub( alp_ini, L_add( alp_s1, alp_s2 ) );
161 5634 : alp = L_max( alp, 1 ); /* alp must not be 0 */
162 5634 : alp_e = shl( exc_sh, 1 );
163 5634 : ps_e = shl( exc_sh, 1 );
164 5634 : alp = ISqrt32( alp, &alp_e ); /* Q31-alp_e */
165 5634 : ps = Mpy_32_16_1( ps, round_fx( alp ) ); /*alp_e+ps_e*/
166 :
167 5634 : ps_e = add( alp_e, ps_e );
168 :
169 : BASOP_SATURATE_WARNING_OFF_EVS
170 : #ifdef ISSUE_1867_replace_overflow_libenc
171 5634 : max_ps_tmp = L_shl_sat( max_ps, sub( max_ps_e, ps_e ) );
172 : #else
173 : max_ps_tmp = L_shl_o( max_ps, sub( max_ps_e, ps_e ), &Overflow );
174 : #endif
175 : BASOP_SATURATE_WARNING_ON_EVS
176 :
177 :
178 5634 : IF( LT_32( max_ps_tmp, ps ) )
179 : {
180 1418 : max_ps = L_add( ps, 0 );
181 1418 : max_ps_e = ps_e;
182 1418 : move16();
183 1418 : T0_fx = add( prev_pitch, i );
184 : }
185 : }
186 315 : mantissa_max = max_ps; /* Q31-ps_e */
187 315 : move32();
188 315 : if ( mantissa_max < 0 )
189 : {
190 0 : T0_fx = st->T0_4th;
191 0 : move16();
192 : }
193 :
194 : /* Update excitation */
195 315 : pT[0] = T0_fx;
196 315 : move16();
197 :
198 315 : return;
199 : }
200 :
201 : /************************************************************/
202 : /* Static functions */
203 : /************************************************************/
204 : /*-------------------------------------------------------------------*
205 : * enc_prm_side_Info_fx()
206 : *
207 : *
208 : *-------------------------------------------------------------------*/
209 984 : void enc_prm_side_Info_fx(
210 : PLC_ENC_EVS_HANDLE hPlc_Ext,
211 : Encoder_State *st )
212 : {
213 : Word16 diff_pitch;
214 : Word16 bits_per_subfr, search_range;
215 :
216 984 : bits_per_subfr = 4;
217 984 : move16();
218 984 : search_range = 8;
219 984 : move16();
220 :
221 984 : IF( GT_16( hPlc_Ext->nBits, 1 ) )
222 : {
223 :
224 437 : push_next_indice( st->hBstr, 1, 1 );
225 :
226 437 : diff_pitch = sub( hPlc_Ext->T0, hPlc_Ext->T0_4th );
227 437 : test();
228 437 : if ( ( GT_16( diff_pitch, sub( search_range, 1 ) ) ) || ( LT_16( diff_pitch, add( -search_range, 1 ) ) ) )
229 : {
230 15 : diff_pitch = -8;
231 15 : move16();
232 : }
233 :
234 437 : push_next_indice( st->hBstr, add( diff_pitch, search_range ), bits_per_subfr );
235 : }
236 : ELSE
237 : {
238 547 : push_next_indice( st->hBstr, 0, 1 );
239 : }
240 :
241 984 : return;
242 : }
243 :
244 : /*-------------------------------------------------------------------*
245 : * encoderSideLossSimulation_fx()
246 : *
247 : * Encoder side loss simulation
248 : *-------------------------------------------------------------------*/
249 1246 : void encoderSideLossSimulation_fx(
250 : Encoder_State *st,
251 : PLC_ENC_EVS_HANDLE hPlc_Ext,
252 : Word16 *lsf_q, /* Qx2.56 */
253 : const Word16 stab_fac, /* Q15 */
254 : const Word16 calcOnlyISF, /* Q0 */
255 : const Word16 L_frame )
256 : {
257 : Word16 lspLocal_Q15[M];
258 : Word16 const *xsfBase; /* base for differential XSF coding */
259 :
260 :
261 : /* Decoder State Update */
262 1246 : IF( EQ_16( L_frame, L_FRAME_16k ) )
263 : {
264 984 : lsf2lsp_fx( lsf_q, lspLocal_Q15, M, INT_FS_16k_FX ); /* Q15 */
265 : }
266 : ELSE
267 : {
268 262 : lsf2lsp_fx( lsf_q, lspLocal_Q15, M, INT_FS_FX ); /* Q15 */
269 : }
270 :
271 :
272 1246 : xsfBase = PlcGetLsfBase( st->lpcQuantization,
273 1246 : st->narrowBand,
274 : st->sr_core );
275 :
276 1246 : Copy( st->mem_MA_fx, hPlc_Ext->mem_MA_14Q1, M ); /* Qx2.56 */
277 1246 : Copy( st->mem_AR_fx, hPlc_Ext->mem_AR, M ); /* Qx2.56 */
278 :
279 :
280 : /* ISF parameter processing for concealment */
281 1246 : updateLSFForConcealment( hPlc_Ext, lsf_q );
282 1246 : hPlc_Ext->stab_fac_Q15 = stab_fac;
283 1246 : move16();
284 :
285 1246 : Copy( lsf_q, hPlc_Ext->lsfold_14Q1, M ); /* Qx2.56 */
286 1246 : Copy( lspLocal_Q15, hPlc_Ext->lspold_Q15, M ); /* Q15 */
287 :
288 :
289 1246 : IF( calcOnlyISF != 0 )
290 : {
291 : /* ISF concealment simulation */
292 931 : getConcealedLSF( hPlc_Ext, xsfBase, st->clas, L_frame );
293 931 : hPlc_Ext->T0 = hPlc_Ext->T0_4th; /* Q0 */
294 931 : move16();
295 : }
296 : ELSE
297 : {
298 : Word16 old_exc_Qx[L_EXC_MEM + 8];
299 : Word16 A_3Q12[( NB_SUBFR16k + 1 ) * ( M + 1 )];
300 : Word16 *speechLookAhead_Qx;
301 :
302 : /* calculate Q-value for input speech */
303 315 : speechLookAhead_Qx = &( st->speech_enc_pe[L_frame] );
304 :
305 315 : Copy( hPlc_Ext->old_exc_Qold, old_exc_Qx, 8 );
306 315 : Copy( hPlc_Ext->LPDmem->old_exc, &old_exc_Qx[8], L_EXC_MEM );
307 315 : Scale_sig( old_exc_Qx, 8, hPlc_Ext->Q_exp );
308 :
309 : /* ISF concealment simulation */
310 315 : getConcealedLP( hPlc_Ext, A_3Q12, xsfBase, st->clas, L_frame );
311 :
312 : /* apply encoder side PLC simulation */
313 315 : hPlc_Ext->pit_min = st->pit_min; /* Q0 */
314 315 : move16();
315 315 : hPlc_Ext->pit_max = st->pit_max; /* Q0 */
316 315 : move16();
317 315 : coderLookAheadInnovation( A_3Q12, &( hPlc_Ext->T0 ), hPlc_Ext, speechLookAhead_Qx, old_exc_Qx, L_frame );
318 : }
319 1246 : return;
320 : }
321 :
322 : /*-------------------------------------------------------------------*
323 : * GplcTcxEncSetup_fx()
324 : *
325 : *
326 : *-------------------------------------------------------------------*/
327 :
328 634 : void GplcTcxEncSetup_fx(
329 : Encoder_State *st,
330 : PLC_ENC_EVS_HANDLE hPlc_Ext,
331 : Word16 Q_new )
332 : {
333 634 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
334 :
335 634 : hPlc_Ext->T0_4th = hTcxEnc->tcxltp_pitch_int;
336 634 : move16();
337 634 : hPlc_Ext->Q_exp = sub( Q_new, hPlc_Ext->Q_new );
338 634 : move16();
339 634 : hPlc_Ext->Q_new = Q_new;
340 634 : move16();
341 634 : set16_fx( hPlc_Ext->old_exc_Qold, 0, 8 );
342 634 : }
343 : /*-------------------------------------------------------------------*
344 : * encSideSpecPowDiffuseDetector_fx()
345 : *
346 : *
347 : *-------------------------------------------------------------------*/
348 612 : Word16 encSideSpecPowDiffuseDetector_fx(
349 : Word16 *lsf_ref, /* Qx2.56 */
350 : Word16 *lsf_con, /* Qx2.56 */
351 : const Word32 sr_core, /* Q0 */
352 : Word16 *prev_lsf4_mean, /* Qx2.56 */
353 : const Word8 sw, /* Q0 */
354 : const Word16 coder_type )
355 : {
356 : Word16 tmp;
357 : Word16 lsf_mod[M];
358 : Word32 dist1, dist2, cum_dist1, cum_dist2;
359 : Word16 lsf4_mean;
360 : Word16 th;
361 : Word16 idx;
362 : Word16 cnt_imprv, i;
363 : Word32 L_tmp;
364 : Word16 th_dif;
365 :
366 : /* calculate the mean of the lowest 4 LSFs */
367 :
368 612 : L_tmp = L_mult( lsf_ref[0], 8192 /*1.0/4.0 Q15*/ ); /* Qx2.56 */
369 612 : L_tmp = L_mac( L_tmp, lsf_ref[1], 8192 /*1.0/4.0 Q15*/ ); /* Qx2.56 */
370 612 : L_tmp = L_mac( L_tmp, lsf_ref[2], 8192 /*1.0/4.0 Q15*/ ); /* Qx2.56 */
371 612 : lsf4_mean = mac_r( L_tmp, lsf_ref[3], 8192 /*1.0/4.0 Q15*/ ); /* Qx2.56 */
372 :
373 612 : IF( sw )
374 : {
375 612 : Copy( lsf_con, lsf_mod, M ); /* Qx2.56 */
376 :
377 612 : modify_lsf( lsf_mod, M, sr_core, 1 );
378 :
379 612 : move16();
380 612 : move16();
381 612 : cum_dist1 = 0;
382 612 : cum_dist2 = 0;
383 :
384 612 : cnt_imprv = 0;
385 612 : move16();
386 :
387 612 : IF( EQ_32( sr_core, INT_FS_16k ) )
388 : {
389 612 : th = 2560; /* Qx2.56 */
390 612 : move16(); /* LSF */
391 612 : th_dif = 288; /* Qx2.56 */
392 612 : move16(); /* LSF */
393 : }
394 : ELSE
395 : {
396 0 : th = 2048; /* Qx2.56 */
397 0 : move16(); /* LSF */
398 0 : th_dif = 230; /* Qx2.56 */
399 0 : move16(); /* LSF */
400 : }
401 :
402 10404 : FOR( i = 0; i < M; i++ )
403 : {
404 9792 : tmp = sub( lsf_con[i], lsf_ref[i] );
405 9792 : dist1 = L_mult( tmp, tmp ); /* 2*(Qx2.56)+1 */
406 9792 : tmp = sub( lsf_mod[i], lsf_ref[i] );
407 9792 : dist2 = L_mult( tmp, tmp ); /* 2*(Qx2.56)+1 */
408 :
409 9792 : if ( GT_32( dist1, dist2 ) )
410 : {
411 654 : cnt_imprv = add( cnt_imprv, 1 );
412 : }
413 9792 : cum_dist1 = L_add( cum_dist1, dist1 );
414 9792 : cum_dist2 = L_add( cum_dist2, dist2 );
415 : }
416 :
417 612 : idx = 0;
418 612 : move16();
419 :
420 612 : test();
421 612 : test();
422 612 : test();
423 612 : test();
424 612 : if ( GT_32( cum_dist1, L_add( cum_dist2, Mpy_32_16_1( cum_dist2, 4915 ) ) ) && GT_16( sub( lsf4_mean, *prev_lsf4_mean ), th_dif ) && LT_16( *prev_lsf4_mean, th ) && GT_16( cnt_imprv, 2 ) && EQ_16( coder_type, GENERIC ) )
425 : {
426 6 : idx = 1;
427 6 : move16();
428 : }
429 : }
430 : ELSE
431 : {
432 0 : move16();
433 0 : idx = 0;
434 : }
435 : /* update parameters */
436 612 : move16();
437 612 : *prev_lsf4_mean = lsf4_mean;
438 :
439 612 : return idx;
440 : }
441 : /*-------------------------------------------------------------------*
442 : * updateSpecPowDiffuseIdx_fx()
443 : *
444 : *
445 : *-------------------------------------------------------------------*/
446 612 : void updateSpecPowDiffuseIdx_fx(
447 : Encoder_State *st )
448 : {
449 : Word16 min_gp;
450 : Word16 k;
451 : #ifndef ISSUE_1867_replace_overflow_libenc
452 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
453 : Flag Overflow = 0;
454 : move32();
455 : #endif
456 : #endif
457 :
458 :
459 612 : move32();
460 612 : move16();
461 612 : st->mean_gc[1] = st->gain_code[0]; /* Q15 */
462 612 : min_gp = st->bpf_gainT[0]; /* Q15 */
463 :
464 2448 : FOR( k = 1; k < 4; k++ )
465 : {
466 : #ifdef ISSUE_1867_replace_overflow_libenc
467 1836 : st->mean_gc[1] = L_add_sat( st->mean_gc[1], st->gain_code[k] );
468 : #else
469 : st->mean_gc[1] = L_add_o( st->mean_gc[1], st->gain_code[k], &Overflow );
470 : #endif
471 1836 : move32();
472 1836 : min_gp = s_min( min_gp, st->bpf_gainT[k] );
473 : }
474 :
475 : /* Suppress saturation warning in threshold comparison. */
476 612 : test();
477 : #ifdef ISSUE_1867_replace_overflow_libenc
478 612 : if ( LT_32( st->mean_gc[1], L_add_sat( st->mean_gc[0], Mpy_32_16_r( st->mean_gc[0], 3211 /*0.098 Q15*/ ) ) ) || GT_16( min_gp, 13435 /*0.82 Q14*/ ) )
479 : #else
480 : if ( LT_32( st->mean_gc[1], L_add_o( st->mean_gc[0], Mpy_32_16_r( st->mean_gc[0], 3211 /*0.098 Q15*/ ), &Overflow ) ) || GT_16( min_gp, 13435 /*0.82 Q14*/ ) )
481 : #endif
482 : {
483 425 : move16();
484 425 : st->glr_idx[0] = 0;
485 : }
486 612 : move16();
487 612 : st->mean_gc[0] = st->mean_gc[1]; /* Q15 */
488 612 : }
|