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 19676 : 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 19676 : IF( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 )
63 : {
64 10312 : Word16 LtpPitchIndex = shr( PeriodicityIndex, 9 );
65 10312 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
66 :
67 10312 : PeriodicityIndex = sub( PeriodicityIndex, 1 );
68 10312 : assert( ( PeriodicityIndex & 0xff ) < ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
69 :
70 10312 : NumRatioBitsBwLtpIndx = NumRatioBits[Bandwidth][LtpPitchIndex];
71 10312 : move16();
72 :
73 10312 : push_next_indice( hBst, s_and( PeriodicityIndex, 0xff ), NumRatioBitsBwLtpIndx );
74 10312 : return NumRatioBitsBwLtpIndx;
75 : }
76 : ELSE
77 : {
78 9364 : push_next_indice( hBst, PeriodicityIndex, 8 );
79 9364 : return 8;
80 : }
81 : }
82 : /*-------------------------------------------------------------------*
83 : * SearchPeriodicityIndex_Single()
84 : *
85 : *
86 : *-------------------------------------------------------------------*/
87 17489621 : 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 17489621 : Limit = L_deposit_l( sub( NumToConsider, 1 ) );
100 17489621 : Limit = L_shl( Limit, FractionalResolution );
101 17489621 : AbsMeanCurrent3 = L_deposit_l( 0 );
102 17489621 : HighestMultiplier = 0;
103 17489621 : move16();
104 :
105 754314908 : FOR( i = Lag; i < Limit; i += Lag )
106 : {
107 736825287 : OldIndex = L_shr( i, FractionalResolution );
108 736825287 : tmp1 = Weight[s_min( HighestMultiplier, 85 )];
109 736825287 : move16();
110 736825287 : AbsMeanCurrent3 = L_add( AbsMeanCurrent3, L_shr( L_mult( AbsMdct3[OldIndex], tmp1 ), 7 ) );
111 736825287 : HighestMultiplier = add( HighestMultiplier, 1 );
112 : }
113 :
114 17489621 : tmp1 = sub( norm_l( AbsMeanCurrent3 ), 1 );
115 17489621 : tmp2 = norm_s( HighestMultiplier );
116 17489621 : Result = div_s( round_fx( L_shl( AbsMeanCurrent3, tmp1 ) ), s_max( shl( HighestMultiplier, tmp2 ), 0x4000 ) );
117 17489621 : if ( HighestMultiplier == 0 )
118 : {
119 9098 : tmp2 = 14 + 16;
120 9098 : move16();
121 : }
122 17489621 : Result = shr( Result, s_min( 15, sub( sub( tmp1, tmp2 ), 7 - 15 ) ) );
123 :
124 17489621 : return Result;
125 : }
126 : /*-------------------------------------------------------------------*
127 : * SearchPeriodicityIndex_Range()
128 : *
129 : *
130 : *-------------------------------------------------------------------*/
131 739718 : 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 739718 : BestScore = -1;
148 739718 : move16();
149 739718 : BestIndex = 0;
150 739718 : move16();
151 :
152 15623982 : FOR( Index = Lo; Index < Hi; Index += Spacing )
153 : {
154 14884264 : CurrentScore = SearchPeriodicityIndex_Single(
155 : AbsMdct3,
156 : NumToConsider,
157 14884264 : add( Index, Adj ),
158 : FractionalResolution );
159 :
160 14884264 : if ( GT_16( CurrentScore, BestScore ) )
161 : {
162 2256472 : BestIndex = Index;
163 2256472 : move16();
164 : }
165 14884264 : BestScore = s_max( BestScore, CurrentScore );
166 : }
167 :
168 739718 : if ( GT_16( BestScore, *Score ) )
169 : {
170 194307 : *PeriodicityIndex = BestIndex;
171 194307 : move16();
172 : }
173 739718 : BestScore = s_max( BestScore, *Score );
174 :
175 739718 : B = sub( BestIndex, shr( Spacing, 1 ) );
176 739718 : B = s_max( Lo, B );
177 :
178 1387612 : FOR( Index = B; Index < BestIndex; ++Index )
179 : {
180 647894 : CurrentScore = SearchPeriodicityIndex_Single(
181 : AbsMdct3,
182 : NumToConsider,
183 647894 : add( Index, Adj ),
184 : FractionalResolution );
185 :
186 647894 : if ( GT_16( CurrentScore, BestScore ) )
187 : {
188 40009 : *PeriodicityIndex = Index;
189 40009 : move16();
190 : }
191 647894 : BestScore = s_max( BestScore, CurrentScore );
192 : }
193 :
194 739718 : B = add( BestIndex, shr( Spacing, 1 ) );
195 :
196 1633226 : FOR( Index = BestIndex + 1; Index <= B; ++Index )
197 : {
198 893508 : CurrentScore = SearchPeriodicityIndex_Single(
199 : AbsMdct3,
200 : NumToConsider,
201 893508 : add( Index, Adj ),
202 : FractionalResolution );
203 :
204 893508 : if ( GT_16( CurrentScore, BestScore ) )
205 : {
206 92908 : *PeriodicityIndex = Index;
207 92908 : move16();
208 : }
209 893508 : BestScore = s_max( BestScore, CurrentScore );
210 : }
211 :
212 739718 : *Score = BestScore;
213 739718 : move16();
214 739718 : }
215 :
216 : /*-------------------------------------------------------------------*
217 : * SearchPeriodicityIndex_fx()
218 : *
219 : *
220 : *-------------------------------------------------------------------*/
221 195542 : 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 :
245 : /* Debug init (not instrumented) */
246 195542 : C = -3000;
247 195542 : move32();
248 195542 : PeriodicityIndex = 0;
249 195542 : move16();
250 195542 : Score = -1;
251 195542 : move16();
252 :
253 195542 : s = sub( Find_Max_Norm32( Mdct, NumToConsider ), 2 );
254 :
255 195542 : A = L_shl( L_abs( Mdct[0] ), s );
256 195542 : B = L_shl( L_abs( Mdct[1] ), s );
257 :
258 195542 : tmp = sub( NumToConsider, 3 );
259 53613704 : FOR( i = 1; i < tmp; i += 3 )
260 : {
261 53418162 : C = L_shl( L_abs( Mdct[i + 1] ), s );
262 53418162 : AbsMdct3[i] = round_fx( L_add( L_add( A, B ), C ) );
263 53418162 : move16();
264 :
265 53418162 : A = L_shl( L_abs( Mdct[i + 2] ), s );
266 53418162 : AbsMdct3[i + 1] = round_fx( L_add( L_add( A, B ), C ) );
267 53418162 : move16();
268 :
269 53418162 : B = L_shl( L_abs( Mdct[i + 3] ), s );
270 53418162 : AbsMdct3[i + 2] = round_fx( L_add( L_add( A, B ), C ) );
271 53418162 : move16();
272 : }
273 :
274 195542 : IF( LT_16( i, sub( NumToConsider, 1 ) ) )
275 : {
276 186676 : C = L_shl( L_abs( Mdct[i + 1] ), s );
277 186676 : AbsMdct3[i] = round_fx( L_add( L_add( A, B ), C ) );
278 186676 : move16();
279 : }
280 :
281 195542 : IF( LT_16( i, sub( NumToConsider, 2 ) ) )
282 : {
283 61834 : A = L_shl( L_abs( Mdct[i + 2] ), s );
284 61834 : assert( C != -3000 );
285 61834 : AbsMdct3[i + 1] = round_fx( L_add( L_add( A, B ), C ) );
286 61834 : move16();
287 : }
288 :
289 195542 : AbsTotal = L_deposit_l( 0 );
290 195542 : IF( UnfilteredMdct != NULL )
291 : {
292 8421965 : FOR( i = 0; i < NumToConsider; ++i )
293 : {
294 8408320 : AbsTotal = L_add( AbsTotal, L_shr( L_abs( UnfilteredMdct[i] ), 16 ) );
295 : }
296 : /* balance difference between filtered and unfiltered mdct samples */
297 13645 : AbsTotal = L_shr( AbsTotal, sub( 4, s ) );
298 : }
299 : ELSE
300 : {
301 181897 : tmp = sub( NumToConsider, 1 );
302 50988848 : FOR( i = 1; i < tmp; i += 3 )
303 : {
304 50806951 : AbsTotal = L_mac0( AbsTotal, AbsMdct3[i], 1 );
305 : }
306 : }
307 :
308 195542 : test();
309 195542 : IF( ( LtpPitchLag > 0 ) && ( GT_16( LtpGain, kLtpHmGainThr ) ) )
310 : {
311 46624 : Bandwidth = 0;
312 46624 : move16();
313 46624 : if ( GE_16( NumToConsider, 256 ) )
314 : {
315 46624 : Bandwidth = 1;
316 46624 : move16();
317 : }
318 :
319 46624 : LtpPitchIndex = sub( mult_r( LtpPitchLag, 1 << ( 15 - kLtpHmFractionalResolution ) ), 2 );
320 46624 : assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
321 :
322 46624 : tmp32 = L_shl( L_deposit_l( sub( NumToConsider, 2 ) ), kLtpHmFractionalResolution );
323 46624 : tmp = shl( 1, NumRatioBits[Bandwidth][LtpPitchIndex] );
324 1118616 : FOR( Multiplier = 1; Multiplier <= tmp; ++Multiplier )
325 : {
326 1071992 : Lag = L_shr( L_mult0( LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier - 1] ), 8 );
327 :
328 1071992 : test();
329 1071992 : IF( ( GE_32( Lag, 4 << kLtpHmFractionalResolution ) ) && ( LE_32( Lag, tmp32 ) ) )
330 : {
331 1063955 : CurrentScore = SearchPeriodicityIndex_Single(
332 : AbsMdct3,
333 : NumToConsider,
334 : Lag,
335 : kLtpHmFractionalResolution );
336 :
337 1063955 : if ( GT_16( CurrentScore, Score ) )
338 : {
339 74073 : PeriodicityIndex = s_or( Multiplier, kLtpHmFlag );
340 : }
341 1063955 : Score = s_max( Score, CurrentScore );
342 : }
343 : }
344 46624 : PeriodicityIndex = s_or( PeriodicityIndex, shl( LtpPitchIndex, 9 ) );
345 : }
346 : ELSE
347 : {
348 148918 : IF( UnfilteredMdct != NULL )
349 : {
350 8397 : MaxAt = 1;
351 8397 : move16();
352 8397 : A = L_shr( AbsMdct3[1], 6 );
353 :
354 1705422 : FOR( i = 4; i < NumToConsider - 1; i += 3 )
355 : {
356 1697025 : if ( GT_32( AbsMdct3[i], AbsMdct3[MaxAt] ) )
357 : {
358 10445 : MaxAt = i;
359 10445 : move16();
360 : }
361 1697025 : A = L_add( A, L_shr( AbsMdct3[i], 6 ) );
362 : }
363 :
364 8397 : if ( GT_32( L_shr( AbsMdct3[MaxAt], 6 ), Mpy_32_16_1( A, 22938 /*0.7 Q15*/ ) ) )
365 : {
366 157 : NumToConsider = s_min( NumToConsider, add( MaxAt, 4 ) );
367 : }
368 : }
369 :
370 148918 : SearchPeriodicityIndex_Range(
371 : AbsMdct3,
372 : NumToConsider,
373 : 0, 16,
374 : 3,
375 : GET_ADJ2( 0, 6, 3 ),
376 : 4,
377 : &PeriodicityIndex,
378 : &Score );
379 :
380 148918 : SearchPeriodicityIndex_Range(
381 : AbsMdct3,
382 : NumToConsider,
383 : 16, 80,
384 : 4,
385 : GET_ADJ2( 16, 8, 4 ),
386 : 4,
387 : &PeriodicityIndex,
388 : &Score );
389 :
390 148918 : SearchPeriodicityIndex_Range(
391 : AbsMdct3,
392 : NumToConsider,
393 : 80, 208,
394 : 3,
395 : GET_ADJ2( 80, 12, 3 ),
396 : 4,
397 : &PeriodicityIndex,
398 : &Score );
399 :
400 148918 : IF( LE_16( NumToConsider, 128 ) ) /* no long lags for band-limited MDCTs */
401 : {
402 157 : SearchPeriodicityIndex_Range(
403 : AbsMdct3,
404 : NumToConsider,
405 157 : 208, add( 88, NumToConsider ),
406 : 0,
407 : GET_ADJ2( 224, 188, 0 ),
408 : 1,
409 : &PeriodicityIndex,
410 : &Score );
411 : }
412 : ELSE
413 : {
414 148761 : test();
415 148761 : IF( GT_16( TargetBits, kSmallerLagsTargetBitsThreshold ) && GE_16( NumToConsider, 256 ) )
416 : {
417 144046 : SearchPeriodicityIndex_Range(
418 : AbsMdct3,
419 : NumToConsider,
420 : 208, 224,
421 : 1,
422 : GET_ADJ2( 208, 28, 1 ),
423 : 1,
424 : &PeriodicityIndex,
425 : &Score );
426 144046 : SearchPeriodicityIndex_Range(
427 : AbsMdct3,
428 : NumToConsider,
429 : 224, 256,
430 : 0,
431 : GET_ADJ2( 224, 188, 0 ),
432 : 1,
433 : &PeriodicityIndex,
434 : &Score );
435 : }
436 : ELSE
437 : {
438 4715 : SearchPeriodicityIndex_Range(
439 : AbsMdct3,
440 : NumToConsider,
441 : 208, 256,
442 : 1,
443 : GET_ADJ2( 208, 28, 1 ),
444 : 1,
445 : &PeriodicityIndex,
446 : &Score );
447 : }
448 : }
449 : }
450 :
451 195542 : IF( AbsTotal > 0 )
452 : {
453 195522 : tmp32 = L_mult0( Score, NumToConsider ); /* -> 16Q15 */
454 195522 : tmp = sub( norm_l( tmp32 ), 1 );
455 195522 : tmp2 = norm_l( AbsTotal );
456 195522 : tmp3 = div_s( round_fx_sat( L_shl( tmp32, tmp ) ), round_fx_sat( L_shl( AbsTotal, tmp2 ) ) );
457 195522 : *RelativeScore = shr_sat( tmp3, add( sub( tmp, tmp2 ), 2 ) ); /* -> 2Q13 */
458 195522 : move16();
459 : }
460 : ELSE
461 : {
462 20 : *RelativeScore = 0;
463 20 : move16();
464 : }
465 :
466 195542 : return PeriodicityIndex;
467 : }
468 : /*-------------------------------------------------------------------*
469 : * PeakFilter()
470 : *
471 : *
472 : *-------------------------------------------------------------------*/
473 :
474 13645 : static void PeakFilter(
475 : const Word32 x[], /* i : absolute spectrum Qx */
476 : Word32 y[], /* O : filtered absolute spectrum, must not alias x[] Q(x-4)*/
477 : const Word16 L_frame /* i : number of spectral lines */
478 : )
479 : {
480 : Word16 flen, i;
481 : /*#define kPeakElevationThreshold 1.0f*/
482 : Word16 m;
483 : Word32 a;
484 :
485 13645 : flen = shr( L_frame, 4 );
486 : /* m = kPeakElevationThreshold / (float)(2*flen + 1); */
487 13645 : m = shr( div_s( 8 /*kPeakElevationThreshold Q3*/, add( shl( flen, 1 ), 1 ) ), 3 ); // Q15
488 :
489 13645 : a = L_deposit_l( 0 );
490 539165 : FOR( i = 0; i < flen; ++i )
491 : {
492 525520 : a = L_add( a, L_shr( x[i], 4 ) );
493 : }
494 :
495 539165 : FOR( i = 0; i < flen; ++i )
496 : {
497 525520 : y[i] = L_max( 0, L_sub( L_shr( x[i], 4 ), Mpy_32_16_1( a, m ) ) ); // Q(x-4)
498 525520 : move32();
499 525520 : a = L_add( a, L_shr( x[i + flen], 4 ) );
500 : }
501 13645 : sub( 0, 0 );
502 7370925 : FOR( ; i < L_frame - flen; ++i )
503 : {
504 7357280 : y[i] = L_max( 0, L_sub( L_shr( x[i], 4 ), Mpy_32_16_1( a, m ) ) ); // Q(x-4)
505 7357280 : move32();
506 7357280 : a = L_sub( a, L_shr( x[i - flen], 4 ) );
507 7357280 : a = L_add( a, L_shr( x[i + flen], 4 ) );
508 : }
509 :
510 539165 : FOR( ; i < L_frame; ++i )
511 : {
512 525520 : y[i] = L_max( 0, L_sub( L_shr( x[i], 4 ), Mpy_32_16_1( a, m ) ) ); // Q(x-4)
513 525520 : move32();
514 525520 : a = L_sub( a, L_shr( x[i - flen], 4 ) );
515 : }
516 13645 : }
517 :
518 : /*-------------------------------------------------------------------*
519 : * tcx_hm_get_re()
520 : *
521 : *
522 : *-------------------------------------------------------------------*/
523 30818 : static Word32 tcx_hm_get_re(
524 : const Word16 x[], /* i: absolute spectrum */
525 : const Word16 gain, /* o: quantized harmonic model gain Q11 */
526 : const Word32 lag, /* i: pitch lag Q0 */
527 : const Word16 fract_res, /* i: fractional resolution of the lag Q0 */
528 : Word16 p[], /* i: harmonic model Q13 */
529 : const Word32 env[], /* i: envelope Q16 */
530 : const Word16 L_frame /* i: number of spectral lines Q0 */
531 : )
532 : {
533 : Word16 i, inv_G, tmp;
534 : Word16 s, s_ne, s_x_ne;
535 : Word16 *x_ne;
536 : Word32 ne[N_MAX_ARI], G, e;
537 :
538 30818 : x_ne = (Word16 *) ne;
539 30818 : assert( L_frame <= N_MAX_ARI );
540 :
541 : /* Calculate new envelope with "gain" harmonic gain ***********************/
542 :
543 30818 : Copy32( env, ne, L_frame );
544 :
545 30818 : tcx_hm_modify_envelope(
546 : gain,
547 : lag,
548 : fract_res,
549 : p,
550 : ne,
551 : L_frame );
552 :
553 : /* Normalize **************************************************************/
554 :
555 30818 : s_ne = getScaleFactor32( ne, L_frame );
556 :
557 30818 : G = L_deposit_l( 0 );
558 19096738 : FOR( i = 0; i < L_frame; ++i )
559 : {
560 19065920 : x_ne[i] = mult( x[i], extract_h( L_shl( ne[i], s_ne ) ) ); /* exp: x_e+15-s_ne */
561 19065920 : move16();
562 19065920 : G = L_mac0( G, x_ne[i], 1 ); /* exp: x_e + 31 - s_ne */
563 : }
564 30818 : s = norm_l( G );
565 30818 : inv_G = div_s( 0x4000, extract_h( L_shl( G, s ) ) ); /* exp: 1 - (x_e + 31 - s_ne - s) */
566 :
567 : /* Calculate error ********************************************************/
568 30818 : s_x_ne = sub( getScaleFactor16( x_ne, L_frame ), 2 );
569 30818 : e = L_deposit_l( 0 );
570 19096738 : FOR( i = 0; i < L_frame; ++i )
571 : {
572 19065920 : tmp = shl( x_ne[i], s_x_ne ); /* exp: x_e + 15 - s_ne - s_x_ne */
573 19065920 : tmp = mult( tmp, tmp ); /* exp: 2 * (x_e + 15 - s_ne - s_x_ne) */
574 19065920 : e = L_mac( e, tmp, tmp ); /* exp: 4 * (x_e + 15 - s_ne - s_x_ne) */
575 : }
576 :
577 30818 : e = Mpy_32_16_1( e, inv_G );
578 30818 : e = Mpy_32_16_1( e, inv_G );
579 30818 : e = Mpy_32_16_1( e, inv_G );
580 30818 : e = Mpy_32_16_1( e, inv_G ); /* exp: 4 * (s - s_x_ne - 15) */
581 :
582 30818 : e = L_shl( e, shl( sub( sub( s, s_x_ne ), 15 ), 2 ) ); /* Q31 */
583 :
584 :
585 30818 : return e;
586 : }
587 : /*-------------------------------------------------------------------*
588 : * tcx_hm_quantize_gain()
589 : *
590 : *
591 : *-------------------------------------------------------------------*/
592 :
593 13645 : static void tcx_hm_quantize_gain(
594 : const Word32 x[], /* i: absolute spectrum Q31-x_e */
595 : const Word16 *x_e, /* i: absolute spectrum exponent Q0 */
596 : const Word32 env[], /* i: envelope Q16 */
597 : const Word32 lag, /* i: pitch lag Q0 */
598 : const Word16 fract_res, /* i: fractional resolution of the lag Q0 */
599 : Word16 p[], /* i: harmonic model Q13 */
600 : const Word16 L_frame, /* i: number of spectral lines Q0 */
601 : const Word16 coder_type, /* i: coder_type Q0 */
602 : Word16 relative_score, /* i: periodicity score Q13 */
603 : Word16 *gain_idx, /* o: quantization index Q0 */
604 : Word16 *gain /* o: quantized harmonic model gain Q11 */
605 : )
606 : {
607 : Word16 g;
608 : Word16 pe; /* Q14 */
609 : Word32 be; /* Q31 */
610 : Word32 e; /* Q31 */
611 : Word16 i;
612 : Word16 x16[N_MAX_ARI], s_x;
613 : Word16 s;
614 :
615 :
616 13645 : assert( coder_type == VOICED || coder_type == GENERIC );
617 13645 : s = 0;
618 13645 : move16();
619 13645 : if ( EQ_16( coder_type, VOICED ) )
620 : {
621 2744 : s = 1;
622 2744 : move16();
623 : }
624 :
625 :
626 13645 : *gain = 0;
627 13645 : move16();
628 :
629 : /* Disable the harmonic model if periodicity is very low */
630 13645 : IF( LT_16( relative_score, kLowPeriodicityThr_fx[s] ) )
631 : {
632 2352 : return;
633 : }
634 :
635 : (void) x_e;
636 :
637 11293 : s_x = getScaleFactor32( x, L_frame );
638 7024733 : FOR( i = 0; i < L_frame; ++i )
639 : {
640 7013440 : x16[i] = extract_h( L_shl( x[i], s_x ) );
641 7013440 : move16();
642 : }
643 :
644 11293 : be = tcx_hm_get_re( x16, *gain, lag, fract_res, p, env, L_frame );
645 :
646 11293 : IF( EQ_16( coder_type, GENERIC ) )
647 : {
648 8549 : e = tcx_hm_get_re(
649 : x16,
650 8549 : qGains[s][0],
651 : lag,
652 : fract_res,
653 : p,
654 : env,
655 : L_frame );
656 :
657 8549 : pe = 17203 /*1.05 Q14*/;
658 8549 : move16();
659 :
660 : /* pe is Q14 */
661 8549 : IF( LT_32( L_shl( Mpy_32_16_1( e, pe ), 1 ), be ) )
662 : {
663 4587 : *gain_idx = 0;
664 4587 : move16();
665 4587 : *gain = qGains[s][0];
666 4587 : move16();
667 : }
668 : }
669 : ELSE
670 : {
671 : /* Iterate over all possible gain values */
672 13720 : FOR( g = 0; g < ( 1 << kTcxHmNumGainBits ); ++g )
673 : {
674 10976 : e = tcx_hm_get_re(
675 : x16,
676 10976 : qGains[s][g],
677 : lag,
678 : fract_res,
679 : p,
680 : env,
681 : L_frame );
682 :
683 : /* Add bit penalty */
684 10976 : pe = 16384 /*1.0 Q14*/;
685 10976 : move16();
686 10976 : if ( *gain == 0 )
687 : {
688 3924 : pe = 17203 /*1.05 Q14*/;
689 3924 : move16();
690 : }
691 :
692 : /* Minimum selection, pe is Q14 */
693 10976 : IF( LT_32( L_shl( Mpy_32_16_1( e, pe ), 1 ), be ) )
694 : {
695 5015 : be = e;
696 5015 : move32();
697 5015 : *gain_idx = g;
698 5015 : move16();
699 5015 : *gain = qGains[s][g];
700 5015 : move16();
701 : }
702 : }
703 : }
704 : }
705 :
706 13645 : static Word16 tcx_hm_search(
707 : const Word32 abs_spectrum[], /* i: absolute spectrum Q31-e */
708 : const Word16 L_frame, /* i: number of spectral lines Q0 */
709 : const Word16 targetBits, /* i: target bit budget Q0 */
710 : const Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */
711 : const Word16 LtpGain, /* i: LTP gain Q15 */
712 : Word16 *RelativeScore /* o: Energy concentration factor Q13 */
713 : )
714 : {
715 : Word32 fspec[N_MAX_ARI];
716 :
717 : /* Filter out noise and keep the peaks */
718 13645 : PeakFilter( abs_spectrum, fspec, L_frame );
719 :
720 : /* Get the best lag index */
721 13645 : return SearchPeriodicityIndex_fx(
722 : fspec,
723 : abs_spectrum,
724 : L_frame,
725 : targetBits,
726 : LtpPitchLag,
727 : LtpGain,
728 : RelativeScore );
729 : }
730 :
731 15794 : void tcx_hm_analyse_fx(
732 : const Word32 abs_spectrum[], /* i: absolute spectrum Q31-e */
733 : const Word16 *spectrum_e, /* i: absolute spectrum exponent Q0 */
734 : const Word16 L_frame, /* i: number of spectral lines Q0 */
735 : Word32 env[], /* i/o: envelope shape Q16 */
736 : const Word16 targetBits, /* i: target bit budget Q0 */
737 : const Word16 coder_type, /* i: coder type Q0 */
738 : Word16 prm_hm[], /* o: HM parameters Q0 */
739 : const Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */
740 : const Word16 LtpGain, /* i: LTP gain Q15 */
741 : Word16 *hm_bits_out /* o: bit consumption Q0 */
742 : )
743 : {
744 : Word32 lag;
745 : Word16 fract_res;
746 : Word16 RelativeScore; /* Q13 */
747 : Word16 gain; /* Q11 */
748 : Word16 p[2 * kTcxHmParabolaHalfWidth + 1]; /* Q13 */
749 : Word16 hm_bits, bw_flag;
750 :
751 :
752 : /* Disable HM for non-GENERC, VOICED coder types */
753 15794 : if ( LT_16( coder_type, VOICED ) )
754 : {
755 2149 : *hm_bits_out = 0;
756 2149 : move16();
757 2149 : prm_hm[0] = 0;
758 2149 : move16();
759 :
760 2149 : return;
761 : }
762 :
763 13645 : bw_flag = 0;
764 13645 : move16();
765 13645 : if ( GE_16( L_frame, 256 ) )
766 : {
767 13645 : bw_flag = 1;
768 13645 : move16();
769 : }
770 :
771 : /* Bit consumption for the HM off case: 1 bit flag */
772 13645 : hm_bits = 1;
773 13645 : move16();
774 13645 : move16();
775 13645 : prm_hm[1] = tcx_hm_search(
776 : abs_spectrum,
777 : L_frame,
778 13645 : sub( targetBits, hm_bits ),
779 : LtpPitchLag,
780 : LtpGain,
781 : &RelativeScore );
782 :
783 : /* Convert the index to lag */
784 13645 : UnmapIndex(
785 13645 : prm_hm[1],
786 : bw_flag,
787 : LtpPitchLag,
788 13645 : ( ( LE_16( sub( targetBits, hm_bits ), kSmallerLagsTargetBitsThreshold ) ) || !bw_flag ),
789 : &fract_res,
790 : &lag );
791 13645 : test();
792 :
793 : /* Render harmonic model */
794 13645 : tcx_hm_render(
795 : lag,
796 : fract_res,
797 : p );
798 :
799 : /* Calculate and quantize gain */
800 13645 : gain = 0;
801 13645 : move16();
802 :
803 13645 : tcx_hm_quantize_gain(
804 : abs_spectrum,
805 : spectrum_e,
806 : env,
807 : lag,
808 : fract_res,
809 : p,
810 : L_frame,
811 : coder_type,
812 : RelativeScore,
813 : &prm_hm[2],
814 : &gain );
815 :
816 : /* Decision */
817 13645 : IF( gain > 0 )
818 : {
819 6979 : prm_hm[0] = 1; /* flag: on */
820 6979 : move16();
821 :
822 6979 : hm_bits = add( hm_bits, CountIndexBits( bw_flag, prm_hm[1] ) );
823 :
824 6979 : if ( EQ_16( coder_type, VOICED ) )
825 : {
826 2392 : hm_bits = add( hm_bits, kTcxHmNumGainBits );
827 : }
828 :
829 6979 : tcx_hm_modify_envelope(
830 : gain,
831 : lag,
832 : fract_res,
833 : p,
834 : env,
835 : L_frame );
836 : }
837 : ELSE
838 : {
839 6666 : prm_hm[0] = 0; /* flag: off */
840 6666 : move16();
841 6666 : prm_hm[1] = -1; /* pitch index */
842 6666 : move16();
843 6666 : prm_hm[2] = 0; /* gain index */
844 6666 : move16();
845 : }
846 :
847 13645 : *hm_bits_out = hm_bits;
848 13645 : move16();
849 : }
|