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"
7 : #include "basop_util.h"
8 : #include "prot_fx.h"
9 : #include "cnst.h"
10 : #include "rom_com.h"
11 :
12 : /*-------------------------------------------------------------------
13 : * Local constants
14 : *-------------------------------------------------------------------*/
15 :
16 : #define ENV_SCALE_OFFSET_1_FX 1515133568l /*90.309f/128.0 Q31*/ /* 10*log10(2^30) */ /* scaled by 1/128.0 */
17 : #define MAX_TEC_BW_LO ( 12 )
18 : #define MAX_NB_TEC_LOW_BAND ( 3 )
19 : #define NBTECLOWBAND 3
20 : #define TECSMOOTHINGDEG 5
21 : #define LOBUF_NO_SMOOTHING_MODE 1
22 :
23 : /*-------------------------------------------------------------------
24 : * resetTecDec_Fx()
25 : *
26 : *
27 : *-------------------------------------------------------------------*/
28 35 : void resetTecDec_Fx(
29 : TEC_DEC_HANDLE hTecDec )
30 : {
31 :
32 35 : set16_fx( hTecDec->pGainTemp_m, 0, CLDFB_NO_COL_MAX );
33 35 : set16_fx( hTecDec->pGainTemp_e, 0, CLDFB_NO_COL_MAX );
34 35 : set16_fx( hTecDec->loBuffer, 0, CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG );
35 :
36 35 : return;
37 : }
38 :
39 : /*-------------------------------------------------------------------
40 : * resetTecEnc_Fx()
41 : *
42 : *
43 : *-------------------------------------------------------------------*/
44 66 : void resetTecEnc_Fx( TEC_ENC_HANDLE hTecEnc, Word16 flag )
45 : {
46 66 : IF( flag == 0 )
47 : {
48 23 : set16_fx( hTecEnc->loBuffer, 0, CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC );
49 23 : set16_fx( hTecEnc->loTempEnv, 0, CLDFB_NO_COL_MAX );
50 23 : set16_fx( hTecEnc->loTempEnv_ns, 0, CLDFB_NO_COL_MAX );
51 23 : set16_fx( hTecEnc->hiTempEnv, 0, CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV );
52 : }
53 : ELSE
54 : {
55 43 : set16_fx( hTecEnc->loBuffer, 0, MAX_TEC_SMOOTHING_DEG );
56 : }
57 66 : return;
58 : }
59 :
60 : /*-------------------------------------------------------------------
61 : * calcVar()
62 : *
63 : *
64 : *-------------------------------------------------------------------*/
65 :
66 9191 : static Word32 calcVar_Fix(
67 : const Word32 in[], /*Q7*/
68 : const Word32 len, /*Q0*/
69 : Word32 *x /*Q7*/ )
70 : {
71 : Word32 xx;
72 : Word32 i;
73 : Word16 exp1;
74 : Word32 ans;
75 : Word16 r_sft;
76 : Word32 tmpX;
77 :
78 9191 : xx = L_deposit_l( 0 );
79 9191 : *x = L_deposit_l( 0 );
80 9191 : move32();
81 156247 : FOR( i = 0; i < len; i++ )
82 : {
83 :
84 147056 : exp1 = norm_l( in[i] );
85 147056 : r_sft = sub( add( exp1, exp1 ), 24 );
86 147056 : tmpX = L_shr( Mpy_32_32( L_shl( in[i], exp1 ), L_shl( in[i], exp1 ) ), r_sft ); /*Q7*/
87 147056 : xx = L_add( xx, tmpX ); /*Q7*/
88 147056 : *x = L_add( *x, in[i] ); /*Q7*/
89 147056 : move32();
90 : }
91 :
92 9191 : ans = L_deposit_l( 0 );
93 9191 : exp1 = norm_l( *x );
94 9191 : r_sft = sub( add( exp1, exp1 ), 24 );
95 9191 : tmpX = Mpy_32_32( L_shl( *x, exp1 ), L_shl( *x, exp1 ) ); /*2*(Q7 + exp1) - 31*/
96 9191 : tmpX = L_shr( tmpX, r_sft ); /*Q7*/
97 9191 : IF( len == 0 )
98 : {
99 0 : return 0;
100 : }
101 9191 : ELSE IF( EQ_32( len, 16 ) )
102 : {
103 9191 : ans = L_sub( xx, L_shr( tmpX, 4 ) ); /*Q7*/
104 : }
105 : ELSE
106 : {
107 : /* Len = 16 Only */
108 0 : ans = L_deposit_l( 0 );
109 : }
110 9191 : return ans; /*Q7*/
111 : }
112 : /*-------------------------------------------------------------------
113 : * calcCorrelationCoefficient2()
114 : *
115 : *
116 : *-------------------------------------------------------------------*/
117 :
118 2991 : static Word32 calcCorrelationCoefficient2_Fix(
119 : const Word32 in_vec1[], /*Q7*/
120 : const Word32 in_vec2[], /*Q7*/
121 : const Word32 len, /*Q0*/
122 : Word32 var_x, /*Q7*/
123 : Word32 var_y, /*Q7*/
124 : Word32 x, /*Q7*/
125 : Word32 y /*Q7*/ )
126 : {
127 :
128 : Word16 i;
129 : Word32 xy;
130 : Word32 xy2;
131 : Word32 ans;
132 : Word16 exp1;
133 : Word16 exp2;
134 : Word16 exp3;
135 : Word16 exp4;
136 : Word16 r_sft;
137 : Word32 tmpXY;
138 : Word32 tmpCor;
139 : Word32 Val1, Val2;
140 :
141 :
142 2991 : xy = L_deposit_l( 0 );
143 :
144 50847 : FOR( i = 0; i < len; i++ )
145 : {
146 47856 : exp1 = norm_l( in_vec1[i] );
147 47856 : exp2 = norm_l( in_vec2[i] );
148 47856 : r_sft = sub( add( exp1, exp2 ), 24 );
149 47856 : tmpXY = L_shr( Mpy_32_32( L_shl( in_vec1[i], exp1 ), L_shl( in_vec2[i], exp2 ) ), r_sft ); /*Q7*/
150 47856 : xy = L_add( xy, tmpXY ); /*Q7*/
151 : }
152 :
153 :
154 2991 : IF( EQ_32( len, 16 ) )
155 : {
156 2991 : exp1 = norm_l( x );
157 2991 : exp2 = norm_l( y );
158 2991 : r_sft = sub( add( exp1, exp2 ), 24 );
159 2991 : xy2 = L_shr( Mpy_32_32( L_shl( x, exp1 ), L_shl( y, exp2 ) ), r_sft + 4 ); /*Q7*/
160 2991 : Val1 = L_sub( xy, xy2 ); /*Q7*/
161 :
162 2991 : test();
163 2991 : IF( var_x == 0 || var_y == 0 )
164 : {
165 0 : ans = L_deposit_l( 0 );
166 : }
167 : ELSE
168 : {
169 :
170 : Word32 sqrtVal1;
171 : Word32 sqrtVal2;
172 2991 : exp1 = norm_l( var_x );
173 2991 : if ( s_and( exp1, 0x1 ) != 0 )
174 : {
175 1495 : exp1 = sub( exp1, 1 );
176 : }
177 2991 : exp2 = norm_l( var_y );
178 2991 : if ( s_and( exp2, 0x1 ) != 0 )
179 : {
180 1474 : exp2 = sub( exp2, 1 );
181 : }
182 :
183 2991 : sqrtVal1 = Sqrt_l( L_shl( var_x, exp1 ), &exp3 ); /*Q7 + exp1*/
184 2991 : sqrtVal1 = L_shr( sqrtVal1, ( shr( add( exp1, 24 ), 1 ) ) ); /*Q7*/
185 2991 : sqrtVal2 = Sqrt_l( L_shl( var_y, exp2 ), &exp4 ); /*Q7 + exp1*/
186 2991 : sqrtVal2 = L_shr( sqrtVal2, ( shr( add( exp2, 24 ), 1 ) ) ); /*Q7*/
187 :
188 2991 : exp1 = norm_l( sqrtVal1 );
189 2991 : exp2 = norm_l( sqrtVal2 );
190 :
191 2991 : r_sft = sub( add( exp1, exp2 ), 24 );
192 2991 : Val2 = L_shr( Mpy_32_32( L_shl( sqrtVal1, exp1 ), L_shl( sqrtVal2, exp2 ) ), r_sft ); /*Q7*/
193 2991 : exp1 = sub( norm_l( Val1 ), 1 );
194 2991 : exp2 = norm_l( Val2 );
195 :
196 2991 : tmpCor = L_deposit_l( 0 );
197 2991 : test();
198 2991 : if ( Val1 != 0 && Val2 != 0 )
199 : {
200 2990 : tmpCor = divide3232( L_shl( Val1, exp1 ), L_shl( Val2, exp2 ) ); /*Q15 - (exp2 - exp1)*/
201 : }
202 :
203 2991 : r_sft = sub( 8, sub( exp2, exp1 ) );
204 2991 : tmpCor = L_shr( tmpCor, r_sft ); /*Q7*/
205 2991 : ans = tmpCor;
206 2991 : move16();
207 : }
208 : }
209 : ELSE
210 : {
211 0 : ans = 0;
212 0 : move16();
213 : }
214 :
215 :
216 2991 : return ans; /*Q7*/
217 : }
218 : /*-------------------------------------------------------------------
219 : * calcLoBufferEnc()
220 : *
221 : *
222 : *-------------------------------------------------------------------*/
223 3100 : static void calcLoBufferEnc_Fx(
224 : Word32 **pCldfbPow_Fx, /* Q31 */
225 : const Word16 scale,
226 : const Word16 startPos, /*Q0*/
227 : const Word16 stopPos, /*Q0*/
228 : const Word16 bandOffsetBottom, /*Q0*/
229 : Word16 *loBuffer /* Q8 = Q(15 - (LD_DATA_SCALE + 1)) */
230 : )
231 : {
232 : Word16 lb;
233 : Word16 li;
234 : Word16 ui;
235 : Word16 slot;
236 : Word32 nrg;
237 : Word32 nrgLog;
238 : Word32 tmp;
239 :
240 52700 : FOR( slot = startPos; slot < stopPos; slot++ )
241 : {
242 49600 : tmp = L_deposit_l( 0 );
243 :
244 : /* scaling nrg : scale - 1 (sum up nrg) + 1 (inv_bw = 0.5) */
245 :
246 198400 : FOR( lb = 0; lb < NBTECLOWBAND; lb++ )
247 : {
248 148800 : li = TecLowBandTable[lb]; /*Q0*/
249 148800 : move16();
250 148800 : ui = sub( TecLowBandTable[lb + 1], 1 );
251 :
252 148800 : assert( ( ui - li ) == 1 );
253 :
254 : /* sum up maximum of 2 nrg values, thus leave 1 bits headroom */
255 148800 : nrg = L_add( L_shr( pCldfbPow_Fx[slot][li + bandOffsetBottom], 1 ),
256 148800 : L_shr( pCldfbPow_Fx[slot][ui + bandOffsetBottom], 1 ) ); /*Q31 - scale*/
257 :
258 :
259 : /* assemble log2(EPS) */
260 148800 : nrgLog = -668792462l /*-0.31143075889 Q31*/;
261 148800 : move32();
262 :
263 148800 : IF( nrg != 0 )
264 : {
265 : /* assemble log2 value and shift factor */
266 148760 : nrgLog = L_sub( L_shr( BASOP_Util_Log2( nrg ), 1 ), L_shl( scale, ( WORD32_BITS - 1 ) - ( LD_DATA_SCALE + 1 ) ) ); /*Q31*/
267 :
268 : /* /\* assemble log2 value and shift factor *\/ */
269 : /* nrgLog = L_shr(BASOP_Util_Log2(nrg),1); */
270 : }
271 :
272 148800 : tmp = L_add( tmp, nrgLog );
273 : }
274 :
275 : /* 0.50171665944 = 10 * log10(2.0) / NbTecLowBand / 2.0 */
276 49600 : loBuffer[slot] = extract_h( L_shl( Mpy_32_16_1( tmp, 16440 /*0.50171665944 Q15*/ ), 1 ) ); /* Q8 = Q(15 - (LD_DATA_SCALE + 1)) */
277 49600 : move16();
278 : }
279 3100 : }
280 : /*-------------------------------------------------------------------
281 : * calcHiTempEnv()
282 : *
283 : *
284 : *-------------------------------------------------------------------*/
285 :
286 3100 : static void calcHiTempEnv_Fx(
287 : Word32 **pCldfbPow, /* Q31 */
288 : Word16 scale,
289 : const Word16 startPos, /*Q0*/
290 : const Word16 stopPos, /*Q0*/
291 : const Word16 lowSubband, /*Q0*/
292 : const Word16 highSubband, /*Q0*/
293 : Word16 *hiTempEnv /* Q7 = Q(15 - (LD_DATA_SCALE + 2)) */
294 : )
295 : {
296 : Word16 k;
297 : Word16 s1;
298 : Word16 s2;
299 : Word16 bwHigh;
300 : Word32 nrg;
301 : Word32 nrgLog;
302 : Word16 normFac;
303 : Word16 timeIndex;
304 :
305 3100 : s1 = 3;
306 3100 : move16();
307 :
308 3100 : bwHigh = sub( highSubband, lowSubband ); /*Q0*/
309 :
310 3100 : normFac = getNormReciprocalWord16( bwHigh );
311 :
312 3100 : scale = sub( scale, s1 );
313 :
314 52700 : FOR( timeIndex = startPos; timeIndex < stopPos; timeIndex++ )
315 : {
316 49600 : nrg = L_deposit_l( 0 );
317 :
318 1041600 : FOR( k = lowSubband; k < highSubband; k++ )
319 : {
320 992000 : nrg = L_add_sat( nrg, L_shr( pCldfbPow[timeIndex][k], s1 ) ); /*Q31 - s1*/
321 : }
322 :
323 :
324 49600 : s2 = norm_l( nrg );
325 49600 : nrg = L_shl( nrg, s2 ); /*Q31 - s1 + s2*/
326 :
327 : /* assemble log2(EPS) */
328 49600 : nrgLog = -668792462l /*-0.31143075889 Q31*/;
329 49600 : move32();
330 :
331 49600 : if ( nrg != 0 )
332 : {
333 : /* assemble log2 value and shift factor */
334 49585 : nrgLog = L_shr( BASOP_Util_Log2( Mpy_32_16_1( nrg, normFac ) ), 1 ); /*Q31 - ( scale + s2 )*/
335 49585 : nrgLog = L_sub( nrgLog, L_shl( add( scale, s2 ), ( WORD32_BITS - 1 ) - ( LD_DATA_SCALE + 1 ) ) ); /*Q31 - ( LD_DATA_SCALE + 1 )*/
336 : }
337 :
338 : /* 0.75257498916 = 10 * log10(2.0) / 4.0 */
339 49600 : hiTempEnv[timeIndex] = extract_h( L_shr( L_shl( Mpy_32_16_1( nrgLog, 24660 /*0.75257498916 Q15*/ ), 2 ), 1 ) ); /* Q7 = Q(15 - (LD_DATA_SCALE + 2)) */
340 49600 : move16();
341 : }
342 3100 : }
343 : /*-------------------------------------------------------------------
344 : * calcLoBufferDec()
345 : *
346 : *
347 : *-------------------------------------------------------------------*/
348 :
349 1248 : static void calcLoBufferDec_Fx(
350 : Word32 **pCldfbReal, /*scale*/
351 : Word32 **pCldfbImag, /*scale*/
352 : Word16 *loBuffer, /*Q15 - ( LD_DATA_SCALE + 1 )*/
353 : const Word16 startPos, /*Q0*/
354 : const Word16 stopPos, /*Q0*/
355 : const Word16 offset, /*Q0*/
356 : const Word16 scale )
357 : {
358 : Word16 k;
359 : Word16 lb;
360 : Word16 s1;
361 : Word16 s2;
362 : Word16 slot;
363 : Word32 nrg32;
364 : Word32 tmp;
365 : Word32 maxVal;
366 :
367 :
368 21216 : FOR( slot = startPos; slot < stopPos; slot++ )
369 : {
370 19968 : tmp = L_deposit_l( 0 );
371 :
372 79872 : FOR( lb = 0; lb < NBTECLOWBAND; lb++ )
373 : {
374 : Word16 li;
375 : Word16 ui;
376 :
377 59904 : li = TecLowBandTable[lb]; /*Q0*/
378 59904 : move16();
379 59904 : ui = TecLowBandTable[lb + 1]; /*Q0*/
380 59904 : move16();
381 :
382 59904 : assert( ( ui - li ) == 2 );
383 :
384 59904 : maxVal = L_deposit_l( 0 );
385 :
386 : /* determine maximum value */
387 179712 : FOR( k = li; k < ui; k++ )
388 : {
389 119808 : maxVal = L_max( maxVal, L_abs( pCldfbReal[slot][k + offset] ) );
390 119808 : maxVal = L_max( maxVal, L_abs( pCldfbImag[slot][k + offset] ) );
391 : }
392 :
393 59904 : IF( maxVal != 0 )
394 : {
395 : /* sum up maximum of 4 squared values, thus leave 2 bits headroom */
396 59895 : s1 = sub( norm_l( maxVal ), 2 );
397 :
398 59895 : nrg32 = L_deposit_l( 0 );
399 :
400 179685 : FOR( k = li; k < ui; k++ )
401 : {
402 : Word16 val;
403 :
404 119790 : val = extract_h( L_shl( pCldfbReal[slot][k + offset], s1 ) ); /*scale+s1-16*/
405 119790 : nrg32 = L_mac( nrg32, val, val ); /*2*(scale+s1-16)*/
406 119790 : val = extract_h( L_shl( pCldfbImag[slot][k + offset], s1 ) ); /*scale+s1-16*/
407 119790 : nrg32 = L_mac( nrg32, val, val ); /*2*(scale+s1-16)*/
408 : }
409 :
410 : /* square(scale) + square(s1) + 1(inv_bw = 0.5) */
411 59895 : s2 = add( shl( add( scale, s1 ), 1 ), 1 );
412 :
413 : /* assemble log value */
414 59895 : tmp = L_add( tmp, L_shr( BASOP_Util_Log2( nrg32 ), 1 ) ); /*s2*/
415 :
416 : /* add shift factors */
417 59895 : tmp = L_sub( tmp, L_shl( s2, ( WORD32_BITS - 1 ) - ( LD_DATA_SCALE + 1 ) ) ); /*Q31 - ( LD_DATA_SCALE + 1 )*/
418 :
419 : /* add scale of reference */
420 59895 : tmp = L_add( tmp, L_shl( 30, ( WORD32_BITS - 1 ) - ( LD_DATA_SCALE + 1 ) ) );
421 :
422 : /* 0.50171665944 = 10 * log10(2.0) / NbTecLowBand / 2.0 */
423 59895 : loBuffer[slot] = extract_h( L_shl( Mpy_32_16_1( tmp, 16440 /*0.50171665944 Q15*/ ), 1 ) ); /*Q15 - ( LD_DATA_SCALE + 1 )*/
424 59895 : move16();
425 : }
426 : ELSE
427 : {
428 : /* 10 * log10(EPS) / 64.0 / 2.0 */
429 9 : loBuffer[slot] = -30720 /*-0.9375 Q15*/;
430 9 : move16();
431 : }
432 : }
433 : }
434 1248 : }
435 : /*-------------------------------------------------------------------
436 : * calcLoTempEnv_Fx()
437 : *
438 : *
439 : *-------------------------------------------------------------------*/
440 3100 : static void calcLoTempEnv_Fx(
441 : Word16 *loBuffer_Fx, /* Q8 = Q(15 - (LD_DATA_SCALE+1)) */
442 : const Word16 noCols, /*Q0*/
443 : Word16 *loTempEnv_Fx, /* Q7 = Q(15 - (LD_DATA_SCALE+2)) */
444 : const Word16 adjFac_Fx /*Q15*/ )
445 : {
446 : Word16 i;
447 : Word16 slot;
448 : Word32 accu;
449 :
450 : /* TecSC_Fx values are scaled by factor 2.0 */
451 52700 : FOR( slot = 0; slot < noCols; slot++ )
452 : {
453 49600 : accu = L_mult0( TecSC_Fx[0], loBuffer_Fx[slot] ); /*Q23*/
454 297600 : FOR( i = 1; i < TECSMOOTHINGDEG + 1; i++ )
455 : {
456 248000 : accu = L_mac0( accu, TecSC_Fx[i], loBuffer_Fx[( slot - i )] ); /*Q23*/
457 : }
458 : /* adjFac is scaled by factor 0.5 */
459 49600 : loTempEnv_Fx[slot] = extract_h( Mpy_32_16_1( accu, adjFac_Fx ) ); /*Q7*/
460 49600 : move16();
461 : }
462 3100 : }
463 : /*-------------------------------------------------------------------
464 : * calcLoTempEnv_ns()
465 : *
466 : *
467 : *-------------------------------------------------------------------*/
468 3100 : static void calcLoTempEnv_ns_Fx(
469 : Word16 *loBuffer_Fx, /* Q8 = Q(15 - (LD_DATA_SCALE+1)) */
470 : const Word16 noCols, /*Q0*/
471 : Word16 *loTempEnv_Fx /* Q7 = Q(15 - (LD_DATA_SCALE+2)) */
472 : )
473 : {
474 : Word16 slot;
475 :
476 52700 : FOR( slot = 0; slot < noCols; slot++ )
477 : {
478 49600 : loTempEnv_Fx[slot] = shr( loBuffer_Fx[slot], 1 ); /*Q7*/
479 49600 : move16();
480 : }
481 :
482 3100 : return;
483 : }
484 : /*-------------------------------------------------------------------
485 : * calcLoTempEnv_ns_TBE()
486 : *
487 : *
488 : *-------------------------------------------------------------------*/
489 5 : static void calcLoTempEnv_TBE_Fx(
490 : Word16 *loBuffer_Fx, /* Q8 = Q(15 - (LD_DATA_SCALE+1)) */
491 : const Word16 noCols, /*Q0*/
492 : Word16 *loTempEnv_Fx, /* Q7 = Q(15 - (LD_DATA_SCALE+2)) */
493 : const Word16 adjFac_Fx /*Q15*/ )
494 : {
495 : Word16 i;
496 : Word16 slot;
497 : Word32 accu;
498 5 : Word16 delay = 1;
499 5 : move16();
500 :
501 : /* TecSC_Fx values are scaled by factor 2.0 */
502 85 : FOR( slot = 0; slot < noCols; slot++ )
503 : {
504 80 : accu = L_mult0( TecSC_Fx[0], loBuffer_Fx[slot - delay] ); /*Q23*/
505 480 : FOR( i = 1; i < TECSMOOTHINGDEG + 1; i++ )
506 : {
507 400 : accu = L_mac0( accu, TecSC_Fx[i], loBuffer_Fx[slot - i - delay] ); /*Q23*/
508 : }
509 : /* adjFac is scaled by factor 0.5 */
510 80 : loTempEnv_Fx[slot] = extract_h( Mpy_32_16_1( accu, adjFac_Fx ) ); /*Q7*/
511 80 : move16();
512 : }
513 5 : }
514 : /*-------------------------------------------------------------------
515 : * calcLoTempEnv_ns_TBE()
516 : *
517 : *
518 : *-------------------------------------------------------------------*/
519 :
520 5 : static void calcLoTempEnv_ns_TBE_Fx(
521 : Word16 *loBuffer_Fx, /* Q8 = Q(15 - (LD_DATA_SCALE+1)) */
522 : const Word16 noCols, /*Q0*/
523 : Word16 *loTempEnv_Fx /* Q7 = Q(15 - (LD_DATA_SCALE+2)) */
524 : )
525 : {
526 : Word16 slot;
527 5 : Word16 delay = 1;
528 5 : Word16 fac = 22938 /*1.4f * 0.5f Q15*/;
529 5 : move16();
530 :
531 85 : FOR( slot = 0; slot < noCols; slot++ )
532 : {
533 : /* fac is scaled by factor 0.5 */
534 80 : loTempEnv_Fx[slot] = mult_r( fac, loBuffer_Fx[( slot - delay )] ); /*Q7*/
535 80 : move16();
536 : }
537 :
538 5 : return;
539 : }
540 : /*-------------------------------------------------------------------
541 : * calcGainLinear_TBE()
542 : *
543 : *
544 : *-------------------------------------------------------------------*/
545 10 : static void calcGainLinear_TBE_Fx(
546 : const Word16 *loTempEnv_m, /* Q7 = Q(15 - (LD_DATA_SCALE+2)) */
547 : const Word16 startPos, /*Q0*/
548 : const Word16 stopPos, /*Q0*/
549 : Word16 *pGainTemp_m, /* Q0 */
550 : Word16 *pGainTemp_e /* Q0 */
551 : )
552 : {
553 :
554 : Word16 slot;
555 : Word16 c;
556 : Word32 logScaleFactor;
557 :
558 :
559 : /* 0.1 * Log2(10.0) scaled by 2.0 */
560 10 : c = 21771 /*2.0*0.33219280948 Q15*/;
561 10 : move16();
562 :
563 170 : FOR( slot = startPos; slot < stopPos; slot++ )
564 : {
565 : Word16 s;
566 : Word16 s2;
567 : Word32 tmp32;
568 :
569 160 : s = 0;
570 160 : move16();
571 :
572 : /* adapt scale to LD_DATA_SCALE */
573 160 : tmp32 = L_shl( L_mult( c, loTempEnv_m[slot] ), 1 ); /*Q31*/
574 :
575 160 : IF( tmp32 > 0 )
576 : {
577 160 : IF( GE_32( tmp32, 1006632960l /*0.46875 Q31*/ ) )
578 : {
579 73 : s = add( s, sub( WORD32_BITS, norm_l( BASOP_Util_InvLog2( L_sub( tmp32, 1006632960l /*0.46875 Q31*/ ) ) ) ) );
580 73 : s = add( s, 30 );
581 : }
582 : ELSE
583 : {
584 87 : s = add( s, sub( WORD32_BITS, norm_l( BASOP_Util_InvLog2( tmp32 ) ) ) );
585 : }
586 :
587 : /* scalefactor for logarithmic domain */
588 160 : logScaleFactor = L_shl( L_mult0( 512 /*1.0/(1<<LD_DATA_SCALE) Q15*/, s ), 16 ); /*Q31*/
589 :
590 : /* scale in logaritmic domain */
591 160 : tmp32 = L_sub( tmp32, logScaleFactor ); /*Q31*/
592 : }
593 :
594 : /* inverse log2 */
595 160 : tmp32 = BASOP_Util_InvLog2( tmp32 ); /*Q31 - s*/
596 :
597 : /* determine headroom */
598 160 : s2 = norm_l( tmp32 );
599 :
600 160 : pGainTemp_m[slot] = extract_h( L_shl( tmp32, s2 ) ); /*Q15 - (s - s2)*/
601 160 : move16();
602 160 : pGainTemp_e[slot] = sub( s, s2 );
603 160 : move16();
604 : }
605 10 : }
606 : /*-------------------------------------------------------------------
607 : * calcGainTemp_TBE()
608 : *
609 : *
610 : *-------------------------------------------------------------------*/
611 1248 : void calcGainTemp_TBE_Fx(
612 : Word32 **pCldfbRealSrc_Fx, /*Q31 - cldfb_exp*/
613 : Word32 **pCldfbImagSrc_Fx, /*Q31 - cldfb_exp*/
614 : Word16 cldfb_exp,
615 : Word16 *loBuffer_Fx, /*Q8*/
616 : const Word16 startPos, /*!< Start position of the current envelope. Q0*/
617 : const Word16 stopPos, /*!< Stop position of the current envelope. Q0*/
618 : const Word16 lowSubband, /* lowSubband */
619 : Word16 *pGainTemp_m, /*Q15 - pGainTemp_e*/
620 : Word16 *pGainTemp_e,
621 : const Word16 code /*Q0*/ )
622 :
623 : {
624 : Word16 loTempEnv_Fx[16];
625 :
626 1248 : const Word16 BW_LO = TecLowBandTable[NBTECLOWBAND];
627 1248 : move16();
628 : Word16 slot;
629 :
630 1248 : Word16 noCols = sub( stopPos, startPos );
631 1248 : Word16 bandOffset = sub( lowSubband, BW_LO );
632 :
633 1248 : assert( lowSubband >= BW_LO );
634 :
635 1248 : calcLoBufferDec_Fx(
636 : pCldfbRealSrc_Fx,
637 : pCldfbImagSrc_Fx,
638 : loBuffer_Fx + MAX_TEC_SMOOTHING_DEG,
639 : startPos,
640 : stopPos,
641 : bandOffset,
642 1248 : sub( 15, cldfb_exp ) );
643 :
644 1248 : IF( code > 0 )
645 : {
646 10 : IF( NE_16( code, 2 ) )
647 : {
648 5 : calcLoTempEnv_TBE_Fx( loBuffer_Fx + MAX_TEC_SMOOTHING_DEG, noCols,
649 : loTempEnv_Fx, 19531 /*0.5f * ratioHiLoFacDec Q15*/ );
650 : }
651 : ELSE
652 : {
653 5 : calcLoTempEnv_ns_TBE_Fx( loBuffer_Fx + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv_Fx );
654 : }
655 :
656 10 : calcGainLinear_TBE_Fx( loTempEnv_Fx, startPos, stopPos,
657 : pGainTemp_m, pGainTemp_e );
658 : }
659 :
660 8736 : FOR( slot = 0; slot < MAX_TEC_SMOOTHING_DEG; slot++ )
661 : {
662 7488 : loBuffer_Fx[slot] = loBuffer_Fx[slot + stopPos]; /*Q8*/
663 7488 : move16();
664 : }
665 1248 : }
666 : /*-------------------------------------------------------------------
667 : * setSubfrConfig()
668 : *
669 : *
670 : *-------------------------------------------------------------------*/
671 :
672 68 : static void setSubfrConfig_Fix(
673 : const Word16 i_offset, /*Q0*/
674 : Word16 *k_offset, /*Q0*/
675 : Word16 *n_subfr, /*Q0*/
676 : const Word16 l_subfr /*Q0*/ )
677 : {
678 68 : *n_subfr = sub( (Word16) N_TEC_TFA_SUBFR, i_offset ); /*Q0*/
679 68 : move16();
680 68 : *k_offset = i_mult( i_offset, l_subfr ); /*Q0*/
681 68 : move16();
682 68 : }
683 : /*-------------------------------------------------------------------
684 : * calcSum_Fx()
685 : *
686 : *
687 : *-------------------------------------------------------------------*/
688 :
689 10 : static Word16 calcSum_Fx(
690 : Word16 *vec_m, /*Q0*/
691 : Word16 *vec_e, /*Q0*/
692 : const Word16 len,
693 : Word16 *sum16_m /*Q0*/
694 : )
695 : {
696 : Word16 slot;
697 : Word16 sum16_e; /* Q0 */
698 :
699 10 : *sum16_m = 0;
700 10 : move16();
701 10 : sum16_e = 0;
702 10 : move16();
703 169 : FOR( slot = 0; slot < len; slot++ )
704 : {
705 159 : sum16_e = BASOP_Util_Add_MantExp(
706 159 : *sum16_m,
707 : sum16_e,
708 159 : vec_m[slot],
709 159 : vec_e[slot],
710 : sum16_m );
711 : }
712 :
713 10 : return sum16_e;
714 : }
715 : /*-------------------------------------------------------------------
716 : * calcSubfrNrg()
717 : *
718 : *
719 : *-------------------------------------------------------------------*/
720 68 : static Word16 calcSubfrNrg_Fx(
721 : Word16 *hb_synth_Fx, /*Q15 - exp_syn*/
722 : Word16 exp_syn,
723 : const Word16 i_offset, /*Q0*/
724 : Word16 *enr_m, /*Q15 - enr_e*/
725 : Word16 *enr_e,
726 : const Word16 k_offset, /*Q0*/
727 : Word16 *sum16_m, /*Q15 - enr_e*/
728 : const Word16 l_subfr /*Q0*/ )
729 : {
730 : Word16 i, j, k;
731 : Word16 s;
732 : Word16 sum16_e;
733 68 : Word16 s2 = 1; /* headroom for a summatoin of length l_subfr ( < 2^s2 = 64 ) */
734 68 : move16();
735 :
736 68 : k = k_offset; /*Q0*/
737 68 : move16();
738 1155 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
739 : {
740 : Word32 nrg32;
741 :
742 1087 : nrg32 = L_deposit_l( 0 );
743 :
744 66307 : FOR( j = 0; j < l_subfr; j++ )
745 : {
746 : Word32 sq;
747 : Word32 sq_shr;
748 :
749 65220 : sq = L_mult( hb_synth_Fx[k], hb_synth_Fx[k] ); /*Q31 - 2*(exp_syn)*/
750 65220 : sq_shr = L_shr( sq, s2 ); /*Q31 - 2*(exp_syn) - s2*/
751 :
752 65220 : nrg32 = L_add( nrg32, sq_shr );
753 65220 : k = add( k, 1 );
754 : }
755 :
756 1087 : IF( nrg32 > 0 )
757 : {
758 : Word16 tmp;
759 1075 : s = norm_l( nrg32 );
760 1075 : tmp = extract_h( L_shl( nrg32, s ) ); /*Q15 - 2*(exp_syn) - s2 + s*/
761 1075 : enr_m[i] = tmp;
762 1075 : move16();
763 1075 : enr_e[i] = -s;
764 1075 : move16();
765 : }
766 : ELSE
767 : {
768 12 : enr_m[i] = 0;
769 12 : move16();
770 12 : enr_e[i] = -15;
771 12 : move16();
772 : }
773 : }
774 :
775 68 : sum16_e = enr_e[i_offset];
776 68 : move16();
777 68 : *sum16_m = enr_m[i_offset]; /*Q15 - enr_e*/
778 68 : move16();
779 1087 : FOR( i = i_offset + 1; i < N_TEC_TFA_SUBFR; i++ )
780 : {
781 :
782 1019 : sum16_e = BASOP_Util_Add_MantExp(
783 1019 : *sum16_m,
784 : sum16_e,
785 1019 : enr_m[i],
786 1019 : enr_e[i],
787 : sum16_m );
788 : }
789 :
790 : /* exp_syn is not used up to here */
791 1155 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
792 : {
793 1087 : enr_e[i] = add( s2, add( enr_e[i], shl( exp_syn, 1 ) ) );
794 1087 : move16();
795 : }
796 68 : sum16_e = add( s2, add( sum16_e, shl( exp_syn, 1 ) ) );
797 :
798 68 : return sum16_e;
799 : }
800 : /*-------------------------------------------------------------------
801 : * procTec()
802 : *
803 : *
804 : *-------------------------------------------------------------------*/
805 :
806 10 : static Word16 procTec_Fx(
807 : Word16 *hb_synth_Fx, /*Q15 - exp_syn*/
808 : Word16 exp_syn,
809 : Word16 *gain_m, /*Q15 - gain_e*/
810 : Word16 *gain_e,
811 : const Word16 i_offset, /*Q0*/
812 : const Word16 l_subfr, /*Q0*/
813 : const Word16 code /*Q0*/ )
814 : {
815 : Word16 i, j, k;
816 : Word16 k_offset, n_subfr;
817 :
818 : Word16 max_inv_curr_enr_m;
819 : Word16 max_inv_curr_enr_e;
820 :
821 : Word16 min_curr_enr_m;
822 : Word16 min_curr_enr_e;
823 :
824 : Word16 lower_limit_gain_m;
825 : Word16 lower_limit_gain_e;
826 :
827 : Word16 upper_limit_gain_m;
828 : Word16 upper_limit_gain_e;
829 :
830 : Word16 enr_m[N_TEC_TFA_SUBFR];
831 : Word16 enr_e[N_TEC_TFA_SUBFR];
832 :
833 : Word16 gain_ave_m;
834 : Word16 gain_ave_e;
835 :
836 : Word16 enr_ave_m;
837 : Word16 enr_ave_e;
838 :
839 : Word16 inv_curr_enr_m[N_TEC_TFA_SUBFR];
840 : Word16 inv_curr_enr_e[N_TEC_TFA_SUBFR];
841 :
842 : Word16 inv_n_subfr;
843 :
844 : Word16 s;
845 : Word16 shift[L_FRAME_MAX];
846 : Word16 min_shift;
847 :
848 10 : setSubfrConfig_Fix( i_offset, &k_offset, &n_subfr, l_subfr );
849 :
850 10 : assert( 8 /* = 2^3 */ < n_subfr );
851 10 : inv_n_subfr = getNormReciprocalWord16Scale( n_subfr, 3 );
852 :
853 10 : enr_ave_e = calcSubfrNrg_Fx( hb_synth_Fx,
854 : exp_syn,
855 : i_offset,
856 : enr_m,
857 : enr_e,
858 : k_offset,
859 : &enr_ave_m, l_subfr );
860 :
861 : /* divided by n_subfr */
862 10 : enr_ave_m = mult_r( enr_ave_m, inv_n_subfr ); /*Q15 - enr_ave_e + 3*/
863 10 : enr_ave_e = sub( enr_ave_e, 3 );
864 :
865 : /* calculate the average of gain */
866 10 : gain_ave_e = calcSum_Fx( &gain_m[i_offset],
867 10 : &gain_e[i_offset],
868 : n_subfr,
869 : &gain_ave_m );
870 :
871 10 : gain_ave_m = mult_r( gain_ave_m, inv_n_subfr ); /*Q15 - enr_ave_e + 3*/
872 10 : gain_ave_e = sub( gain_ave_e, 3 );
873 :
874 10 : k = k_offset;
875 10 : move16();
876 169 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
877 : {
878 159 : IF( enr_m[i] > 0 )
879 : {
880 159 : BASOP_Util_Divide_MantExp( enr_ave_m, enr_ave_e,
881 159 : enr_m[i], enr_e[i],
882 159 : &inv_curr_enr_m[i], &inv_curr_enr_e[i] );
883 : }
884 : ELSE
885 : {
886 : /* 1.0e+12 */
887 0 : inv_curr_enr_m[i] = 28282 /*0.8631 Q15*/;
888 0 : move16();
889 0 : inv_curr_enr_e[i] = 39;
890 0 : move16();
891 : }
892 :
893 159 : s = norm_s( inv_curr_enr_m[i] );
894 159 : inv_curr_enr_m[i] = shl( inv_curr_enr_m[i], s ); /*Q15 - inv_curr_enr_e + s*/
895 159 : move16();
896 159 : inv_curr_enr_e[i] = sub( inv_curr_enr_e[i], s );
897 159 : move16();
898 :
899 159 : IF( gain_m[i] > 0 )
900 : {
901 159 : BASOP_Util_Divide_MantExp( gain_m[i], gain_e[i],
902 : gain_ave_m, gain_ave_e,
903 159 : &gain_m[i], &gain_e[i] );
904 : }
905 : ELSE
906 : {
907 0 : return exp_syn;
908 : }
909 : }
910 :
911 : /* find the maximum of inv_curr_enr */
912 10 : max_inv_curr_enr_e = inv_curr_enr_e[i_offset];
913 10 : move16();
914 10 : max_inv_curr_enr_m = inv_curr_enr_m[i_offset];
915 10 : move16();
916 :
917 159 : FOR( i = i_offset + 1; i < N_TEC_TFA_SUBFR; i++ )
918 : {
919 149 : test();
920 149 : test();
921 149 : IF( LT_16( max_inv_curr_enr_e, inv_curr_enr_e[i] ) || ( EQ_16( max_inv_curr_enr_e, inv_curr_enr_e[i] ) && LT_16( max_inv_curr_enr_m, inv_curr_enr_m[i] ) ) )
922 : {
923 24 : max_inv_curr_enr_e = inv_curr_enr_e[i];
924 24 : move16();
925 24 : max_inv_curr_enr_m = inv_curr_enr_m[i];
926 24 : move16();
927 : }
928 : }
929 :
930 : /* evaluate lower limit of the gain's */
931 10 : BASOP_Util_Divide_MantExp( 32767, 0,
932 : max_inv_curr_enr_m, max_inv_curr_enr_e,
933 : &min_curr_enr_m, &min_curr_enr_e );
934 :
935 10 : s = norm_s( min_curr_enr_m );
936 10 : min_curr_enr_m = shl( min_curr_enr_m, s ); /*Q15 - min_curr_enr_e + s*/
937 10 : min_curr_enr_e = sub( min_curr_enr_e, s );
938 :
939 10 : lower_limit_gain_e = -3;
940 10 : move16();
941 10 : lower_limit_gain_m = 26214 /*0.1 * 8 Q15*/; /* norm = 0 */
942 10 : move16();
943 :
944 10 : test();
945 10 : test();
946 10 : IF( ( GT_16( lower_limit_gain_e, min_curr_enr_e ) ) || ( EQ_16( lower_limit_gain_e, min_curr_enr_e ) && GT_16( lower_limit_gain_m, min_curr_enr_m ) ) )
947 : {
948 8 : lower_limit_gain_m = min_curr_enr_m;
949 8 : move16();
950 8 : lower_limit_gain_e = sub( min_curr_enr_e, 1 );
951 : }
952 :
953 : /* upper_limit_gain */
954 10 : upper_limit_gain_m = 19661 /*0.6f Q15*/; /* norm = 0 */
955 10 : move16();
956 10 : upper_limit_gain_e = 1;
957 10 : move16();
958 10 : IF( EQ_16( code, LOBUF_NO_SMOOTHING_MODE ) )
959 : {
960 5 : upper_limit_gain_m = 24576 /*0.75f Q15*/; /* norm = 0 */
961 5 : move16();
962 5 : upper_limit_gain_e = 2;
963 5 : move16();
964 : }
965 :
966 10 : min_shift = 15; /* min_shift <= 15 */
967 10 : move16();
968 :
969 10 : k = k_offset;
970 10 : move16();
971 169 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
972 : {
973 159 : test();
974 159 : test();
975 159 : IF( ( GT_16( lower_limit_gain_e, gain_e[i] ) ) || ( EQ_16( lower_limit_gain_e, gain_e[i] ) && GT_16( lower_limit_gain_m, gain_m[i] ) ) )
976 : {
977 4 : gain_m[i] = lower_limit_gain_m; /*Q15 - gain_e*/
978 4 : move16();
979 4 : gain_e[i] = lower_limit_gain_e;
980 4 : move16();
981 : }
982 :
983 159 : gain_m[i] = mult_r( gain_m[i], inv_curr_enr_m[i] ); /*Q15 - gain_e - inv_curr_enr_e*/
984 159 : move16();
985 159 : gain_e[i] = add( gain_e[i], inv_curr_enr_e[i] );
986 159 : move16();
987 :
988 159 : s = norm_s( gain_m[i] );
989 159 : gain_m[i] = shl( gain_m[i], s ); /*Q15 - gain_e + s*/
990 159 : move16();
991 159 : gain_e[i] = sub( gain_e[i], s );
992 159 : move16();
993 :
994 159 : test();
995 159 : test();
996 159 : IF( ( LT_16( upper_limit_gain_e, gain_e[i] ) ) || ( EQ_16( upper_limit_gain_e, gain_e[i] ) && LT_16( upper_limit_gain_m, gain_m[i] ) ) )
997 : {
998 :
999 46 : gain_m[i] = upper_limit_gain_m; /*Q15 - gain_e*/
1000 46 : move16();
1001 46 : gain_e[i] = upper_limit_gain_e;
1002 46 : move16();
1003 : }
1004 :
1005 159 : gain_m[i] = Sqrt16( gain_m[i], &gain_e[i] ); /*Q15 - gain_e*/
1006 159 : move16();
1007 159 : s = norm_s( gain_m[i] );
1008 159 : gain_m[i] = shl( gain_m[i], s ); /*Q15 - gain_e + s*/
1009 159 : move16();
1010 159 : gain_e[i] = sub( gain_e[i], s );
1011 159 : move16();
1012 :
1013 9699 : FOR( j = 0; j < l_subfr; j++ )
1014 : {
1015 9540 : s = norm_s( hb_synth_Fx[k] );
1016 9540 : hb_synth_Fx[k] = mult_r( gain_m[i], shl( hb_synth_Fx[k], s ) ); /*Q15 - gain_e - exp_syn + s*/
1017 9540 : move16();
1018 9540 : shift[k] = sub( s, gain_e[i] );
1019 9540 : move16();
1020 :
1021 9540 : if ( GT_16( min_shift, shift[k] ) )
1022 : {
1023 40 : min_shift = shift[k];
1024 40 : move16();
1025 : }
1026 9540 : k = add( k, 1 );
1027 : }
1028 : }
1029 :
1030 10 : s = exp_syn;
1031 10 : move16();
1032 :
1033 10 : exp_syn = sub( s, min_shift );
1034 10 : if ( GT_16( exp_syn, 15 ) )
1035 : {
1036 7 : exp_syn = 15;
1037 7 : move16();
1038 : }
1039 :
1040 10 : if ( exp_syn < 0 )
1041 : {
1042 0 : exp_syn = 0;
1043 0 : move16();
1044 : }
1045 :
1046 10 : min_shift = sub( s, exp_syn ); /* exp_syn(old) - exp_syn(new) */
1047 :
1048 10 : k = k_offset;
1049 10 : move16();
1050 169 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
1051 : {
1052 9699 : FOR( j = 0; j < l_subfr; j++ )
1053 : {
1054 9540 : s = sub( shift[k], min_shift );
1055 :
1056 9540 : if ( s > 0 )
1057 : {
1058 9152 : hb_synth_Fx[k] = shr( hb_synth_Fx[k], s ); /*Q15 - exp_syn - s*/
1059 9152 : move16();
1060 : }
1061 9540 : k = add( k, 1 );
1062 : }
1063 : }
1064 :
1065 10 : return exp_syn;
1066 : }
1067 : /*-------------------------------------------------------------------
1068 : * procTfa_TBE()
1069 : *
1070 : *
1071 : *-------------------------------------------------------------------*/
1072 58 : static Word16 procTfa_Fx(
1073 : Word16 *hb_synth_Fx, /*Q15 - exp_syn*/
1074 : Word16 exp_syn,
1075 : const Word16 i_offset, /*Q0*/
1076 : const Word16 l_subfr /*Q0*/ )
1077 : {
1078 : Word16 i, j, k;
1079 : Word16 k_offset, n_subfr;
1080 :
1081 : Word16 enr_m[N_TEC_TFA_SUBFR];
1082 : Word16 enr_e[N_TEC_TFA_SUBFR];
1083 :
1084 : Word16 enr_ave_m;
1085 : Word16 enr_ave_e;
1086 :
1087 : Word16 inv_n_subfr;
1088 :
1089 : Word16 s;
1090 : Word16 shift[L_FRAME_MAX];
1091 : Word16 min_shift;
1092 :
1093 : Word16 gain_m[N_TEC_TFA_SUBFR];
1094 : Word16 gain_e[N_TEC_TFA_SUBFR];
1095 :
1096 58 : setSubfrConfig_Fix( i_offset, &k_offset, &n_subfr, l_subfr );
1097 :
1098 58 : assert( 8 /* = 2^3 */ < n_subfr );
1099 58 : inv_n_subfr = getNormReciprocalWord16Scale( n_subfr, 3 );
1100 :
1101 58 : enr_ave_e = calcSubfrNrg_Fx( hb_synth_Fx,
1102 : exp_syn,
1103 : i_offset,
1104 : enr_m,
1105 : enr_e,
1106 : k_offset,
1107 : &enr_ave_m, l_subfr );
1108 :
1109 58 : enr_ave_m = mult_r( enr_ave_m, inv_n_subfr ); /*Q15 - enr_ave_e + 3*/
1110 58 : enr_ave_e = sub( enr_ave_e, 3 );
1111 :
1112 58 : min_shift = 15; /* min_shift <= 15 */
1113 58 : move16();
1114 :
1115 58 : k = k_offset;
1116 58 : move16();
1117 986 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
1118 : {
1119 928 : IF( enr_m[i] > 0 )
1120 : {
1121 916 : BASOP_Util_Divide_MantExp( enr_ave_m, enr_ave_e,
1122 916 : enr_m[i], enr_e[i],
1123 916 : &gain_m[i], &gain_e[i] );
1124 : }
1125 : ELSE
1126 : {
1127 : /* gain = 1 */
1128 12 : gain_m[i] = 32767;
1129 12 : move16();
1130 12 : gain_e[i] = 0;
1131 12 : move16();
1132 : }
1133 :
1134 928 : gain_m[i] = Sqrt16( gain_m[i], &gain_e[i] ); /*Q15 - gain_e*/
1135 928 : move16();
1136 :
1137 928 : s = norm_s( gain_m[i] );
1138 928 : gain_m[i] = shl( gain_m[i], s ); /*Q15 - gain_e + s*/
1139 928 : move16();
1140 928 : gain_e[i] = sub( gain_e[i], s );
1141 928 : move16();
1142 :
1143 56608 : FOR( j = 0; j < l_subfr; j++ )
1144 : {
1145 55680 : s = norm_s( hb_synth_Fx[k] );
1146 55680 : hb_synth_Fx[k] = mult_r( gain_m[i], shl( hb_synth_Fx[k], s ) ); /*Q15 - gain_e - exp_syn + s*/
1147 55680 : move16();
1148 55680 : shift[k] = sub( s, gain_e[i] );
1149 55680 : move16();
1150 :
1151 55680 : if ( GT_16( min_shift, shift[k] ) )
1152 : {
1153 220 : min_shift = shift[k];
1154 220 : move16();
1155 : }
1156 55680 : k = add( k, 1 );
1157 : }
1158 : }
1159 :
1160 : /* determin new exponent for hb_synth */
1161 58 : s = exp_syn;
1162 58 : move16();
1163 58 : exp_syn = sub( s, min_shift );
1164 58 : if ( GT_16( exp_syn, 15 ) )
1165 : {
1166 10 : exp_syn = 15;
1167 10 : move16();
1168 : }
1169 :
1170 58 : if ( exp_syn < 0 )
1171 : {
1172 0 : exp_syn = 0;
1173 0 : move16();
1174 : }
1175 :
1176 58 : min_shift = sub( s, exp_syn ); /* exp_syn(old) - exp_syn(new) */
1177 :
1178 58 : k = k_offset;
1179 58 : move16();
1180 986 : FOR( i = i_offset; i < N_TEC_TFA_SUBFR; i++ )
1181 : {
1182 56608 : FOR( j = 0; j < l_subfr; j++ )
1183 : {
1184 55680 : s = sub( shift[k], min_shift );
1185 :
1186 55680 : if ( s > 0 )
1187 : {
1188 54834 : hb_synth_Fx[k] = shr( hb_synth_Fx[k], s ); /*Q15 - exp_syn - s*/
1189 54834 : move16();
1190 : }
1191 55680 : k = add( k, 1 );
1192 : }
1193 : }
1194 :
1195 58 : return exp_syn;
1196 : }
1197 : /*-------------------------------------------------------------------
1198 : * procTecTfa_TBE()
1199 : *
1200 : *
1201 : *-------------------------------------------------------------------*/
1202 68 : Word16 procTecTfa_TBE_Fx(
1203 : Word16 *hb_synth_Fx, /*Q15 - hb_synth_fx_exp*/
1204 : Word16 hb_synth_fx_exp,
1205 : Word16 *gain_m, /*Q15 - gain_e*/
1206 : Word16 *gain_e,
1207 : Word16 flat_flag, /*Q0*/
1208 : Word16 last_core, /*Q0*/
1209 : Word16 l_subfr, /*Q0*/
1210 : Word16 code /*Q0*/ )
1211 : {
1212 68 : Word16 i_offset = 0;
1213 68 : move16();
1214 68 : Word16 exp_syn_frame = sub( 15, hb_synth_fx_exp );
1215 :
1216 :
1217 68 : IF( flat_flag )
1218 : {
1219 58 : exp_syn_frame = procTfa_Fx( hb_synth_Fx,
1220 : exp_syn_frame,
1221 : i_offset,
1222 : l_subfr );
1223 : }
1224 : ELSE
1225 : {
1226 10 : if ( ( last_core != ACELP_CORE ) )
1227 : {
1228 1 : i_offset = 1;
1229 1 : move16();
1230 : }
1231 :
1232 :
1233 10 : exp_syn_frame = procTec_Fx( hb_synth_Fx,
1234 : exp_syn_frame,
1235 : gain_m,
1236 : gain_e,
1237 : i_offset,
1238 : l_subfr, code );
1239 : }
1240 :
1241 68 : hb_synth_fx_exp = sub( 15, exp_syn_frame );
1242 :
1243 68 : return hb_synth_fx_exp;
1244 : }
1245 :
1246 :
1247 : /*-------------------------------------------------------------------
1248 : * calcHiEnvLoBuff()
1249 : *
1250 : *
1251 : *-------------------------------------------------------------------*/
1252 :
1253 3100 : void calcHiEnvLoBuff_Fix(
1254 : const Word16 noCols, /*Q0*/
1255 : const Word16 *pFreqBandTable, /*!< freqbandTable. Q0*/
1256 : const Word16 nSfb, /*!< Number of scalefactors. Q0*/
1257 : Word32 **pCldfbPow_Fix /* pCldfbPow_FixScale*/,
1258 : Word16 *loBuffer_Fix /* Q8*/,
1259 : Word16 *hiTempEnvOrig_Fix /* Q7*/,
1260 : Word16 pCldfbPow_FixScale )
1261 : {
1262 3100 : const Word16 BW_LO = TecLowBandTable[NBTECLOWBAND];
1263 3100 : move16();
1264 3100 : const Word16 lowSubband = pFreqBandTable[0];
1265 3100 : move16();
1266 3100 : const Word16 highSubband = pFreqBandTable[nSfb];
1267 3100 : move16();
1268 :
1269 : Word16 bandOffsetBottom;
1270 :
1271 3100 : Word16 *hiTempEnv = hiTempEnvOrig_Fix + EXT_DELAY_HI_TEMP_ENV; /*Q7*/
1272 :
1273 3100 : move16();
1274 3100 : move16();
1275 3100 : move16();
1276 3100 : bandOffsetBottom = sub( lowSubband, BW_LO );
1277 :
1278 3100 : assert( bandOffsetBottom > 0 );
1279 3100 : assert( noCols <= CLDFB_NO_COL_MAX );
1280 :
1281 : /* ============================================================ */
1282 : /* = calc hiTempEnv = */
1283 :
1284 3100 : calcHiTempEnv_Fx( pCldfbPow_Fix, sub( pCldfbPow_FixScale, 30 ), 0, noCols, lowSubband, highSubband, hiTempEnv + DELAY_TEMP_ENV_BUFF_TEC );
1285 :
1286 : /* = = */
1287 : /* ============================================================ */
1288 :
1289 : /* ============================================================ */
1290 : /* = calc loBuffer = */
1291 :
1292 3100 : calcLoBufferEnc_Fx( pCldfbPow_Fix, sub( pCldfbPow_FixScale, 30 ), 0, noCols, bandOffsetBottom, loBuffer_Fix + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC );
1293 :
1294 : /* = = */
1295 : /* ============================================================ */
1296 3100 : }
1297 :
1298 : /*-------------------------------------------------------------------
1299 : * calcLoEnvCheckCorrHiLo()
1300 : *
1301 : *
1302 : *-------------------------------------------------------------------*/
1303 3100 : void calcLoEnvCheckCorrHiLo_Fix(
1304 : const Word16 noCols, /*Q0*/
1305 : const Word16 *pFreqBandTable, /*!< freqbandTable. Q0*/
1306 : Word16 *loBuffer_Fix /*Word16* loBuffer Q8*/,
1307 : Word16 *loTempEnv_Fix /*Word16* loTempEnv Q7*/,
1308 : Word16 *loTempEnv_ns_Fix /* Word16* loTempEnv_ns Q7*/,
1309 : Word16 *hiTempEnvOrig_Fix /*Word16* hiTempEnvOrig Q7*/,
1310 : Word16 *corrFlag /*int* corrFlag Q0*/
1311 : )
1312 : {
1313 3100 : const Word16 BW_LO = TecLowBandTable[NBTECLOWBAND];
1314 3100 : move16();
1315 3100 : const Word16 lowSubband = pFreqBandTable[0]; /*Q0*/
1316 3100 : move16();
1317 : Word16 i;
1318 :
1319 : Word16 bandOffsetBottom;
1320 :
1321 : Word32 hiVar_Fix, loVar_Fix;
1322 : Word32 hiSum_Fix, loSum_Fix;
1323 : Word32 hiTempEnv32_Fix[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC];
1324 : Word32 loTempEnv32_Fix[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC];
1325 : Word32 loTempEnv32_ns_Fix[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC];
1326 :
1327 : Word32 corrCoef_Fix;
1328 :
1329 : Word32 EQ1, EQ2, EQ3;
1330 : Word32 EQ4, EQ5, EQ6;
1331 :
1332 3100 : Word16 code = 0; /* SET TENTATIVELY */
1333 3100 : move16();
1334 : Word32 loVar_ns_Fix;
1335 : Word32 diff_hi_lo_sum_Fix;
1336 : Word32 loSum_ns_Fix;
1337 3100 : Word16 *hiTempEnv = hiTempEnvOrig_Fix + EXT_DELAY_HI_TEMP_ENV; /*Q7*/
1338 :
1339 :
1340 3100 : move16();
1341 3100 : move16();
1342 3100 : move16();
1343 3100 : bandOffsetBottom = sub( lowSubband, BW_LO );
1344 :
1345 3100 : assert( bandOffsetBottom > 0 );
1346 3100 : assert( noCols <= CLDFB_NO_COL_MAX );
1347 :
1348 :
1349 80600 : FOR( i = 0; i < noCols + DELAY_TEMP_ENV_BUFF_TEC; i++ )
1350 : {
1351 77500 : hiTempEnv32_Fix[i] = L_deposit_l( hiTempEnv[i] ); /*Q7*/
1352 77500 : move32();
1353 : }
1354 3100 : hiVar_Fix = calcVar_Fix( hiTempEnv32_Fix, (Word32) noCols, &hiSum_Fix ); /*Q7*/
1355 :
1356 :
1357 : /* ============================================================ */
1358 : /* = calc loTempEnv = */
1359 :
1360 :
1361 3100 : calcLoTempEnv_Fx( loBuffer_Fix + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv_Fix, 26041 /*0.5 * ratioHiLoFac Q15*/ );
1362 :
1363 :
1364 3100 : calcLoTempEnv_ns_Fx( loBuffer_Fix + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv_ns_Fix );
1365 :
1366 : /* = = */
1367 : /* ============================================================ */
1368 :
1369 :
1370 52700 : FOR( i = 0; i < noCols; i++ )
1371 : {
1372 49600 : loTempEnv32_ns_Fix[i] = L_deposit_l( loTempEnv_ns_Fix[i] );
1373 49600 : move32();
1374 : }
1375 3100 : loVar_ns_Fix = calcVar_Fix( loTempEnv32_ns_Fix, noCols, &loSum_ns_Fix ); /*Q7*/
1376 :
1377 3100 : diff_hi_lo_sum_Fix = L_sub( loSum_ns_Fix, hiSum_Fix );
1378 :
1379 3100 : EQ4 = L_sub( L_shr( hiVar_Fix, 7 ), 800 ); /*Q0*/
1380 3100 : EQ5 = L_sub( L_shr( loVar_ns_Fix, 7 ), 720 ); /*Q0*/
1381 :
1382 3100 : EQ6 = L_sub( L_shr( diff_hi_lo_sum_Fix, 7 ), 100 ); /*Q0*/
1383 :
1384 3100 : test();
1385 3100 : test();
1386 3100 : if ( EQ4 > 0 && EQ5 > 0 && EQ6 < 0 )
1387 : {
1388 109 : code = 1;
1389 109 : move16();
1390 : }
1391 :
1392 :
1393 3100 : *corrFlag = 0;
1394 3100 : move16();
1395 :
1396 3100 : assert( code == 0 || code == 1 );
1397 :
1398 3100 : IF( code )
1399 : {
1400 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1401 : /* ++++ code == 1 +++++*/
1402 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1403 : Word16 maxPosHi, maxPosLo;
1404 : Word16 maxHiFix, maxLoFix;
1405 :
1406 109 : maxHiFix = hiTempEnv[0]; /*Q7*/
1407 109 : move16();
1408 109 : maxLoFix = loTempEnv_ns_Fix[0]; /*Q7*/
1409 109 : move16();
1410 109 : maxPosHi = maxPosLo = 0;
1411 109 : move16();
1412 109 : move16();
1413 1744 : FOR( i = 1; i < noCols; i++ )
1414 : {
1415 1635 : if ( LT_16( maxHiFix, hiTempEnv[i] ) )
1416 : {
1417 453 : maxPosHi = i;
1418 453 : move16();
1419 : }
1420 1635 : maxHiFix = s_max( maxHiFix, hiTempEnv[i] );
1421 :
1422 1635 : if ( LT_16( maxLoFix, loTempEnv_ns_Fix[i] ) )
1423 : {
1424 456 : maxPosLo = i;
1425 456 : move16();
1426 : }
1427 1635 : maxLoFix = s_max( maxLoFix, loTempEnv_ns_Fix[i] );
1428 : }
1429 :
1430 109 : if ( LT_16( abs_s( sub( maxPosHi, maxPosLo ) ), 2 ) )
1431 : {
1432 90 : *corrFlag = 2;
1433 90 : move16();
1434 : }
1435 :
1436 : {
1437 :
1438 109 : Word16 feature_max_Fix = 0;
1439 109 : move16();
1440 109 : Word16 pos_feature_max = 0;
1441 109 : move16();
1442 : Word16 feature_Fix[16];
1443 : Word16 min_local_Fix, max_local_Fix;
1444 : Word16 j;
1445 109 : Word16 len_window = EXT_DELAY_HI_TEMP_ENV + 1;
1446 109 : move16();
1447 109 : Word16 *curr_pos_Fix = hiTempEnv; /*Q7*/
1448 :
1449 109 : move16();
1450 109 : move16();
1451 109 : move16();
1452 109 : move16();
1453 :
1454 109 : feature_max_Fix = 0;
1455 109 : move16();
1456 109 : pos_feature_max = 0;
1457 109 : move16();
1458 :
1459 1853 : FOR( i = 0; i < 16; i++ )
1460 : {
1461 1744 : max_local_Fix = min_local_Fix = curr_pos_Fix[0]; /*Q7*/
1462 1744 : move16();
1463 1744 : move16();
1464 :
1465 5232 : FOR( j = 1; j < len_window; j++ )
1466 : {
1467 3488 : if ( LT_16( max_local_Fix, curr_pos_Fix[-j] ) )
1468 : {
1469 1315 : max_local_Fix = curr_pos_Fix[-j]; /*Q7*/
1470 1315 : move16();
1471 : }
1472 :
1473 3488 : if ( GT_16( min_local_Fix, curr_pos_Fix[-j] ) )
1474 : {
1475 1424 : min_local_Fix = curr_pos_Fix[-j]; /*Q7*/
1476 1424 : move16();
1477 : }
1478 : }
1479 1744 : feature_Fix[i] = sub( max_local_Fix, min_local_Fix );
1480 1744 : move16();
1481 :
1482 1744 : if ( LT_16( feature_max_Fix, feature_Fix[i] ) )
1483 : {
1484 367 : pos_feature_max = i;
1485 367 : move16();
1486 : }
1487 1744 : feature_max_Fix = s_max( feature_max_Fix, feature_Fix[i] );
1488 1744 : curr_pos_Fix += 1;
1489 : }
1490 :
1491 109 : IF( *corrFlag > 0 )
1492 : {
1493 90 : test();
1494 90 : if ( ( LE_16( feature_max_Fix, 2560 /*20 in Q7*/ ) || GE_16( abs_s( sub( pos_feature_max, maxPosHi ) ), 3 ) ) )
1495 : {
1496 44 : *corrFlag = 0;
1497 44 : move16();
1498 : }
1499 : }
1500 : }
1501 : }
1502 : ELSE
1503 : {
1504 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1505 : /* ++++ code == 0 ++++*/
1506 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1507 :
1508 :
1509 : /* ============================================================ */
1510 : /* = calc the variance of loTempEnv = */
1511 :
1512 50847 : FOR( i = 0; i < noCols; i++ )
1513 : {
1514 47856 : loTempEnv32_Fix[i] = L_deposit_l( loTempEnv_Fix[i] ); /*Q7*/
1515 47856 : move32();
1516 : }
1517 2991 : loVar_Fix = calcVar_Fix( loTempEnv32_Fix, noCols, &loSum_Fix ); /*Q7*/
1518 : /* = = */
1519 : /* ============================================================ */
1520 :
1521 : /* ============================================================ */
1522 : /* = calc correlation coefficient between = */
1523 : /* = loTempEnv and hiTempEnv = */
1524 2991 : corrCoef_Fix = calcCorrelationCoefficient2_Fix(
1525 : hiTempEnv32_Fix, loTempEnv32_Fix,
1526 : noCols, hiVar_Fix, loVar_Fix, hiSum_Fix, loSum_Fix );
1527 : /* = = */
1528 : /* ============================================================ */
1529 :
1530 :
1531 2991 : EQ1 = L_sub( L_shl( corrCoef_Fix, 8 ), 28819 /*thCorrCoef Q15*/ ); /*Q15*/
1532 2991 : EQ2 = L_sub( L_shl( hiVar_Fix, 0 ), Mpy_32_16_1( loVar_Fix, 11957 /*thRatio Q15*/ ) ); /*Q7*/
1533 2991 : EQ3 = L_sub( L_shr( hiVar_Fix, 2 ), Mpy_32_16_1( loVar_Fix, 16620 /*thRatio2 Q13*/ ) ); /*Q5*/
1534 :
1535 2991 : test();
1536 2991 : test();
1537 2991 : if ( EQ1 >= 0 && EQ2 > 0 /*ratio > thRatio*/ && EQ3 < 0 )
1538 : {
1539 94 : *corrFlag = 1;
1540 94 : move16();
1541 : }
1542 : }
1543 :
1544 49600 : FOR( i = 0; i < MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC; i++ )
1545 : {
1546 46500 : loBuffer_Fix[i] = loBuffer_Fix[noCols + i]; /*Q8*/
1547 46500 : move16();
1548 : }
1549 :
1550 37200 : FOR( i = 0; i < DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV; i++ )
1551 : {
1552 34100 : hiTempEnvOrig_Fix[i] = hiTempEnvOrig_Fix[noCols + i]; /*Q7*/
1553 34100 : move16();
1554 : }
1555 3100 : }
1556 :
1557 : /*-------------------------------------------------------------------
1558 : * tecEnc_TBE()
1559 : *
1560 : *
1561 : *-------------------------------------------------------------------*/
1562 :
1563 604 : void tecEnc_TBE_fx(
1564 : Word16 *corrFlag, /*Q0*/
1565 : const Word16 *voicing, /*Q15*/
1566 : const Word16 coder_type /*Q0*/ )
1567 : {
1568 : Word16 voice_sum;
1569 : Word16 voice_diff;
1570 :
1571 : /*-----------------------------------------------------------------*
1572 : * TEC updates
1573 : *-----------------------------------------------------------------*/
1574 :
1575 604 : voice_sum = add( shr( voicing[0], 1 ), shr( voicing[1], 1 ) ); /*voice_sum = voicing[0] + voicing[1];*/ /*Q15*/
1576 604 : voice_diff = sub( voicing[0], voicing[1] ); /*voice_diff = voicing[0] - voicing[1]; Q15*/
1577 :
1578 604 : if ( voice_diff < 0 )
1579 : {
1580 294 : voice_diff = negate( voice_diff ); /*voice_diff *= -1.0f;*/
1581 : }
1582 :
1583 604 : IF( EQ_16( *corrFlag, 1 ) )
1584 : {
1585 24 : test();
1586 24 : test();
1587 24 : test();
1588 : /*if( ((voice_sum > 0.35 * 2 && voice_sum < 0.55 * 2) && (voice_diff < 0.2)) )*/
1589 24 : if ( ( coder_type == INACTIVE ) || ( GT_16( voice_sum, 11469 /*0.35 Q15*/ ) && LT_16( voice_sum, 18022 /*0.55 Q15*/ ) && ( sub( voice_diff, 6554 /*0.2 Q15*/ ) < 0 ) ) )
1590 : {
1591 1 : *corrFlag = 0;
1592 1 : move16();
1593 : }
1594 : }
1595 604 : if ( GT_16( voice_sum, 19661 /*0.6 Q15*/ ) ) /*if( voice_sum > 0.6 * 2 )*/
1596 : {
1597 504 : *corrFlag = 0;
1598 504 : move16();
1599 : }
1600 604 : }
1601 : /*-------------------------------------------------------------------
1602 : * set_TEC_TFA_code()
1603 : *
1604 : *
1605 : *-------------------------------------------------------------------*/
1606 604 : void set_TEC_TFA_code_fx(
1607 : const Word16 corrFlag, /*Q0*/
1608 : Word16 *tec_flag, /*Q0*/
1609 : Word16 *tfa_flag /*Q0*/ )
1610 : {
1611 604 : *tec_flag = 0;
1612 604 : move16();
1613 604 : IF( *tfa_flag == 0 )
1614 : {
1615 546 : test();
1616 546 : if ( EQ_16( corrFlag, 1 ) || EQ_16( corrFlag, 2 ) )
1617 : {
1618 8 : *tec_flag = 1;
1619 8 : move16();
1620 : }
1621 :
1622 546 : if ( EQ_16( corrFlag, 2 ) )
1623 : {
1624 5 : *tfa_flag = 1;
1625 5 : move16();
1626 : }
1627 : }
1628 604 : }
|