shithub: sox

Download patch

ref: 76caa137725af8725d869657b9c91f7a1523ea0e
parent: cd6f068af3d62ce561a146571439bfdd844ed922
author: cbagwell <cbagwell>
date: Tue Dec 7 11:57:37 EST 1999

Various updates.

--- a/libst.c
+++ b/libst.c
@@ -36,22 +36,22 @@
 short sample;
     {
     static const unsigned char exp_lut[256] = 
-			      {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
-                               4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-                               5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-                               5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
+        {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+         4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+         5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+         5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+         6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+         6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+         6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+         6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
     int sign, exponent, mantissa;
     unsigned char ulawbyte;
 
@@ -61,8 +61,8 @@
     if ( sample > uCLIP ) sample = uCLIP;		/* clip the magnitude */
 
     /* Convert from 16 bit linear to ulaw. */
-    sample = sample + uBIAS;
-    exponent = exp_lut[( sample >> 7 ) & 0xFF];
+    sample += uBIAS;
+    exponent = exp_lut[sample >> 7]; /* no need to mask because uCLIP>=sample>=0 */
     mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
     ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
 #ifdef ZEROTRAP
@@ -92,7 +92,7 @@
 st_ulaw_to_linear( ulawbyte )
 unsigned char ulawbyte;
     {
-    static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
+    static const int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
     int sign, exponent, mantissa, sample;
 
     ulawbyte = ~ ulawbyte;
--- a/libst.h
+++ b/libst.h
@@ -22,10 +22,10 @@
 extern int           ulaw_exp_table[256];
 extern const unsigned char ulaw_comp_table[16384];
 #define st_ulaw_to_linear(ulawbyte)   ulaw_exp_table[ulawbyte]
-#define st_linear_to_ulaw(linearword) ulaw_comp_table[((short)linearword / 4) & 0x3fff]
+#define st_linear_to_ulaw(linearword) ulaw_comp_table[(unsigned short)linearword >> 2]
 #else
-unsigned char st_linear_to_ulaw(P1(short));
-int           st_ulaw_to_linear(P1(unsigned char));
+unsigned char st_linear_to_ulaw(P1(short))REGPARM(1);
+int           st_ulaw_to_linear(P1(unsigned char))REGPARM(1);
 #endif
 
 #ifdef FAST_ALAW_CONVERSION
@@ -32,9 +32,9 @@
 extern const short         Alaw_exp_table[256];
 extern const unsigned char Alaw_comp_table[16384];
 #define st_Alaw_to_linear(Alawbyte)   Alaw_exp_table[Alawbyte]
-#define st_linear_to_Alaw(linearword) Alaw_comp_table[((short)linearword / 4) & 0x3fff]
+#define st_linear_to_Alaw(linearword) Alaw_comp_table[(unsigned short)linearword >> 2]
 #else
-unsigned char st_linear_to_Alaw(P1(short));
-int           st_Alaw_to_linear(P1(unsigned char));
+unsigned char st_linear_to_Alaw(P1(short))REGPARM(1);
+int           st_Alaw_to_linear(P1(unsigned char))REGPARM(1);
 #endif
 
--- a/src/flanger.c
+++ b/src/flanger.c
@@ -56,7 +56,6 @@
 #include <math.h>
 #include <string.h>
 #include "st.h"
-#include "libst.h"
 
 #define MOD_SINE	0
 #define MOD_TRIANGLE	1
--- a/src/oss.c
+++ b/src/oss.c
@@ -18,11 +18,15 @@
  * and on LINUX_PLAYER patches added by Greg Lee
  * which was originally from Directo to Sound Blaster device driver (sbdsp.c).
  * SBLAST patches by John T. Kohl.
+ *
+ * Changes:
+ *
+ * Nov. 26, 1999 Stan Brooks <stabro@megsinet.net>
+ *   Moved initialization code common to startread and startwrite
+ *   into a single function ossdspinit().
+ *
  */
 
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -36,99 +40,11 @@
 #include <sys/ioctl.h>
 #include "st.h"
 
-/*
- * Do anything required before you start reading samples.
- * Read file header.
- *	Find out sampling rate,
- *	size and style of samples,
- *	mono/stereo/quad.
- */
-void ossdspstartread(ft)
+/* common r/w initialization code */
+static void ossdspinit(ft)
 ft_t ft;
 {
-    int tmp;
     int samplesize = 8, dsp_stereo;
-
-    if (ft->info.rate == 0.0) ft->info.rate = 8000;
-    if (ft->info.size == -1) ft->info.size = BYTE;
-    if (ft->info.size == BYTE) {
-	samplesize = 8;
-	if (ft->info.style == -1)
-	    ft->info.style = UNSIGNED;
-	if (ft->info.style != UNSIGNED) {
-	    fail("OSS driver only supports unsigned with bytes");
-	}
-    }
-    else if (ft->info.size == WORD) {
-	samplesize = 16;
-	if (ft->info.style == -1)
-	    ft->info.style = SIGN2;
-	if (ft->info.style != SIGN2) {
-	    fail("OSS driver only supports signed with words");
-	}
-    }
-    else {
-	fail("OSS driver only supports bytes and words");
-    }
-
-    if (ft->info.channels == -1) ft->info.channels = 1;
-    else if (ft->info.channels > 2) ft->info.channels = 2;
-
-    ioctl(fileno(ft->fp), SNDCTL_DSP_RESET, 0);
-    ioctl (fileno(ft->fp), SNDCTL_DSP_GETBLKSIZE, &ft->file.size);
-    if (ft->file.size < 4 || ft->file.size > 65536) {
-	fail("Invalid audio buffer size %d", ft->file.size);
-    }
-    ft->file.count = 0;
-    ft->file.pos = 0;
-    ft->file.eof = 0;
-
-    if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
-	fail("Unable to allocate input/output buffer of size %d", ft->file.size);
-    }
-
-    if (ioctl(fileno(ft->fp), SNDCTL_DSP_SYNC, NULL) < 0) {
-	fail("Unable to sync dsp");
-    }
-
-    tmp = samplesize;
-    ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp);
-    if (tmp != samplesize) {
-	fail("Unable to set the sample size to %d", samplesize);
-    }
-
-    if (ft->info.channels == 2) dsp_stereo = 1;
-    else dsp_stereo = 0;
-
-    tmp = dsp_stereo;
-    ioctl(fileno(ft->fp), SNDCTL_DSP_STEREO, &tmp);
-    if (tmp != dsp_stereo) {
-	ft->info.channels = 1;
-	warn("Couldn't set to %s", dsp_stereo?  "stereo":"mono");
-	dsp_stereo = 0;
-    }
-
-    tmp = ft->info.rate;
-    ioctl (fileno(ft->fp), SNDCTL_DSP_SPEED, &tmp);
-    if (ft->info.rate != tmp) {
-	if (ft->info.rate - tmp > tmp/10 || tmp - ft->info.rate > tmp/10)
-	{
-	    warn("Unable to set audio speed to %d (set to %d)",
-		     ft->info.rate, tmp);
-	    ft->info.rate = tmp;
-	}
-    }
-
-    /* Change to unbuffered mode*/
-    setvbuf(ft->fp, NULL, _IONBF, sizeof(char) * ft->file.size);
-
-    sigintreg(ft);	/* Prepare to catch SIGINT */
-}
-
-void ossdspstartwrite(ft)
-ft_t ft;
-{
-    int samplesize = 8, dsp_stereo;
     int tmp;
 
     if (ft->info.rate == 0.0) ft->info.rate = 8000;
@@ -200,8 +116,16 @@
     tmp = ft->info.rate;
     ioctl (fileno(ft->fp), SNDCTL_DSP_SPEED, &tmp);
     if (ft->info.rate != tmp) {
-	if (ft->info.rate - tmp > tmp/10 || tmp - ft->info.rate > tmp/10)
-	{
+	/* If the rate the sound card is using is not within 2% of what
+	 * the user specified then override the user setting.
+	 * The only reason not to always override this is because of
+	 * clock-rounding problems. Sound cards will sometimes use
+	 * things like 44101 when you ask for 44100.  No need overriding
+	 * this and having strange output file rates for something that
+	 * we can't hear anyways.
+	 */
+	if (ft->info.rate - tmp > (tmp * .02) || 
+	    tmp - ft->info.rate > (tmp * .02)) {
 	    warn("Unable to set audio speed to %d (set to %d)",
 		     ft->info.rate, tmp);
 	    ft->info.rate = tmp;
@@ -211,5 +135,23 @@
     /* Change to non-buffered I/O */
     setvbuf(ft->fp, NULL, _IONBF, sizeof(char) * ft->file.size);
 }
+/*
+ * Do anything required before you start reading samples.
+ * Read file header.
+ *	Find out sampling rate,
+ *	size and style of samples,
+ *	mono/stereo/quad.
+ */
+void ossdspstartread(ft)
+ft_t ft;
+{
+    ossdspinit(ft);
+    sigintreg(ft);	/* Prepare to catch SIGINT */
+}
 
+void ossdspstartwrite(ft)
+ft_t ft;
+{
+    ossdspinit(ft);
+}
 #endif
--- a/src/phaser.c
+++ b/src/phaser.c
@@ -59,7 +59,6 @@
 #include <math.h>
 #include <string.h>
 #include "st.h"
-#include "libst.h"
 
 #define MOD_SINE	0
 #define MOD_TRIANGLE	1
--- a/src/raw.c
+++ b/src/raw.c
@@ -149,7 +149,6 @@
 ft_t ft;
 LONG *buf, nsamp;
 {
-	register LONG datum;
 	int done = 0;
 
 	switch(ft->info.size) {
@@ -158,6 +157,7 @@
 		    {
 			case SIGN2:
 				while(done < nsamp) {
+					LONG datum;
 					datum = blockgetc(ft);
 					if (ft->file.eof)
 						return done;
@@ -168,6 +168,7 @@
 				return done;
 			case UNSIGNED:
 				while(done < nsamp) {
+					LONG datum;
 					datum = blockgetc(ft);
 					if (ft->file.eof)
 						return done;
@@ -180,6 +181,7 @@
 				return done;
 			case ULAW:
 				while(done < nsamp) {
+					LONG datum;
 					datum = blockgetc(ft);
 					if (ft->file.eof)
 						return done;
@@ -191,15 +193,15 @@
 				return done;
 			case ALAW:
 				while(done < nsamp) {
-				        datum = blockgetc(ft);
-				        if (ft->file.eof)
-				                return done;
-				        datum = st_Alaw_to_linear(datum);
-				        /* scale signed up to long's range */
-				        *buf++ = LEFT(datum, 16);
-				        done++;
+					LONG datum;
+					datum = blockgetc(ft);
+					if (ft->file.eof)
+						return done;
+					datum = st_Alaw_to_linear(datum);
+					/* scale signed up to long's range */
+					*buf++ = LEFT(datum, 16);
+					done++;
 				}
-
 				return done;
 		    }
 		    break;
@@ -363,7 +365,6 @@
 ft_t ft;
 LONG *buf, nsamp;
 {
-	register int datum;
 	int done = 0;
 
 	switch(ft->info.size) {
@@ -372,6 +373,7 @@
 		    {
 			case SIGN2:
 				while(done < nsamp) {
+					int datum;
 					/* scale signed up to long's range */
 					datum = (int) RIGHT(*buf++, 24);
 					blockputc(ft, datum);
@@ -380,6 +382,7 @@
 				return;
 			case UNSIGNED:
 				while(done < nsamp) {
+					int datum;
 					/* scale signed up to long's range */
 					datum = (int) RIGHT(*buf++, 24);
 					/* Convert to unsigned */
@@ -390,6 +393,7 @@
 				return;
 			case ULAW:
 				while(done < nsamp) {
+					int datum;
 					/* scale signed up to long's range */
 					datum = (int) RIGHT(*buf++, 16);
 					/* round up to 12 bits of data */
@@ -401,6 +405,7 @@
 				return;
 			case ALAW:
 				while(done < nsamp) {
+					int datum;
 					/* scale signed up to long's range */
 					datum = (int) RIGHT(*buf++, 16);
 					/* round up to 12 bits of data */
@@ -420,6 +425,7 @@
 				return;
 			case UNSIGNED:
 				while(done < nsamp) {
+					int datum;
 					unsigned short s;
 					/* scale signed up to long's range */
 					datum = *buf++ + 0x8000; /* round for 16 bit */
--- a/src/sox.c
+++ b/src/sox.c
@@ -348,6 +348,19 @@
 			break;
 		}
 	}
+
+	/* SJB: fix the -X extract interval for # channels...
+	 * this is not perfect re cases where channels=-1,
+	 * and also indicates that info.x0, info.x1, info.x
+	 * SHOULD be (long long) instead of (ULONG), for large files
+	 */
+	if (ft->info.channels > 1) {
+		if (ft->info.x0 != 0)
+			ft->info.x0 *= ft->info.channels;
+		if (ft->info.x1 != MAXULONG && ft->info.x1 < MAXULONG/ft->info.channels)
+			ft->info.x1 *= ft->info.channels;
+	}
+
 }
 
 static void init(P0) {
--- a/src/st.h
+++ b/src/st.h
@@ -36,17 +36,21 @@
 #endif
 
 #define MAXLONG 0x7fffffffL
-#define MAXULONG 0xffffffff
+#define MAXULONG 0xffffffffL
 
 /* various gcc optimizations */
 #ifdef __GNUC__
 #define NORET __attribute__((noreturn))
-#define REGPARM(n) __attribute__((regparm(n)))
 #define INLINE inline
 #else
 #define NORET
-#define REGPARM(n)
 #define INLINE
+#endif
+
+#ifdef USE_REGPARM
+#define REGPARM(n) __attribute__((regparm(n)))
+#else
+#define REGPARM(n)
 #endif
 
 /*
--- a/src/vibro.c
+++ b/src/vibro.c
@@ -58,7 +58,7 @@
 }
 
 /* This was very painful.  We need a sine library. */
-
+/* SJB: this is somewhat different than st_sine()  */
 static void sine(buf, len, depth)
 short *buf;
 int len;
--- a/test/Makefile
+++ b/test/Makefile
@@ -10,7 +10,7 @@
 all: ding model lding lmodel corr
 
 corr: corr.c
-	$(CC) $(CFLAGS) $(LDFLAGS) -o $2 $<
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
 
 ding: ding.c
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
--- a/test/README
+++ b/test/README
@@ -28,16 +28,17 @@
 ./ltest -l resample -qs 0.80 0 >B
 gnuplot plotAB
 
-The script gtest.pl is for testing sox's adpcm and gsm wav support.
+The script wtest.pl is for testing sox's adpcm and gsm wav support.
 
 It accepts one of these options:
     -t  Use 'toast' gsm for compress/decompress
-             -a  Use sox (MS) ADPCM
-	     -i  Use sox IMA ADPCM
-	     -g  Use sox wav-gsm6.10
+    -a  Use sox (MS) ADPCM
+    -i  Use sox IMA ADPCM
+    -g  Use sox wav-gsm6.10
 If using sox, you may also append an optional effect, eg:
     ./wtest -g filter 0-3500 >A
 will apply a lowpass filter with 6dB corner at 3500 Hz before the compression phase.
+
 Then, as above, 'gnuplot plotA' will graph dB gain and dB error-level
 vs. freq for you.
 
@@ -58,10 +59,10 @@
 frequencies 0.00 0.01 ... 0.99 of the Nyquist frequency.  This input
 has:
      400 samples samples of silence,
-		4000 samples with smooth envelope rising to volume -v0.5
-	 16000 samples at -v0.5
-	  4000 samples with smooth envelope falling to 0,
-		 400 sample more of silence.
+    4000 samples with smooth envelope rising to volume -v0.5
+   16000 samples at -v0.5
+    4000 samples with smooth envelope falling to 0,
+     400 sample more of silence.
 
 The rising/falling envelopes are shaped like rising, falling portions
 of the (1-cos(x)) function.
@@ -76,18 +77,18 @@
 
 step 1:  the entire sample file is read in, and the center-of-gravity of
          the squared samples is found.  This is the time offset which should
-				 correspond to the center of the filtered/resampled tone-pulse.
+	 correspond to the center of the filtered/resampled tone-pulse.
 
 step 2:  let N = 16000*(rate1/rate0) be the number of samples at output rate
-				 which would correspond to the 16000 sample duration at max volume.
-				 We focus on the samples between
-				     (center - 0.3*N)    and    (center + 0.9*N)
-				 where the transient effects of attack/release envelope should be
-				 small.
-				 We do a least-squares fit of a sinusoid at the adjusted frequency
-				 to this segment of 0.6*N samples, and print out the component
-				 s2max which can be explained, and also the rms level of the 'error'
-				 or unexplained part.
+	 which would correspond to the 16000 sample duration at max volume.
+	 We focus on the samples between
+         (center - 0.3*N)    and    (center + 0.9*N)
+	 where the transient effects of attack/release envelope should be
+	 small.
+	 We do a least-squares fit of a sinusoid at the adjusted frequency
+	 to this segment of 0.6*N samples, and print out the component
+	 s2max which can be explained, and also the rms level of the 'error'
+	 or unexplained part.
 
 That's pretty much it... the ltest perl-script glues it together and outputs
 adjusted data which the gnuplot will like.
--- a/test/wtest.pl
+++ b/test/wtest.pl
@@ -28,7 +28,7 @@
 
 my $rate=8000; # sample rates
 my $p=200;  # silence before/after tonepulse
-my $env="-e400:800:400"; # attack, duration, drop
+my $env="400:800:400"; # attack, duration, drop
 
 my ($ding,$model,$t,$rms,$lim)=("./ding","./model","sw",11585.2, 0.5);
 
@@ -55,7 +55,7 @@
 	print("by $sox -r$rate in.sw $fmt out.wav $effect\n");
 }
 print("#   with tone pulses from 0.00 to 0.99 percent of Nyquist\n");
-print("#   produced by $ding -f0.xx -v0.5 -o$p $env -p$p d/i0.xx.$t\n");
+print("#   produced by $ding -f0.xx -v0.5 -e$p:$env:$p d/i0.xx.$t\n");
 print("#   col 1 is frequency/Nyquist\n");
 print("#   col 2 is (power) dB gain\n");
 print("#   col 3 is (power) dB level of error signal\n");
@@ -71,8 +71,8 @@
 
 	#if ($f>0.995) { $f=0.999; }
 	my $s=sprintf("%4.2f",$f);
-	#print "$ding -v0.5 -o$p $env -p$p -f$s -d1.0 d/i$s.$t\n";
-	qx{$ding -v0.5 -o$p $env -p$p -f$s -d1.0 d/i$s.$t &>/dev/null};
+	#print "$ding -f$s -v0.5 -e$p:$env:$p -d1.0 d/i$s.$t\n";
+	qx{$ding -f$s -v0.5 -e$p:$env:$p -d1.0 d/i$s.$t &>/dev/null};
 
 	if ($fmt eq '-t') {
 		qx{$toast -l d/i$s.$t};
@@ -86,7 +86,7 @@
 		unlink "d/g$s.wav";
 	}
 
-	@mod = grep {/v2max/} qx{$model -f$s $env $rate d/i$s.$t 2>&1};
+	@mod = grep {/v2max/} qx{$model -f$s -e$env $rate d/i$s.$t 2>&1};
 	print STDERR "$s: ",@mod;
 	$_=shift(@mod);
 	if (m{s2max *([0-9.]+), *v2max *([0-9.]+), *rmserr *(-?[0-9.]+)}) {