Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 :
6 : #include <stdint.h>
7 : #include <assert.h>
8 : #include "options.h"
9 : #include "cnst.h"
10 : #include "basop_util.h"
11 : #include "rom_com.h"
12 : #include "rom_enc.h"
13 : #include "prot_fx.h"
14 : #include "prot_fx_enc.h" /* Function prototypes */
15 :
16 : /*-------------------------------------------------------------------*
17 : * EncodeIndex_fx()
18 : *
19 : *
20 : *-------------------------------------------------------------------*/
21 :
22 : /*ari_hm_enc.c*/
23 : /* Q13 format */
24 : const Word16 kLowPeriodicityThr_fx[2] = { 4096 /*0.5f Q13*/, 1638 /*0.2f Q13*/ };
25 :
26 54 : Word16 EncodeIndex_fx(
27 : const Word16 Bandwidth,
28 : Word16 PeriodicityIndex,
29 : BSTR_ENC_HANDLE hBst /* i/o: bitstream handle */
30 : )
31 : {
32 : Word16 NumRatioBitsBwLtpIndx;
33 :
34 54 : IF( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 )
35 : {
36 44 : Word16 LtpPitchIndex = shr( PeriodicityIndex, 9 );
37 44 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
38 :
39 44 : PeriodicityIndex = sub( PeriodicityIndex, 1 );
40 44 : assert( ( PeriodicityIndex & 0xff ) < ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
41 :
42 44 : NumRatioBitsBwLtpIndx = NumRatioBits[Bandwidth][LtpPitchIndex];
43 44 : move16();
44 :
45 44 : push_next_indice( hBst, s_and( PeriodicityIndex, 0xff ), NumRatioBitsBwLtpIndx );
46 44 : return NumRatioBitsBwLtpIndx;
47 : }
48 : ELSE
49 : {
50 10 : push_next_indice( hBst, PeriodicityIndex, 8 );
51 10 : return 8;
52 : }
53 : }
54 19681 : Word16 EncodeIndex_ivas_fx(
55 : const Word16 Bandwidth,
56 : Word16 PeriodicityIndex,
57 : BSTR_ENC_HANDLE hBst /* i/o: bitstream handle */
58 : )
59 : {
60 : Word16 NumRatioBitsBwLtpIndx;
61 :
62 19681 : IF( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 )
63 : {
64 10315 : Word16 LtpPitchIndex = shr( PeriodicityIndex, 9 );
65 10315 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
66 :
67 10315 : PeriodicityIndex = sub( PeriodicityIndex, 1 );
68 10315 : assert( ( PeriodicityIndex & 0xff ) < ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
69 :
70 10315 : NumRatioBitsBwLtpIndx = NumRatioBits[Bandwidth][LtpPitchIndex];
71 10315 : move16();
72 :
73 10315 : push_next_indice( hBst, s_and( PeriodicityIndex, 0xff ), NumRatioBitsBwLtpIndx );
74 10315 : return NumRatioBitsBwLtpIndx;
75 : }
76 : ELSE
77 : {
78 9366 : push_next_indice( hBst, PeriodicityIndex, 8 );
79 9366 : return 8;
80 : }
81 : }
82 : /*-------------------------------------------------------------------*
83 : * SearchPeriodicityIndex_Single()
84 : *
85 : *
86 : *-------------------------------------------------------------------*/
87 17490375 : static Word16 SearchPeriodicityIndex_Single(
88 : const Word16 AbsMdct3[], // Qx
89 : const Word16 NumToConsider,
90 : const Word32 Lag,
91 : const Word16 FractionalResolution )
92 : {
93 : Word16 HighestMultiplier;
94 : Word32 AbsMeanCurrent3; /* Mean for BucketWidth == 3 */
95 : Word32 Limit, OldIndex, i;
96 : Word16 Result, tmp1, tmp2;
97 :
98 :
99 17490375 : Limit = L_deposit_l( sub( NumToConsider, 1 ) );
100 17490375 : Limit = L_shl( Limit, FractionalResolution );
101 17490375 : AbsMeanCurrent3 = L_deposit_l( 0 );
102 17490375 : HighestMultiplier = 0;
103 17490375 : move16();
104 :
105 754312059 : FOR( i = Lag; i < Limit; i += Lag )
106 : {
107 736821684 : OldIndex = L_shr( i, FractionalResolution );
108 736821684 : tmp1 = Weight[s_min( HighestMultiplier, 85 )];
109 736821684 : move16();
110 736821684 : AbsMeanCurrent3 = L_add( AbsMeanCurrent3, L_shr( L_mult( AbsMdct3[OldIndex], tmp1 ), 7 ) );
111 736821684 : HighestMultiplier = add( HighestMultiplier, 1 );
112 : }
113 :
114 17490375 : tmp1 = sub( norm_l( AbsMeanCurrent3 ), 1 );
115 17490375 : tmp2 = norm_s( HighestMultiplier );
116 17490375 : Result = div_s( round_fx( L_shl( AbsMeanCurrent3, tmp1 ) ), s_max( shl( HighestMultiplier, tmp2 ), 0x4000 ) );
117 17490375 : if ( HighestMultiplier == 0 )
118 : {
119 9098 : tmp2 = 14 + 16;
120 9098 : move16();
121 : }
122 17490375 : Result = shr( Result, s_min( 15, sub( sub( tmp1, tmp2 ), 7 - 15 ) ) );
123 :
124 17490375 : return Result;
125 : }
126 : /*-------------------------------------------------------------------*
127 : * SearchPeriodicityIndex_Range()
128 : *
129 : *
130 : *-------------------------------------------------------------------*/
131 739738 : static void SearchPeriodicityIndex_Range(
132 : const Word16 AbsMdct3[], // Qx
133 : const Word16 NumToConsider,
134 : const Word16 Lo,
135 : const Word16 Hi,
136 : const Word16 FractionalResolution,
137 : const Word16 Adj,
138 : const Word16 Spacing,
139 : Word16 *PeriodicityIndex,
140 : Word16 *Score // Q0
141 : )
142 : {
143 : Word16 Index, BestIndex;
144 : Word16 CurrentScore, BestScore;
145 : Word16 B;
146 :
147 739738 : BestScore = -1;
148 739738 : move16();
149 739738 : BestIndex = 0;
150 739738 : move16();
151 :
152 15624402 : FOR( Index = Lo; Index < Hi; Index += Spacing )
153 : {
154 14884664 : CurrentScore = SearchPeriodicityIndex_Single(
155 : AbsMdct3,
156 : NumToConsider,
157 14884664 : add( Index, Adj ),
158 : FractionalResolution );
159 :
160 14884664 : if ( GT_16( CurrentScore, BestScore ) )
161 : {
162 2256614 : BestIndex = Index;
163 2256614 : move16();
164 : }
165 14884664 : BestScore = s_max( BestScore, CurrentScore );
166 : }
167 :
168 739738 : if ( GT_16( BestScore, *Score ) )
169 : {
170 194290 : *PeriodicityIndex = BestIndex;
171 194290 : move16();
172 : }
173 739738 : BestScore = s_max( BestScore, *Score );
174 :
175 739738 : B = sub( BestIndex, shr( Spacing, 1 ) );
176 739738 : B = s_max( Lo, B );
177 :
178 1387592 : FOR( Index = B; Index < BestIndex; ++Index )
179 : {
180 647854 : CurrentScore = SearchPeriodicityIndex_Single(
181 : AbsMdct3,
182 : NumToConsider,
183 647854 : add( Index, Adj ),
184 : FractionalResolution );
185 :
186 647854 : if ( GT_16( CurrentScore, BestScore ) )
187 : {
188 40012 : *PeriodicityIndex = Index;
189 40012 : move16();
190 : }
191 647854 : BestScore = s_max( BestScore, CurrentScore );
192 : }
193 :
194 739738 : B = add( BestIndex, shr( Spacing, 1 ) );
195 :
196 1633270 : FOR( Index = BestIndex + 1; Index <= B; ++Index )
197 : {
198 893532 : CurrentScore = SearchPeriodicityIndex_Single(
199 : AbsMdct3,
200 : NumToConsider,
201 893532 : add( Index, Adj ),
202 : FractionalResolution );
203 :
204 893532 : if ( GT_16( CurrentScore, BestScore ) )
205 : {
206 92887 : *PeriodicityIndex = Index;
207 92887 : move16();
208 : }
209 893532 : BestScore = s_max( BestScore, CurrentScore );
210 : }
211 :
212 739738 : *Score = BestScore;
213 739738 : move16();
214 739738 : }
215 :
216 : /*-------------------------------------------------------------------*
217 : * SearchPeriodicityIndex_fx()
218 : *
219 : *
220 : *-------------------------------------------------------------------*/
221 195557 : Word16 SearchPeriodicityIndex_fx(
222 : const Word32 Mdct[], /* i : Coefficients, Mdct[0..NumCoeffs-1] */
223 : const Word32 UnfilteredMdct[], /* i : Unfiltered coefficients, UnfilteredMdct[0..NumCoeffs-1] */
224 : Word16 NumToConsider, /* i : Number of coefficients */
225 : const Word16 TargetBits, /* i : Target bit budget (excl. Done flag) */
226 : const Word16 LtpPitchLag, /* i : TCX-LTP pitch */
227 : const Word16 LtpGain, /* i : LTP gain Q15 */
228 : Word16 *RelativeScore /* o : Energy concentration factor (2Q13) */
229 : )
230 : {
231 : Word16 AbsMdct3[MAX_LENGTH];
232 : Word32 A, B, C;
233 : Word16 i;
234 : Word16 MaxAt;
235 : Word16 Score, CurrentScore;
236 : Word16 PeriodicityIndex;
237 : Word32 AbsTotal; /* 16Q15 */
238 : Word16 Multiplier;
239 : Word16 LtpPitchIndex;
240 : Word8 Bandwidth;
241 : Word32 Lag;
242 : Word16 s, tmp, tmp2, tmp3;
243 : Word32 tmp32;
244 : #ifndef ISSUE_1867_replace_overflow_libenc
245 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
246 : Flag Overflow = 0;
247 : move32();
248 : #endif
249 : #endif
250 :
251 : /* Debug init (not instrumented) */
252 195557 : C = -3000;
253 195557 : move32();
254 195557 : PeriodicityIndex = 0;
255 195557 : move16();
256 195557 : Score = -1;
257 195557 : move16();
258 :
259 195557 : s = sub( Find_Max_Norm32( Mdct, NumToConsider ), 2 );
260 :
261 195557 : A = L_shl( L_abs( Mdct[0] ), s );
262 195557 : B = L_shl( L_abs( Mdct[1] ), s );
263 :
264 195557 : tmp = sub( NumToConsider, 3 );
265 53606706 : FOR( i = 1; i < tmp; i += 3 )
266 : {
267 53411149 : C = L_shl( L_abs( Mdct[i + 1] ), s );
268 53411149 : AbsMdct3[i] = round_fx( L_add( L_add( A, B ), C ) );
269 53411149 : move16();
270 :
271 53411149 : A = L_shl( L_abs( Mdct[i + 2] ), s );
272 53411149 : AbsMdct3[i + 1] = round_fx( L_add( L_add( A, B ), C ) );
273 53411149 : move16();
274 :
275 53411149 : B = L_shl( L_abs( Mdct[i + 3] ), s );
276 53411149 : AbsMdct3[i + 2] = round_fx( L_add( L_add( A, B ), C ) );
277 53411149 : move16();
278 : }
279 :
280 195557 : IF( LT_16( i, sub( NumToConsider, 1 ) ) )
281 : {
282 186612 : C = L_shl( L_abs( Mdct[i + 1] ), s );
283 186612 : AbsMdct3[i] = round_fx( L_add( L_add( A, B ), C ) );
284 186612 : move16();
285 : }
286 :
287 195557 : IF( LT_16( i, sub( NumToConsider, 2 ) ) )
288 : {
289 61787 : A = L_shl( L_abs( Mdct[i + 2] ), s );
290 61787 : assert( C != -3000 );
291 61787 : AbsMdct3[i + 1] = round_fx( L_add( L_add( A, B ), C ) );
292 61787 : move16();
293 : }
294 :
295 195557 : AbsTotal = L_deposit_l( 0 );
296 195557 : IF( UnfilteredMdct != NULL )
297 : {
298 8422606 : FOR( i = 0; i < NumToConsider; ++i )
299 : {
300 8408960 : AbsTotal = L_add( AbsTotal, L_shr( L_abs( UnfilteredMdct[i] ), 16 ) );
301 : }
302 : /* balance difference between filtered and unfiltered mdct samples */
303 13646 : AbsTotal = L_shr( AbsTotal, sub( 4, s ) );
304 : }
305 : ELSE
306 : {
307 181911 : tmp = sub( NumToConsider, 1 );
308 50981572 : FOR( i = 1; i < tmp; i += 3 )
309 : {
310 50799661 : AbsTotal = L_mac0( AbsTotal, AbsMdct3[i], 1 );
311 : }
312 : }
313 :
314 195557 : test();
315 195557 : IF( ( LtpPitchLag > 0 ) && ( GT_16( LtpGain, kLtpHmGainThr ) ) )
316 : {
317 46635 : Bandwidth = 0;
318 46635 : move16();
319 46635 : if ( GE_16( NumToConsider, 256 ) )
320 : {
321 46635 : Bandwidth = 1;
322 46635 : move16();
323 : }
324 :
325 46635 : LtpPitchIndex = sub( mult_r( LtpPitchLag, 1 << ( 15 - kLtpHmFractionalResolution ) ), 2 );
326 46635 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
327 :
328 46635 : tmp32 = L_shl( L_deposit_l( sub( NumToConsider, 2 ) ), kLtpHmFractionalResolution );
329 46635 : tmp = shl( 1, NumRatioBits[Bandwidth][LtpPitchIndex] );
330 1118995 : FOR( Multiplier = 1; Multiplier <= tmp; ++Multiplier )
331 : {
332 1072360 : Lag = L_shr( L_mult0( LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier - 1] ), 8 );
333 :
334 1072360 : test();
335 1072360 : IF( ( GE_32( Lag, 4 << kLtpHmFractionalResolution ) ) && ( LE_32( Lag, tmp32 ) ) )
336 : {
337 1064325 : CurrentScore = SearchPeriodicityIndex_Single(
338 : AbsMdct3,
339 : NumToConsider,
340 : Lag,
341 : kLtpHmFractionalResolution );
342 :
343 1064325 : if ( GT_16( CurrentScore, Score ) )
344 : {
345 74089 : PeriodicityIndex = s_or( Multiplier, kLtpHmFlag );
346 : }
347 1064325 : Score = s_max( Score, CurrentScore );
348 : }
349 : }
350 46635 : PeriodicityIndex = s_or( PeriodicityIndex, shl( LtpPitchIndex, 9 ) );
351 : }
352 : ELSE
353 : {
354 148922 : IF( UnfilteredMdct != NULL )
355 : {
356 8397 : MaxAt = 1;
357 8397 : move16();
358 8397 : A = L_shr( AbsMdct3[1], 6 );
359 :
360 1705422 : FOR( i = 4; i < NumToConsider - 1; i += 3 )
361 : {
362 1697025 : if ( GT_32( AbsMdct3[i], AbsMdct3[MaxAt] ) )
363 : {
364 10445 : MaxAt = i;
365 10445 : move16();
366 : }
367 1697025 : A = L_add( A, L_shr( AbsMdct3[i], 6 ) );
368 : }
369 :
370 8397 : if ( GT_32( L_shr( AbsMdct3[MaxAt], 6 ), Mpy_32_16_1( A, 22938 /*0.7 Q15*/ ) ) )
371 : {
372 157 : NumToConsider = s_min( NumToConsider, add( MaxAt, 4 ) );
373 : }
374 : }
375 :
376 148922 : SearchPeriodicityIndex_Range(
377 : AbsMdct3,
378 : NumToConsider,
379 : 0, 16,
380 : 3,
381 : GET_ADJ2( 0, 6, 3 ),
382 : 4,
383 : &PeriodicityIndex,
384 : &Score );
385 :
386 148922 : SearchPeriodicityIndex_Range(
387 : AbsMdct3,
388 : NumToConsider,
389 : 16, 80,
390 : 4,
391 : GET_ADJ2( 16, 8, 4 ),
392 : 4,
393 : &PeriodicityIndex,
394 : &Score );
395 :
396 148922 : SearchPeriodicityIndex_Range(
397 : AbsMdct3,
398 : NumToConsider,
399 : 80, 208,
400 : 3,
401 : GET_ADJ2( 80, 12, 3 ),
402 : 4,
403 : &PeriodicityIndex,
404 : &Score );
405 :
406 148922 : IF( LE_16( NumToConsider, 128 ) ) /* no long lags for band-limited MDCTs */
407 : {
408 157 : SearchPeriodicityIndex_Range(
409 : AbsMdct3,
410 : NumToConsider,
411 157 : 208, add( 88, NumToConsider ),
412 : 0,
413 : GET_ADJ2( 224, 188, 0 ),
414 : 1,
415 : &PeriodicityIndex,
416 : &Score );
417 : }
418 : ELSE
419 : {
420 148765 : test();
421 148765 : IF( GT_16( TargetBits, kSmallerLagsTargetBitsThreshold ) && GE_16( NumToConsider, 256 ) )
422 : {
423 144050 : SearchPeriodicityIndex_Range(
424 : AbsMdct3,
425 : NumToConsider,
426 : 208, 224,
427 : 1,
428 : GET_ADJ2( 208, 28, 1 ),
429 : 1,
430 : &PeriodicityIndex,
431 : &Score );
432 144050 : SearchPeriodicityIndex_Range(
433 : AbsMdct3,
434 : NumToConsider,
435 : 224, 256,
436 : 0,
437 : GET_ADJ2( 224, 188, 0 ),
438 : 1,
439 : &PeriodicityIndex,
440 : &Score );
441 : }
442 : ELSE
443 : {
444 4715 : SearchPeriodicityIndex_Range(
445 : AbsMdct3,
446 : NumToConsider,
447 : 208, 256,
448 : 1,
449 : GET_ADJ2( 208, 28, 1 ),
450 : 1,
451 : &PeriodicityIndex,
452 : &Score );
453 : }
454 : }
455 : }
456 :
457 195557 : IF( AbsTotal > 0 )
458 : {
459 195537 : tmp32 = L_mult0( Score, NumToConsider ); /* -> 16Q15 */
460 195537 : tmp = sub( norm_l( tmp32 ), 1 );
461 195537 : tmp2 = norm_l( AbsTotal );
462 : #ifdef ISSUE_1867_replace_overflow_libenc
463 195537 : tmp3 = div_s( round_fx_sat( L_shl( tmp32, tmp ) ), round_fx_sat( L_shl( AbsTotal, tmp2 ) ) );
464 : #else
465 : tmp3 = div_s( round_fx_o( L_shl_o( tmp32, tmp, &Overflow ), &Overflow ), round_fx_o( L_shl_o( AbsTotal, tmp2, &Overflow ), &Overflow ) );
466 : #endif
467 195537 : *RelativeScore = shr_sat( tmp3, add( sub( tmp, tmp2 ), 2 ) ); /* -> 2Q13 */
468 195537 : move16();
469 : }
470 : ELSE
471 : {
472 20 : *RelativeScore = 0;
473 20 : move16();
474 : }
475 :
476 195557 : return PeriodicityIndex;
477 : }
478 : /*-------------------------------------------------------------------*
479 : * PeakFilter()
480 : *
481 : *
482 : *-------------------------------------------------------------------*/
483 :
484 13646 : static void PeakFilter(
485 : const Word32 x[], /* i : absolute spectrum Qx */
486 : Word32 y[], /* O : filtered absolute spectrum, must not alias x[] Q(x-4)*/
487 : const Word16 L_frame /* i : number of spectral lines */
488 : )
489 : {
490 : Word16 flen, i;
491 : /*#define kPeakElevationThreshold 1.0f*/
492 : Word16 m;
493 : Word32 a;
494 :
495 13646 : flen = shr( L_frame, 4 );
496 : /* m = kPeakElevationThreshold / (float)(2*flen + 1); */
497 13646 : m = shr( div_s( 8 /*kPeakElevationThreshold Q3*/, add( shl( flen, 1 ), 1 ) ), 3 ); // Q15
498 :
499 13646 : a = L_deposit_l( 0 );
500 539206 : FOR( i = 0; i < flen; ++i )
501 : {
502 525560 : a = L_add( a, L_shr( x[i], 4 ) );
503 : }
504 :
505 539206 : FOR( i = 0; i < flen; ++i )
506 : {
507 525560 : y[i] = L_max( 0, L_sub( L_shr( x[i], 4 ), Mpy_32_16_1( a, m ) ) ); // Q(x-4)
508 525560 : move32();
509 525560 : a = L_add( a, L_shr( x[i + flen], 4 ) );
510 : }
511 13646 : sub( 0, 0 );
512 7371486 : FOR( ; i < L_frame - flen; ++i )
513 : {
514 7357840 : y[i] = L_max( 0, L_sub( L_shr( x[i], 4 ), Mpy_32_16_1( a, m ) ) ); // Q(x-4)
515 7357840 : move32();
516 7357840 : a = L_sub( a, L_shr( x[i - flen], 4 ) );
517 7357840 : a = L_add( a, L_shr( x[i + flen], 4 ) );
518 : }
519 :
520 539206 : FOR( ; i < L_frame; ++i )
521 : {
522 525560 : y[i] = L_max( 0, L_sub( L_shr( x[i], 4 ), Mpy_32_16_1( a, m ) ) ); // Q(x-4)
523 525560 : move32();
524 525560 : a = L_sub( a, L_shr( x[i - flen], 4 ) );
525 : }
526 13646 : }
527 :
528 : /*-------------------------------------------------------------------*
529 : * tcx_hm_get_re()
530 : *
531 : *
532 : *-------------------------------------------------------------------*/
533 30825 : static Word32 tcx_hm_get_re(
534 : const Word16 x[], /* i: absolute spectrum */
535 : const Word16 gain, /* o: quantized harmonic model gain Q11 */
536 : const Word32 lag, /* i: pitch lag Q0 */
537 : const Word16 fract_res, /* i: fractional resolution of the lag Q0 */
538 : Word16 p[], /* i: harmonic model Q13 */
539 : const Word32 env[], /* i: envelope Q16 */
540 : const Word16 L_frame /* i: number of spectral lines Q0 */
541 : )
542 : {
543 : Word16 i, inv_G, tmp;
544 : Word16 s, s_ne, s_x_ne;
545 : Word16 *x_ne;
546 : Word32 ne[N_MAX_ARI], G, e;
547 :
548 30825 : x_ne = (Word16 *) ne;
549 30825 : assert( L_frame <= N_MAX_ARI );
550 :
551 : /* Calculate new envelope with "gain" harmonic gain ***********************/
552 :
553 30825 : Copy32( env, ne, L_frame );
554 :
555 30825 : tcx_hm_modify_envelope(
556 : gain,
557 : lag,
558 : fract_res,
559 : p,
560 : ne,
561 : L_frame );
562 :
563 : /* Normalize **************************************************************/
564 :
565 30825 : s_ne = getScaleFactor32( ne, L_frame );
566 :
567 30825 : G = L_deposit_l( 0 );
568 19101225 : FOR( i = 0; i < L_frame; ++i )
569 : {
570 19070400 : x_ne[i] = mult( x[i], extract_h( L_shl( ne[i], s_ne ) ) ); /* exp: x_e+15-s_ne */
571 19070400 : move16();
572 19070400 : G = L_mac0( G, x_ne[i], 1 ); /* exp: x_e + 31 - s_ne */
573 : }
574 30825 : s = norm_l( G );
575 30825 : inv_G = div_s( 0x4000, extract_h( L_shl( G, s ) ) ); /* exp: 1 - (x_e + 31 - s_ne - s) */
576 :
577 : /* Calculate error ********************************************************/
578 30825 : s_x_ne = sub( getScaleFactor16( x_ne, L_frame ), 2 );
579 30825 : e = L_deposit_l( 0 );
580 19101225 : FOR( i = 0; i < L_frame; ++i )
581 : {
582 19070400 : tmp = shl( x_ne[i], s_x_ne ); /* exp: x_e + 15 - s_ne - s_x_ne */
583 19070400 : tmp = mult( tmp, tmp ); /* exp: 2 * (x_e + 15 - s_ne - s_x_ne) */
584 19070400 : e = L_mac( e, tmp, tmp ); /* exp: 4 * (x_e + 15 - s_ne - s_x_ne) */
585 : }
586 :
587 30825 : e = Mpy_32_16_1( e, inv_G );
588 30825 : e = Mpy_32_16_1( e, inv_G );
589 30825 : e = Mpy_32_16_1( e, inv_G );
590 30825 : e = Mpy_32_16_1( e, inv_G ); /* exp: 4 * (s - s_x_ne - 15) */
591 :
592 30825 : e = L_shl( e, shl( sub( sub( s, s_x_ne ), 15 ), 2 ) ); /* Q31 */
593 :
594 :
595 30825 : return e;
596 : }
597 : /*-------------------------------------------------------------------*
598 : * tcx_hm_quantize_gain()
599 : *
600 : *
601 : *-------------------------------------------------------------------*/
602 :
603 13646 : static void tcx_hm_quantize_gain(
604 : const Word32 x[], /* i: absolute spectrum Q31-x_e */
605 : const Word16 *x_e, /* i: absolute spectrum exponent Q0 */
606 : const Word32 env[], /* i: envelope Q16 */
607 : const Word32 lag, /* i: pitch lag Q0 */
608 : const Word16 fract_res, /* i: fractional resolution of the lag Q0 */
609 : Word16 p[], /* i: harmonic model Q13 */
610 : const Word16 L_frame, /* i: number of spectral lines Q0 */
611 : const Word16 coder_type, /* i: coder_type Q0 */
612 : Word16 relative_score, /* i: periodicity score Q13 */
613 : Word16 *gain_idx, /* o: quantization index Q0 */
614 : Word16 *gain /* o: quantized harmonic model gain Q11 */
615 : )
616 : {
617 : Word16 g;
618 : Word16 pe; /* Q14 */
619 : Word32 be; /* Q31 */
620 : Word32 e; /* Q31 */
621 : Word16 i;
622 : Word16 x16[N_MAX_ARI], s_x;
623 : Word16 s;
624 :
625 :
626 13646 : assert( coder_type == VOICED || coder_type == GENERIC );
627 13646 : s = 0;
628 13646 : move16();
629 13646 : if ( EQ_16( coder_type, VOICED ) )
630 : {
631 2745 : s = 1;
632 2745 : move16();
633 : }
634 :
635 :
636 13646 : *gain = 0;
637 13646 : move16();
638 :
639 : /* Disable the harmonic model if periodicity is very low */
640 13646 : IF( LT_16( relative_score, kLowPeriodicityThr_fx[s] ) )
641 : {
642 2351 : return;
643 : }
644 :
645 : (void) x_e;
646 :
647 11295 : s_x = getScaleFactor32( x, L_frame );
648 7026015 : FOR( i = 0; i < L_frame; ++i )
649 : {
650 7014720 : x16[i] = extract_h( L_shl( x[i], s_x ) );
651 7014720 : move16();
652 : }
653 :
654 11295 : be = tcx_hm_get_re( x16, *gain, lag, fract_res, p, env, L_frame );
655 :
656 11295 : IF( EQ_16( coder_type, GENERIC ) )
657 : {
658 8550 : e = tcx_hm_get_re(
659 : x16,
660 8550 : qGains[s][0],
661 : lag,
662 : fract_res,
663 : p,
664 : env,
665 : L_frame );
666 :
667 8550 : pe = 17203 /*1.05 Q14*/;
668 8550 : move16();
669 :
670 : /* pe is Q14 */
671 8550 : IF( LT_32( L_shl( Mpy_32_16_1( e, pe ), 1 ), be ) )
672 : {
673 4588 : *gain_idx = 0;
674 4588 : move16();
675 4588 : *gain = qGains[s][0];
676 4588 : move16();
677 : }
678 : }
679 : ELSE
680 : {
681 : /* Iterate over all possible gain values */
682 13725 : FOR( g = 0; g < ( 1 << kTcxHmNumGainBits ); ++g )
683 : {
684 10980 : e = tcx_hm_get_re(
685 : x16,
686 10980 : qGains[s][g],
687 : lag,
688 : fract_res,
689 : p,
690 : env,
691 : L_frame );
692 :
693 : /* Add bit penalty */
694 10980 : pe = 16384 /*1.0 Q14*/;
695 10980 : move16();
696 10980 : if ( *gain == 0 )
697 : {
698 3925 : pe = 17203 /*1.05 Q14*/;
699 3925 : move16();
700 : }
701 :
702 : /* Minimum selection, pe is Q14 */
703 10980 : IF( LT_32( L_shl( Mpy_32_16_1( e, pe ), 1 ), be ) )
704 : {
705 5016 : be = e;
706 5016 : move32();
707 5016 : *gain_idx = g;
708 5016 : move16();
709 5016 : *gain = qGains[s][g];
710 5016 : move16();
711 : }
712 : }
713 : }
714 : }
715 :
716 13646 : static Word16 tcx_hm_search(
717 : const Word32 abs_spectrum[], /* i: absolute spectrum Q31-e */
718 : const Word16 L_frame, /* i: number of spectral lines Q0 */
719 : const Word16 targetBits, /* i: target bit budget Q0 */
720 : const Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */
721 : const Word16 LtpGain, /* i: LTP gain Q15 */
722 : Word16 *RelativeScore /* o: Energy concentration factor Q13 */
723 : )
724 : {
725 : Word32 fspec[N_MAX_ARI];
726 :
727 : /* Filter out noise and keep the peaks */
728 13646 : PeakFilter( abs_spectrum, fspec, L_frame );
729 :
730 : /* Get the best lag index */
731 13646 : return SearchPeriodicityIndex_fx(
732 : fspec,
733 : abs_spectrum,
734 : L_frame,
735 : targetBits,
736 : LtpPitchLag,
737 : LtpGain,
738 : RelativeScore );
739 : }
740 :
741 15775 : void tcx_hm_analyse_fx(
742 : const Word32 abs_spectrum[], /* i: absolute spectrum Q31-e */
743 : const Word16 *spectrum_e, /* i: absolute spectrum exponent Q0 */
744 : const Word16 L_frame, /* i: number of spectral lines Q0 */
745 : Word32 env[], /* i/o: envelope shape Q16 */
746 : const Word16 targetBits, /* i: target bit budget Q0 */
747 : const Word16 coder_type, /* i: coder type Q0 */
748 : Word16 prm_hm[], /* o: HM parameters Q0 */
749 : const Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */
750 : const Word16 LtpGain, /* i: LTP gain Q15 */
751 : Word16 *hm_bits_out /* o: bit consumption Q0 */
752 : )
753 : {
754 : Word32 lag;
755 : Word16 fract_res;
756 : Word16 RelativeScore; /* Q13 */
757 : Word16 gain; /* Q11 */
758 : Word16 p[2 * kTcxHmParabolaHalfWidth + 1]; /* Q13 */
759 : Word16 hm_bits, bw_flag;
760 :
761 :
762 : /* Disable HM for non-GENERC, VOICED coder types */
763 15775 : if ( LT_16( coder_type, VOICED ) )
764 : {
765 2129 : *hm_bits_out = 0;
766 2129 : move16();
767 2129 : prm_hm[0] = 0;
768 2129 : move16();
769 :
770 2129 : return;
771 : }
772 :
773 13646 : bw_flag = 0;
774 13646 : move16();
775 13646 : if ( GE_16( L_frame, 256 ) )
776 : {
777 13646 : bw_flag = 1;
778 13646 : move16();
779 : }
780 :
781 : /* Bit consumption for the HM off case: 1 bit flag */
782 13646 : hm_bits = 1;
783 13646 : move16();
784 13646 : move16();
785 13646 : prm_hm[1] = tcx_hm_search(
786 : abs_spectrum,
787 : L_frame,
788 13646 : sub( targetBits, hm_bits ),
789 : LtpPitchLag,
790 : LtpGain,
791 : &RelativeScore );
792 :
793 : /* Convert the index to lag */
794 13646 : UnmapIndex(
795 13646 : prm_hm[1],
796 : bw_flag,
797 : LtpPitchLag,
798 13646 : ( ( LE_16( sub( targetBits, hm_bits ), kSmallerLagsTargetBitsThreshold ) ) || !bw_flag ),
799 : &fract_res,
800 : &lag );
801 13646 : test();
802 :
803 : /* Render harmonic model */
804 13646 : tcx_hm_render(
805 : lag,
806 : fract_res,
807 : p );
808 :
809 : /* Calculate and quantize gain */
810 13646 : gain = 0;
811 13646 : move16();
812 :
813 13646 : tcx_hm_quantize_gain(
814 : abs_spectrum,
815 : spectrum_e,
816 : env,
817 : lag,
818 : fract_res,
819 : p,
820 : L_frame,
821 : coder_type,
822 : RelativeScore,
823 : &prm_hm[2],
824 : &gain );
825 :
826 : /* Decision */
827 13646 : IF( gain > 0 )
828 : {
829 6981 : prm_hm[0] = 1; /* flag: on */
830 6981 : move16();
831 :
832 6981 : hm_bits = add( hm_bits, CountIndexBits( bw_flag, prm_hm[1] ) );
833 :
834 6981 : if ( EQ_16( coder_type, VOICED ) )
835 : {
836 2393 : hm_bits = add( hm_bits, kTcxHmNumGainBits );
837 : }
838 :
839 6981 : tcx_hm_modify_envelope(
840 : gain,
841 : lag,
842 : fract_res,
843 : p,
844 : env,
845 : L_frame );
846 : }
847 : ELSE
848 : {
849 6665 : prm_hm[0] = 0; /* flag: off */
850 6665 : move16();
851 6665 : prm_hm[1] = -1; /* pitch index */
852 6665 : move16();
853 6665 : prm_hm[2] = 0; /* gain index */
854 6665 : move16();
855 : }
856 :
857 13646 : *hm_bits_out = hm_bits;
858 13646 : move16();
859 : }
|