diff options
author | Andrew Mahone <andrew.mahone@gmail.com> | 2009-12-13 03:45:40 +0000 |
---|---|---|
committer | Andrew Mahone <andrew.mahone@gmail.com> | 2009-12-13 03:45:40 +0000 |
commit | af5bad46d883731728b9e4c797cae015e17f11f3 (patch) | |
tree | 21a6fd00a8c1c90dcb1501b27d8253ccea162e7c /apps/codecs/libfaad | |
parent | 7668e3fe51ed0d2bb00ba5580b45e289ae0e836b (diff) | |
download | rockbox-af5bad46d883731728b9e4c797cae015e17f11f3.tar.gz rockbox-af5bad46d883731728b9e4c797cae015e17f11f3.zip |
Libfaad pow2/log2 improvements:
Correct pow2_* to calculate correct output for input < 0.0 or between 0.0 and 1.0 instead of returning 0. This will change output, but the float version of this codec uses pow(2.0,x) in place of these functions, so this behavior was probably a bug
Replace 64-bit multiply in pow2_* with left or right shift by whole part of input, rounding if shifting right. An ARM-specific optimized version is provided as a C inline function, other targets use a C macro.
Increase constant size of table for pow2 to improve accuracy, also avoid early truncation in linear interpolation of result.
Move constant tables for pow2 and log2 to iram.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23967 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libfaad')
-rw-r--r-- | apps/codecs/libfaad/common.c | 140 | ||||
-rw-r--r-- | apps/codecs/libfaad/common.h | 4 | ||||
-rw-r--r-- | apps/codecs/libfaad/fixed.h | 25 |
3 files changed, 105 insertions, 64 deletions
diff --git a/apps/codecs/libfaad/common.c b/apps/codecs/libfaad/common.c index e8340d318d..025c8f8c5b 100644 --- a/apps/codecs/libfaad/common.c +++ b/apps/codecs/libfaad/common.c | |||
@@ -248,33 +248,78 @@ uint32_t random_int(void) | |||
248 | #define TABLE_BITS 6 | 248 | #define TABLE_BITS 6 |
249 | /* just take the maximum number of bits for interpolation */ | 249 | /* just take the maximum number of bits for interpolation */ |
250 | #define INTERP_BITS (REAL_BITS-TABLE_BITS) | 250 | #define INTERP_BITS (REAL_BITS-TABLE_BITS) |
251 | 251 | /* precision of values in pow2_tab */ | |
252 | static const real_t pow2_tab[] = { | 252 | #define POWTBL_BITS (31-(INTERP_BITS)) |
253 | REAL_CONST(1.000000000000000), REAL_CONST(1.010889286051701), REAL_CONST(1.021897148654117), | 253 | #define POWTBL_PRECIS (1U<<(POWTBL_BITS)) |
254 | REAL_CONST(1.033024879021228), REAL_CONST(1.044273782427414), REAL_CONST(1.055645178360557), | 254 | static const uint32_t pow2_tab[] ICONST_ATTR = { |
255 | REAL_CONST(1.067140400676824), REAL_CONST(1.078760797757120), REAL_CONST(1.090507732665258), | 255 | UFIX_CONST(1.000000000000000,POWTBL_PRECIS), |
256 | REAL_CONST(1.102382583307841), REAL_CONST(1.114386742595892), REAL_CONST(1.126521618608242), | 256 | UFIX_CONST(1.010889286051701,POWTBL_PRECIS), |
257 | REAL_CONST(1.138788634756692), REAL_CONST(1.151189229952983), REAL_CONST(1.163724858777578), | 257 | UFIX_CONST(1.021897148654117,POWTBL_PRECIS), |
258 | REAL_CONST(1.176396991650281), REAL_CONST(1.189207115002721), REAL_CONST(1.202156731452703), | 258 | UFIX_CONST(1.033024879021228,POWTBL_PRECIS), |
259 | REAL_CONST(1.215247359980469), REAL_CONST(1.228480536106870), REAL_CONST(1.241857812073484), | 259 | UFIX_CONST(1.044273782427414,POWTBL_PRECIS), |
260 | REAL_CONST(1.255380757024691), REAL_CONST(1.269050957191733), REAL_CONST(1.282870016078778), | 260 | UFIX_CONST(1.055645178360557,POWTBL_PRECIS), |
261 | REAL_CONST(1.296839554651010), REAL_CONST(1.310961211524764), REAL_CONST(1.325236643159741), | 261 | UFIX_CONST(1.067140400676824,POWTBL_PRECIS), |
262 | REAL_CONST(1.339667524053303), REAL_CONST(1.354255546936893), REAL_CONST(1.369002422974591), | 262 | UFIX_CONST(1.078760797757120,POWTBL_PRECIS), |
263 | REAL_CONST(1.383909881963832), REAL_CONST(1.398979672538311), REAL_CONST(1.414213562373095), | 263 | UFIX_CONST(1.090507732665258,POWTBL_PRECIS), |
264 | REAL_CONST(1.429613338391970), REAL_CONST(1.445180806977047), REAL_CONST(1.460917794180647), | 264 | UFIX_CONST(1.102382583307841,POWTBL_PRECIS), |
265 | REAL_CONST(1.476826145939499), REAL_CONST(1.492907728291265), REAL_CONST(1.509164427593423), | 265 | UFIX_CONST(1.114386742595892,POWTBL_PRECIS), |
266 | REAL_CONST(1.525598150744538), REAL_CONST(1.542210825407941), REAL_CONST(1.559004400237837), | 266 | UFIX_CONST(1.126521618608242,POWTBL_PRECIS), |
267 | REAL_CONST(1.575980845107887), REAL_CONST(1.593142151342267), REAL_CONST(1.610490331949254), | 267 | UFIX_CONST(1.138788634756692,POWTBL_PRECIS), |
268 | REAL_CONST(1.628027421857348), REAL_CONST(1.645755478153965), REAL_CONST(1.663676580326736), | 268 | UFIX_CONST(1.151189229952983,POWTBL_PRECIS), |
269 | REAL_CONST(1.681792830507429), REAL_CONST(1.700106353718524), REAL_CONST(1.718619298122478), | 269 | UFIX_CONST(1.163724858777578,POWTBL_PRECIS), |
270 | REAL_CONST(1.737333835273706), REAL_CONST(1.756252160373300), REAL_CONST(1.775376492526521), | 270 | UFIX_CONST(1.176396991650281,POWTBL_PRECIS), |
271 | REAL_CONST(1.794709075003107), REAL_CONST(1.814252175500399), REAL_CONST(1.834008086409342), | 271 | UFIX_CONST(1.189207115002721,POWTBL_PRECIS), |
272 | REAL_CONST(1.853979125083386), REAL_CONST(1.874167634110300), REAL_CONST(1.894575981586966), | 272 | UFIX_CONST(1.202156731452703,POWTBL_PRECIS), |
273 | REAL_CONST(1.915206561397147), REAL_CONST(1.936061793492294), REAL_CONST(1.957144124175400), | 273 | UFIX_CONST(1.215247359980469,POWTBL_PRECIS), |
274 | REAL_CONST(1.978456026387951), REAL_CONST(2.000000000000000) | 274 | UFIX_CONST(1.228480536106870,POWTBL_PRECIS), |
275 | UFIX_CONST(1.241857812073484,POWTBL_PRECIS), | ||
276 | UFIX_CONST(1.255380757024691,POWTBL_PRECIS), | ||
277 | UFIX_CONST(1.269050957191733,POWTBL_PRECIS), | ||
278 | UFIX_CONST(1.282870016078778,POWTBL_PRECIS), | ||
279 | UFIX_CONST(1.296839554651010,POWTBL_PRECIS), | ||
280 | UFIX_CONST(1.310961211524764,POWTBL_PRECIS), | ||
281 | UFIX_CONST(1.325236643159741,POWTBL_PRECIS), | ||
282 | UFIX_CONST(1.339667524053303,POWTBL_PRECIS), | ||
283 | UFIX_CONST(1.354255546936893,POWTBL_PRECIS), | ||
284 | UFIX_CONST(1.369002422974591,POWTBL_PRECIS), | ||
285 | UFIX_CONST(1.383909881963832,POWTBL_PRECIS), | ||
286 | UFIX_CONST(1.398979672538311,POWTBL_PRECIS), | ||
287 | UFIX_CONST(1.414213562373095,POWTBL_PRECIS), | ||
288 | UFIX_CONST(1.429613338391970,POWTBL_PRECIS), | ||
289 | UFIX_CONST(1.445180806977047,POWTBL_PRECIS), | ||
290 | UFIX_CONST(1.460917794180647,POWTBL_PRECIS), | ||
291 | UFIX_CONST(1.476826145939499,POWTBL_PRECIS), | ||
292 | UFIX_CONST(1.492907728291265,POWTBL_PRECIS), | ||
293 | UFIX_CONST(1.509164427593423,POWTBL_PRECIS), | ||
294 | UFIX_CONST(1.525598150744538,POWTBL_PRECIS), | ||
295 | UFIX_CONST(1.542210825407941,POWTBL_PRECIS), | ||
296 | UFIX_CONST(1.559004400237837,POWTBL_PRECIS), | ||
297 | UFIX_CONST(1.575980845107887,POWTBL_PRECIS), | ||
298 | UFIX_CONST(1.593142151342267,POWTBL_PRECIS), | ||
299 | UFIX_CONST(1.610490331949254,POWTBL_PRECIS), | ||
300 | UFIX_CONST(1.628027421857348,POWTBL_PRECIS), | ||
301 | UFIX_CONST(1.645755478153965,POWTBL_PRECIS), | ||
302 | UFIX_CONST(1.663676580326736,POWTBL_PRECIS), | ||
303 | UFIX_CONST(1.681792830507429,POWTBL_PRECIS), | ||
304 | UFIX_CONST(1.700106353718524,POWTBL_PRECIS), | ||
305 | UFIX_CONST(1.718619298122478,POWTBL_PRECIS), | ||
306 | UFIX_CONST(1.737333835273706,POWTBL_PRECIS), | ||
307 | UFIX_CONST(1.756252160373300,POWTBL_PRECIS), | ||
308 | UFIX_CONST(1.775376492526521,POWTBL_PRECIS), | ||
309 | UFIX_CONST(1.794709075003107,POWTBL_PRECIS), | ||
310 | UFIX_CONST(1.814252175500399,POWTBL_PRECIS), | ||
311 | UFIX_CONST(1.834008086409342,POWTBL_PRECIS), | ||
312 | UFIX_CONST(1.853979125083386,POWTBL_PRECIS), | ||
313 | UFIX_CONST(1.874167634110300,POWTBL_PRECIS), | ||
314 | UFIX_CONST(1.894575981586966,POWTBL_PRECIS), | ||
315 | UFIX_CONST(1.915206561397147,POWTBL_PRECIS), | ||
316 | UFIX_CONST(1.936061793492294,POWTBL_PRECIS), | ||
317 | UFIX_CONST(1.957144124175400,POWTBL_PRECIS), | ||
318 | UFIX_CONST(1.978456026387951,POWTBL_PRECIS), | ||
319 | UFIX_CONST(2.000000000000000,POWTBL_PRECIS) | ||
275 | }; | 320 | }; |
276 | 321 | ||
277 | static const real_t log2_tab[] = { | 322 | static const real_t log2_tab[] ICONST_ATTR = { |
278 | REAL_CONST(0.000000000000000), REAL_CONST(0.022367813028455), REAL_CONST(0.044394119358453), | 323 | REAL_CONST(0.000000000000000), REAL_CONST(0.022367813028455), REAL_CONST(0.044394119358453), |
279 | REAL_CONST(0.066089190457772), REAL_CONST(0.087462841250339), REAL_CONST(0.108524456778169), | 324 | REAL_CONST(0.066089190457772), REAL_CONST(0.087462841250339), REAL_CONST(0.108524456778169), |
280 | REAL_CONST(0.129283016944966), REAL_CONST(0.149747119504682), REAL_CONST(0.169925001442312), | 325 | REAL_CONST(0.129283016944966), REAL_CONST(0.149747119504682), REAL_CONST(0.169925001442312), |
@@ -299,12 +344,12 @@ static const real_t log2_tab[] = { | |||
299 | REAL_CONST(0.988684686772166), REAL_CONST(1.000000000000000) | 344 | REAL_CONST(0.988684686772166), REAL_CONST(1.000000000000000) |
300 | }; | 345 | }; |
301 | 346 | ||
302 | real_t pow2_fix(real_t val) | 347 | uint32_t pow2_fix(real_t val) |
303 | { | 348 | { |
304 | uint32_t x1, x2; | 349 | uint32_t x1, x2; |
305 | uint32_t errcorr; | 350 | uint32_t errcorr; |
306 | uint32_t index_frac; | 351 | uint32_t index_frac; |
307 | real_t retval; | 352 | uint32_t retval; |
308 | int32_t whole = (val >> REAL_BITS); | 353 | int32_t whole = (val >> REAL_BITS); |
309 | 354 | ||
310 | /* rest = [0..1] */ | 355 | /* rest = [0..1] */ |
@@ -313,41 +358,27 @@ real_t pow2_fix(real_t val) | |||
313 | /* index into pow2_tab */ | 358 | /* index into pow2_tab */ |
314 | int32_t index = rest >> (REAL_BITS-TABLE_BITS); | 359 | int32_t index = rest >> (REAL_BITS-TABLE_BITS); |
315 | 360 | ||
316 | |||
317 | if (val == 0) | ||
318 | return (1<<REAL_BITS); | ||
319 | |||
320 | /* leave INTERP_BITS bits */ | 361 | /* leave INTERP_BITS bits */ |
321 | index_frac = rest >> (REAL_BITS-TABLE_BITS-INTERP_BITS); | 362 | index_frac = rest >> (REAL_BITS-TABLE_BITS-INTERP_BITS); |
322 | index_frac = index_frac & ((1<<INTERP_BITS)-1); | 363 | index_frac = index_frac & ((1<<INTERP_BITS)-1); |
323 | 364 | ||
324 | if (whole > 0) | ||
325 | { | ||
326 | retval = 1 << whole; | ||
327 | } else { | ||
328 | retval = REAL_CONST(1) >> -whole; | ||
329 | } | ||
330 | |||
331 | x1 = pow2_tab[index & ((1<<TABLE_BITS)-1)]; | 365 | x1 = pow2_tab[index & ((1<<TABLE_BITS)-1)]; |
332 | x2 = pow2_tab[(index & ((1<<TABLE_BITS)-1)) + 1]; | 366 | x2 = pow2_tab[(index & ((1<<TABLE_BITS)-1)) + 1]; |
333 | errcorr = ( (index_frac*(x2-x1))) >> INTERP_BITS; | 367 | errcorr = ( (index_frac*(x2-x1))); |
334 | 368 | ||
335 | if (whole > 0) | 369 | retval = errcorr + (x1<<INTERP_BITS); |
336 | { | 370 | |
337 | retval = retval * (errcorr + x1); | 371 | retval = DESCALE_SHIFT(retval, whole, POWTBL_BITS + INTERP_BITS - REAL_BITS); |
338 | } else { | ||
339 | retval = MUL_R(retval, (errcorr + x1)); | ||
340 | } | ||
341 | 372 | ||
342 | return retval; | 373 | return retval; |
343 | } | 374 | } |
344 | 375 | ||
345 | int32_t pow2_int(real_t val) | 376 | uint32_t pow2_int(real_t val) |
346 | { | 377 | { |
347 | uint32_t x1, x2; | 378 | uint32_t x1, x2; |
348 | uint32_t errcorr; | 379 | uint32_t errcorr; |
349 | uint32_t index_frac; | 380 | uint32_t index_frac; |
350 | real_t retval; | 381 | uint32_t retval; |
351 | int32_t whole = (val >> REAL_BITS); | 382 | int32_t whole = (val >> REAL_BITS); |
352 | 383 | ||
353 | /* rest = [0..1] */ | 384 | /* rest = [0..1] */ |
@@ -356,24 +387,17 @@ int32_t pow2_int(real_t val) | |||
356 | /* index into pow2_tab */ | 387 | /* index into pow2_tab */ |
357 | int32_t index = rest >> (REAL_BITS-TABLE_BITS); | 388 | int32_t index = rest >> (REAL_BITS-TABLE_BITS); |
358 | 389 | ||
359 | |||
360 | if (val == 0) | ||
361 | return 1; | ||
362 | |||
363 | /* leave INTERP_BITS bits */ | 390 | /* leave INTERP_BITS bits */ |
364 | index_frac = rest >> (REAL_BITS-TABLE_BITS-INTERP_BITS); | 391 | index_frac = rest >> (REAL_BITS-TABLE_BITS-INTERP_BITS); |
365 | index_frac = index_frac & ((1<<INTERP_BITS)-1); | 392 | index_frac = index_frac & ((1<<INTERP_BITS)-1); |
366 | 393 | ||
367 | if (whole > 0) | ||
368 | retval = 1 << whole; | ||
369 | else | ||
370 | retval = 0; | ||
371 | |||
372 | x1 = pow2_tab[index & ((1<<TABLE_BITS)-1)]; | 394 | x1 = pow2_tab[index & ((1<<TABLE_BITS)-1)]; |
373 | x2 = pow2_tab[(index & ((1<<TABLE_BITS)-1)) + 1]; | 395 | x2 = pow2_tab[(index & ((1<<TABLE_BITS)-1)) + 1]; |
374 | errcorr = ( (index_frac*(x2-x1))) >> INTERP_BITS; | 396 | errcorr = ( (index_frac*(x2-x1))); |
397 | |||
398 | retval = errcorr + (x1<<INTERP_BITS); | ||
375 | 399 | ||
376 | retval = MUL_R(retval, (errcorr + x1)); | 400 | retval = DESCALE_SHIFT(retval, whole, POWTBL_BITS + INTERP_BITS); |
377 | 401 | ||
378 | return retval; | 402 | return retval; |
379 | } | 403 | } |
diff --git a/apps/codecs/libfaad/common.h b/apps/codecs/libfaad/common.h index fe0d02b228..658e92f23f 100644 --- a/apps/codecs/libfaad/common.h +++ b/apps/codecs/libfaad/common.h | |||
@@ -404,8 +404,8 @@ uint32_t random_int(void); | |||
404 | #define LOG2_MIN_INF REAL_CONST(-10000) | 404 | #define LOG2_MIN_INF REAL_CONST(-10000) |
405 | int32_t log2_int(uint32_t val); | 405 | int32_t log2_int(uint32_t val); |
406 | int32_t log2_fix(uint32_t val); | 406 | int32_t log2_fix(uint32_t val); |
407 | int32_t pow2_int(real_t val); | 407 | uint32_t pow2_int(real_t val); |
408 | real_t pow2_fix(real_t val); | 408 | uint32_t pow2_fix(real_t val); |
409 | #endif | 409 | #endif |
410 | uint8_t get_sr_index(const uint32_t samplerate); | 410 | uint8_t get_sr_index(const uint32_t samplerate); |
411 | uint8_t max_pred_sfb(const uint8_t sr_index); | 411 | uint8_t max_pred_sfb(const uint8_t sr_index); |
diff --git a/apps/codecs/libfaad/fixed.h b/apps/codecs/libfaad/fixed.h index da895e81bc..9781a846f7 100644 --- a/apps/codecs/libfaad/fixed.h +++ b/apps/codecs/libfaad/fixed.h | |||
@@ -49,10 +49,11 @@ extern "C" { | |||
49 | 49 | ||
50 | typedef int32_t real_t; | 50 | typedef int32_t real_t; |
51 | 51 | ||
52 | 52 | #define UFIX_CONST(A,PRECISION) ((uint32_t)((A)*(PRECISION)+0.5)) | |
53 | #define REAL_CONST(A) (((A) >= 0) ? ((real_t)((A)*(REAL_PRECISION)+0.5)) : ((real_t)((A)*(REAL_PRECISION)-0.5))) | 53 | #define FIX_CONST(A,PRECISION) (((A) >= 0) ? ((real_t)((A)*(PRECISION)+0.5)) : ((real_t)((A)*(PRECISION)-0.5))) |
54 | #define COEF_CONST(A) (((A) >= 0) ? ((real_t)((A)*(COEF_PRECISION)+0.5)) : ((real_t)((A)*(COEF_PRECISION)-0.5))) | 54 | #define REAL_CONST(A) FIX_CONST((A),(REAL_PRECISION)) |
55 | #define FRAC_CONST(A) (((A) == 1.00) ? ((real_t)FRAC_MAX) : (((A) >= 0) ? ((real_t)((A)*(FRAC_PRECISION)+0.5)) : ((real_t)((A)*(FRAC_PRECISION)-0.5)))) | 55 | #define COEF_CONST(A) FIX_CONST((A),(COEF_PRECISION)) |
56 | #define FRAC_CONST(A) (((A) == 1.00) ? ((real_t)FRAC_MAX) : FIX_CONST((A),(FRAC_PRECISION))) | ||
56 | //#define FRAC_CONST(A) (((A) >= 0) ? ((real_t)((A)*(FRAC_PRECISION)+0.5)) : ((real_t)((A)*(FRAC_PRECISION)-0.5))) | 57 | //#define FRAC_CONST(A) (((A) >= 0) ? ((real_t)((A)*(FRAC_PRECISION)+0.5)) : ((real_t)((A)*(FRAC_PRECISION)-0.5))) |
57 | 58 | ||
58 | #define Q2_BITS 22 | 59 | #define Q2_BITS 22 |
@@ -128,6 +129,8 @@ static INLINE void ComplexMult(real_t *y1, real_t *y2, | |||
128 | #define MUL_Q2(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (Q2_BITS-1))) >> Q2_BITS) | 129 | #define MUL_Q2(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (Q2_BITS-1))) >> Q2_BITS) |
129 | #define MUL_SHIFT6(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (6-1))) >> 6) | 130 | #define MUL_SHIFT6(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (6-1))) >> 6) |
130 | #define MUL_SHIFT23(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (23-1))) >> 23) | 131 | #define MUL_SHIFT23(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (23-1))) >> 23) |
132 | #define DESCALE(A,S) ((S)>0?(((A)>>((S)-1))+1)>>1:(A)<<-(S)) | ||
133 | #define DESCALE_SHIFT(A,SH,SC) DESCALE((A),(SC)-(SH) | ||
131 | 134 | ||
132 | #elif defined(__GNUC__) && defined (__arm__) | 135 | #elif defined(__GNUC__) && defined (__arm__) |
133 | 136 | ||
@@ -205,6 +208,18 @@ static INLINE void ComplexMult(real_t *y1, real_t *y2, | |||
205 | *y2 = yt2 << (FRAC_SIZE-FRAC_BITS); | 208 | *y2 = yt2 << (FRAC_SIZE-FRAC_BITS); |
206 | } | 209 | } |
207 | 210 | ||
211 | static inline real_t DESCALE_SHIFT(unsigned val, int shift, int scale) | ||
212 | { | ||
213 | unsigned out; | ||
214 | if ((out = val >> (scale - shift - 1))) | ||
215 | { | ||
216 | out++; | ||
217 | out >>= 1; | ||
218 | } else | ||
219 | out = val << (shift - scale); | ||
220 | return out; | ||
221 | } | ||
222 | |||
208 | #else | 223 | #else |
209 | 224 | ||
210 | /* multiply with real shift */ | 225 | /* multiply with real shift */ |
@@ -225,6 +240,8 @@ static INLINE void ComplexMult(real_t *y1, real_t *y2, | |||
225 | #define MUL_Q2(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (Q2_BITS-1))) >> Q2_BITS) | 240 | #define MUL_Q2(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (Q2_BITS-1))) >> Q2_BITS) |
226 | #define MUL_SHIFT6(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (6-1))) >> 6) | 241 | #define MUL_SHIFT6(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (6-1))) >> 6) |
227 | #define MUL_SHIFT23(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (23-1))) >> 23) | 242 | #define MUL_SHIFT23(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (23-1))) >> 23) |
243 | #define DESCALE(A,S) ((S)>0?(((A)>>((S)-1))+1)>>1:(A)<<-(S)) | ||
244 | #define DESCALE_SHIFT(A,SH,SC) DESCALE((A),(SC)-(SH) | ||
228 | 245 | ||
229 | /* Complex multiplication */ | 246 | /* Complex multiplication */ |
230 | static INLINE void ComplexMult(real_t *y1, real_t *y2, | 247 | static INLINE void ComplexMult(real_t *y1, real_t *y2, |