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 25262040 : 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 : T0 = mult_r_sat( add_sat( pitch[2], pitch[3] ), 256 );
289 90278 : pos_limit = sub( L_frame, L_SUBFR );
290 90278 : j = s_min( 1, s_max( 0, sub( pos, pos_limit ) ) );
291 90278 : Ltmp = L_deposit_l( cor_max[0] );
292 90278 : IF( j > 0 )
293 : {
294 14255 : j = 16384;
295 14255 : move16();
296 14255 : pos = sub( pos, T0 ); /* T0 [34 231] */
297 14255 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[1] );
298 14255 : Ltmp = L_add( Ltmp, cor_max[1] );
299 14255 : IF( GT_16( pos, pos_limit ) )
300 : {
301 1940 : j = 10923;
302 1940 : move16();
303 1940 : pos = sub( pos, T0 ); /* T0 [34 231] */
304 1940 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[2] );
305 1940 : Ltmp = L_add( Ltmp, cor_max[2] );
306 : }
307 14255 : IF( GT_16( pos, pos_limit ) )
308 : {
309 271 : j = 8192;
310 271 : move16();
311 271 : pos = sub( pos, T0 ); /* T0 [34 231] */
312 271 : Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[3] );
313 271 : Ltmp = L_add( Ltmp, cor_max[3] );
314 : }
315 : }
316 :
317 90278 : voicing = cor_max[0];
318 90278 : move16();
319 90278 : IF( j > 0 )
320 : {
321 14255 : voicing = extract_l( Mult_32_16( Ltmp, j ) );
322 : }
323 : /*------------------------------------------------------------------------*
324 : * Compute pitch coherence
325 : *------------------------------------------------------------------------*/
326 :
327 90278 : pc = 0;
328 90278 : move16();
329 90278 : test();
330 90278 : test();
331 90278 : IF( EQ_16( codec_mode, MODE1 ) || !( NE_16( LTP_Gain, -32768 /*-1.f Q15*/ ) && EQ_16( mode, CLASSIFIER_TCX ) ) )
332 : {
333 33065 : pc = shr( abs_s( sub( add_sat( pitch[3], sub( pitch[2], pitch[1] ) ), pitch[0] ) ), 6 );
334 :
335 33065 : IF( EQ_16( L_frame, L_FRAME16k ) )
336 : {
337 8045 : pc = mult_r( pc, 26214 ); /* Renormalization for 12.8kHz core*/
338 : }
339 : }
340 :
341 : /*------------------------------------------------------------------------*
342 : * Compute spectral tilt
343 : *------------------------------------------------------------------------*/
344 90278 : pt1 = (Word16 *) synth + L_SUBFR;
345 90278 : move16();
346 90278 : pt2 = (Word16 *) synth + L_SUBFR - 1;
347 90278 : move16();
348 90278 : Ltmp = L_mult0( *pt1, *pt1 );
349 90278 : Ltmp1 = L_mult0( *pt1, *pt2 );
350 19914560 : FOR( j = 1; j < L_SUBFR * ( nb_subfr - 1 ); j++ )
351 : {
352 19824282 : pt1++;
353 19824282 : pt2++;
354 19824282 : Ltmp = L_mac0_sat( Ltmp, *pt1, *pt1 );
355 19824282 : Ltmp1 = L_mac0_sat( Ltmp1, *pt1, *pt2 );
356 : }
357 90278 : tilt = 0;
358 90278 : move16();
359 :
360 90278 : IF( Ltmp != 0 )
361 : {
362 : BASOP_SATURATE_WARNING_OFF_EVS
363 90248 : tmp16 = extract_l( L_or( L_shr( Ltmp1, 32 ), 1 ) ); /* sets a flag -1 or 1 for sign of Ltmp1 */
364 : BASOP_SATURATE_WARNING_ON_EVS
365 90248 : Ltmp1 = L_abs( Ltmp1 );
366 90248 : exp1 = norm_l( Ltmp1 );
367 90248 : tmp_y = extract_h( L_shl( Ltmp1, exp1 ) );
368 90248 : exp1 = sub( 31 - 1 + 3, exp1 );
369 90248 : exp2 = norm_l( Ltmp );
370 90248 : tmp_x = extract_h( L_shl( Ltmp, exp2 ) );
371 90248 : exp2 = sub( 31 - 1 + 3, exp2 );
372 : BASOP_SATURATE_WARNING_OFF_EVS
373 90248 : tmpS = shr( sub_sat( tmp_x, tmp_y ), 16 ); /* if tmp_x >= tmp_y tmpS = 0, -1 otherwise */
374 : BASOP_SATURATE_WARNING_ON_EVS
375 90248 : tmp_y = shl( tmp_y, tmpS );
376 90248 : exp1 = sub( exp1, tmpS );
377 :
378 90248 : tilt = div_s( tmp_y, tmp_x );
379 90248 : tilt = shl_sat( tilt, sub( exp1, exp2 ) ); /* saturate to 1.0 */
380 :
381 90248 : tilt = i_mult2( tilt, tmp16 );
382 : }
383 :
384 : /*------------------------------------------------------------------------*
385 : * Compute pitch-synchronous energy at the frame end
386 : *------------------------------------------------------------------------*/
387 90278 : ener = frame_energy_fx( L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn );
388 :
389 : /*------------------------------------------------------------------------*
390 : * transform parameters between 0 & 1
391 : * find unique merit function
392 : *------------------------------------------------------------------------*/
393 90278 : enern = mac_r( C_ENR_FX, K_ENR_FX, ener ); /*Q8*/
394 :
395 90278 : tiltn = extract_h( L_shr( L_mac( C_TILT_FX, K_TILT_FX, tilt ), 6 ) ); /*Q14 -> Q8*/
396 :
397 90278 : corn = extract_h( L_shr( L_mac( C_COR_FX, K_COR_FX, voicing ), 6 ) ); /*Q14 -> Q8*/
398 :
399 90278 : zcn = extract_h( L_shl( L_mac( C_ZC_FX, K_ZC_FX, zc_frame ), 4 ) ); /* Q4 -> Q8*/
400 :
401 : BASOP_SATURATE_WARNING_OFF_EVS
402 90278 : tmp16 = sub_sat( LTP_Gain, -32768 /*-1.f Q15*/ );
403 : BASOP_SATURATE_WARNING_ON_EVS
404 90278 : test();
405 90278 : test();
406 90278 : IF( EQ_16( codec_mode, MODE2 ) && tmp16 != 0 && EQ_16( mode, CLASSIFIER_TCX ) )
407 : {
408 57213 : pcn = round_fx( L_shl( Mpy_32_16_1( C_PC_FX /*Q16*/, LTP_Gain /*Q15*/ ), 8 ) ); /*Q16*/
409 : }
410 : ELSE
411 : {
412 33065 : pcn = extract_h( L_shl( L_mac( C_PC_FX, K_PC_FX, pc ), 8 ) ); /* Q0 -> Q8*/
413 : }
414 :
415 90278 : pcn = s_min( 256, pcn );
416 90278 : pcn = s_max( 0, pcn );
417 : /* fmerit1 = (1.0f/6.0f) * (tiltn + 2.0f*corn + zcn + pcn + enern) */
418 90278 : Ltmp = L_mult( tiltn, UNS6 );
419 90278 : Ltmp = L_mac( Ltmp, corn, 2 * UNS6 );
420 90278 : Ltmp = L_mac( Ltmp, zcn, UNS6 );
421 90278 : Ltmp = L_mac( Ltmp, pcn, UNS6 );
422 90278 : Ltmp = L_mac( Ltmp, enern, UNS6 );
423 : BASOP_SATURATE_WARNING_OFF_EVS
424 90278 : fmerit1 = round_fx_sat( L_shl_sat( Ltmp, 15 - 8 ) ); /*Q15 can saturate to 1.0 */
425 : BASOP_SATURATE_WARNING_ON_EVS
426 90278 : test();
427 90278 : IF( EQ_16( codec_mode, MODE2 ) && narrowBand != 0 )
428 : {
429 0 : fmerit1 = mult_r( fmerit1, 29491 /*0.9f Q15*/ ); /* 0.90 */
430 : }
431 90278 : IF( EQ_16( codec_mode, MODE1 ) )
432 : {
433 19666 : *class_para = round_fx( L_shl( Ltmp, 14 - 8 ) ); /*Q14 - cannot be saturated, degrades HF synthesis */
434 19666 : move16();
435 : }
436 :
437 : /*------------------------------------------------------------------------*
438 : * frame classification
439 : *------------------------------------------------------------------------*/
440 90278 : IF( NE_16( coder_type, VOICED ) )
441 : {
442 90278 : Word16 result = UNVOICED_CLAS;
443 90278 : move16();
444 90278 : SWITCH( *clas )
445 : {
446 73041 : case VOICED_CLAS:
447 : case ONSET:
448 : case SIN_ONSET:
449 : case VOICED_TRANSITION:
450 73041 : test();
451 73041 : test();
452 73041 : IF( LT_16( fmerit1, 12780 /*0.39f Q15*/ ) )
453 : {
454 3782 : result = UNVOICED_CLAS;
455 3782 : move16();
456 : }
457 69259 : ELSE IF( LT_16( fmerit1, 20644 /*0.63f Q15*/ ) && ( LT_16( ener, -3840 ) || EQ_16( codec_mode, MODE2 ) ) )
458 : {
459 18046 : result = VOICED_TRANSITION;
460 18046 : move16();
461 : }
462 : ELSE
463 : {
464 51213 : result = VOICED_CLAS;
465 51213 : move16();
466 : }
467 :
468 73041 : BREAK;
469 :
470 17237 : case UNVOICED_CLAS:
471 : case UNVOICED_TRANSITION:
472 : case INACTIVE_CLAS:
473 17237 : IF( GT_16( fmerit1, 18350 /*0.56f Q15*/ ) )
474 : {
475 9670 : result = ONSET;
476 9670 : move16();
477 : }
478 7567 : ELSE IF( GT_16( fmerit1, 14746 /*0.45f Q15*/ ) )
479 : {
480 2519 : result = UNVOICED_TRANSITION;
481 2519 : move16();
482 : }
483 : ELSE
484 : {
485 5048 : result = UNVOICED_CLAS;
486 5048 : move16();
487 : }
488 17237 : BREAK;
489 : }
490 90278 : *clas = result;
491 90278 : move16();
492 : }
493 : }
494 :
495 :
496 149301 : IF( EQ_16( codec_mode, MODE1 ) )
497 : {
498 : /*------------------------------------------------------------------------*
499 : * Overwrite classification decision in case of music
500 : *------------------------------------------------------------------------*/
501 36855 : IF( EQ_16( coder_type, AUDIO ) )
502 : {
503 6834 : ( *decision_hyst ) = add( *decision_hyst, 4 );
504 6834 : move16();
505 : }
506 : ELSE
507 : {
508 30021 : ( *decision_hyst ) = sub( *decision_hyst, 1 );
509 30021 : move16();
510 : }
511 :
512 36855 : IF( EQ_16( coder_type, INACTIVE ) )
513 : {
514 12565 : *decision_hyst = sub( *decision_hyst, 10 );
515 12565 : move16();
516 : }
517 36855 : IF( GT_16( *decision_hyst, 200 ) )
518 : {
519 3836 : *decision_hyst = 200;
520 3836 : move16();
521 : }
522 33019 : ELSE IF( *decision_hyst < 0 )
523 : {
524 23586 : *decision_hyst = 0;
525 23586 : move16();
526 : }
527 :
528 36855 : test();
529 36855 : test();
530 36855 : if ( GT_16( *decision_hyst, 16 ) && LT_16( *clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) )
531 : {
532 1038 : *clas = VOICED_CLAS;
533 1038 : move16();
534 : }
535 : } /*MODE1*/
536 :
537 : /*---------------------------------------------------------------------------------*
538 : * Measure energy on active voice frames (to improve FEC performance)
539 : *---------------------------------------------------------------------------------*/
540 149301 : IF( EQ_16( *clas, VOICED_CLAS ) )
541 : {
542 78951 : test();
543 78951 : test();
544 78951 : test();
545 78951 : test();
546 78951 : test();
547 78951 : 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 ) ) ) ) )
548 : {
549 : /* pitch-synchronous energy at the frame end */
550 33213 : enern = frame_energy_fx( L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn );
551 : }
552 : /* update of long-term active speech energy */
553 78951 : Ltmp = L_mult0( 655, frame_ener ); /* 0.01 */
554 78951 : *lp_speech = mac_r( Ltmp, 32440, *lp_speech );
555 78951 : move16(); /* lp_speech update */
556 : }
557 :
558 149301 : IF( EQ_16( codec_mode, MODE1 ) )
559 : {
560 :
561 : /*---------------------------------------------------------------------------------*
562 : * Overwrite classification decision to UNVOICED_CLAS in case of INACTIVE frame
563 : *---------------------------------------------------------------------------------*/
564 36855 : test();
565 36855 : if ( EQ_16( coder_type, INACTIVE ) && NE_16( *clas, INACTIVE_CLAS ) )
566 : {
567 0 : *clas = UNVOICED_CLAS;
568 0 : move16();
569 : }
570 :
571 : /*---------------------------------------------------------------------------------*
572 : * Classification refinement to improve noise coding (only in AMR-WB IO mode)
573 : *---------------------------------------------------------------------------------*/
574 36855 : IF( Opt_AMR_WB )
575 : {
576 0 : *locattack = 0;
577 0 : move16();
578 :
579 : /*-----------------------------------------------------------------------------*
580 : * Unvoiced signal but not silence
581 : *-----------------------------------------------------------------------------*/
582 :
583 0 : test();
584 0 : IF( EQ_16( *clas, UNVOICED_CLAS ) && NE_16( coder_type, INACTIVE ) )
585 : {
586 0 : IF( LE_16( *lp_speech, 40 * 256 /*Q8*/ ) )
587 : {
588 0 : *UV_cnt = 16;
589 0 : move16();
590 : }
591 : ELSE
592 : {
593 0 : move16();
594 0 : *UV_cnt = sub( *UV_cnt, 8 );
595 : }
596 : }
597 :
598 : /*-----------------------------------------------------------------------------*
599 : * Neither unvoiced nor clean silence
600 : * Number of frames between UV is increased
601 : *-----------------------------------------------------------------------------*/
602 :
603 0 : ELSE IF( NE_16( coder_type, INACTIVE ) )
604 : {
605 0 : move16();
606 0 : *UV_cnt = add( *UV_cnt, 1 );
607 : }
608 :
609 : /*-----------------------------------------------------------------------------*
610 : * Maximum/minimum number of frames between UV reached
611 : *-----------------------------------------------------------------------------*/
612 :
613 0 : /* Range 0..300 */ move16();
614 0 : *UV_cnt = s_max( s_min( 300, *UV_cnt ), 0 );
615 :
616 : /*-----------------------------------------------------------------------------*
617 : * IF VAD = 0 (no voice activity)
618 : * long-term average updated towards to speech
619 : * maximum number of frames between UV is limited to 125
620 : * Else
621 : * update long-term average
622 : *-----------------------------------------------------------------------------*/
623 :
624 0 : IF( EQ_16( coder_type, INACTIVE ) )
625 : {
626 0 : move16();
627 0 : *LT_UV_cnt = mult_r( 31130 /*0.95f*/, *LT_UV_cnt ); /* tend to speech if no activity */
628 0 : *UV_cnt = s_min( 125, *UV_cnt );
629 0 : move16();
630 : }
631 : ELSE
632 : {
633 : /* *LT_UV_cnt = 0.9f * *LT_UV_cnt + 0.1f * *UV_cnt */
634 :
635 0 : Ltmp = L_mult( 3277 /*0.1f*/, *UV_cnt );
636 : /* Bring to Q22 */
637 0 : Ltmp = L_shl( Ltmp, 6 );
638 : /* Add to 0.9 x *LT_UV_cnt (Already in Q6) */
639 0 : Ltmp = L_mac( Ltmp, 29491 /*0.9f*/, *LT_UV_cnt ); /* Q22*/
640 : /* Store */
641 0 : *LT_UV_cnt = round_fx( Ltmp );
642 0 : move16();
643 : }
644 :
645 : /*-----------------------------------------------------------------------------*
646 : * Compute frame energy difference
647 : * IF long-term average is high and energy difference is relatively low
648 : * classification is overwritten to AUDIO
649 : * IF energy difference > 6.0dB
650 : * consider an attack
651 : *-----------------------------------------------------------------------------*/
652 :
653 0 : diff_ener = sub( ener, *Last_ener );
654 0 : *Last_ener = ener;
655 0 : move16();
656 0 : *amr_io_class = *clas;
657 0 : move16();
658 0 : test();
659 0 : if ( GT_16( *LT_UV_cnt, LT_UV_THR_FX ) && LT_16( diff_ener, 12 * 256 /*Q8*/ ) )
660 : {
661 0 : move16();
662 0 : *amr_io_class = AUDIO_CLAS;
663 : }
664 0 : test();
665 0 : test();
666 0 : if ( ( GT_16( diff_ener, 6 * 256 /*Q8*/ ) && EQ_16( *clas, AUDIO_CLAS ) ) || GT_16( diff_ener, 9 * 256 /*Q8*/ ) )
667 : {
668 0 : *locattack = 1;
669 0 : move16();
670 : }
671 :
672 : /*------------------------------------------------------------------------*
673 : * Find mean of the past 40 frames energy variation
674 : *------------------------------------------------------------------------*/
675 :
676 0 : IF( NE_16( coder_type, INACTIVE ) )
677 : {
678 0 : Ltmp = L_deposit_l( 0 );
679 0 : FOR( i = 1; i < MAX_LT; i++ )
680 : {
681 0 : Ltmp = L_mac( Ltmp, INV_MAX_LT_FX, lt_diff_etot[i - 1] ); /* divide by MAX_LT */
682 0 : lt_diff_etot[i - 1] = lt_diff_etot[i];
683 0 : move16();
684 : }
685 0 : Ltmp = L_mac( Ltmp, INV_MAX_LT_FX, lt_diff_etot[i - 1] ); /* divide by MAX_LT */
686 : /* Ltmp is in Q24 (Q16+Q8) */
687 :
688 : /*------------------------------------------------------------------------*
689 : * Find statistical deviation of the energy variation history
690 : * against the last 15 frames
691 : *------------------------------------------------------------------------*/
692 :
693 0 : Ltmp1 = L_deposit_l( 1 );
694 0 : FOR( i = MAX_LT - 15; i < MAX_LT; i++ )
695 : {
696 : /* ftmp_c = lt_diff_etot[i] - mean_diff */
697 0 : tmp16 = mac_r( Ltmp, lt_diff_etot[i], -32768L );
698 : /* fcorr += ftmp_c*ftmp_c */
699 0 : Ltmp1 = L_mac0( Ltmp1, tmp16, tmp16 ); /* in Q16 (Q8xQ8)*/
700 : }
701 0 : lt_diff_etot[i - 1] = diff_ener;
702 0 : move16();
703 :
704 : /*------------------------------------------------------------------------*
705 : * Compute statistical deviation
706 : * Overwrite classification, if needed
707 : *------------------------------------------------------------------------*/
708 :
709 : /* dev = (float)sqrt(fcorr / (MAX_LT-15)) */
710 0 : Ltmp = Sqrt_Ratio32( Ltmp1, 16 /*Q16*/, MAX_LT - 15, 0 /*Q0*/, &tmp16 );
711 0 : tmp16 = round_fx( L_shr( Ltmp, sub( 15 - 8, tmp16 ) ) ); /* Put in Q8 (Don't care about Possible Saturation) */
712 :
713 0 : test();
714 0 : IF( EQ_16( *amr_io_class, AUDIO_CLAS ) && GT_16( tmp16, 5 * 256 /*Q8*/ ) )
715 : {
716 0 : *amr_io_class = *clas;
717 0 : move16();
718 : /* *UV_cnt = (short)(80 + *UV_cnt*0.2f) */
719 0 : *UV_cnt = add( 80, mult( *UV_cnt, 6554 ) );
720 0 : move16();
721 : }
722 : }
723 : } /*if (Opt_AMR_WB)*/
724 : } /*if (codec_mode==MODE1)*/
725 :
726 :
727 : } /* Do the classification only
728 : - MODE1: when the class is not transmitted in the bitstream
729 : - MODE2: on good frames (classifier is also called for bfi=1) */
730 :
731 :
732 : /* update the memory of synthesis for frame class estimation */
733 254310 : IF( EQ_16( codec_mode, 2 ) )
734 : {
735 114184 : Copy( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM );
736 : }
737 : ELSE
738 : {
739 140126 : Copy_Scale_sig( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, negate( tmp_scale ) );
740 140126 : *Q_mem_syn = sub( add( Q_syn, tmp_scale_syn ), tmp_scale );
741 140126 : move16();
742 : }
743 :
744 :
745 254310 : return;
746 : }
747 :
748 100332 : static Word16 FEC_dec_class_fx(
749 : Decoder_State *st_fx, /* i/o: decoder state structure */
750 : Word32 *enr_q /* i : decoded energy Q0 */
751 : )
752 : {
753 : Word16 clas, tmpS;
754 : Word16 sfrac;
755 : Word32 L_tmp;
756 :
757 100332 : clas = ONSET;
758 100332 : move16();
759 :
760 100332 : IF( NE_16( st_fx->coder_type, VOICED ) )
761 : {
762 : /* decode the class */
763 96143 : tmpS = (Word16) get_next_indice_fx( st_fx, FEC_BITS_CLS );
764 :
765 96143 : IF( tmpS == 0 )
766 : {
767 41127 : clas = UNVOICED_CLAS;
768 41127 : move16();
769 : }
770 55016 : ELSE IF( EQ_16( tmpS, 1 ) )
771 : {
772 6401 : IF( GE_16( st_fx->last_good, VOICED_TRANSITION ) )
773 : {
774 5387 : clas = VOICED_TRANSITION;
775 5387 : move16();
776 : }
777 : ELSE
778 : {
779 1014 : clas = UNVOICED_TRANSITION;
780 1014 : move16();
781 : }
782 : }
783 48615 : ELSE IF( EQ_16( tmpS, 2 ) )
784 : {
785 41933 : clas = VOICED_CLAS;
786 41933 : move16();
787 : }
788 : }
789 : ELSE
790 : {
791 4189 : clas = VOICED_CLAS;
792 4189 : move16();
793 : }
794 :
795 : /* decode the energy */
796 100332 : test();
797 100332 : test();
798 100332 : IF( GT_16( st_fx->acelp_cfg.FEC_mode, 1 ) )
799 : {
800 57623 : tmpS = (Word16) get_next_indice_fx( st_fx, FEC_BITS_ENR );
801 : /* convert from logarithmic to linear domain (the range is 0 : 3.0 : 96 dB) */
802 57623 : tmpS = mult_r( shl( tmpS, 10 ), 24576 ); /* Q10*Q13->Q8 */
803 57623 : L_tmp = L_mult( tmpS, 10885 ); /* 0.332192 in Q15 */
804 57623 : L_tmp = L_shr( L_tmp, 8 ); /* From Q24 to Q16 */
805 57623 : sfrac = L_Extract_lc( L_tmp, &tmpS );
806 57623 : *enr_q = Pow2( tmpS, sfrac );
807 57623 : move32();
808 : }
809 :
810 100332 : return clas;
811 : }
812 :
813 109205 : Word16 FEC_pos_dec_fx(
814 : Decoder_State *st_fx, /* i/o: decoder state structure */
815 : Word16 *last_pulse_pos,
816 : /* o : last glotal pulse position in the lost ACB */ // Q0
817 : Word32 *enr_q, /* o : decoded energy in Q0 */
818 : const Word16 nBits_es_Pred /* i : number of bits for Es_pred Q */
819 : )
820 : {
821 : Word16 pitch_index, T0, T0_frac, T0_min, T0_max;
822 : Word16 bit_pos_pitch_index, nBits;
823 :
824 109205 : T0 = 0;
825 109205 : move16();
826 109205 : IF( GT_16( st_fx->coder_type, UNVOICED ) )
827 : {
828 : /* decode the clas and energy information */
829 103271 : IF( LT_16( st_fx->coder_type, AUDIO ) )
830 : {
831 100332 : st_fx->clas_dec = FEC_dec_class_fx( st_fx, enr_q );
832 100332 : move16();
833 :
834 100332 : test();
835 100332 : test();
836 100332 : test();
837 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 ) ) )
838 : {
839 38 : st_fx->clas_dec = SIN_ONSET;
840 38 : move16();
841 : }
842 : }
843 :
844 103271 : test();
845 103271 : IF( EQ_16( st_fx->coder_type, GENERIC ) && GT_16( st_fx->acelp_cfg.FEC_mode, 2 ) )
846 : {
847 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 */
848 9006 : bit_pos_pitch_index = add( add( st_fx->next_bit_pos, FEC_BITS_POS ), nBits_es_Pred );
849 9006 : test();
850 9006 : test();
851 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 ) )
852 : {
853 : /* Harmonic flag is present */
854 6467 : bit_pos_pitch_index = add( bit_pos_pitch_index, 1 );
855 : }
856 : /* retrieve the pitch index */
857 9006 : pitch_index = (Word16) get_indice( st_fx, bit_pos_pitch_index, nBits );
858 :
859 : /* decode pitch period */
860 9006 : T0_min = PIT_MIN;
861 9006 : move16();
862 9006 : T0_max = PIT_MAX;
863 9006 : move16();
864 9006 : pit16k_Q_dec_fx( pitch_index, 10, 1, &T0, &T0_frac, &T0_min, &T0_max, &st_fx->BER_detect );
865 :
866 : /* decode last pulse position */
867 9006 : *last_pulse_pos = (Word16) get_next_indice_fx( st_fx, FEC_BITS_POS );
868 :
869 : /* respect the sign */
870 9006 : IF( GE_16( *last_pulse_pos, 128 ) )
871 : {
872 1550 : *last_pulse_pos = negate( s_and( *last_pulse_pos, 0x7F ) );
873 1550 : move16();
874 : }
875 9006 : IF( GE_16( T0, 128 ) )
876 : {
877 2860 : *last_pulse_pos = add( *last_pulse_pos, *last_pulse_pos );
878 2860 : move16();
879 : }
880 :
881 9006 : if ( st_fx->BER_detect )
882 : {
883 0 : *last_pulse_pos = 0;
884 0 : move16();
885 : }
886 : }
887 : }
888 :
889 109205 : return T0;
890 : }
891 : /*----------------------------------------------------------------------*
892 : * Corre:
893 : *
894 : * Correlation function. Signal x is compared to target signal y
895 : * Information about the similarity between vectors is returned in *gain
896 : *----------------------------------------------------------------------*/
897 106744 : static void Corre(
898 : const Word16 *x, /* i : vector 1 Q12 */
899 : const Word16 *y, /* i : vector 2 Q12 */
900 : const Word16 l, /* i : length of vectors */
901 : Word16 *gain /* o : normalized correlation gain Q15 */
902 : )
903 : {
904 : Word16 cor, cor_exp;
905 : Word16 den, den_exp;
906 : Word16 den2, den2_exp;
907 : Word32 tmp;
908 : Word16 tmp_exp;
909 :
910 : /* keep Q15 normalized result */
911 106744 : cor = extract_h( Dot_product12( x, y, l, &cor_exp ) );
912 106744 : den = add_sat( extract_h( Dot_product12( y, y, l, &den_exp ) ), 1 );
913 106744 : den2 = extract_h( Dot_product12( x, x, l, &den2_exp ) );
914 :
915 : /* keep Q31 normalized result */
916 106744 : tmp = L_mult( den, den2 );
917 106744 : tmp_exp = norm_l( tmp );
918 106744 : tmp = L_shl( tmp, tmp_exp );
919 106744 : tmp_exp = sub( add( den_exp, den2_exp ), tmp_exp );
920 :
921 106744 : tmp = Isqrt_lc( tmp, &tmp_exp );
922 : /* keep Q15 result */
923 106744 : gain[0] = shl_sat( mult_r( cor, extract_h( tmp ) ), add( cor_exp, tmp_exp ) );
924 106744 : move16();
925 106744 : }
|