Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <assert.h>
38 : #include <stdint.h>
39 : #include "options.h"
40 : #ifdef DEBUGGING
41 : #include "debug.h"
42 : #endif
43 : #include <math.h>
44 : #include "cnst.h"
45 : #include "prot.h"
46 : #include "basop_util.h"
47 : #include "basop_proto_func.h"
48 : #include "wmc_auto.h"
49 :
50 :
51 : #define WMC_TOOL_SKIP
52 :
53 : /*-------------------------------------------------------*
54 : * expfp()
55 : *
56 : * Fixed point implementation of exp()
57 : *-------------------------------------------------------*/
58 :
59 : /*! r: Q15 */
60 364592641 : Word16 expfp(
61 : const Word16 x, /* i : mantissa Q15-e */
62 : const Word16 x_e /* i : exponent Q0 */
63 : )
64 : {
65 : Word16 xi, xf, tmp;
66 : Word16 b0, b1, b2, b3;
67 : Word32 y, L_tmp;
68 :
69 364592641 : assert( x <= 0 );
70 :
71 364592641 : L_tmp = L_negate( L_shl( L_deposit_h( x ), sub( x_e, 15 ) ) );
72 :
73 : /* split into integer and fractional parts */
74 364592641 : xi = round_fx( L_tmp );
75 364592641 : xf = extract_l( L_tmp );
76 :
77 : BASOP_SATURATE_WARNING_OFF;
78 364592641 : xf = negate( xf );
79 : BASOP_SATURATE_WARNING_ON;
80 :
81 : /* Fractional part */
82 : /* y = 65536
83 : + xf
84 : + ((xf*xf) / (2*65536))
85 : + ((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)
86 : + ((((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)*xf) / (4*65536)); */
87 364592641 : y = L_mac0( 65536, xf, 1 );
88 364592641 : tmp = shr( mult( xf, xf ), 2 );
89 364592641 : y = L_mac0( y, tmp, 1 );
90 364592641 : tmp = shr( mult( shr( mult( tmp, xf ), 1 ), 65536 / 3 ), 1 );
91 364592641 : y = L_mac0( y, tmp, 1 );
92 364592641 : tmp = shr( mult( tmp, xf ), 3 );
93 364592641 : y = L_mac0( y, tmp, 1 );
94 :
95 : /* Integer part */
96 364592641 : b0 = s_and( xi, 1 );
97 364592641 : b1 = s_and( xi, 2 );
98 364592641 : b2 = s_and( xi, 4 );
99 364592641 : b3 = s_and( xi, 8 );
100 :
101 364592641 : if ( b0 != 0 )
102 175604528 : y = Mpy_32_16( y, 24109 ); /* exp(-1) in -1Q16 */
103 364592641 : if ( b1 != 0 )
104 173927447 : y = Mpy_32_16( y, 17739 ); /* exp(-2) in -2Q17 */
105 364592641 : if ( b2 != 0 )
106 190242693 : y = Mpy_32_16( y, 19205 ); /* exp(-4) in -5Q20 */
107 364592641 : if ( b3 != 0 )
108 21067784 : y = Mpy_32_16( y, 22513 ); /* exp(-8) in -11Q26 */
109 :
110 : /* scaling: -1*b0 - 2*b1 -5*b2 -11*b3 */
111 364592641 : y = L_shr( y, add( add( xi, shr( xi, 2 ) ), shr( b3, 3 ) ) );
112 :
113 : /* zero for xi >= 16 */
114 364592641 : if ( shr( xi, 4 ) > 0 )
115 : {
116 0 : y = L_deposit_l( 0 );
117 0 : move16();
118 : }
119 :
120 364592641 : return round_fx( L_shl( y, 15 ) );
121 : }
122 :
123 :
124 : /*-------------------------------------------------------*
125 : * powfp_odd2()
126 : *
127 : * Fixed point implementation of pow(), where base is fixed point (16/16) and exponent a small *odd* integer
128 : *-------------------------------------------------------*/
129 : /*
130 : *
131 : * Returns: *pout1 = ( (base/65536)^(2*exp - 1) ) * 65536
132 : * *pout2 = ( (base/65536)^(2*exp + 1) ) * 65536
133 : *
134 : * NOTE: This function must be in sync with ari_decode_14bits_pow() */
135 :
136 12973501 : void powfp_odd2(
137 : const Word16 base, /* Q15 */
138 : const Word16 exp, /* Q0 */
139 : Word16 *pout1, /* Q15 */
140 : Word16 *pout2 /* Q15 */
141 : )
142 : {
143 : /* this version is in sync with ari_enc_14bits_pow()
144 : * that is, we have to start multiplication from the largest power-of-two, in order to
145 : * get the rounding errors to appear at the same places */
146 : Word16 pows[12]; /* powers of two exponents*/
147 : Word16 exp2;
148 : Word16 out, out2;
149 : Word16 k, h, maxk;
150 :
151 12973501 : assert( exp >= 0 );
152 :
153 12973501 : out = base;
154 12973501 : move16();
155 12973501 : out2 = 0x7FFF;
156 12973501 : move16();
157 12973501 : IF( exp != 0 )
158 : {
159 12973501 : exp2 = sub( exp, 1 );
160 12973501 : maxk = sub( 15, norm_s( exp ) );
161 12973501 : assert( maxk < 12 );
162 :
163 12973501 : pows[0] = base;
164 12973501 : move16();
165 39176581 : FOR( k = 0; k < maxk; k++ )
166 : {
167 26203080 : pows[k + 1] = mult_r( pows[k], pows[k] );
168 26203080 : move16();
169 : }
170 12973501 : k = sub( k, 1 );
171 12973501 : h = shl( 1, k ); /* highest bit of exp2 */
172 12973501 : out2 = base;
173 12973501 : move16();
174 12973501 : out = mult_r( out, pows[k + 1] ); /* we already know that "exp" has the highest bit set to one since we calculated .. */
175 : /* .. the effective length of "exp" earlier on, thus we omit the branch for out2 */
176 12973501 : if ( s_and( exp2, h ) != 0 )
177 : {
178 3822711 : out2 = mult_r( out2, pows[k + 1] );
179 : }
180 :
181 12973501 : h = shr( h, 1 );
182 26203080 : FOR( k = sub( k, 1 ); k >= 0; k-- )
183 : {
184 13229579 : if ( s_and( exp, h ) != 0 )
185 : {
186 5076559 : out = mult_r( out, pows[k + 1] );
187 : }
188 :
189 13229579 : if ( s_and( exp2, h ) != 0 )
190 : {
191 7336663 : out2 = mult_r( out2, pows[k + 1] );
192 : }
193 :
194 13229579 : h = shr( h, 1 );
195 : }
196 : }
197 :
198 12973501 : *pout1 = out2;
199 12973501 : move16();
200 12973501 : *pout2 = out;
201 12973501 : move16();
202 :
203 12973501 : return;
204 : }
205 :
206 :
207 : /*------------------------------------------------------------------------
208 : * Function: tcx_arith_scale_envelope
209 : *
210 : * For optimal performance of the arithmetic coder, the envelope shape must
211 : * be scaled such that the expected bit-consumption of a signal that
212 : * follows the scaled shape coincides with the target bitrate.
213 : * This function calculates a first-guess scaling and then uses the bi-section
214 : * search to find the optimal scaling.
215 : *
216 : * We assume that lines follow the Laplacian distribution, whereby the expected
217 : * bit-consumption would be log2(2*e*s[k]), where s[k] is the envelope value
218 : * for the line in question. However, this theoretical formula assumes that
219 : * all lines are encoded with magnitude+sign. Since the sign is unnecessary
220 : * for 0-values, that estimate of bit-consumption is biased when s[k] is small.
221 : * Analytical solution of the expectation for small s[k] is difficult, whereby
222 : * we use the approximation log2(2*e*s[k] + 0.15 + 0.035 / s[k]) which is accurate
223 : * on the range 0.08 to 1.0.
224 : *
225 : * NOTE: This function must be bit-exact on all platforms such that encoder
226 : * and decoder remain synchronized.
227 : *-------------------------------------------------------------------------*/
228 :
229 635091 : void tcx_arith_scale_envelope(
230 : const Word16 L_spec_core, /* i : number of lines to scale Q0 */
231 : Word16 L_frame, /* i : number of lines Q0 */
232 : const Word32 env[], /* i : unscaled envelope Q16 */
233 : Word16 target_bits, /* i : number of available bits Q0 */
234 : const Word16 low_complexity, /* i : low-complexity Q0 */
235 : Word16 s_env[], /* o : scaled envelope Q15-e */
236 : Word16 *s_env_e /* o : scaled envelope exponent Q0 */
237 : )
238 : {
239 : Word32 ienv[N_MAX_ARI];
240 : Word16 scale, iscale, iscale_e, a_e, b, b_e;
241 : Word16 lob, hib, adjust;
242 : Word16 k, iter, max_iter, lob_bits, hib_bits;
243 : Word16 statesi, bits;
244 : Word32 mean, a, s, L_tmp;
245 : Word16 mean_e, tmp, tmp2;
246 : #ifdef BASOP_NOGLOB
247 : Flag Overflow;
248 : #endif /* BASOP_NOGLOB */
249 :
250 :
251 635091 : lob_bits = 0;
252 635091 : move16();
253 635091 : hib_bits = 0;
254 635091 : move16();
255 :
256 : /* Boosting to account for expected spectrum truncation (kMax) */
257 : /* target_bits = (int16_t)(target_bits * (1.2f - 0.00045f * target_bits + 0.00000025f * target_bits * target_bits)); */
258 635091 : L_tmp = L_shr( Mpy_32_16( L_mult0( target_bits, target_bits ), 17180 ), 6 ); /* Q15; 17180 -> 0.00000025f (Q36) */
259 635091 : L_tmp = L_sub( L_tmp, L_shr( L_mult0( target_bits, 30199 ), 11 ) ); /* Q15; 30199 -> 0.00045f (Q26) */
260 635091 : L_tmp = L_add( L_tmp, 39322 ); /* Q15; 39322 -> 1.2f (Q15) */
261 635091 : L_tmp = Mpy_32_16( L_tmp, target_bits ); /* Q0 */
262 635091 : assert( L_tmp < 32768 );
263 635091 : target_bits = extract_l( L_tmp );
264 :
265 : /* Calculate inverse envelope and find initial scale guess based on mean */
266 635091 : mean = L_deposit_l( 0 );
267 131009953 : FOR( k = 0; k < L_frame; k++ )
268 : {
269 : /* ienv[k] = 1.0f / env[k];
270 : mean += ienv[k]; */
271 :
272 130374862 : tmp = norm_l( env[k] );
273 130374862 : tmp2 = sub( 15, tmp );
274 : #ifndef BASOP_NOGLOB
275 : tmp = Inv16( round_fx( L_shl( env[k], tmp ) ), &tmp2 );
276 : #else /* BASOP_NOGLOB */
277 130374862 : tmp = Inv16( round_fx_o( L_shl( env[k], tmp ), &Overflow ), &tmp2 );
278 : #endif /* BASOP_NOGLOB */
279 130374862 : ienv[k] = L_shl( L_deposit_h( tmp ), sub( tmp2, 15 ) ); /* Q16 */
280 130374862 : move32();
281 130374862 : mean = L_add( mean, ienv[k] );
282 : }
283 635091 : tmp = norm_s( L_frame );
284 635091 : tmp2 = div_s( 8192, shl( L_frame, tmp ) );
285 635091 : tmp = shl( tmp2, sub( tmp, 7 ) );
286 635091 : mean = L_shr( Mpy_32_16( mean, tmp ), 6 ); /* Q16 */
287 :
288 : /* Rate dependent compensation to get closer to the target on average */
289 : /* mean = powf(mean, (float)L_frame / target_bits * 0.357f); */
290 635091 : tmp = BASOP_Util_Divide1616_Scale( L_frame, target_bits, &tmp2 );
291 635091 : tmp = mult_r( tmp, FL2WORD16( 0.357f ) );
292 635091 : mean = BASOP_Util_fPow( mean, 15, L_deposit_h( tmp ), tmp2, &mean_e );
293 :
294 : /* Find first-guess scaling coefficient "scale" such that if "mean" is the
295 : * mean of the envelope, then the mean bit-consumption is approximately
296 : *
297 : * log2(2*e*mean*scale + 0.15 + 0.035/(mean*scale)) * L_frame = target_bits
298 : */
299 : /* a = 2*2.71828183f*mean*mean; */
300 635091 : tmp = round_fx( mean );
301 635091 : a = L_mult( mult_r( tmp, FL2WORD16_SCALE( 2.71828183f, 2 ) ), tmp );
302 635091 : a_e = add( shl( mean_e, 1 ), 3 );
303 :
304 : /* b = (0.15f - powf(2.0f, target_bits/(float)L_frame)) * mean; */
305 635091 : tmp = BASOP_Util_Divide1616_Scale( target_bits, L_frame, &tmp2 );
306 635091 : tmp = round_fx( BASOP_util_Pow2( L_deposit_h( tmp ), tmp2, &tmp2 ) );
307 635091 : b_e = BASOP_Util_Add_MantExp( FL2WORD16( 0.15f ), 0, negate( tmp ), tmp2, &b );
308 635091 : b = mult_r( b, round_fx( mean ) );
309 635091 : b_e = add( b_e, mean_e );
310 :
311 : /* scale = (-b + sqrtf(b*b - 4.0f*a*0.035f)) / (2.0f * a); */
312 : #ifndef BASOP_NOGLOB
313 : tmp = round_fx( BASOP_Util_Add_Mant32Exp( L_mult( b, b ), shl( b_e, 1 ), Mpy_32_16( a, FL2WORD16( -4.0f * 0.035f ) ), a_e, &tmp2 ) );
314 : #else
315 635091 : tmp = round_fx_o( BASOP_Util_Add_Mant32Exp( L_mult( b, b ), shl( b_e, 1 ), Mpy_32_16( a, FL2WORD16( -4.0f * 0.035f ) ), a_e, &tmp2 ), &Overflow );
316 : #endif
317 :
318 635091 : IF( tmp <= 0 )
319 : {
320 0 : tmp = 0;
321 :
322 0 : FOR( k = 0; k < L_frame; k++ )
323 : {
324 0 : s_env[k] = 0;
325 0 : move16();
326 : }
327 : }
328 : ELSE
329 : {
330 635091 : tmp = Sqrt16( tmp, &tmp2 );
331 : }
332 :
333 635091 : tmp2 = BASOP_Util_Add_MantExp( negate( b ), b_e, tmp, tmp2, &scale );
334 635091 : scale = BASOP_Util_Divide1616_Scale( scale, round_fx( a ), &tmp );
335 : #ifndef BASOP_NOGLOB
336 : scale = shl( scale, sub( sub( add( tmp, tmp2 ), a_e ), 1 ) ); /* Q15 */
337 : #else
338 635091 : scale = shl_o( scale, sub( sub( add( tmp, tmp2 ), a_e ), 1 ), &Overflow ); /* Q15 */
339 : #endif
340 :
341 : /* iscale = 1.0f / scale; */
342 635091 : iscale_e = 0;
343 635091 : move16();
344 635091 : iscale = Inv16( s_max( 1, scale ), &iscale_e );
345 :
346 635091 : lob = 0;
347 635091 : move16();
348 635091 : hib = 0;
349 635091 : move16();
350 :
351 635091 : max_iter = 2;
352 635091 : move16();
353 635091 : if ( low_complexity )
354 : {
355 514606 : max_iter = 1;
356 514606 : move16();
357 : }
358 :
359 1390667 : FOR( iter = 0; iter < max_iter; iter++ )
360 : {
361 755576 : statesi = 0x7FFF;
362 755576 : move16();
363 755576 : bits = 0;
364 755576 : move16();
365 :
366 154545580 : FOR( k = 0; k < L_frame; k++ )
367 : {
368 153790004 : s = Mpy_32_16( ienv[k], scale ); /* Q16 */
369 :
370 153790004 : IF( L_sub( s, FL2WORD32_SCALE( 0.08f, 15 ) ) <= 0 )
371 : {
372 : /* If s = 0.08, the expected bit-consumption is log2(1.0224). Below 0.08, the bit-consumption
373 : estimate function becomes inaccurate, so use log2(1.0224) for all values below 0.08. */
374 : /* round(state * 1.0224 * 32768) */
375 1566639 : statesi = mult_r( statesi, FL2WORD16_SCALE( 1.0224, 1 ) );
376 1566639 : tmp = norm_s( statesi );
377 1566639 : statesi = shl( statesi, tmp );
378 1566639 : bits = add( bits, sub( 1, tmp ) );
379 : }
380 152223365 : ELSE IF( L_sub( s, FL2WORD32_SCALE( 255.0, 15 ) ) <= 0 )
381 : {
382 : /* a = 5.436564f * s + 0.15f + 0.035f * env[k] * iscale; */
383 152223365 : L_tmp = L_shl( Mpy_32_16( s, FL2WORD16_SCALE( 5.436564f, 3 ) ), 3 );
384 152223365 : L_tmp = L_add( L_tmp, FL2WORD32_SCALE( 0.15f, 15 ) );
385 152223365 : L_tmp = L_add( L_tmp, L_shl( Mpy_32_16( env[k], mult_r( FL2WORD16( 0.035f ), iscale ) ), iscale_e ) );
386 :
387 152223365 : tmp = norm_l( L_tmp );
388 : #ifndef BASOP_NOGLOB
389 : statesi = mult_r( statesi, round_fx( L_shl( L_tmp, tmp ) ) );
390 : #else /* BASOP_NOGLOB */
391 152223365 : statesi = mult_r( statesi, round_fx_o( L_shl( L_tmp, tmp ), &Overflow ) );
392 : #endif /* BASOP_NOGLOB */
393 152223365 : bits = add( bits, sub( 15, tmp ) );
394 :
395 152223365 : tmp = norm_s( statesi );
396 152223365 : statesi = shl( statesi, tmp );
397 152223365 : bits = sub( bits, tmp );
398 : }
399 : ELSE
400 : {
401 : /* for large envelope values, s > 255, bit consumption is approx log2(2*e*s)
402 : * further, we use round(log2(x)) = floor(log2(x)+0.5) = floor(log2(x*sqrt(2))) */
403 : /* a = 5.436564f * s; */
404 0 : L_tmp = Mpy_32_16( s, FL2WORD16_SCALE( 5.436564f * 1.4142f, 3 ) ); /* Q13 */
405 0 : bits = add( bits, sub( 17, norm_l( L_tmp ) ) );
406 : }
407 : }
408 :
409 755576 : IF( sub( bits, target_bits ) <= 0 )
410 : {
411 : /* Bits leftover => scale is too small */
412 110221 : lob = scale;
413 110221 : move16();
414 110221 : lob_bits = bits;
415 110221 : move16();
416 :
417 110221 : IF( hib > 0 ) /* Bisection search */
418 : {
419 95757 : adjust = div_s( sub( hib_bits, target_bits ), sub( hib_bits, lob_bits ) );
420 95757 : scale = add( mult_r( sub( lob, hib ), adjust ), hib );
421 : }
422 : ELSE
423 : {
424 : /* Initial scale adaptation */
425 : /* adjust = 1.05f * target_bits / (float)bits;
426 : scale *= adjust; */
427 14464 : adjust = mult_r( FL2WORD16_SCALE( 1.05f, 1 ), target_bits );
428 14464 : adjust = BASOP_Util_Divide1616_Scale( adjust, bits, &tmp );
429 14464 : scale = shl( mult_r( scale, adjust ), add( 1, tmp ) );
430 : }
431 : }
432 : ELSE
433 : {
434 : /* Ran out of bits => scale is too large */
435 645355 : hib = scale;
436 645355 : move16();
437 645355 : hib_bits = bits;
438 645355 : move16();
439 :
440 645355 : IF( lob > 0 ) /* Bisection search */
441 : {
442 1757 : adjust = div_s( sub( hib_bits, target_bits ), sub( hib_bits, lob_bits ) );
443 1757 : scale = add( mult_r( sub( lob, hib ), adjust ), hib );
444 : }
445 : ELSE
446 : { /* Initial scale adaptation */
447 643598 : test();
448 643598 : IF( target_bits <= 0 || bits <= 0 ) /* safety check in case of bit errors */
449 : {
450 0 : adjust = 0;
451 0 : move16();
452 :
453 0 : FOR( k = 0; k < L_frame; k++ )
454 : {
455 0 : s_env[k] = 0;
456 0 : move16();
457 : }
458 : }
459 : ELSE
460 : {
461 643598 : adjust = div_s( mult_r( 31130 /*0.95f Q15*/, target_bits ), bits );
462 : }
463 643598 : scale = mult_r( scale, adjust );
464 : }
465 : }
466 755576 : iscale_e = 0;
467 755576 : move16();
468 :
469 755576 : IF( scale == 0 ) /* safety check in case of bit errors */
470 : {
471 0 : iscale = 0;
472 0 : move16();
473 :
474 0 : FOR( k = 0; k < L_frame; k++ )
475 : {
476 0 : s_env[k] = 0;
477 0 : move16();
478 : }
479 : }
480 : ELSE
481 : {
482 755576 : iscale = Inv16( scale, &iscale_e );
483 : }
484 : }
485 635091 : L_frame = L_spec_core;
486 635091 : move16();
487 :
488 635091 : tmp = getScaleFactor32( env, L_frame );
489 635091 : *s_env_e = sub( add( 15, iscale_e ), tmp );
490 635091 : move16();
491 : BASOP_SATURATE_WARNING_OFF;
492 : #ifndef BASOP_NOGLOB
493 : a = L_shl( 1265000, sub( 15, *s_env_e ) );
494 : #else /* BASOP_NOGLOB */
495 635091 : a = L_shl_o( 1265000, sub( 15, *s_env_e ), &Overflow );
496 : #endif /* BASOP_NOGLOB */
497 : BASOP_SATURATE_WARNING_ON;
498 :
499 374980611 : FOR( k = 0; k < L_frame; k++ )
500 : {
501 374345520 : L_tmp = Mpy_32_16( L_shl( env[k], tmp ), iscale );
502 374345520 : L_tmp = L_min( L_tmp, a );
503 374345520 : s_env[k] = round_fx( L_tmp );
504 374345520 : move16();
505 : }
506 :
507 635091 : return;
508 : }
509 :
510 :
511 : /*------------------------------------------------------------------------
512 : * Function: tcx_arith_render_envelope
513 : *
514 : * Calculate the envelope of the spectrum based on the LPC shape. The
515 : * envelope is used in a perceptual domain, whereby the LPC shape has to
516 : * be multiplied by the perceptual model.
517 : * Operations that are performed on the spectrum, which change the magnitude
518 : * expectation of lines, such as low-frequency emphasis, are included in the
519 : * envelope shape.
520 : * NOTE: This function must be bit-exact on all platforms such that encoder
521 : * and decoder remain synchronized.
522 : *-------------------------------------------------------------------------*/
523 :
524 635091 : void tcx_arith_render_envelope(
525 : const Word16 A_ind[], /* i : LPC coefficients of signal envelope */
526 : const Word16 L_frame, /* i : number of spectral lines */
527 : const Word16 L_spec, /* i : length of the coded spectrum */
528 : const Word16 preemph_fac, /* i : pre-emphasis factor */
529 : const Word16 gamma_w, /* i : A_ind -> weighted envelope factor */
530 : const Word16 gamma_uw, /* i : A_ind -> non-weighted envelope factor */
531 : Word32 env[] /* o : shaped signal envelope */
532 : )
533 : {
534 : Word16 k;
535 : Word16 tmpA[M + 2];
536 : Word16 signal_env[FDNS_NPTS], signal_env_e[FDNS_NPTS];
537 : Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS];
538 :
539 : /* Compute perceptual LPC envelope, transform it into freq.-domain gains */
540 635091 : basop_weight_a( A_ind, tmpA, gamma_w );
541 635091 : basop_lpc2mdct( tmpA, M, NULL, NULL, gainlpc, gainlpc_e );
542 :
543 : /* Add pre-emphasis tilt to LPC envelope, transform LPC into MDCT gains */
544 635091 : basop_weight_a_inv( A_ind, signal_env, gamma_uw );
545 635091 : basop_E_LPC_a_add_tilt( signal_env, tmpA, preemph_fac );
546 635091 : basop_lpc2mdct( tmpA, M + 1, signal_env, signal_env_e, NULL, NULL );
547 :
548 : /* Compute weighted signal envelope in perceptual domain */
549 41280915 : FOR( k = 0; k < FDNS_NPTS; k++ )
550 : {
551 40645824 : signal_env[k] = mult_r( signal_env[k], gainlpc[k] );
552 40645824 : move16();
553 40645824 : signal_env_e[k] = add( signal_env_e[k], gainlpc_e[k] );
554 40645824 : move16();
555 : }
556 :
557 : /* Adaptive low frequency emphasis */
558 166042643 : FOR( k = 0; k < L_frame; k++ )
559 : {
560 165407552 : env[k] = 0x10000;
561 165407552 : move32();
562 : }
563 :
564 635091 : basop_PsychAdaptLowFreqDeemph( env, gainlpc, gainlpc_e, NULL );
565 :
566 : /* Scale from FDNS_NPTS to L_frame and multiply LFE gains */
567 635091 : basop_mdct_noiseShaping_interp( env, L_frame, signal_env, signal_env_e );
568 :
569 209617315 : FOR( k = L_frame; k < L_spec; ++k )
570 : {
571 208982224 : env[k] = env[k - 1];
572 208982224 : move32();
573 : }
574 :
575 635091 : return;
576 : }
577 :
578 : #undef WMC_TOOL_SKIP
|