[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