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