[xiph-cvs] cvs commit: vorbis/lib lookup.c lsp.c os.h vorbisfile.c

Monty xiphmont at xiph.org
Thu Oct 19 03:21:06 PDT 2000



xiphmont    00/10/19 03:21:06

  Modified:    lib      Tag: branch_beta3 lookup.c lsp.c os.h vorbisfile.c
  Log:
  cast/rounding asm for vorbisfile float->int and lsp lookups

Revision  Changes    Path
No                   revision

No                   revision

1.2.2.1   +8 -6      vorbis/lib/lookup.c

Index: lookup.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/lookup.c,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- lookup.c	2000/10/12 03:12:53	1.2
+++ lookup.c	2000/10/19 10:21:02	1.2.2.1
@@ -12,27 +12,29 @@
  ********************************************************************
 
   function: lookup based functions
-  last mod: $Id: lookup.c,v 1.2 2000/10/12 03:12:53 xiphmont Exp $
+  last mod: $Id: lookup.c,v 1.2.2.1 2000/10/19 10:21:02 xiphmont Exp $
 
  ********************************************************************/
 
 #include <math.h>
 #include "lookup.h"
 #include "lookup_data.h"
+#include "os.h"
 
 #ifdef FLOAT_LOOKUP
 
 /* interpolated lookup based cos function, domain 0 to PI only */
 float vorbis_coslook(float a){
-  float d=a*(.31830989*(float)COS_LOOKUP_SZ);
-  int i=d;
+  double d=a*(.31830989*(float)COS_LOOKUP_SZ);
+  int i=vorbis_ftoi(d-.5);
+
   return COS_LOOKUP[i]+ (d-i)*(COS_LOOKUP[i+1]-COS_LOOKUP[i]);
 }
 
 /* interpolated 1./sqrt(p) where .5 <= p < 1. */
 float vorbis_invsqlook(float a){
-  float d=a*(2.*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
-  int i=d;
+  double d=a*(2.*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
+  int i=vorbis_ftoi(d-.5);
   return INVSQ_LOOKUP[i]+ (d-i)*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]);
 }
 
@@ -44,7 +46,7 @@
 #include <stdio.h>
 /* interpolated lookup based fromdB function, domain -140dB to 0dB only */
 float vorbis_fromdBlook(float a){
-  int i=a*((float)(-(1<<FROMdB2_SHIFT)));
+  int i=vorbis_ftoi(a*((float)(-(1<<FROMdB2_SHIFT)))-5.);
   return (i<0)?1.:
     ((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.:
      FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);

1.10.2.1  +5 -1      vorbis/lib/lsp.c

Index: lsp.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/lsp.c,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -u -r1.10 -r1.10.2.1
--- lsp.c	2000/10/12 03:12:53	1.10
+++ lsp.c	2000/10/19 10:21:02	1.10.2.1
@@ -12,7 +12,7 @@
  ********************************************************************
 
   function: LSP (also called LSF) conversion routines
-  last mod: $Id: lsp.c,v 1.10 2000/10/12 03:12:53 xiphmont Exp $
+  last mod: $Id: lsp.c,v 1.10.2.1 2000/10/19 10:21:02 xiphmont Exp $
 
   The LSP generation code is taken (with minimal modification) from
   "On the Computation of the LSP Frequencies" by Joseph Rothweiler
@@ -65,6 +65,9 @@
                             float amp,float ampoffset){
   int i;
   float wdel=M_PI/ln;
+  vorbis_fpu_control fpu;
+  
+  vorbis_fpu_setround(&fpu);
   for(i=0;i<m;i++)lsp[i]=vorbis_coslook(lsp[i]);
 
   i=0;
@@ -87,6 +90,7 @@
     curve[i++]=q;
     while(map[i]==k)curve[i++]=q;
   }
+  vorbis_fpu_restore(fpu);
 }
 
 #else

1.10.2.1  +56 -1     vorbis/lib/os.h

Index: os.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/os.h,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -u -r1.10 -r1.10.2.1
--- os.h	2000/10/12 03:12:53	1.10
+++ os.h	2000/10/19 10:21:02	1.10.2.1
@@ -14,11 +14,13 @@
  ********************************************************************
 
  function: #ifdef jail to whip a few platforms into the UNIX ideal.
- last mod: $Id: os.h,v 1.10 2000/10/12 03:12:53 xiphmont Exp $
+ last mod: $Id: os.h,v 1.10.2.1 2000/10/19 10:21:02 xiphmont Exp $
 
  ********************************************************************/
 
 #include <math.h>
+#include <ogg/os_types.h>
+
 #ifndef _V_IFDEFJAIL_H_
 #define _V_IFDEFJAIL_H_
 
@@ -55,6 +57,59 @@
 
 #ifndef max
 #  define max(x,y)  ((x)<(y)?(y):(x))
+#endif
+
+
+#if defined(__i386__) && defined(__GNUC__)
+
+/* both GCC and MSVC are kinda stupid about rounding/casting to int.
+   Because of encapsulation constraints (GCC can't see inside the asm
+   block and so we end up doing stupid things like a store/load that
+   is collectively a noop), we do it this way */
+
+/* we must set up the fpu before this works!! */
+
+typedef ogg_int16_t vorbis_fpu_control;
+
+static inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
+  ogg_int16_t ret;
+  ogg_int16_t temp;
+  __asm__ __volatile__("fnstcw %0\n\t"
+	  "movw %0,%%dx\n\t"
+	  "orw $62463,%%dx\n\t"
+	  "movw %%dx,%1\n\t"
+	  "fldcw %1\n\t":"=m"(ret):"m"(temp): "dx");
+  *fpu=ret;
+}
+
+static inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
+  __asm__ __volatile__("fldcw %0":: "m"(fpu));
+}
+
+/* assumes the FPU is in round mode! */
+static inline int vorbis_ftoi(double f){  /* yes, double!  Otherwise,
+                                             we get extra fst/fld to
+                                             truncate precision */
+  int i;
+  __asm__("fistl %0": "=m"(i) : "t"(f));
+  return(i);
+}
+
+#else
+
+static int vorbis_ftoi(double f){
+  return (int)(f+.5);
+}
+
+
+typedef vorbis_fpu_control int;
+
+static inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
+}
+
+static inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
+}
+
 #endif
 
 #endif /* _OS_H */

1.30.2.2  +23 -6     vorbis/lib/vorbisfile.c

Index: vorbisfile.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/vorbisfile.c,v
retrieving revision 1.30.2.1
retrieving revision 1.30.2.2
diff -u -r1.30.2.1 -r1.30.2.2
--- vorbisfile.c	2000/10/14 03:14:07	1.30.2.1
+++ vorbisfile.c	2000/10/19 10:21:02	1.30.2.2
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.30.2.1 2000/10/14 03:14:07 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.30.2.2 2000/10/19 10:21:02 xiphmont Exp $
 
  ********************************************************************/
 
@@ -1130,6 +1130,7 @@
 
         long channels=ov_info(vf,-1)->channels;
         long bytespersample=word * channels;
+	vorbis_fpu_control fpu;
         if(samples>length/bytespersample)samples=length/bytespersample;
         
         /* a tight loop to pack each size */
@@ -1137,63 +1138,79 @@
           int val;
           if(word==1){
             int off=(sgned?0:128);
+	    vorbis_fpu_setround(&fpu);
             for(j=0;j<samples;j++)
               for(i=0;i<channels;i++){
-		val=(int)(pcm[i][j]*128. + 0.5);
+		val=vorbis_ftoi(pcm[i][j]*128.);
                 if(val>127)val=127;
                 else if(val<-128)val=-128;
                 *buffer++=val+off;
               }
+	    vorbis_fpu_restore(fpu);
           }else{
             int off=(sgned?0:32768);
 
             if(host_endian==bigendianp){
               if(sgned){
+
+		vorbis_fpu_setround(&fpu);
                 for(i=0;i<channels;i++) { /* It's faster in this order */
                   float *src=pcm[i];
                   short *dest=((short *)buffer)+i;
                   for(j=0;j<samples;j++) {
-		    val=(int)(src[j]*32768. + 0.5);
+		    val=vorbis_ftoi(src[j]*32768.);
                     if(val>32767)val=32767;
                     else if(val<-32768)val=-32768;
                     *dest=val;
                     dest+=channels;
                   }
                 }
+		vorbis_fpu_restore(fpu);
+
               }else{
+
+		vorbis_fpu_setround(&fpu);
                 for(i=0;i<channels;i++) {
                   float *src=pcm[i];
                   short *dest=((short *)buffer)+i;
                   for(j=0;j<samples;j++) {
-		    val=(int)(src[j]*32768. + 0.5);
+		    val=vorbis_ftoi(src[j]*32768.);
                     if(val>32767)val=32767;
                     else if(val<-32768)val=-32768;
                     *dest=val+off;
                     dest+=channels;
                   }
                 }
+		vorbis_fpu_restore(fpu);
+
               }
             }else if(bigendianp){
+
+	      vorbis_fpu_setround(&fpu);
               for(j=0;j<samples;j++)
                 for(i=0;i<channels;i++){
-		  val=(int)(pcm[i][j]*32768. + 0.5);
+		  val=vorbis_ftoi(pcm[i][j]*32768.);
                   if(val>32767)val=32767;
                   else if(val<-32768)val=-32768;
                   val+=off;
                   *buffer++=(val>>8);
                   *buffer++=(val&0xff);
                 }
+	      vorbis_fpu_restore(fpu);
+
             }else{
               int val;
+	      vorbis_fpu_setround(&fpu);
               for(j=0;j<samples;j++)
                  for(i=0;i<channels;i++){
-		  val=(int)(pcm[i][j]*32768. + 0.5);
+		  val=vorbis_ftoi(pcm[i][j]*32768.);
                   if(val>32767)val=32767;
                   else if(val<-32768)val=-32768;
                   val+=off;
                   *buffer++=(val&0xff);
                   *buffer++=(val>>8);
                   }
+	      vorbis_fpu_restore(fpu);  
 
             }
           }

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list