diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000000000000000000000000000000000000..13461770f883e16ae184856666f068710b2072e4 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,44 @@ +dnl @synopsis AC_C99_FUNC_LRINTF +dnl +dnl Check whether C99's lrintf function is available. +dnl @version 1.1 +dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com> +dnl +dnl Permission to use, copy, modify, distribute, and sell this file for any +dnl purpose is hereby granted without fee, provided that the above copyright +dnl and this permission notice appear in all copies. No representations are +dnl made about the suitability of this software for any purpose. It is +dnl provided "as is" without express or implied warranty. +dnl +AC_DEFUN([AC_C99_FUNC_LRINTF], +[AC_CACHE_CHECK(for lrintf, + ac_cv_c99_lrintf, +[AC_TRY_COMPILE([ +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 +#define __USE_ISOC99 1 +#define __USE_ISOC9X 1 +#include <math.h>], +[ int value = lrintf (0.432) ; ], ac_cv_c99_lrintf=yes, ac_cv_c99_lrintf=no)]) +if test $ac_cv_c99_lrintf = yes; then + AC_DEFINE(HAVE_LRINTF, 1, + [Define if you have C99's lrintf function.]) +fi +])# AC_C99_LRINTF + +AC_DEFUN([AC_C99_FUNC_LRINT], +[AC_CACHE_CHECK(for lrint, + ac_cv_c99_lrint, +[AC_TRY_COMPILE([ +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 +#define __USE_ISOC99 1 +#define __USE_ISOC9X 1 +#include <math.h>], +[ int value = lrint (0.432) ; ], ac_cv_c99_lrint=yes, ac_cv_c99_lrint=no)]) +if test $ac_cv_c99_lrint = yes; then + AC_DEFINE(HAVE_LRINT, 1, + [Define if you have C99's lrint function.]) +fi +])# AC_C99_LRINT + diff --git a/configure.ac b/configure.ac index 330162db0e7efe7b9afa4d1c7d505c87c2d4e7bf..befb94f98ed6eb1b27a6463fdc5b0e3c12a6eba3 100644 --- a/configure.ac +++ b/configure.ac @@ -118,6 +118,9 @@ if test $ac_cv_c_compiler_gnu = yes ; then #CFLAGS="$CFLAGS -fvisibility=hidden -W -Wstrict-prototypes -Wmissing-prototypes -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wno-parentheses" fi +AC_C99_FUNC_LRINTF +AC_C99_FUNC_LRINT + AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) diff --git a/libcelt/celt.c b/libcelt/celt.c index d9124f94783e92fcc6d2acde1da8a1d8da56cfbb..b99bbf0380abec91baafe8ff67b1afd9f47188be 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -50,6 +50,7 @@ #include "rate.h" #include "stack_alloc.h" #include "mathops.h" +#include "float_cast.h" static const celt_word16_t preemph = QCONST16(0.8f,15); @@ -163,7 +164,7 @@ static inline celt_int16_t FLOAT2INT16(float x) x = x*32768.; x = MAX32(x, -32768); x = MIN32(x, 32767); - return (celt_int16_t)floor(.5+x); + return (celt_int16_t)float2int(x); } static inline celt_word16_t SIG2WORD16(celt_sig_t x) @@ -598,31 +599,32 @@ int celt_encode_float(CELTEncoder * restrict st, celt_sig_t * restrict pcm, unsi /* Residual quantisation */ quant_bands(st->mode, X, P, NULL, bandE, stereo_mode, pulses, shortBlocks, &st->enc); - if (C==2) + if (st->pitch_enabled) { - renormalise_bands(st->mode, X); - } - /* Synthesis */ - denormalise_bands(st->mode, X, freq, bandE); - - - CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N)); - - compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem); - /* De-emphasis and put everything back at the right place in the synthesis history */ + if (C==2) + renormalise_bands(st->mode, X); + /* Synthesis */ + denormalise_bands(st->mode, X, freq, bandE); + + + CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N)); + + compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem); + /* De-emphasis and put everything back at the right place in the synthesis history */ #ifndef SHORTCUTS - for (c=0;c<C;c++) - { - int j; - for (j=0;j<N;j++) + for (c=0;c<C;c++) { - celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c], - MULT16_32_Q15(preemph,st->preemph_memD[c])); - st->preemph_memD[c] = tmp; - pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp)); + int j; + for (j=0;j<N;j++) + { + celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c], + MULT16_32_Q15(preemph,st->preemph_memD[c])); + st->preemph_memD[c] = tmp; + pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp)); + } } - } #endif + } /*if (ec_enc_tell(&st->enc, 0) < nbCompressedBytes*8 - 7) celt_warning_int ("many unused bits: ", nbCompressedBytes*8-ec_enc_tell(&st->enc, 0));*/ /*printf ("%d\n", ec_enc_tell(&st->enc, 0)-8*nbCompressedBytes);*/ diff --git a/libcelt/float_cast.h b/libcelt/float_cast.h new file mode 100644 index 0000000000000000000000000000000000000000..9e74c69aebd4ec284e5fa1bb0804d3ce2f478e95 --- /dev/null +++ b/libcelt/float_cast.h @@ -0,0 +1,107 @@ +/* +** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> +** +** Permission to use, copy, modify, distribute, and sell this file for any +** purpose is hereby granted without fee, provided that the above copyright +** and this permission notice appear in all copies. No representations are +** made about the suitability of this software for any purpose. It is +** provided "as is" without express or implied warranty. +*/ + +/* Version 1.1 */ + +#ifndef FLOAT_CAST_H +#define FLOAT_CAST_H + +/*============================================================================ +** On Intel Pentium processors (especially PIII and probably P4), converting +** from float to int is very slow. To meet the C specs, the code produced by +** most C compilers targeting Pentium needs to change the FPU rounding mode +** before the float to int conversion is performed. +** +** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It +** is this flushing of the pipeline which is so slow. +** +** Fortunately the ISO C99 specifications define the functions lrint, lrintf, +** llrint and llrintf which fix this problem as a side effect. +** +** On Unix-like systems, the configure process should have detected the +** presence of these functions. If they weren't found we have to replace them +** here with a standard C cast. +*/ + +/* +** The C99 prototypes for lrint and lrintf are as follows: +** +** long int lrintf (float x) ; +** long int lrint (double x) ; +*/ + +/* The presence of the required functions are detected during the configure +** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in +** the config.h file. +*/ + +#if (HAVE_LRINTF) +/*#if 0*/ + + /* These defines enable functionality introduced with the 1999 ISO C + ** standard. They must be defined before the inclusion of math.h to + ** engage them. If optimisation is enabled, these functions will be + ** inlined. With optimisation switched off, you have to link in the + ** maths library using -lm. + */ + + #define _ISOC9X_SOURCE 1 + #define _ISOC99_SOURCE 1 + + #define __USE_ISOC9X 1 + #define __USE_ISOC99 1 + + #include <math.h> + #define float2int(x) lrintf(x) + +#elif (defined(HAVE_LRINT)) + +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 + +#define __USE_ISOC9X 1 +#define __USE_ISOC99 1 + +#include <math.h> +#define float2int(x) lrint(x) + +#elif (defined (WIN32) || defined (_WIN32)) + + #include <math.h> + + /* Win32 doesn't seem to have these functions. + ** Therefore implement inline versions of these functions here. + */ + + __inline long int + float2int (float flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + +#else + + #warning "Don't have the functions lrint() and lrintf ()." + #warning "Replacing these functions with a standard C cast." + + #include <math.h> + + #define float2int(flt) ((int)(floor(.5+flt))) + +#endif + + +#endif /* FLOAT_CAST_H */