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);
+}
+
+
+
+
+