Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : #include "prot_fx.h" /* Function prototypes */
7 : #include "cnst.h" /* Common constants */
8 : #include "rom_com.h" /* Static table prototypes */
9 :
10 : /*! r: Approximate integer division for positive input using lookup table */
11 804159 : UWord32 intLimCDivPos_fx(
12 : UWord32 NUM, /* Qx */
13 : Word16 DEN /* Q0 */
14 : )
15 : {
16 : UWord32 UL_ru, UL_rl;
17 804159 : Mpy_32_32_uu( UL_lshl( NUM, 1 ), intLimCDivInvDQ31[DEN], &UL_ru, &UL_rl ); /* Qx */
18 804159 : return UL_ru;
19 : }
20 :
21 : /*! r: Approximate integer division for signed input using lookup table */
22 561052 : static Word32 intLimCDivSigned_fx(
23 : Word32 NUM, /* Qx */
24 : Word16 DEN /* Q0 */
25 : )
26 : {
27 : Word32 L_tmp;
28 :
29 561052 : L_tmp = intLimCDivPos_fx( L_abs( NUM ), DEN ); /* Qx */
30 561052 : if ( NUM < 0 )
31 : {
32 74649 : L_tmp = L_negate( L_tmp ); /* one op */
33 : }
34 561052 : return L_tmp;
35 : }
36 :
37 : /*! r: Approximate integer division for negative input */
38 619926 : Word16 shrtCDivSignedApprox(
39 : const Word16 num, /* Q0 */
40 : const Word16 den /* Q0 */
41 : )
42 : {
43 : Word16 pool_part;
44 :
45 619926 : pool_part = extract_h( L_mult( negate( abs_s( num ) ), lim_neg_inv_tbl_fx[den] ) ); /* Q0 */
46 : /* neg_in always, positive out always, so that positive truncation(rounding) is used */
47 619926 : if ( num < 0 )
48 : {
49 12338 : pool_part = negate( pool_part ); /* make negative, one op */
50 : }
51 619926 : return pool_part;
52 : }
53 :
54 121408 : static void nearProjQ15_fx(
55 : const Word16 x, /* i : input coefficient Q15*/
56 : Word16 *result /* o : projection Q15*/
57 : )
58 : {
59 : const Word16 a[4] = { 14967, -25518, 3415, 32351 }; /* Q15 */
60 121408 : move16();
61 121408 : move16();
62 121408 : move16();
63 121408 : move16();
64 : Word32 b;
65 : UWord16 lsb;
66 :
67 121408 : b = L_deposit_l( a[0] );
68 121408 : b = L_shl( L_deposit_l( add( a[1], extract_h( L_mult0( extract_l( b ), x ) ) ) ), 1 ); /* Q15 */
69 121408 : Mpy_32_16_ss( b, x, &b, &lsb ); /* Q15 */
70 121408 : b = L_add( L_deposit_l( a[2] ), b ); /* Q15 */
71 121408 : Mpy_32_16_ss( b, x, &b, &lsb ); /* Q15 */
72 121408 : b = L_add( L_deposit_l( a[3] ), b ); /* Q15 */
73 121408 : *result = extract_l( b ); /* Q15 */
74 121408 : move16();
75 121408 : return;
76 : }
77 :
78 : /*-------------------------------------------------------------------*
79 : * obtainEnergyQuantizerDensity_fx()
80 : *
81 : *
82 : *-------------------------------------------------------------------*/
83 61426 : void obtainEnergyQuantizerDensity_fx(
84 : const Word16 L, /* i : left vector energy Q0*/
85 : const Word16 R, /* i : right vector energy Q0*/
86 : Word16 *Density /* o : quantizer density Q0*/
87 : )
88 : {
89 : Word16 Rnrg, den, n;
90 :
91 61426 : den = sub( shl( L, 1 ), 1 );
92 61426 : IF( LE_16( den, 67 ) )
93 : {
94 59776 : Rnrg = extract_l( intLimCDivPos_fx( L_deposit_l( R ), den ) ); /* Q0 */
95 : }
96 : ELSE
97 : {
98 1650 : n = norm_s( den );
99 1650 : move16();
100 1650 : Rnrg = shr( div_s( R, shl( den, n ) ), sub( 15, n ) ); /* n */
101 : }
102 61426 : Rnrg = add( Rnrg, 28 ); /* Q0 */
103 :
104 61426 : Rnrg = s_min( Rnrg, 56 ); /* Q0 */
105 61426 : Rnrg = s_min( Rnrg, sub( R, 96 ) ); /* Q0 */
106 :
107 61426 : Rnrg = s_max( Rnrg, 3 );
108 61426 : *Density = obtainEnergyQuantizerDensity_f[Rnrg]; /* Q0 */
109 61426 : move16();
110 61426 : return;
111 : }
112 :
113 :
114 : /*-------------------------------------------------------------------*
115 : * dsDirac2Dirac_fx()
116 : *
117 : *
118 : *-------------------------------------------------------------------*/
119 619926 : void dsDirac2Dirac_fx(
120 : const Word16 dsDiracIndex, /* i : input index Q0*/
121 : Word16 *diracs /* o : number of diracs Q0*/
122 : )
123 : {
124 619926 : *diracs = dsDiracsTab[dsDiracIndex]; /* Q0 */
125 619926 : move16();
126 619926 : return;
127 : }
128 :
129 681352 : void dsDiracPerQuanta_fx(
130 : const Word16 td, /* i : Length of vector segment Q0*/
131 : const Word16 t_quanta, /* i : Assigned number of quanta Q0*/
132 : const Word16 dsm, /* i : Conservative rounding flag Q0*/
133 : const unsigned char *const *frQuanta, /* i : Quanta lookup table */
134 : Word16 *DsIdx /* o : Lookup table index Q0*/
135 : )
136 : {
137 : const unsigned char *sv;
138 : Word16 nsv;
139 : Word16 t_quanta_o;
140 : Word16 dsIndex;
141 : Word16 i;
142 :
143 681352 : sv = frQuanta[td]; /* Q0 */
144 681352 : nsv = sv[0];
145 681352 : move16();
146 681352 : t_quanta_o = sub( t_quanta, QUANTAQ3OFFSET ); /* Q0 */
147 :
148 681352 : IF( GE_16( t_quanta_o, sv[nsv] ) )
149 : {
150 36849 : *DsIdx = nsv; /* Q0 */
151 36849 : move16();
152 36849 : return;
153 : }
154 :
155 644503 : IF( LE_16( t_quanta_o, sv[1] ) )
156 : {
157 84538 : *DsIdx = 1; /* Q0 */
158 84538 : move16();
159 84538 : return;
160 : }
161 :
162 :
163 559965 : dsIndex = shl( 1, frQuanta[0][td] ); /* Q0 */
164 559965 : IF( GT_16( t_quanta_o, sv[nsv >> 1] ) )
165 : {
166 185736 : dsIndex = sub( nsv, dsIndex ); /* Q0 */
167 : }
168 1995553 : FOR( i = frQuanta[0][td] - 1; i >= 0; i-- )
169 : {
170 1435588 : dsIndex = add( dsIndex, shl( sub( shl( lshr( sub( sv[dsIndex], t_quanta_o ), 15 ), 1 ), 1 ), i ) ); /* Q0 */
171 : }
172 :
173 559965 : dsIndex = add( dsIndex, lshr( sub( sv[dsIndex], t_quanta_o ), 15 ) ); /* Q0 */
174 559965 : dsIndex = sub( dsIndex, lshr( sub( 1, dsIndex ), 15 ) ); /* Q0 */
175 :
176 559965 : if ( EQ_16( dsm, PVQ_CONS ) )
177 : {
178 222696 : *DsIdx = dsIndex; /* Q0 */
179 222696 : move16();
180 222696 : return;
181 : }
182 337269 : *DsIdx = add( dsIndex, lshr( sub( add( sv[dsIndex + 1], sv[dsIndex] ), shl( t_quanta_o, 1 ) ), 15 ) ); /* Q0 */
183 337269 : move16();
184 337269 : return;
185 : }
186 :
187 63131 : void QuantaPerDsDirac_fx(
188 : const Word16 td, /* i : Length of vector segment Q0*/
189 : const Word16 dsDiracIndex, /* i : Quanta table index Q0*/
190 : const unsigned char *const *dimFrQuanta, /* i : Quanta lookup table */
191 : Word16 *Quanta /* i : Quanta Q0*/
192 : )
193 : {
194 63131 : *Quanta = dimFrQuanta[td][dsDiracIndex];
195 63131 : move16();
196 63131 : if ( dsDiracIndex == 0 )
197 : {
198 0 : *Quanta = -1; /* single op */
199 0 : move16();
200 : }
201 63131 : *Quanta = add( *Quanta, QUANTAQ3OFFSET ); /* Q0 */
202 63131 : move16();
203 63131 : return;
204 : }
205 :
206 619926 : void conservativeL1Norm_fx(
207 : const Word16 L, /* i : Length of vector segment Q0*/
208 : const Word16 Qvec, /* i : Assigned number of quanta Q0*/
209 : const Word16 Fcons, /* i : Conservative rounding flag Q0*/
210 : const Word16 Qavail, /* i : Input quanta remaining Q0*/
211 : const Word16 Qreserv, /* i : Input quanta in reservoir Q0*/
212 : const Word16 Dspec, /* i : assigned diracs from bitalloc Q0*/
213 : Word16 *Dvec, /* o : actual number of diracs Q0*/
214 : Word16 *Qspare, /* o : Output quanta remaining Q0*/
215 : Word16 *Qreservplus, /* o : Output quanta in reservoir Q0*/
216 : Word16 *Dspecplus /* o : Output number of diracs Q0*/
217 : )
218 : {
219 :
220 : Word16 Minit, Mprime;
221 : Word16 Qtestminus;
222 : const unsigned char *frQuantaL;
223 :
224 619926 : frQuantaL = hBitsN[L];
225 :
226 619926 : *Qreservplus = add( Qreserv, sub( Qvec, QUANTAQ3OFFSET ) ); /* Q0 */
227 619926 : move16();
228 619926 : dsDiracPerQuanta_fx( L, Qvec, Fcons, hBitsN, &Minit );
229 :
230 619926 : Mprime = Minit;
231 619926 : move16();
232 : DO
233 : {
234 682860 : Qtestminus = (Word16) frQuantaL[Mprime];
235 682860 : move16();
236 682860 : *Qspare = sub( Qavail, Qtestminus ); /* Q0 */
237 682860 : move16();
238 682860 : Mprime = sub( Mprime, 1 ); /* Q0 */
239 : }
240 682860 : WHILE( ( Mprime >= 0 ) && LT_16( *Qspare, QUANTAQ3OFFSET ) );
241 :
242 619926 : if ( Mprime < 0 )
243 : {
244 57142 : *Qspare = add( Qavail, QUANTAQ3OFFSET ); /* single op Q0*/
245 57142 : move16();
246 : }
247 619926 : dsDirac2Dirac_fx( add( Mprime, 1 ), Dvec );
248 :
249 619926 : *Dspecplus = add( Dspec, *Dvec ); /* Q0 */
250 619926 : move16();
251 619926 : *Qreservplus = sub( *Qreservplus, (Word16) frQuantaL[Minit] ); /* Q0 */
252 619926 : move16();
253 619926 : *Qspare = sub( *Qspare, QUANTAQ3OFFSET ); /* Q0 */
254 619926 : move16();
255 :
256 619926 : return;
257 : }
258 :
259 :
260 558500 : void bandBitsAdjustment_fx(
261 : const Word16 Brc, /* i : Current number of read quanta in range coder Q0*/
262 : const UWord32 INTrc, /* i : Range coder state Q0*/
263 : const Word16 Bavail, /* i : Available number of quanta Q3*/
264 : const Word16 Nbands, /* i : Number of bands Q0*/
265 : const Word16 D, /* i : Remaining number of bands to encode Q0*/
266 : const Word16 L, /* i : Size of current band Q0*/
267 : const Word16 Bband, /* i : Quanta allocation for current band Q0*/
268 : const Word16 Breserv, /* i : Quanta reservoir Q0*/
269 : Word16 *Bband_adj, /* o : Actual used number of quanta Q0*/
270 : Word16 *Brem, /* o : Quanta remaining Q0*/
271 : Word16 *Breservplus /* o : Quanta pool size Q0*/
272 : )
273 : {
274 : Word16 Btemp;
275 : Word16 Bff;
276 : Word32 L_tmp;
277 :
278 558500 : rangeCoderFinalizationFBits_fx( Brc, INTrc, &Bff );
279 :
280 558500 : IF( LT_16( D, Nbands ) )
281 : {
282 499626 : L_tmp = L_deposit_l( sub( Breserv, Bff ) ); /* Q0 */
283 499626 : Btemp = extract_l( intLimCDivSigned_fx( L_tmp, s_min( D, 3 ) ) ); /* result always fits in Word16 Q0*/
284 499626 : *Breservplus = add( Bband, Breserv ); /* Q0 */
285 499626 : move16();
286 : }
287 : ELSE
288 : {
289 58874 : Btemp = 0;
290 58874 : move16();
291 58874 : *Breservplus = add( Bband, Bff ); /* Q0 */
292 58874 : move16();
293 : }
294 558500 : *Bband_adj = s_min( extract_l( L_mult( L, 40 ) ), Bband ); /* Q3 */
295 558500 : move16();
296 558500 : *Brem = sub( Bavail, Bff ); /* Q0 */
297 558500 : move16();
298 558500 : *Bband_adj = s_min( *Brem, add( *Bband_adj, Btemp ) ); /* Q0 */
299 558500 : move16();
300 558500 : *Bband_adj = s_max( 0, *Bband_adj ); /* Q0 */
301 558500 : move16();
302 558500 : return;
303 : }
304 :
305 :
306 60704 : static Word16 Ratio_base2Q11_fx( /* o : Q11 */
307 : const Word16 opp, /* i : opposite Q15 */
308 : const Word16 near /* i : near Q15 */
309 : )
310 : {
311 : Word16 mc, nc, ms, ns, d, z;
312 : Word16 result;
313 : Word32 acc;
314 :
315 60704 : ns = norm_s( opp ); /* exponent */
316 60704 : nc = norm_s( near ); /* exponent */
317 :
318 60704 : ms = shl( opp, ns ); /* mantissa */
319 60704 : mc = shl( near, nc ); /* mantissa */
320 :
321 60704 : acc = L_mac( 538500224L, mc, -2776 ); /* a0*mc + a1, acc(Q27), a0(Q11), a1(Q27) */
322 60704 : z = mac_r( acc, ms, -2776 ); /* z in Q11, a0 in Q11 */
323 60704 : d = sub( ms, mc ); /* d in Q15 */
324 60704 : z = mult_r( z, d ); /* z in Q11 */
325 :
326 60704 : result = add( z, shl( sub( nc, ns ), 11 ) ); /* Q11 */
327 :
328 60704 : return result;
329 : }
330 :
331 60704 : static void Ratio_rQ3_fx(
332 : Word16 opp, /* i : opposite Q15*/
333 : Word16 near, /* i : near Q15*/
334 : Word16 *result /* o : ratio Q3*/
335 : )
336 : {
337 : Word16 tmp;
338 :
339 60704 : tmp = add( 1 << 7, Ratio_base2Q11_fx( opp, near ) ); /* Q11 */
340 60704 : *result = shr( tmp, 8 ); /* Q3 */
341 60704 : move16();
342 60704 : return;
343 : }
344 :
345 :
346 61426 : void densityAngle2RmsProjDec_fx(
347 : const Word16 D, /* i : density Q0*/
348 : const Word16 indexphi, /* i : decoded index from AR dec Q0*/
349 : Word16 *oppQ15, /* o : opposite Q15*/
350 : Word16 *nearQ15, /* o : near Q15*/
351 : Word16 *oppRatioQ3 /* o : ratio Q3*/
352 : )
353 : {
354 : Word16 phiQ14q;
355 : Word16 oppTail, nearTail;
356 :
357 61426 : phiQ14q = (Word16) intLimCDivPos_fx( (UWord32) L_shl( L_deposit_l( indexphi ), 13 ), shr( D, 1 ) ); /* Q14 */
358 61426 : move16();
359 61426 : if ( indexphi < 0 )
360 : {
361 336 : phiQ14q = 1 << 13; /* one op */
362 336 : move16();
363 : }
364 :
365 61426 : oppTail = shr( sub( 16320, phiQ14q ), 15 );
366 61426 : nearTail = shr( sub( phiQ14q, 64 ), 15 );
367 :
368 61426 : IF( s_or( oppTail, nearTail ) < 0 )
369 : {
370 722 : *oppQ15 = s_and( oppTail, ( 1 << 15 ) - 1 ); /* Q15 */
371 722 : move16();
372 722 : *nearQ15 = s_and( nearTail, ( 1 << 15 ) - 1 ); /* Q15 */
373 722 : move16();
374 722 : *oppRatioQ3 = shl( add( 1, shl( nearTail, 1 ) ), 14 ); /* Q3 */
375 722 : move16();
376 : }
377 : ELSE
378 : {
379 60704 : nearProjQ15_fx( shl( sub( 1 << 14, phiQ14q ), 1 ), oppQ15 );
380 60704 : nearProjQ15_fx( shl( phiQ14q, 1 ), nearQ15 );
381 60704 : Ratio_rQ3_fx( *oppQ15, *nearQ15, oppRatioQ3 );
382 : }
383 :
384 61426 : return;
385 : }
386 :
387 31540 : void densityAngle2RmsProjEnc_fx(
388 : const Word16 D, /* i : density Q0*/
389 : const Word16 phiQ14uq, /* i : angle Q14*/
390 : Word16 *indexphi, /* o : index Q0*/
391 : Word16 *oppQ15, /* o : opposite Q15*/
392 : Word16 *nearQ15, /* o : near Q15*/
393 : Word16 *oppRatioQ3 /* o : ratio Q3*/
394 : )
395 : {
396 31540 : *indexphi = mult_r( shl( D, 1 ), phiQ14uq ); /* Q0 */
397 31540 : move16();
398 31540 : if ( s_and( D, 1 ) > 0 )
399 : {
400 180 : *indexphi = -1; /* one op */
401 180 : move16();
402 : }
403 31540 : densityAngle2RmsProjDec_fx( D, *indexphi, oppQ15, nearQ15, oppRatioQ3 );
404 :
405 31540 : return;
406 : }
407 :
408 61426 : void NearOppSplitAdjustment_fx(
409 : const Word16 qband, /* i : quanta for current band Q0*/
410 : const Word16 qzero, /* i : range coder finalization quanta Q0*/
411 : const Word16 Qac, /* i : range coder current quanta Q0*/
412 : const UWord32 INTac, /* i : range coder state Q0*/
413 : const Word16 qglobal, /* i : quanta input Q0*/
414 : const Word16 FlagCons, /* i : conservative rounding flag Q0*/
415 : const Word16 Np, /* i : number of parts Q0*/
416 : const Word16 Nhead, /* i : first part Q0*/
417 : const Word16 Ntail, /* i : remaining parts Q0*/
418 : const Word16 Nnear, /* i : length of near component Q0*/
419 : const Word16 Nopp, /* i : length of opposite component Q0*/
420 : Word16 oppRQ3, /* i : ratio Q0*/
421 : Word16 *qnear, /* o : quantized near Q0*/
422 : Word16 *qopp, /* o : quantized opposite Q0*/
423 : Word16 *qglobalupd /* o : quanta remaining Q0*/
424 : )
425 : {
426 :
427 : Word16 qac, qboth, qskew, qavg, qmin, Midx;
428 : Word32 L_QIb, L_qnum;
429 : Word16 QIb, QIa;
430 : #ifndef ISSUE_1836_replace_overflow_libcom
431 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
432 : Flag Overflow = 0;
433 : move32();
434 : #endif
435 : #endif
436 :
437 61426 : rangeCoderFinalizationFBits_fx( Qac, INTac, &qac );
438 61426 : qboth = sub( qband, sub( qac, qzero ) ); /* Q0 */
439 : /* skew calc code */
440 61426 : qskew = 0;
441 61426 : move16();
442 61426 : IF( GT_16( Nhead, 1 ) )
443 : {
444 61426 : qavg = extract_h( L_shl( intLimCDivSigned_fx( L_deposit_l( qboth ), Np ), 16 ) ); /* qboth may be negative Q0*/
445 61426 : dsDiracPerQuanta_fx( Ntail, qavg, FlagCons, hBitsN, &Midx );
446 61426 : QuantaPerDsDirac_fx( Nhead, Midx, hBitsN, &qmin );
447 61426 : qskew = sub( qavg, qmin ); /* Q0 */
448 61426 : qskew = s_max( 0, qskew ); /* Q0 */
449 : } /* end of skew calc code*/
450 :
451 61426 : QIa = add( extract_l( intLimCDivPos_fx( (UWord32) L_deposit_l( Nopp ), Nnear ) ), 1 ); /* always positive Word16 out Q0*/
452 61426 : L_qnum = L_sub( L_deposit_l( sub( sub( add( qband, qzero ), qac ), qskew ) ), L_mult0( Nopp, oppRQ3 ) ); /* Q0 */
453 :
454 61426 : L_QIb = L_deposit_l( 0 );
455 61426 : IF( L_qnum > 0 )
456 : {
457 60456 : L_QIb = (Word32) intLimCDivPos_fx( L_qnum, QIa ); /* Q0 */
458 : }
459 61426 : *qnear = qboth; /* Q3 */
460 61426 : move16();
461 : #ifdef ISSUE_1836_replace_overflow_libcom
462 61426 : QIb = extract_h( L_shl_sat( L_QIb, 16 ) ); /* may saturate Q0*/
463 : #else
464 : QIb = extract_h( L_shl_o( L_QIb, 16, &Overflow ) ); /* may saturate Q0*/
465 : #endif
466 61426 : if ( LE_16( QIb, qboth ) )
467 : {
468 60569 : *qnear = QIb; /* Q0 */
469 60569 : move16();
470 : }
471 61426 : *qopp = sub( qboth, *qnear ); /* Q0 */
472 61426 : move16();
473 61426 : *qglobalupd = sub( qglobal, sub( qac, qzero ) ); /* Q0 */
474 61426 : move16();
475 :
476 61426 : return;
477 : }
478 :
479 :
480 : /*--------------------------------------------------------------------------*
481 : * apply_gain()
482 : *
483 : * Apply gain
484 : *--------------------------------------------------------------------------*/
485 :
486 57421 : void apply_gain_fx(
487 : const Word16 *ord, /* i : Indices for energy order Q0 */
488 : const Word16 *band_start, /* i : Sub band start indices Q0 */
489 : const Word16 *band_end, /* i : Sub band end indices Q0 */
490 : const Word16 num_sfm, /* i : Number of bands Q0 */
491 : const Word16 *gains, /* i : Band gain vector Qx */
492 : Word16 *xq /* i/o: Float synthesis / Gain adjusted synth Q15/Qx */
493 : )
494 : {
495 : Word16 band, i;
496 : Word16 g; /* Q12 */
497 :
498 891964 : FOR( band = 0; band < num_sfm; band++ )
499 : {
500 834543 : g = gains[ord[band]];
501 834543 : move16();
502 15381119 : FOR( i = band_start[band]; i < band_end[band]; i++ )
503 : {
504 : /*xq[i] *= g; */
505 14546576 : xq[i] = mult_r( g, xq[i] );
506 14546576 : move16(); /*12+15+1-16=12 */
507 : }
508 : }
509 :
510 57421 : return;
511 : }
512 :
513 : /*--------------------------------------------------------------------------*
514 : * fine_gain_quant_fx()
515 : *
516 : * Fine gain quantization
517 : *--------------------------------------------------------------------------*/
518 29388 : void fine_gain_quant_fx(
519 : BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
520 : const Word16 *ord, /* i : Indices for energy order Q0 */
521 : const Word16 num_sfm, /* i : Number of bands Q0 */
522 : const Word16 *gain_bits, /* i : Gain adjustment bits per sub band Q0 */
523 : Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */
524 : const Word16 *gopt /* i : Optimal gains Q12 */
525 : )
526 : {
527 : Word16 band;
528 : Word16 gbits;
529 : Word16 idx;
530 : Word16 gain_db, gain_dbq;
531 : Word16 err;
532 :
533 : Word16 tmp1, tmp2, exp1, exp2;
534 : Word32 L_tmp;
535 : UWord16 lsb;
536 : #ifndef ISSUE_1836_replace_overflow_libcom
537 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
538 : Flag Overflow = 0;
539 : move32();
540 : #endif
541 : #endif
542 :
543 463959 : FOR( band = 0; band < num_sfm; band++ )
544 : {
545 434571 : gbits = gain_bits[ord[band]]; /* Q0 */
546 434571 : move16();
547 434571 : test();
548 434571 : IF( fg_pred[band] != 0 && gbits > 0 )
549 : {
550 34472 : exp1 = norm_s( gopt[band] );
551 34472 : exp1 = sub( exp1, 1 );
552 34472 : tmp1 = shl( gopt[band], exp1 );
553 34472 : exp2 = norm_s( fg_pred[band] );
554 34472 : tmp2 = shl( fg_pred[band], exp2 ); /* Q12 + exp2 */
555 34472 : exp1 = add( 15, sub( exp1, exp2 ) );
556 34472 : err = div_s( tmp1, tmp2 ); /* Q15 */
557 34472 : tmp1 = norm_s( err );
558 34472 : exp2 = Log2_norm_lc( L_deposit_h( shl( err, tmp1 ) ) );
559 34472 : tmp1 = sub( 14, tmp1 );
560 34472 : tmp1 = sub( tmp1, exp1 );
561 34472 : L_tmp = L_Comp( tmp1, exp2 );
562 34472 : Mpy_32_16_ss( L_tmp, 24660, &L_tmp, &lsb ); /* 24660 = 20*log10(2) in Q12 */ /*16+12-15=13 */
563 : #ifdef ISSUE_1836_replace_overflow_libcom
564 34472 : gain_db = round_fx_sat( L_shl_sat( L_tmp, 17 ) );
565 : #else
566 : gain_db = round_fx_sat( L_shl_o( L_tmp, 17, &Overflow ) );
567 : #endif
568 :
569 34472 : idx = squant_fx( gain_db, &gain_dbq, finegain_fx[gbits - 1], gain_cb_size[gbits - 1] );
570 34472 : push_indice( hBstr, IND_PVQ_FINE_GAIN, idx, gbits );
571 :
572 34472 : L_tmp = L_mult0( gain_dbq, 21771 ); /* 21771=0.05*log2(10) */ /* 14+17=31 */
573 34472 : L_tmp = L_shr( L_tmp, 15 ); /* Q16 */
574 34472 : tmp1 = L_Extract_lc( L_tmp, &exp1 );
575 34472 : tmp1 = abs_s( tmp1 );
576 34472 : tmp1 = extract_l( Pow2( 14, tmp1 ) );
577 34472 : exp1 = sub( 14, exp1 );
578 :
579 34472 : L_tmp = L_mult0( fg_pred[band], tmp1 ); /*12+exp1 */
580 34472 : fg_pred[band] = round_fx_sat( L_shl_sat( L_tmp, sub( 16, exp1 ) ) ); /*12+exp1+16-exp1-16=12 */
581 34472 : move16();
582 : }
583 : }
584 :
585 29388 : return;
586 : }
587 :
588 : /*-------------------------------------------------------------------*
589 : * srt_vec_ind()
590 : *
591 : * sort vector and save sorting indeces
592 : *-------------------------------------------------------------------*/
593 :
594 601584 : void srt_vec_ind16_fx(
595 : const Word16 *linear, /* linear input Q3*/
596 : Word16 *srt, /* sorted output Q3*/
597 : Word16 *I, /* index for sorted output Q0*/
598 : Word16 length /* Q0 */
599 : )
600 : {
601 : Word16 pos, npos;
602 : Word16 idxMem;
603 : Word16 valMem;
604 :
605 : /*initilize */
606 1530010 : FOR( pos = 0; pos < length; pos++ )
607 : {
608 928426 : I[pos] = pos; /* Q0 */
609 928426 : move16();
610 : }
611 :
612 601584 : Copy( linear, srt, length ); /* Q3 */
613 :
614 : /* now iterate */
615 928426 : FOR( pos = 0; pos < ( length - 1 ); pos++ )
616 : {
617 1436577 : FOR( npos = ( pos + 1 ); npos < length; npos++ )
618 : {
619 1109735 : IF( LT_16( srt[npos], srt[pos] ) )
620 : {
621 517031 : idxMem = I[pos]; /* Q0 */
622 517031 : move16();
623 517031 : I[pos] = I[npos]; /* Q0 */
624 517031 : move16();
625 517031 : I[npos] = idxMem; /* Q0 */
626 517031 : move16();
627 :
628 517031 : valMem = srt[pos]; /* Q0 */
629 517031 : move16();
630 517031 : srt[pos] = srt[npos]; /* Q0 */
631 517031 : move16();
632 517031 : srt[npos] = valMem; /* Q0 */
633 517031 : move16();
634 : }
635 : }
636 : }
637 :
638 601584 : return;
639 : }
640 :
641 : /*-----------------------------------------------------------------------------
642 : * atan2_fx():
643 : *
644 : * Approximates arctan piecewise with various 4th to 5th order least square fit
645 : * polynomials for input in 5 segments:
646 : * - 0.0 to 1.0
647 : * - 1.0 to 2.0
648 : * - 2.0 to 4.0
649 : * - 4.0 to 8.0
650 : * - 8.0 to infinity
651 : *---------------------------------------------------------------------------*/
652 6908547 : Word16 atan2_fx( /* o: Angle between 0 and PI/2 radian (Q14) */
653 : const Word32 y, /* i : near side (Argument must be positive) (Q15) */
654 : const Word32 x /* i : opposite side (Q15) */
655 : )
656 : {
657 : Word32 acc, arg;
658 : Word16 man, expo, reciprocal;
659 : Word16 angle, w, z;
660 :
661 6908547 : IF( x == 0 )
662 : {
663 54788 : return 25736; /* PI/2 in Q14 */
664 : }
665 6853759 : man = ratio( y, x, &expo ); /* man in Q14 */
666 6853759 : expo = sub( expo, ( 15 - 14 ) ); /* Now, man is considered in Q15 */
667 6853759 : arg = L_shr( (Word32) man, expo );
668 :
669 6853759 : IF( L_shr( arg, 3 + 15 ) != 0 )
670 : /*===============================*
671 : * 8.0 <= x < infinity *
672 : *===============================*/
673 : {
674 : /* atan(x) = PI/2 - 1/x + 1/(3x^3) - 1/(5x^5) + ...
675 : * ~ PI/2 - 1/x, for x >= 8.
676 : */
677 403265 : expo = norm_l( arg );
678 403265 : man = extract_h( L_shl( arg, expo ) );
679 403265 : reciprocal = div_s( 0x3fff, man );
680 403265 : expo = sub( 15 + 1, expo );
681 403265 : reciprocal = shr( reciprocal, expo ); /* Q14 */
682 403265 : angle = sub( 25736, reciprocal ); /* Q14 (PI/2 - 1/x) */
683 :
684 : /* For 8.0 <= x < 10.0, 1/(5x^5) is not completely negligible.
685 : * For more accurate result, add very small correction term.
686 : */
687 403265 : if ( LT_32( L_shr( arg, 15 ), 10L ) )
688 : {
689 84732 : angle = add( angle, 8 ); /* Add tiny correction term. */
690 : }
691 : }
692 6450494 : ELSE IF( L_shr( arg, 2 + 15 ) != 0 )
693 : /*==========================*
694 : * 4.0 <= x < 8.0 *
695 : *==========================*/
696 : {
697 : /* interval: [3.999, 8.001]
698 : * atan(x) ~ (((a0*x + a1)*x + a2)*x + a3)*x + a4
699 : * = (((a0*8*y + a1)*8*y + a2)*8*y + a3)*8*y + a4 Substitute 8*y -> x
700 : * = (((a0*8^3*y + a1*8^2)*y + a2*8)*y + a3)*8*y + a4
701 : * = ((( c0*y + c1)*y + c2)*y + c3)*8*y + c4,
702 : * where y = x/8
703 : * and a0 = -1.28820869667651e-04, a1 = 3.88263533346295e-03,
704 : * a2 = -4.64216306484597e-02, a3 = 2.75986060068931e-01,
705 : * a4 = 7.49208077809799e-01.
706 : */
707 264681 : w = extract_l( L_shr( arg, 3 ) ); /* Q15 y = x/8 */
708 264681 : acc = L_add( 533625337L, 0 ); /* Q31 c1 = a1*8^2 */
709 264681 : z = mac_r( acc, w, -2161 ); /* Q15 c0 = a0*8^3 */
710 264681 : acc = L_add( -797517542L, 0 ); /* Q31 c2 = a2*8 */
711 264681 : z = mac_r( acc, w, z ); /* Q15 */
712 264681 : acc = L_add( 592675551L, 0 ); /* Q31 c3 = a3 */
713 264681 : z = mac_r( acc, w, z ); /* z (in:Q15, out:Q12) */
714 264681 : acc = L_add( 201114012L, 0 ); /* Q28 c4 = a4 */
715 264681 : acc = L_mac( acc, w, z ); /* Q28 */
716 264681 : angle = extract_l( L_shr( acc, ( 28 - 14 ) ) ); /* Q14 result of atan(x), where 4 <= x < 8 */
717 : }
718 6185813 : ELSE IF( L_shr( arg, 1 + 15 ) != 0 )
719 : /*==========================*
720 : * 2.0 <= x < 4.0 *
721 : *==========================*/
722 : {
723 : /* interval: [1.999, 4.001]
724 : * atan(x) ~ (((a0*x + a1)*x + a2)*x + a3)*x + a4
725 : * = (((a0*4*y + a1)*4*y + a2)*4*y + a3)*4*y + a4 Substitute 4*y -> x
726 : * = (((a0*16*y + a1*4)*y + a2)*4*y + a3)*4*y + a4
727 : * = (((a0*32*y + a1*8)*y + a2*2)*2*y + a3)*4*y + a4
728 : * = ((( c0*y + c1)*y + c2)*2*y + c3)*4*y + c4,
729 : * where y = x/4
730 : * and a0 = -0.00262378195660943, a1 = 0.04089687039888652,
731 : * a2 = -0.25631148958325911, a3 = 0.81685854627399479,
732 : * a4 = 0.21358070563097167
733 : * */
734 422123 : w = extract_l( L_shr( arg, 2 ) ); /* Q15 y = x/4 */
735 422123 : acc = L_add( 702602883L, 0 ); /* Q31 c1 = a1*8 */
736 422123 : z = mac_r( acc, w, -2751 ); /* Q15 c0 = a0*32 */
737 422123 : acc = L_add( -1100849465L, 0 ); /* Q31 c2 = a2*2 */
738 422123 : z = mac_r( acc, w, z ); /* z (in:Q15, out:Q14) */
739 422123 : acc = L_add( 877095185L, 0 ); /* Q30 c3 = a3 */
740 422123 : z = mac_r( acc, w, z ); /* z (in:Q14, out:Q12) */
741 422123 : acc = L_add( 57332634L, 0 ); /* Q28 c4 = a4 */
742 422123 : acc = L_mac( acc, w, z ); /* Q28 */
743 422123 : angle = extract_l( L_shr( acc, ( 28 - 14 ) ) ); /* Q14 result of atan(x) where 2 <= x < 4 */
744 : }
745 5763690 : ELSE IF( L_shr( arg, 15 ) != 0 )
746 : /*==========================*
747 : * 1.0 <= x < 2.0 *
748 : *==========================*/
749 : {
750 : /* interval: [0.999, 2.001]
751 : * atan(x) ~ (((a0*x + 1)*x + a2)*x + a3)*x + a4
752 : * = (((a0*2*y + a1)*2*y + a2)*2*y + a3)*2*y + a4 Substitute 2*y -> x
753 : * = (((a0*4*y + a1*2)*y + a2)*2*y + a3)*2*y + a4
754 : * = (((a0*4*y + a1*2)*y + a2)*y + a3/2)*4*y + a4
755 : * = ((( c0*y + c1)*y + c2)*y + c3)*4*y + c4,
756 : * where y = x/2
757 : * and a0 = -0.0160706457245251, a1 = 0.1527106504065224,
758 : * a2 = -0.6123208404800871, a3 = 1.3307896976322915,
759 : * a4 = -0.0697089375247448
760 : */
761 1078082 : w = extract_l( L_shr( arg, 1 ) ); /* Q15 y= x/2 */
762 1078082 : acc = L_add( 655887249L, 0 ); /* Q31 c1 = a1*2 */
763 1078082 : z = mac_r( acc, w, -2106 ); /* Q15 c0 = a0*4 */
764 1078082 : acc = L_add( -1314948992L, 0 ); /* Q31 c2 = a2 */
765 1078082 : z = mac_r( acc, w, z );
766 1078082 : acc = L_add( 1428924557L, 0 ); /* Q31 c3 = a3/2 */
767 1078082 : z = mac_r( acc, w, z ); /* z (in:Q15, out:Q13) */
768 1078082 : acc = L_add( -37424701L, 0 ); /* Q29 c4 = a4 */
769 1078082 : acc = L_mac( acc, w, z ); /* Q29 */
770 1078082 : angle = extract_l( L_shr( acc, ( 29 - 14 ) ) ); /* Q14 result of atan(x) where 1 <= x < 2 */
771 : }
772 : ELSE
773 : /*==========================*
774 : * 0.0 <= x < 1.0 *
775 : *==========================*/
776 : {
777 : /* interval: [-0.001, 1.001]
778 : * atan(x) ~ ((((a0*x + a1)*x + a2)*x + a3)*x + a4)*x + a5
779 : * = ((((a0*2*x + a1*2)*x/2 + a2)*x + a3)*x + a4)*x + a5
780 : * = (((( c0*x + c1)*x/2 + c2)*x + c3)*x + c4)*x + c5
781 : * where
782 : * a0 = -5.41182677118661e-02, a1 = 2.76690449232515e-01,
783 : * a2 = -4.63358392562492e-01, a3 = 2.87188466598566e-02,
784 : * a4 = 9.97438122814383e-01, a5 = 5.36158556179092e-05.
785 : */
786 4685608 : w = extract_l( arg ); /* Q15 */
787 4685608 : acc = L_add( 1188376431L, 0 ); /* Q31 c1 = a1*2 */
788 4685608 : z = mac_r( acc, w, -3547 ); /* Q15 c0 = a0*2 */
789 4685608 : acc = L_add( -995054571L, 0 ); /* Q31 c2 = a2 */
790 4685608 : z = extract_h( L_mac0( acc, w, z ) ); /* Q15 non-fractional mode multiply */
791 4685608 : acc = L_add( 61673254L, 0 ); /* Q31 c3 = a3 */
792 4685608 : z = mac_r( acc, w, z );
793 4685608 : acc = L_add( 2141982059L, 0 ); /* Q31 c4 = a4 */
794 4685608 : z = mac_r( acc, w, z );
795 4685608 : acc = L_add( 115139L, 0 ); /* Q31 c5 = a5 */
796 4685608 : acc = L_mac( acc, w, z ); /* Q31 */
797 4685608 : angle = extract_l( L_shr( acc, 31 - 14 ) ); /* Q14 result of atan(x), where 0 <= x < 1 */
798 : }
799 :
800 6853759 : return angle; /* Q14 between 0 and PI/2 radian. */
801 : }
|