shithub: opus

Download patch

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 */