ref: d9b9565a4b799591d7dcd2b8b31f5ed7cc0eec04
parent: 58b3727fcf38747dc37604da06f22badeda49e89
author: Jean-Marc Valin <[email protected]>
date: Sun Aug 31 19:34:47 EDT 2008
Added Erik de Castro Lopo's float_cast.h to use lrintf() when available. Also disables the synthesis on the encoder side when pitch is disabled.
--- /dev/null
+++ b/acinclude.m4
@@ -1,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
+
--- a/configure.ac
+++ b/configure.ac
@@ -118,6 +118,9 @@
#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)
--- 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 @@
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 @@
/* 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);*/
--- /dev/null
+++ b/libcelt/float_cast.h
@@ -1,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 */