Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include "options.h" /* Compilation switches */
7 : #include "cnst.h" /* Common constants */
8 : #include "rom_com.h" /* Static table prototypes */
9 : #include "prot_fx.h" /* Function prototypes */
10 : #include "basop_util.h"
11 :
12 : /*-------------------------------------------------------------------*
13 : * Local function prototypes
14 : *-------------------------------------------------------------------*/
15 : static Word16 FEC_dec_class_fx( Decoder_State *st_fx, Word32 *enr_q );
16 : static void Corre( const Word16 *x, const Word16 *y, const Word16 l, Word16 *gain );
17 :
18 : /*---------------------------------------------------------------------*
19 : * Local Constants
20 : *---------------------------------------------------------------------*/
21 : #define UNS6 10923 / 2
22 : #define UNS5 13107 / 2
23 :
24 : #define K_COR_FX 14004 /* Q14 0.8547f <-0.29, 0.88> */
25 : #define C_COR_FX 266180599 /* Q14+16 0.2479f */
26 :
27 : #define K_TILT_FX 13653 /*Q14 0.8333f <-0.35, 0.85> */
28 : #define C_TILT_FX 313210491 /*Q14+16 0.2917f */
29 :
30 : #define K_ZC_FX -1310 /*Q15 -0.04f <63, 38> */
31 : #define C_ZC_FX 2642416 /*11Q20 2.52 */
32 :
33 : #define K_ENR_FX 1311 /*Q15 0.04 <-14, 11> */
34 : #define C_ENR_FX 9395241 /*Q8+16 0.56f */
35 :
36 : #define K_PC_FX -1169 /*Q15 -0.0357f <45, 17> */
37 : #define C_PC_FX 105323 /*Q0+16 1.6071f */
38 :
39 :
40 : /*======================================================================*/
41 : /* FUNCTION : FEC_clas_estim() */
42 : /*----------------------------------------------------------------------*/
43 : /* PURPOSE : Estimation of classification */
44 : /* information, if not available in the bitsream */
45 : /* */
46 : /*======================================================================*/
47 :
48 254310 : void FEC_clas_estim_fx(
49 : Decoder_State *st_fx, /* i/o: decoder state handle */
50 : const Word16 Opt_AMR_WB,
51 : /* i : flag indicating AMR-WB IO mode */ /*A*/
52 : const Word16 L_frame, /* i : length of the frame */
53 : Word16 *clas, /* i/o: frame classification */
54 : const Word16 coder_type, /* i : coder type */
55 : const Word16 *pitch, /* i : pitch values for each subframe (Q6)*/
56 : Word16 *syn, /* i : synthesis buffer */
57 : Word16 *lp_speech, /* i/o: long term active speech energy average Q8 */
58 : Word16 *decision_hyst,
59 : /* i/o: hysteresis of the music/speech decision */ /*A*/
60 : Word16 *UV_cnt,
61 : /* i/o: number of consecutives frames classified as UV */ /*A*/
62 : Word16 *LT_UV_cnt, // Q6
63 : /* i/o: long term consecutives frames classified as UV */ /*A*/
64 : Word16 *Last_ener, // Q8
65 : /* i/o: last_energy frame */ /*A*/
66 : Word16 *locattack,
67 : /* i/o: detection of attack (mainly to localized speech burst) */ /*A*/
68 : Word16 *lt_diff_etot, // Q8
69 : /* i/o: long-term total energy variation */ /*A*/
70 : Word16 *amr_io_class,
71 : /* i/o: classification for AMR-WB IO mode */ /*A*/
72 : Word16 Q_syn, /* i : Synthesis scaling */
73 : Word16 *class_para, // Q14
74 : /* o : classification para. fmerit1 */ /*A*/
75 : Word16 *mem_syn_clas_estim, /* i/o: memory of the synthesis signal for frame class estimation */
76 : Word16 *Q_mem_syn,
77 : /* i/o: exponent for memory of synthesis signal for frame class estimation */ /*B*/
78 : Word16 LTP_Gain,
79 : /* i : LTP gain is 0..0.6 or -1 Q15 */ /*B*/
80 : Word16 mode,
81 : /* i : signal classifier mode */ /*B*/
82 : Word16 bfi,
83 : /* i : bad frame indicator */ /*B*/
84 : Word32 last_core_brate, /* i : bitrate of previous frame */
85 : const Word16 FEC_mode /* i : ACELP FEC mode */
86 : )
87 : {
88 : Word16 i, j, pos;
89 254310 : Word16 *pt1, *pt2, zc_frame, frame_ener = 1, tmp_scale = 0, tmp_scale_syn, tmp_scale_mem;
90 254310 : Word16 tiltn, corn, zcn, pcn, fmerit1, enern, ener = 0 /*not necessary, just to quiet a warning so not cmplxty counted*/, tilt, diff_ener;
91 : Word16 voicing, cor_max[4], *synth, tmp16, exp1, exp2;
92 : Word32 Ltmp, Ltmp1;
93 : Word16 tmpS, T0, pc, /*max,*/ tmp_x, tmp_y;
94 : Word16 old_synth[L_SYN_MEM_CLAS_ESTIM + L_FRAME16k];
95 : Word16 nb_subfr;
96 : Word16 pos_limit;
97 : Word16 codec_mode, narrowBand, tcxonly, preemph_fac;
98 : Word16 memmax;
99 254310 : move16();
100 254310 : move16();
101 254310 : move16();
102 :
103 254310 : nb_subfr = shr( L_frame, 6 );
104 254310 : memmax = 0;
105 254310 : move16();
106 254310 : tmp_scale_syn = 0;
107 254310 : move16();
108 :
109 254310 : codec_mode = st_fx->codec_mode;
110 254310 : move16();
111 254310 : tcxonly = st_fx->tcxonly; /* i : tcxonly flag */ /*B*/
112 254310 : move16();
113 254310 : narrowBand = st_fx->narrowBand; /* i : narrowband flag */ /*B*/
114 254310 : move16();
115 254310 : preemph_fac = st_fx->preemph_fac; /* i : preemphasis factor */ /*B*/
116 254310 : move16();
117 : /*------------------------------------------------------------------------*
118 : * Copy synthesized into local buffer
119 : *------------------------------------------------------------------------*/
120 :
121 : /* After Rate Switching st->last_core is reset to 0. Check for last_core_brate is needed */
122 254310 : test();
123 254310 : test();
124 254310 : test();
125 254310 : test();
126 254310 : test();
127 254310 : test();
128 254310 : test();
129 254310 : test();
130 254310 : test();
131 254310 : test();
132 254310 : test();
133 254310 : test();
134 254310 : IF( ( EQ_32( last_core_brate, SID_1k75 ) || EQ_32( last_core_brate, ACELP_6k60 ) || EQ_32( last_core_brate, ACELP_8k85 ) || EQ_32( last_core_brate, ACELP_12k65 ) || EQ_32( last_core_brate, ACELP_14k25 ) || EQ_32( last_core_brate, ACELP_15k85 ) || EQ_32( last_core_brate, ACELP_18k25 ) || EQ_32( last_core_brate, ACELP_19k85 ) || EQ_32( last_core_brate, ACELP_23k05 ) || EQ_32( last_core_brate, ACELP_23k85 ) ) && !Opt_AMR_WB && EQ_16( codec_mode, MODE2 ) && GT_16( L_frame, L_FRAME ) )
135 : {
136 : Word16 oldLenClasBuff, newLenClasBuff;
137 669 : oldLenClasBuff = extract_l( L_shr( Mpy_32_16_1( L_mult0( st_fx->last_L_frame, getInvFrameLen( st_fx->L_frame ) /*Q21*/ ) /*Q21*/, L_SYN_MEM_CLAS_ESTIM /*Q0*/ ) /*Q6*/, 6 ) /*Q0*/ );
138 669 : newLenClasBuff = L_SYN_MEM_CLAS_ESTIM;
139 669 : move16();
140 669 : lerp( &mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM - oldLenClasBuff], &mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM - newLenClasBuff], newLenClasBuff, oldLenClasBuff );
141 : }
142 254310 : synth = old_synth + L_SYN_MEM_CLAS_ESTIM;
143 :
144 : /*Rescale synthesis mem buffer or synthesis buffer, if necessary -
145 : allign them to the same scaling in case of switching MODE2->MODE1*/
146 254310 : IF( EQ_16( codec_mode, MODE2 ) )
147 : {
148 114184 : memmax = 1;
149 114184 : move16();
150 : /*find maximum of mem syn*/
151 29573656 : FOR( i = 0; i < L_SYN_MEM_CLAS_ESTIM; i++ )
152 : {
153 29459472 : memmax = s_max( memmax, mem_syn_clas_estim[i] );
154 : }
155 :
156 114184 : tmp_scale = sub( *Q_mem_syn, Q_syn );
157 114184 : IF( tmp_scale > 0 ) /*mem syn is bigger, scale it down*/
158 : {
159 4723 : tmp_scale_mem = negate( tmp_scale );
160 4723 : Scale_sig( mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, tmp_scale_mem );
161 : }
162 : ELSE /*synthesis is bigger, scale it down*/
163 : {
164 : /*check for upscaling mem syn, first*/
165 109461 : tmp_scale_mem = norm_s( sub( memmax, 1 ) );
166 109461 : if ( EQ_16( memmax, 1 ) )
167 : {
168 4696 : tmp_scale_mem = 14;
169 4696 : move16();
170 : }
171 109461 : tmp_scale_syn = sub( add( *Q_mem_syn, tmp_scale_mem ), Q_syn ); /*if this is negative, syn can be scaled down*/
172 109461 : test();
173 109461 : IF( tmp_scale_syn > 0 || EQ_16( mode, 1 /*CLASSIFIER_TCX*/ ) ) /*dont scale up syn, but scale mem_syn, adequately*/
174 : {
175 109461 : tmp_scale_mem = sub( tmp_scale_mem, tmp_scale_syn );
176 109461 : tmp_scale_syn = 0;
177 109461 : move16();
178 : }
179 :
180 109461 : Scale_sig( mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, tmp_scale_mem );
181 109461 : *Q_mem_syn = add( *Q_mem_syn, tmp_scale_mem );
182 109461 : move16();
183 : }
184 : }
185 :
186 254310 : tmp_scale = -1;
187 254310 : move16();
188 :
189 254310 : Copy_Scale_sig( mem_syn_clas_estim, old_synth, L_SYN_MEM_CLAS_ESTIM, tmp_scale );
190 254310 : Copy_Scale_sig( syn, synth, L_frame, add( tmp_scale_syn, tmp_scale ) );
191 :
192 : /*Tell MODE2 decoder the scaling of the buffer*/
193 254310 : *Q_mem_syn = add( add( Q_syn, tmp_scale_syn ), tmp_scale );
194 254310 : move16();
195 :
196 : /**Q_mem_syn = *Q_syn; move16();*/
197 :
198 254310 : test();
199 254310 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( mode, 1 /*CLASSIFIER_TCX*/ ) )
200 : {
201 : /* TCX outputs non-pe-speech */
202 113574 : move16();
203 113574 : tmp16 = shl( syn[-1], tmp_scale ); /*dont forget to scale the mem*/
204 113574 : preemph_copy_fx( synth, synth, preemph_fac, L_frame, &tmp16 );
205 : }
206 :
207 : /*------------------------------------------------------------------------*
208 : * GC, TC and AC frames
209 : *------------------------------------------------------------------------*/
210 : /* Do the classification only
211 : - MODE1: when the class is not transmitted in the bitstream
212 : - MODE2: on good frames (classifier is also called for bfi=1) */
213 254310 : test();
214 254310 : test();
215 254310 : test();
216 254310 : test();
217 254310 : test();
218 254310 : test();
219 254310 : IF( ( EQ_16( codec_mode, MODE1 ) && ( FEC_mode == 0 || LE_16( coder_type, UNVOICED ) || Opt_AMR_WB ) ) || ( EQ_16( codec_mode, MODE2 ) && NE_16( bfi, 1 ) && !tcxonly ) )
220 : {
221 : /*------------------------------------------------------------------------*
222 : * Overwrite classification decision using coder_type information
223 : *------------------------------------------------------------------------*/
224 149301 : test();
225 149301 : IF( EQ_16( coder_type, VOICED ) )
226 : {
227 26700 : *clas = VOICED_CLAS;
228 26700 : move16();
229 : }
230 122601 : ELSE IF( EQ_16( coder_type, UNVOICED ) )
231 : {
232 19758 : *clas = UNVOICED_CLAS;
233 19758 : move16();
234 : }
235 102843 : ELSE IF( EQ_16( coder_type, INACTIVE ) && !Opt_AMR_WB )
236 : {
237 12565 : *clas = INACTIVE_CLAS;
238 12565 : move16();
239 : }
240 : ELSE
241 : {
242 : /*------------------------------------------------------------------------*
243 : * Compute the zero crossing rate for all subframes
244 : *------------------------------------------------------------------------*/
245 :
246 90278 : pt1 = (Word16 *) synth - 1;
247 90278 : move16();
248 90278 : tmpS = shr( *pt1, 15 ); /* sets 'tmpS to -1 if *pt1 < 0 */
249 90278 : Ltmp = L_deposit_l( 0 );
250 25782630 : FOR( j = 0; j < L_SUBFR * nb_subfr; j++ )
251 : {
252 25692352 : tmp16 = add( 1, tmpS );
253 25692352 : pt1++;
254 25692352 : if ( *pt1 != 0 ) /* Do only count zero crossing, no zero touchings */
255 : {
256 25262033 : tmpS = shr( *pt1, 15 ); /* 1Clk: >=0 ---> 0 OTHERWISE -1 */
257 : }
258 25692352 : Ltmp = L_msu0( Ltmp, tmpS, tmp16 );
259 : }
260 :
261 90278 : zc_frame = shl( extract_l( Ltmp ), 4 ); /* Q4 */
262 :
263 90278 : if ( EQ_16( L_frame, L_FRAME16k ) )
264 : {
265 : /*zc_frame *= 0.8f;*/ /* Renormalization for 12.8kHz core*/
266 40331 : zc_frame = mult_r( zc_frame, 26214 );
267 : }
268 :
269 :
270 : /*------------------------------------------------------------------------*
271 : * Compute the normalized correlation pitch-synch. at the end of the frame
272 : *------------------------------------------------------------------------*/
273 90278 : T0 = shr( pitch[3], 6 );
274 90278 : Ltmp1 = L_mult( pitch[3], 256 );
275 :
276 90278 : if ( GT_16( T0, L_SUBFR * 3 / 2 ) )
277 : {
278 65357 : T0 = mac_r( Ltmp1, pitch[2], 256 );
279 : }
280 :
281 :
282 90278 : pt1 = synth;
283 90278 : move16();
284 90278 : pos = sub( L_frame, T0 ); /* T0 [34 231] */
285 :
286 :
287 90278 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[0] );
288 90278 : IF( NE_16( st_fx->element_mode, EVS_MONO ) )
289 : {
290 89632 : IF( LT_16( sub( pos, T0 ), sub( L_frame, L_SUBFR ) ) )
291 : {
292 87427 : T0 = mult_r_sat( add_sat( pitch[2], pitch[3] ), 256 );
293 : }
294 : }
295 : ELSE
296 : {
297 646 : T0 = mult_r_sat( add_sat( pitch[2], pitch[3] ), 256 );
298 : }
299 90278 : pos_limit = sub( L_frame, L_SUBFR );
300 90278 : j = s_min( 1, s_max( 0, sub( pos, pos_limit ) ) );
301 90278 : Ltmp = L_deposit_l( cor_max[0] );
302 90278 : IF( j > 0 )
303 : {
304 14255 : j = 16384;
305 14255 : move16();
306 14255 : pos = sub( pos, T0 ); /* T0 [34 231] */
307 14255 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[1] );
308 14255 : Ltmp = L_add( Ltmp, cor_max[1] );
309 14255 : IF( GT_16( pos, pos_limit ) )
310 : {
311 1939 : j = 10923;
312 1939 : move16();
313 1939 : pos = sub( pos, T0 ); /* T0 [34 231] */
314 1939 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[2] );
315 1939 : Ltmp = L_add( Ltmp, cor_max[2] );
316 : }
317 14255 : IF( GT_16( pos, pos_limit ) )
318 : {
319 368 : j = 8192;
320 368 : move16();
321 368 : pos = sub( pos, T0 ); /* T0 [34 231] */
322 368 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[3] );
323 368 : Ltmp = L_add( Ltmp, cor_max[3] );
324 : }
325 : }
326 :
327 90278 : voicing = cor_max[0];
328 90278 : move16();
329 90278 : IF( j > 0 )
330 : {
331 14255 : voicing = extract_l( Mult_32_16( Ltmp, j ) );
332 : }
333 : /*------------------------------------------------------------------------*
334 : * Compute pitch coherence
335 : *------------------------------------------------------------------------*/
336 :
337 90278 : pc = 0;
338 90278 : move16();
339 90278 : test();
340 90278 : test();
341 90278 : IF( EQ_16( codec_mode, MODE1 ) || !( NE_16( LTP_Gain, -32768 /*-1.f Q15*/ ) && EQ_16( mode, CLASSIFIER_TCX ) ) )
342 : {
343 33065 : pc = shr( abs_s( sub( add_sat( pitch[3], sub( pitch[2], pitch[1] ) ), pitch[0] ) ), 6 );
344 :
345 33065 : IF( EQ_16( L_frame, L_FRAME16k ) )
346 : {
347 8045 : pc = mult_r( pc, 26214 ); /* Renormalization for 12.8kHz core*/
348 : }
349 : }
350 :
351 : /*------------------------------------------------------------------------*
352 : * Compute spectral tilt
353 : *------------------------------------------------------------------------*/
354 90278 : pt1 = (Word16 *) synth + L_SUBFR;
355 90278 : move16();
356 90278 : pt2 = (Word16 *) synth + L_SUBFR - 1;
357 90278 : move16();
358 90278 : Ltmp = L_mult0( *pt1, *pt1 );
359 90278 : Ltmp1 = L_mult0( *pt1, *pt2 );
360 19914560 : FOR( j = 1; j < L_SUBFR * ( nb_subfr - 1 ); j++ )
361 : {
362 19824282 : pt1++;
363 19824282 : pt2++;
364 19824282 : Ltmp = L_mac0_sat( Ltmp, *pt1, *pt1 );
365 19824282 : Ltmp1 = L_mac0_sat( Ltmp1, *pt1, *pt2 );
366 : }
367 90278 : tilt = 0;
368 90278 : move16();
369 :
370 90278 : IF( Ltmp != 0 )
371 : {
372 : BASOP_SATURATE_WARNING_OFF_EVS
373 90248 : tmp16 = extract_l( L_or( L_shr( Ltmp1, 32 ), 1 ) ); /* sets a flag -1 or 1 for sign of Ltmp1 */
374 : BASOP_SATURATE_WARNING_ON_EVS
375 90248 : Ltmp1 = L_abs( Ltmp1 );
376 90248 : exp1 = norm_l( Ltmp1 );
377 90248 : tmp_y = extract_h( L_shl( Ltmp1, exp1 ) );
378 90248 : exp1 = sub( 31 - 1 + 3, exp1 );
379 90248 : exp2 = norm_l( Ltmp );
380 90248 : tmp_x = extract_h( L_shl( Ltmp, exp2 ) );
381 90248 : exp2 = sub( 31 - 1 + 3, exp2 );
382 : BASOP_SATURATE_WARNING_OFF_EVS
383 90248 : tmpS = shr( sub_sat( tmp_x, tmp_y ), 16 ); /* if tmp_x >= tmp_y tmpS = 0, -1 otherwise */
384 : BASOP_SATURATE_WARNING_ON_EVS
385 90248 : tmp_y = shl( tmp_y, tmpS );
386 90248 : exp1 = sub( exp1, tmpS );
387 :
388 90248 : tilt = div_s( tmp_y, tmp_x );
389 90248 : tilt = shl_sat( tilt, sub( exp1, exp2 ) ); /* saturate to 1.0 */
390 :
391 90248 : tilt = i_mult2( tilt, tmp16 );
392 : }
393 :
394 : /*------------------------------------------------------------------------*
395 : * Compute pitch-synchronous energy at the frame end
396 : *------------------------------------------------------------------------*/
397 90278 : ener = frame_energy_fx( L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn );
398 :
399 : /*------------------------------------------------------------------------*
400 : * transform parameters between 0 & 1
401 : * find unique merit function
402 : *------------------------------------------------------------------------*/
403 90278 : enern = mac_r( C_ENR_FX, K_ENR_FX, ener ); /*Q8*/
404 :
405 90278 : tiltn = extract_h( L_shr( L_mac( C_TILT_FX, K_TILT_FX, tilt ), 6 ) ); /*Q14 -> Q8*/
406 :
407 90278 : corn = extract_h( L_shr( L_mac( C_COR_FX, K_COR_FX, voicing ), 6 ) ); /*Q14 -> Q8*/
408 :
409 90278 : zcn = extract_h( L_shl( L_mac( C_ZC_FX, K_ZC_FX, zc_frame ), 4 ) ); /* Q4 -> Q8*/
410 :
411 : BASOP_SATURATE_WARNING_OFF_EVS
412 90278 : tmp16 = sub_sat( LTP_Gain, -32768 /*-1.f Q15*/ );
413 : BASOP_SATURATE_WARNING_ON_EVS
414 90278 : test();
415 90278 : test();
416 90278 : IF( EQ_16( codec_mode, MODE2 ) && tmp16 != 0 && EQ_16( mode, CLASSIFIER_TCX ) )
417 : {
418 57213 : pcn = round_fx( L_shl( Mpy_32_16_1( C_PC_FX /*Q16*/, LTP_Gain /*Q15*/ ), 8 ) ); /*Q16*/
419 : }
420 : ELSE
421 : {
422 33065 : pcn = extract_h( L_shl( L_mac( C_PC_FX, K_PC_FX, pc ), 8 ) ); /* Q0 -> Q8*/
423 : }
424 :
425 90278 : pcn = s_min( 256, pcn );
426 90278 : pcn = s_max( 0, pcn );
427 : /* fmerit1 = (1.0f/6.0f) * (tiltn + 2.0f*corn + zcn + pcn + enern) */
428 90278 : Ltmp = L_mult( tiltn, UNS6 );
429 90278 : Ltmp = L_mac( Ltmp, corn, 2 * UNS6 );
430 90278 : Ltmp = L_mac( Ltmp, zcn, UNS6 );
431 90278 : Ltmp = L_mac( Ltmp, pcn, UNS6 );
432 90278 : Ltmp = L_mac( Ltmp, enern, UNS6 );
433 : BASOP_SATURATE_WARNING_OFF_EVS
434 90278 : fmerit1 = round_fx_sat( L_shl_sat( Ltmp, 15 - 8 ) ); /*Q15 can saturate to 1.0 */
435 : BASOP_SATURATE_WARNING_ON_EVS
436 90278 : test();
437 90278 : IF( EQ_16( codec_mode, MODE2 ) && narrowBand != 0 )
438 : {
439 0 : fmerit1 = mult_r( fmerit1, 29491 /*0.9f Q15*/ ); /* 0.90 */
440 : }
441 90278 : IF( EQ_16( codec_mode, MODE1 ) )
442 : {
443 19666 : *class_para = round_fx( L_shl( Ltmp, 14 - 8 ) ); /*Q14 - cannot be saturated, degrades HF synthesis */
444 19666 : move16();
445 : }
446 :
447 : /*------------------------------------------------------------------------*
448 : * frame classification
449 : *------------------------------------------------------------------------*/
450 90278 : IF( NE_16( coder_type, VOICED ) )
451 : {
452 90278 : Word16 result = UNVOICED_CLAS;
453 90278 : move16();
454 90278 : SWITCH( *clas )
455 : {
456 73045 : case VOICED_CLAS:
457 : case ONSET:
458 : case SIN_ONSET:
459 : case VOICED_TRANSITION:
460 73045 : test();
461 73045 : test();
462 73045 : IF( LT_16( fmerit1, 12780 /*0.39f Q15*/ ) )
463 : {
464 3775 : result = UNVOICED_CLAS;
465 3775 : move16();
466 : }
467 69270 : ELSE IF( LT_16( fmerit1, 20644 /*0.63f Q15*/ ) && ( LT_16( ener, -3840 ) || EQ_16( codec_mode, MODE2 ) ) )
468 : {
469 18044 : result = VOICED_TRANSITION;
470 18044 : move16();
471 : }
472 : ELSE
473 : {
474 51226 : result = VOICED_CLAS;
475 51226 : move16();
476 : }
477 :
478 73045 : BREAK;
479 :
480 17233 : case UNVOICED_CLAS:
481 : case UNVOICED_TRANSITION:
482 : case INACTIVE_CLAS:
483 17233 : IF( GT_16( fmerit1, 18350 /*0.56f Q15*/ ) )
484 : {
485 9670 : result = ONSET;
486 9670 : move16();
487 : }
488 7563 : ELSE IF( GT_16( fmerit1, 14746 /*0.45f Q15*/ ) )
489 : {
490 2517 : result = UNVOICED_TRANSITION;
491 2517 : move16();
492 : }
493 : ELSE
494 : {
495 5046 : result = UNVOICED_CLAS;
496 5046 : move16();
497 : }
498 17233 : BREAK;
499 : }
500 90278 : *clas = result;
501 90278 : move16();
502 : }
503 : }
504 :
505 :
506 149301 : IF( EQ_16( codec_mode, MODE1 ) )
507 : {
508 : /*------------------------------------------------------------------------*
509 : * Overwrite classification decision in case of music
510 : *------------------------------------------------------------------------*/
511 36855 : IF( EQ_16( coder_type, AUDIO ) )
512 : {
513 6834 : ( *decision_hyst ) = add( *decision_hyst, 4 );
514 6834 : move16();
515 : }
516 : ELSE
517 : {
518 30021 : ( *decision_hyst ) = sub( *decision_hyst, 1 );
519 30021 : move16();
520 : }
521 :
522 36855 : IF( EQ_16( coder_type, INACTIVE ) )
523 : {
524 12565 : *decision_hyst = sub( *decision_hyst, 10 );
525 12565 : move16();
526 : }
527 36855 : IF( GT_16( *decision_hyst, 200 ) )
528 : {
529 3836 : *decision_hyst = 200;
530 3836 : move16();
531 : }
532 33019 : ELSE IF( *decision_hyst < 0 )
533 : {
534 23586 : *decision_hyst = 0;
535 23586 : move16();
536 : }
537 :
538 36855 : test();
539 36855 : test();
540 36855 : if ( GT_16( *decision_hyst, 16 ) && LT_16( *clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) )
541 : {
542 1029 : *clas = VOICED_CLAS;
543 1029 : move16();
544 : }
545 : } /*MODE1*/
546 :
547 : /*---------------------------------------------------------------------------------*
548 : * Measure energy on active voice frames (to improve FEC performance)
549 : *---------------------------------------------------------------------------------*/
550 149301 : IF( EQ_16( *clas, VOICED_CLAS ) )
551 : {
552 78955 : test();
553 78955 : test();
554 78955 : test();
555 78955 : test();
556 78955 : test();
557 78955 : IF( ( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, VOICED ) ) || ( EQ_16( codec_mode, MODE1 ) && ( Opt_AMR_WB || ( NE_16( coder_type, GENERIC ) && NE_16( coder_type, TRANSITION ) ) ) ) )
558 : {
559 : /* pitch-synchronous energy at the frame end */
560 33208 : enern = frame_energy_fx( L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn );
561 : }
562 : /* update of long-term active speech energy */
563 78955 : Ltmp = L_mult0( 655, frame_ener ); /* 0.01 */
564 78955 : *lp_speech = mac_r( Ltmp, 32440, *lp_speech );
565 78955 : move16(); /* lp_speech update */
566 : }
567 :
568 149301 : IF( EQ_16( codec_mode, MODE1 ) )
569 : {
570 :
571 : /*---------------------------------------------------------------------------------*
572 : * Overwrite classification decision to UNVOICED_CLAS in case of INACTIVE frame
573 : *---------------------------------------------------------------------------------*/
574 36855 : test();
575 36855 : if ( EQ_16( coder_type, INACTIVE ) && NE_16( *clas, INACTIVE_CLAS ) )
576 : {
577 0 : *clas = UNVOICED_CLAS;
578 0 : move16();
579 : }
580 :
581 : /*---------------------------------------------------------------------------------*
582 : * Classification refinement to improve noise coding (only in AMR-WB IO mode)
583 : *---------------------------------------------------------------------------------*/
584 36855 : IF( Opt_AMR_WB )
585 : {
586 0 : *locattack = 0;
587 0 : move16();
588 :
589 : /*-----------------------------------------------------------------------------*
590 : * Unvoiced signal but not silence
591 : *-----------------------------------------------------------------------------*/
592 :
593 0 : test();
594 0 : IF( EQ_16( *clas, UNVOICED_CLAS ) && NE_16( coder_type, INACTIVE ) )
595 : {
596 0 : IF( LE_16( *lp_speech, 40 * 256 /*Q8*/ ) )
597 : {
598 0 : *UV_cnt = 16;
599 0 : move16();
600 : }
601 : ELSE
602 : {
603 0 : move16();
604 0 : *UV_cnt = sub( *UV_cnt, 8 );
605 : }
606 : }
607 :
608 : /*-----------------------------------------------------------------------------*
609 : * Neither unvoiced nor clean silence
610 : * Number of frames between UV is increased
611 : *-----------------------------------------------------------------------------*/
612 :
613 0 : ELSE IF( NE_16( coder_type, INACTIVE ) )
614 : {
615 0 : move16();
616 0 : *UV_cnt = add( *UV_cnt, 1 );
617 : }
618 :
619 : /*-----------------------------------------------------------------------------*
620 : * Maximum/minimum number of frames between UV reached
621 : *-----------------------------------------------------------------------------*/
622 :
623 0 : /* Range 0..300 */ move16();
624 0 : *UV_cnt = s_max( s_min( 300, *UV_cnt ), 0 );
625 :
626 : /*-----------------------------------------------------------------------------*
627 : * IF VAD = 0 (no voice activity)
628 : * long-term average updated towards to speech
629 : * maximum number of frames between UV is limited to 125
630 : * Else
631 : * update long-term average
632 : *-----------------------------------------------------------------------------*/
633 :
634 0 : IF( EQ_16( coder_type, INACTIVE ) )
635 : {
636 0 : move16();
637 0 : *LT_UV_cnt = mult_r( 31130 /*0.95f*/, *LT_UV_cnt ); /* tend to speech if no activity */
638 0 : *UV_cnt = s_min( 125, *UV_cnt );
639 0 : move16();
640 : }
641 : ELSE
642 : {
643 : /* *LT_UV_cnt = 0.9f * *LT_UV_cnt + 0.1f * *UV_cnt */
644 :
645 0 : Ltmp = L_mult( 3277 /*0.1f*/, *UV_cnt );
646 : /* Bring to Q22 */
647 0 : Ltmp = L_shl( Ltmp, 6 );
648 : /* Add to 0.9 x *LT_UV_cnt (Already in Q6) */
649 0 : Ltmp = L_mac( Ltmp, 29491 /*0.9f*/, *LT_UV_cnt ); /* Q22*/
650 : /* Store */
651 0 : *LT_UV_cnt = round_fx( Ltmp );
652 0 : move16();
653 : }
654 :
655 : /*-----------------------------------------------------------------------------*
656 : * Compute frame energy difference
657 : * IF long-term average is high and energy difference is relatively low
658 : * classification is overwritten to AUDIO
659 : * IF energy difference > 6.0dB
660 : * consider an attack
661 : *-----------------------------------------------------------------------------*/
662 :
663 0 : diff_ener = sub( ener, *Last_ener );
664 0 : *Last_ener = ener;
665 0 : move16();
666 0 : *amr_io_class = *clas;
667 0 : move16();
668 0 : test();
669 0 : if ( GT_16( *LT_UV_cnt, LT_UV_THR_FX ) && LT_16( diff_ener, 12 * 256 /*Q8*/ ) )
670 : {
671 0 : move16();
672 0 : *amr_io_class = AUDIO_CLAS;
673 : }
674 0 : test();
675 0 : test();
676 0 : if ( ( GT_16( diff_ener, 6 * 256 /*Q8*/ ) && EQ_16( *clas, AUDIO_CLAS ) ) || GT_16( diff_ener, 9 * 256 /*Q8*/ ) )
677 : {
678 0 : *locattack = 1;
679 0 : move16();
680 : }
681 :
682 : /*------------------------------------------------------------------------*
683 : * Find mean of the past 40 frames energy variation
684 : *------------------------------------------------------------------------*/
685 :
686 0 : IF( NE_16( coder_type, INACTIVE ) )
687 : {
688 0 : Ltmp = L_deposit_l( 0 );
689 0 : FOR( i = 1; i < MAX_LT; i++ )
690 : {
691 0 : Ltmp = L_mac( Ltmp, INV_MAX_LT_FX, lt_diff_etot[i - 1] ); /* divide by MAX_LT */
692 0 : lt_diff_etot[i - 1] = lt_diff_etot[i];
693 0 : move16();
694 : }
695 0 : Ltmp = L_mac( Ltmp, INV_MAX_LT_FX, lt_diff_etot[i - 1] ); /* divide by MAX_LT */
696 : /* Ltmp is in Q24 (Q16+Q8) */
697 :
698 : /*------------------------------------------------------------------------*
699 : * Find statistical deviation of the energy variation history
700 : * against the last 15 frames
701 : *------------------------------------------------------------------------*/
702 :
703 0 : Ltmp1 = L_deposit_l( 1 );
704 0 : FOR( i = MAX_LT - 15; i < MAX_LT; i++ )
705 : {
706 : /* ftmp_c = lt_diff_etot[i] - mean_diff */
707 0 : tmp16 = mac_r( Ltmp, lt_diff_etot[i], -32768L );
708 : /* fcorr += ftmp_c*ftmp_c */
709 0 : Ltmp1 = L_mac0( Ltmp1, tmp16, tmp16 ); /* in Q16 (Q8xQ8)*/
710 : }
711 0 : lt_diff_etot[i - 1] = diff_ener;
712 0 : move16();
713 :
714 : /*------------------------------------------------------------------------*
715 : * Compute statistical deviation
716 : * Overwrite classification, if needed
717 : *------------------------------------------------------------------------*/
718 :
719 : /* dev = (float)sqrt(fcorr / (MAX_LT-15)) */
720 0 : Ltmp = Sqrt_Ratio32( Ltmp1, 16 /*Q16*/, MAX_LT - 15, 0 /*Q0*/, &tmp16 );
721 0 : tmp16 = round_fx( L_shr( Ltmp, sub( 15 - 8, tmp16 ) ) ); /* Put in Q8 (Don't care about Possible Saturation) */
722 :
723 0 : test();
724 0 : IF( EQ_16( *amr_io_class, AUDIO_CLAS ) && GT_16( tmp16, 5 * 256 /*Q8*/ ) )
725 : {
726 0 : *amr_io_class = *clas;
727 0 : move16();
728 : /* *UV_cnt = (short)(80 + *UV_cnt*0.2f) */
729 0 : *UV_cnt = add( 80, mult( *UV_cnt, 6554 ) );
730 0 : move16();
731 : }
732 : }
733 : } /*if (Opt_AMR_WB)*/
734 : } /*if (codec_mode==MODE1)*/
735 :
736 :
737 : } /* Do the classification only
738 : - MODE1: when the class is not transmitted in the bitstream
739 : - MODE2: on good frames (classifier is also called for bfi=1) */
740 :
741 :
742 : /* update the memory of synthesis for frame class estimation */
743 254310 : IF( EQ_16( codec_mode, 2 ) )
744 : {
745 114184 : Copy( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM );
746 : }
747 : ELSE
748 : {
749 140126 : Copy_Scale_sig( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, negate( tmp_scale ) );
750 140126 : *Q_mem_syn = sub( add( Q_syn, tmp_scale_syn ), tmp_scale );
751 140126 : move16();
752 : }
753 :
754 :
755 254310 : return;
756 : }
757 :
758 100332 : static Word16 FEC_dec_class_fx(
759 : Decoder_State *st_fx, /* i/o: decoder state structure */
760 : Word32 *enr_q /* i : decoded energy Q0 */
761 : )
762 : {
763 : Word16 clas, tmpS;
764 : Word16 sfrac;
765 : Word32 L_tmp;
766 :
767 100332 : clas = ONSET;
768 100332 : move16();
769 :
770 100332 : IF( NE_16( st_fx->coder_type, VOICED ) )
771 : {
772 : /* decode the class */
773 96143 : tmpS = (Word16) get_next_indice_fx( st_fx, FEC_BITS_CLS );
774 :
775 96143 : IF( tmpS == 0 )
776 : {
777 41127 : clas = UNVOICED_CLAS;
778 41127 : move16();
779 : }
780 55016 : ELSE IF( EQ_16( tmpS, 1 ) )
781 : {
782 6401 : IF( GE_16( st_fx->last_good, VOICED_TRANSITION ) )
783 : {
784 5387 : clas = VOICED_TRANSITION;
785 5387 : move16();
786 : }
787 : ELSE
788 : {
789 1014 : clas = UNVOICED_TRANSITION;
790 1014 : move16();
791 : }
792 : }
793 48615 : ELSE IF( EQ_16( tmpS, 2 ) )
794 : {
795 41933 : clas = VOICED_CLAS;
796 41933 : move16();
797 : }
798 : }
799 : ELSE
800 : {
801 4189 : clas = VOICED_CLAS;
802 4189 : move16();
803 : }
804 :
805 : /* decode the energy */
806 100332 : test();
807 100332 : test();
808 100332 : IF( GT_16( st_fx->acelp_cfg.FEC_mode, 1 ) )
809 : {
810 57623 : tmpS = (Word16) get_next_indice_fx( st_fx, FEC_BITS_ENR );
811 : /* convert from logarithmic to linear domain (the range is 0 : 3.0 : 96 dB) */
812 57623 : tmpS = mult_r( shl( tmpS, 10 ), 24576 ); /* Q10*Q13->Q8 */
813 57623 : L_tmp = L_mult( tmpS, 10885 ); /* 0.332192 in Q15 */
814 57623 : L_tmp = L_shr( L_tmp, 8 ); /* From Q24 to Q16 */
815 57623 : sfrac = L_Extract_lc( L_tmp, &tmpS );
816 57623 : *enr_q = Pow2( tmpS, sfrac );
817 57623 : move32();
818 : }
819 :
820 100332 : return clas;
821 : }
822 :
823 109205 : Word16 FEC_pos_dec_fx(
824 : Decoder_State *st_fx, /* i/o: decoder state structure */
825 : Word16 *last_pulse_pos,
826 : /* o : last glotal pulse position in the lost ACB */ // Q0
827 : Word32 *enr_q, /* o : decoded energy in Q0 */
828 : const Word16 nBits_es_Pred /* i : number of bits for Es_pred Q */
829 : )
830 : {
831 : Word16 pitch_index, T0, T0_frac, T0_min, T0_max;
832 : Word16 bit_pos_pitch_index, nBits;
833 :
834 109205 : T0 = 0;
835 109205 : move16();
836 109205 : IF( GT_16( st_fx->coder_type, UNVOICED ) )
837 : {
838 : /* decode the clas and energy information */
839 103271 : IF( LT_16( st_fx->coder_type, AUDIO ) )
840 : {
841 100332 : st_fx->clas_dec = FEC_dec_class_fx( st_fx, enr_q );
842 100332 : move16();
843 :
844 100332 : test();
845 100332 : test();
846 100332 : test();
847 100332 : if ( EQ_16( st_fx->coder_type, GENERIC ) && EQ_16( st_fx->clas_dec, VOICED_CLAS ) && ( LE_16( st_fx->last_good, UNVOICED_CLAS ) || EQ_16( st_fx->last_good, INACTIVE_CLAS ) ) )
848 : {
849 38 : st_fx->clas_dec = SIN_ONSET;
850 38 : move16();
851 : }
852 : }
853 :
854 103271 : test();
855 103271 : IF( EQ_16( st_fx->coder_type, GENERIC ) && GT_16( st_fx->acelp_cfg.FEC_mode, 2 ) )
856 : {
857 9006 : nBits = st_fx->acelp_cfg.pitch_bits[0]; /* The first pitch index is located right after the actual position + the last pulse position index + predicted innovation energy index */
858 9006 : bit_pos_pitch_index = add( add( st_fx->next_bit_pos, FEC_BITS_POS ), nBits_es_Pred );
859 9006 : test();
860 9006 : test();
861 9006 : if ( GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && EQ_16( st_fx->coder_type, GENERIC ) )
862 : {
863 : /* Harmonic flag is present */
864 6467 : bit_pos_pitch_index = add( bit_pos_pitch_index, 1 );
865 : }
866 : /* retrieve the pitch index */
867 9006 : pitch_index = (Word16) get_indice( st_fx, bit_pos_pitch_index, nBits );
868 :
869 : /* decode pitch period */
870 9006 : T0_min = PIT_MIN;
871 9006 : move16();
872 9006 : T0_max = PIT_MAX;
873 9006 : move16();
874 9006 : pit16k_Q_dec_fx( pitch_index, 10, 1, &T0, &T0_frac, &T0_min, &T0_max, &st_fx->BER_detect );
875 :
876 : /* decode last pulse position */
877 9006 : *last_pulse_pos = (Word16) get_next_indice_fx( st_fx, FEC_BITS_POS );
878 :
879 : /* respect the sign */
880 9006 : IF( GE_16( *last_pulse_pos, 128 ) )
881 : {
882 1550 : *last_pulse_pos = negate( s_and( *last_pulse_pos, 0x7F ) );
883 1550 : move16();
884 : }
885 9006 : IF( GE_16( T0, 128 ) )
886 : {
887 2860 : *last_pulse_pos = add( *last_pulse_pos, *last_pulse_pos );
888 2860 : move16();
889 : }
890 :
891 9006 : if ( st_fx->BER_detect )
892 : {
893 0 : *last_pulse_pos = 0;
894 0 : move16();
895 : }
896 : }
897 : }
898 :
899 109205 : return T0;
900 : }
901 : /*----------------------------------------------------------------------*
902 : * Corre:
903 : *
904 : * Correlation function. Signal x is compared to target signal y
905 : * Information about the similarity between vectors is returned in *gain
906 : *----------------------------------------------------------------------*/
907 106840 : static void Corre(
908 : const Word16 *x, /* i : vector 1 Q12 */
909 : const Word16 *y, /* i : vector 2 Q12 */
910 : const Word16 l, /* i : length of vectors */
911 : Word16 *gain /* o : normalized correlation gain Q15 */
912 : )
913 : {
914 : Word16 cor, cor_exp;
915 : Word16 den, den_exp;
916 : Word16 den2, den2_exp;
917 : Word32 tmp;
918 : Word16 tmp_exp;
919 :
920 : /* keep Q15 normalized result */
921 106840 : cor = extract_h( Dot_product12( x, y, l, &cor_exp ) );
922 106840 : den = add_sat( extract_h( Dot_product12( y, y, l, &den_exp ) ), 1 );
923 106840 : den2 = extract_h( Dot_product12( x, x, l, &den2_exp ) );
924 :
925 : /* keep Q31 normalized result */
926 106840 : tmp = L_mult( den, den2 );
927 106840 : tmp_exp = norm_l( tmp );
928 106840 : tmp = L_shl( tmp, tmp_exp );
929 106840 : tmp_exp = sub( add( den_exp, den2_exp ), tmp_exp );
930 :
931 106840 : tmp = Isqrt_lc( tmp, &tmp_exp );
932 : /* keep Q15 result */
933 106840 : gain[0] = shl_sat( mult_r( cor, extract_h( tmp ) ), add( cor_exp, tmp_exp ) );
934 106840 : move16();
935 106840 : }
|