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