shithub: sox

Download patch

ref: 796aea8705015d43aeab9ab5a44f0c3f58aa0a32
parent: 4f2944e51b8a9017b27ddf3267c775fe81d26025
author: cbagwell <cbagwell>
date: Fri Sep 1 13:10:23 EDT 2000

Added new trim effect and removed unneeded code from sox.c.

--- a/Changelog
+++ b/Changelog
@@ -79,6 +79,7 @@
     256.
   o Matthias Nutt helped add support for specifying multiple effects
     to SoX on the command line.
+  o Curt Zirzow added a trim effect to trim off audio data.
 
 sox-12.16
 ---------
--- a/Makefile.dos
+++ b/Makefile.dos
@@ -22,7 +22,7 @@
           lowpass.obj map.obj mask.obj phaser.obj pick.obj pitch.obj pan.obj \
 	  polyphase.obj rate.obj resample.obj reverb.obj \
 	  reverse.obj speed.obj split.obj stat.obj stretch.obj \
-	  swap.obj vibro.obj vol.obj
+	  swap.obj trim.obj vibro.obj vol.obj
 
 LIBOBJS   = $(FOBJ) $(EOBJ) handlers.obj libst.obj misc.obj getopt.obj util.obj
 
--- a/Makefile.gcc
+++ b/Makefile.gcc
@@ -37,7 +37,8 @@
           copy.o cut.o deemphas.o echo.o echos.o filter.o flanger.o \
           highp.o highpass.o lowp.o lowpass.o map.o mask.o pan.o \
           phaser.o pick.o pitch.o polyphas.o rate.o resample.o reverb.o \
-          reverse.o speed.o split.o stat.o stretch.o swap.o vibro.o vol.o
+          reverse.o speed.o split.o stat.o stretch.o swap.o \
+	  trimo vibro.o vol.o
 
 SOUNDLIB = libst.a
 LIBOBJS = $(FOBJ) $(EOBJ) handlers.o libst.o misc.o util.o getopt.o
--- a/README
+++ b/README
@@ -67,6 +67,7 @@
   o Convert from mono to stereo
   o Swap stereo channels
   o Display general stats on a sound sample
+  o Trim audio data from beginning and end of file.
   o Add the world-famous Fender Vibro-Champ effect
   o Adjust volume of samples
 
--- a/sox.1
+++ b/sox.1
@@ -112,6 +112,8 @@
 .br
     \fBswap\fR [ \fI1 2\fR | \fI1 2 3 4\fR ]
 .br
+    \fBtrim\fR \fIstart\fR [ \fIlength\fR ]
+.br
     \fBvibro\fR \fIspeed\fR [ \fIdepth\fR ]
 .br
     \fBvol\fR \fIgain\fR [ \fItype\fR ]
@@ -1000,6 +1002,17 @@
 This is done by repeating an output channel on the command line.  For example,
 swap 2 2 will overwrite channel 1 with channel 2's data; creating a stereo
 file with both channels containing the same audio data.
+.TP 10
+trim \fIstart\fR [ \fIlength\fR ]
+Trim can trim off unwanted audio data from the beginning and end of the
+audio file.  Audio samples are not sent to the output stream until
+the \fIstart\fR location is reached.  \fIstart\fR is an integer number that
+tells the exact sample number to start at.
+.br
+The optional \fIlength\fR parameter tells the number of samples to output
+after the \fIstart\fR sample and is used to trim off the back side of the
+audio data.  Using a value of 0 for the \fIstart\fR parameter will allow
+trimming off the back side only.
 .TP 10
 vibro \fIspeed \fB [ \fIdepth\fB ]
 Add the world-famous Fender Vibro-Champ sound
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -49,7 +49,8 @@
 	  copy.o cut.o deemphas.o echo.o echos.o filter.o flanger.o \
 	  highp.o highpass.o lowp.o lowpass.o map.o mask.o pan.o \
 	  phaser.o pick.o pitch.o polyphas.o rate.o resample.o reverb.o \
-	  reverse.o speed.o split.o stat.o stretch.o swap.o vibro.o vol.o
+	  reverse.o speed.o split.o stat.o stretch.o swap.o trim.o \
+	  vibro.o vol.o trim.o
 
 OSSOBJ_0    =
 OSSOBJ_1    = oss.o
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -630,6 +630,10 @@
 extern int st_vol_flow();
 extern int st_vol_stop();
 
+extern int st_trim_getopts(); 
+extern int st_trim_start();
+extern int st_trim_flow();
+extern int st_trim_stop();
 
 /*
  * ST_EFF_CHAN means that the number of channels can change.
@@ -747,6 +751,11 @@
 	{"vol", ST_EFF_MCHAN, 
 		st_vol_getopts, st_vol_start, st_vol_flow, 
 		st_null_drain, st_vol_stop},
+        {"trim", ST_EFF_MCHAN, 
+                st_trim_getopts, st_trim_start, st_trim_flow, 
+                st_null_drain, st_nothing},
+
 	{0, 0, 0, 0, 0, 0, 0}
 };
+
 
--- a/src/sox.c
+++ b/src/sox.c
@@ -1,4 +1,4 @@
-/*
+/*)
  * Sox - The Swiss Army Knife of Audio Manipulation.
  *
  * This is the main function for the command line sox program.
@@ -12,12 +12,6 @@
  *
  * Change History:
  *
- * Nov. 1, 1999 - Stan Brooks (stabro@megsinet.com)
- *   Added -X input option, to extract range of samples.
- *   Moved volume and dovolume from static variables into ft->info...
- *   TODO: This should allow a way (kluge) of specifying multiple
- *   inputs to be mixed together.
- *
  * June 1, 1998 - Chris Bagwell (cbagwell@sprynet.com)
  *   Added patch to get volume working again.  Based on patch sent from
  *   Matija Nalis <mnalis@public.srce.hr>.
@@ -73,11 +67,12 @@
  * Rewrite for multiple effects: Aug 24, 1994.
  */
 
+static int dovolume = 0;        /* User wants volume change */
+static double volume = 1.0;     /* Linear volume change */
 static int clipped = 0;		/* Volume change clipping errors */
-static int writing = 0;	/* are we writing to a file? */
+static int writing = 0;	        /* are we writing to a file? */
 static int soxpreview = 0;	/* preview mode */
 
-
 static LONG ibufl[BUFSIZ/2];	/* Left/right interleave buffers */
 static LONG ibufr[BUFSIZ/2];	
 static LONG obufl[BUFSIZ/2];
@@ -237,11 +232,11 @@
 	}
 
 	/* Check global arguments */
-	if (informat.info.dovol && informat.info.vol == 0.0)
+	if (dovolume && volume == 0.0)
 		st_fail("Volume must be non-zero");
 
 	/* negative volume is phase-reversal */
-	if (informat.info.vol < 0.0)
+	if (volume < 0.0)
 	    st_report("Volume adjustment is negative.  This will result in a phase change\n");
 
 	/* If file types have not been set with -t, set from file names. */
@@ -275,9 +270,9 @@
 }
 
 #ifdef HAVE_GETOPT_H
-static char *getoptstr = "+r:v:t:c:B:X:phsuUAaigbwlfdDxV";
+static char *getoptstr = "+r:v:t:c:phsuUAaigbwlfdDxV";
 #else
-static char *getoptstr = "r:v:t:c:B:X:phsuUAaigbwlfdDxV";
+static char *getoptstr = "r:v:t:c:phsuUAaigbwlfdDxV";
 #endif
 
 static void doopts(argc, argv)
@@ -304,15 +299,6 @@
 				ft->filetype++;
 			break;
 
-		case 'X':  /* extract a subinterval of samples as input */
-			if (! ft) usage("-X");
-			str = optarg;
-			/* FIXME: allow "A-B" "-B" "A-" "A,B" also maybe lists of ranges */
-			if ( 2 != sscanf(str, "%lu-%lu", &ft->info.x0, &ft->info.x1))
-				st_fail("eXtract range '%s' is not valid", optarg);
-			if (ft->info.x1==0) ft->info.x1 -= 1; /* MAXULONG */
-			break;
-
 		case 'r':
 			if (! ft) usage("-r");
 			str = optarg;
@@ -326,11 +312,12 @@
 				st_fail("-r must be given a positive integer");
 			break;
 		case 'v':
-			if (!ft || ft->info.dovol) usage("-v");
+			if (!ft || dovolume) usage("-v");
 			str = optarg;
-			if (! sscanf(str, "%lf", &ft->info.vol)) /* neg volume is ok */
-				st_fail("Volume value '%s' is not a number", optarg);
-			ft->info.dovol = 1;
+			if (! sscanf(str, "%lf", &volume))
+			    st_fail("Volume value '%s' is not a number", 
+				    optarg);
+			dovolume = 1;
 			break;
 
 		case 'c':
@@ -339,12 +326,6 @@
 			if (! sscanf(str, "%d", &ft->info.channels))
 				st_fail("-c must be given a number");
 			break;
-		case 'B':
-			if (! ft) usage("-B");
-			str = optarg;
-			if (! sscanf(str, "%hu", &ft->info.bs) || ft->info.bs<=0) /* blocksize */
-				st_fail("-B must be given a positive number");
-			break;
 		case 'b':
 			if (! ft) usage("-b");
 			ft->info.size = ST_SIZE_BYTE;
@@ -409,19 +390,6 @@
 			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) {
@@ -431,12 +399,6 @@
 	informat.info.size      = outformat.info.size  = -1;
 	informat.info.encoding  = outformat.info.encoding = -1;
 	informat.info.channels  = outformat.info.channels = -1;
-	informat.info.bs        = outformat.info.bs    = 0;
-	informat.info.dovol     = outformat.info.dovol = 0;
-	informat.info.vol       = outformat.info.vol   = 1.0;
-	informat.info.x         = outformat.info.x  = 0;
-	informat.info.x0        = outformat.info.x0 = 0;
-	informat.info.x1        = outformat.info.x1 = -1;
 	informat.comment   = outformat.comment = NULL;
 	informat.swap      = 0;
 	informat.filetype  = outformat.filetype  = (char *) 0;
@@ -465,10 +427,8 @@
     }
     st_checkformat(&informat);
     
-    if (informat.info.dovol)
-	st_report("Volume factor: %f\n", informat.info.vol);
-    if (informat.info.x0 || informat.info.x1 != MAXULONG)
-	st_report("Extract samples %lu <= x < %lu\n", informat.info.x0, informat.info.x0);
+    if (dovolume)
+	st_report("Volume factor: %f\n", volume);
     
     st_report("Input file: using sample rate %lu\n\tsize %s, encoding %s, %d %s",
 	   informat.info.rate, st_sizes_str[informat.info.size], 
@@ -560,27 +520,26 @@
     }
 
 
-    /* Run input data through effects and get more until olen == 0 */
+    /* 
+     * Just like errno, we must set st_errno to known values before
+     * calling I/O operations.
+     */
     informat.st_errno = 0;
     outformat.st_errno = 0;
-    while (informat.info.x < informat.info.x1) {
-	ULONG ct, r;
 
-	/* Read (extracted) chunk of input data. */
-	ct = (informat.info.x < informat.info.x0)?
-	  (informat.info.x0 - informat.info.x) : (informat.info.x1 - informat.info.x);
-	if (ct > BUFSIZ) ct = BUFSIZ;
-	r = (*informat.h->read)(&informat, efftab[0].obuf, ct);
-	if (!r) break;
-	informat.info.x += r;
-	if (informat.info.x <= informat.info.x0) continue;
-	efftab[0].olen = r;
-	efftab[0].odone = 0;
+    /* Prime while() loop by reading initial chunk of input data. */
+    efftab[0].olen = (*informat.h->read)(&informat, 
+                                         efftab[0].obuf, (LONG) BUFSIZ);
+    efftab[0].odone = 0;
 
-	/* Change the volume of this initial input data if needed. */
-	if (informat.info.dovol)
-	    clipped += volumechange(efftab[0].obuf, efftab[0].olen, informat.info.vol);
+    /* Change the volume of this initial input data if needed. */
+    if (dovolume)
+	clipped += volumechange(efftab[0].obuf, efftab[0].olen,
+		                volume);
 
+    /* Run input data through effects and get more until olen == 0 */
+    while (efftab[0].olen > 0)
+    {
 	/* mark chain as empty */
 	for(e = 1; e < neffects; e++)
 	    efftab[e].odone = efftab[e].olen = 0;
@@ -595,8 +554,10 @@
 		    break;
 
 	    /* If outputing and output data was generated then write it */
-	    if (writing&&(efftab[neffects-1].olen>efftab[neffects-1].odone)) {
-		w = (* outformat.h->write)(&outformat, efftab[neffects-1].obuf, 
+	    if (writing&&(efftab[neffects-1].olen>efftab[neffects-1].odone)) 
+	    {
+		w = (* outformat.h->write)(&outformat, 
+			                   efftab[neffects-1].obuf, 
 				           (LONG) efftab[neffects-1].olen);
 	        efftab[neffects-1].odone = efftab[neffects-1].olen;
 	    }
@@ -613,6 +574,15 @@
 		}
 	} while (havedata);
 
+        /* Read another chunk of input data. */
+        efftab[0].olen = (*informat.h->read)(&informat, 
+                                             efftab[0].obuf, (LONG) BUFSIZ);
+        efftab[0].odone = 0;
+
+        /* Change volume of these samples if needed. */
+        if (dovolume)
+	    clipped += volumechange(efftab[0].obuf, efftab[0].olen,
+		                    volume);
     }
 
     if (informat.st_errno)
@@ -937,7 +907,7 @@
 }
 
 static void statistics(P0) {
-	if (informat.info.dovol && clipped > 0)
+	if (dovolume && clipped > 0)
 		st_report("Volume change clipped %d samples", clipped);
 }
 
--- a/src/st.h
+++ b/src/st.h
@@ -92,12 +92,6 @@
 	int		size;		/* word length of data */
 	int		encoding;	/* format of sample numbers */
 	int		channels;	/* number of sound channels */
-	unsigned short	bs;		/* requested blocksize, eg for output .wav's */
-	unsigned char	dovol;		/* has volume factor */
-	double		vol;		/* volume factor */
-	ULONG		x;		/* current sample number */
-	ULONG		x0;		/* 1st sample (if source) */
-	ULONG		x1;		/* top sample (if source) */
 };
 
 /* Loop parameters */
--- /dev/null
+++ b/src/trim.c
@@ -1,0 +1,158 @@
+/*
+ * July 5, 1991
+ * Copyright 1991 Lance Norskog And Sundry Contributors
+ * This source code is freely redistributable and may be used for
+ * any purpose.  This copyright notice must be maintained. 
+ * Lance Norskog And Sundry Contributors are not responsible for 
+ * the consequences of using this software.
+ */
+
+/*
+ * Sound Tools skeleton effect file.
+ */
+
+#include "st.h"
+
+
+typedef struct
+{
+
+        /* options here */
+        LONG start;
+        LONG length;
+
+        /* internal stuff */
+        LONG index;
+        LONG trimmed;
+        int done;
+
+} * trim_t;
+
+/*
+ * Process options
+ */
+int st_trim_getopts(effp, n, argv) 
+eff_t effp;
+int n;
+char **argv;
+{
+        trim_t trim = (trim_t) effp->priv;
+
+        trim->start = 0;
+        trim->length = 0;
+
+        switch (n) {
+                case 2:
+                        trim->length = atol(argv[1]);
+            case 1:
+                        trim->start = atol(argv[0]);
+                        break;
+                default:
+                        st_fail("Trim usage: trim start [length]");
+                        return ST_EOF;
+                        break;
+
+        }
+        return (ST_SUCCESS);
+}
+
+/*
+ * Start processing
+ */
+int st_trim_start(effp)
+eff_t effp;
+{
+        trim_t trim = (trim_t) effp->priv;
+
+
+        trim->start = (LONG)(effp->ininfo.channels * effp->ininfo.rate *  (0.001e0) * trim->start);
+        if (trim->start < 0) 
+        {
+                st_fail("trim: start must be positive");
+        }
+
+		trim->length = (LONG)(effp->ininfo.channels * effp->ininfo.rate * (0.001e0) * trim->length);
+        if (trim->length < 0) 
+        {
+                st_fail("trim: start must be positive");
+        }
+
+        trim->done = 0;
+        trim->index = 0;
+        trim->trimmed = 0;
+
+    return (ST_SUCCESS);
+}
+
+/*
+ * Read up to len samples from file.
+ * Convert to signed longs.
+ * Place in buf[].
+ * Return number of samples read.
+ */
+
+int st_trim_flow(effp, ibuf, obuf, isamp, osamp)
+eff_t effp;
+LONG *ibuf, *obuf;
+LONG *isamp, *osamp;
+{
+	int done;
+	int offset;
+	int start_trim = 0;
+
+	trim_t trim = (trim_t) effp->priv;
+	
+	done = ((*isamp < *osamp) ? *isamp : *osamp);
+	*isamp = done; /* always read this much */
+
+	if (trim->done) {
+		*osamp = 0;
+		return (ST_SUCCESS);
+	}
+
+	trim->index += done;
+	offset = 0;
+	if (! trim->trimmed) {
+		if (trim->start > trim->index) {
+			*osamp = 0;
+			return (ST_SUCCESS);
+		} else {
+			start_trim = 1;
+			offset =  (trim->start==0? 0: trim->index - trim->start);
+			done -= offset; /* adjust done */
+		}
+	}
+
+	if (trim->trimmed || start_trim ) {
+
+		if (trim->length && ( (trim->trimmed+done) > trim->length)) {
+			fprintf(stderr, "passed done\n");
+			done = trim->length - trim->trimmed ;
+			*osamp = done;
+			trim->done = 1;
+		}
+
+		trim->trimmed += done;
+	}
+
+	memcpy(obuf, ibuf+offset, done * sizeof(LONG));
+	*osamp = done;
+	return (ST_SUCCESS);
+}
+
+/*
+ * Do anything required when you stop reading samples.  
+ * Don't close input file! 
+ */
+int st_trim_stop(effp)
+eff_t effp;
+{
+
+        /* nothing to do */
+    return (ST_SUCCESS);
+}
+
+
+
+
+