ref: 3b1fd9df8568594a3b324e276f1e110a7a01f664
parent: 5fd2e6c5adf521b2875f69a08b6b3a62a235bd03
author: cbagwell <cbagwell>
date: Sat Mar 3 15:31:10 EST 2001
Commiting minor updates to mix program.
--- a/mix.c
+++ b/mix.c
@@ -17,10 +17,6 @@
* mix functionality.
*/
-/* FIXME: Quickly ported from 12.16 to 12.17.2... Make sure all st_*
- * functions are checking return values!
- */
-
#include "st.h"
#include <stdio.h>
#include <string.h>
@@ -62,16 +58,13 @@
static int clipped = 0; /* Volume change clipping errors */
static int writing = 0; /* are we writing to a file? */
-void init();
-void doopts(int, char **);
-void usage(char *);
-int filetype(int);
-void process();
-void statistics();
-LONG volumechange();
-void checkeffect(eff_t);
-int flow_effect(int);
-int drain_effect(int);
+static void init();
+static void doopts(int, char **);
+static void usage(char *);
+static int filetype(int);
+static void process();
+static void statistics();
+static LONG volumechange();
struct st_soundstream informat, mixformat, outformat;
@@ -86,6 +79,7 @@
char **argv;
{
myname = argv[0];
+
init();
ifile = mfile = ofile = NULL;
@@ -104,6 +98,12 @@
st_fail("Can't open input file '%s': %s",
ifile, strerror(errno));
ft->filename = ifile;
+#if defined(DUMB_FILESYSTEM)
+ ft->seekable = 0;
+#else
+ ft->seekable = (filetype(fileno(informat.fp)) == S_IFREG);
+#endif
+
optind++;
/* Get mix format options */
@@ -120,11 +120,18 @@
st_fail("Can't open mix file '%s': %s",
mfile, strerror(errno));
ft->filename = mfile;
+#if defined(DUMB_FILESYSTEM)
+ ft->seekable = 0;
+#else
+ ft->seekable = (filetype(fileno(informat.fp)) == S_IFREG);
+#endif
+
optind++;
/* Get output format options */
ft = &outformat;
doopts(argc, argv);
+
writing = 1;
if (writing) {
/* Get output file */
@@ -132,53 +139,26 @@
usage("No output file?");
ofile = argv[optind];
ft->filename = ofile;
- /*
- * There are two choices here:
- * 1) stomp the old file - normal shell "> file" behavior
- * 2) fail if the old file already exists - csh mode
- */
- if (! strcmp(ofile, "-"))
- {
- ft->fp = stdout;
- /* stdout tends to be line-buffered. Override this */
- /* to be Full Buffering. */
- if (setvbuf (ft->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
- st_fail("Can't set write buffer");
- }
- else {
-
- ft->fp = fopen(ofile, WRITEBINARY);
-
- if (ft->fp == NULL)
- st_fail("Can't open output file '%s': %s",
- ofile, strerror(errno));
-
- /* stdout tends to be line-buffered. Override this */
- /* to be Full Buffering. */
- if (setvbuf (ft->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
- st_fail("Can't set write buffer");
-
- } /* end of else != stdout */
-
/* Move past filename */
optind++;
+
+ /* Hold off on opening file until the very last minute.
+ * This allows us to verify header in input files are
+ * what they should be and parse effect command lines.
+ * That way if anything is found invalid, we will abort
+ * without truncating any existing file that has the same
+ * output filename.
+ */
+
} /* end if writing */
/* Check global arguments */
- if (volume <= 0.0)
- st_fail("Volume must be greater than 0.0");
-
-#if defined(DUMB_FILESYSETM)
- informat.seekable = 0;
- mixformat.seekable = 0;
- outformat.seekable = 0;
-#else
- informat.seekable = (filetype(fileno(informat.fp)) == S_IFREG);
- mixformat.seekable = (filetype(fileno(mixformat.fp)) == S_IFREG);
- outformat.seekable = (filetype(fileno(outformat.fp)) == S_IFREG);
-#endif
+ /* negative volume is phase-reversal */
+ if (dovolume && 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. */
if (! informat.filetype) {
if ((informat.filetype = strrchr(ifile, LASTCHAR)) != NULL)
@@ -221,12 +201,12 @@
}
#ifdef HAVE_GETOPT_H
-char *getoptstr = "+r:v:t:c:phsuUAagbwlfdDxV";
+char *getoptstr = "+r:v:t:c:hsuUAagbwlfdDxV";
#else
-char *getoptstr = "r:v:t:c:phsuUAagbwlfdDxV";
+char *getoptstr = "r:v:t:c:hsuUAagbwlfdDxV";
#endif
-void doopts(int argc, char **argv)
+static void doopts(int argc, char **argv)
{
int c;
char *str;
@@ -317,6 +297,10 @@
if (! ft) usage("-a");
ft->info.encoding = ST_ENCODING_ADPCM;
break;
+ case 'i':
+ if (! ft) usage("-i");
+ ft->info.encoding = ST_ENCODING_IMA_ADPCM;
+ break;
case 'g':
if (! ft) usage("-g");
ft->info.encoding = ST_ENCODING_GSM;
@@ -334,7 +318,7 @@
}
}
-void init() {
+static void init() {
/* init files */
st_initformat(&informat);
@@ -354,20 +338,33 @@
* one buffer at a time
*/
-void process() {
+static void process() {
LONG result, i, *ibuf, *mbuf, *obuf, ilen=0, mlen=0, olen=0;
- st_gettype(&informat);
- st_gettype(&mixformat);
+ if ( st_gettype(&informat) )
+ st_fail("bad input format");
+
+ if ( st_gettype(&mixformat) )
+ st_fail("bad input format");
+
if (writing)
- st_gettype(&outformat);
+ if (st_gettype(&outformat))
+ st_fail("bad output format");
/* Read and write starters can change their formats. */
- (* informat.h->startread)(&informat);
+ if ((* informat.h->startread)(&informat) == ST_EOF)
+ {
+ st_fail(informat.st_errstr);
+ }
+
if (st_checkformat(&informat))
st_fail("bad input format");
- (* mixformat.h->startread)(&mixformat);
+ if ((* mixformat.h->startread)(&mixformat) == ST_EOF)
+ {
+ st_fail(mixformat.st_errstr);
+ }
+
if (st_checkformat(&mixformat))
st_fail("bad input format");
@@ -388,22 +385,65 @@
if (mixformat.comment)
st_report("Mix file: comment \"%s\"\n", mixformat.comment);
-/*
- Expect the formats of the input and mix files to be compatible.
- Although it's true that I could fix it up on the fly, it's easier
- for me to tell the user to use sox to fix it first and it's also
- more reliable; better to use the code that Chris, Lance & Co have
- written well than for me to rewrite the same stuff badly!
-
- Sample rates are a cause for failure.
-*/
+ /* Expect the formats to have the same sample rate. Although its
+ * possible to auto-convert the sample rate of one file to match
+ * the other using the rate effect, its easier to tell the user
+ * to figure it out and run sox on the input file seperately to
+ * correct it before hand.
+ */
if(informat.info.rate != mixformat.info.rate)
st_fail("fail: Input and mix files have different sample rates.\nUse sox to resample one of them.\n");
/* need to check EFF_REPORT */
if (writing) {
+ /*
+ * There are two choices here:
+ * 1) stomp the old file - normal shell "> file" behavior
+ * 2) fail if the old file already exists - csh mode
+ */
+ if (! strcmp(ofile, "-"))
+ {
+ ft->fp = stdout;
+
+ /* stdout tends to be line-buffered. Override this */
+ /* to be Full Buffering. */
+ if (setvbuf (ft->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
+ {
+ st_fail("Can't set write buffer");
+ }
+ }
+ else {
+
+ ft->fp = fopen(ofile, WRITEBINARY);
+
+ if (ft->fp == NULL)
+ st_fail("Can't open output file '%s': %s",
+ ofile, strerror(errno));
+
+ /* stdout tends to be line-buffered. Override this */
+ /* to be Full Buffering. */
+ if (setvbuf (ft->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
+ {
+ st_fail("Can't set write buffer");
+ }
+
+ } /* end of else != stdout */
+#if defined(DUMB_FILESYSTEM)
+ outformat.seekable = 0;
+#else
+ outformat.seekable = (filetype(fileno(outformat.fp)) == S_IFREG);
+#endif
+
+ /* FIXME: We are defaulting to using the first file's format
+ * for the output file. Should compare the two inputs and
+ * warn user that the output file will use the first input
+ * file's values.
+ */
st_copyformat(&informat, &outformat);
- (* outformat.h->startwrite)(&outformat);
+ if ((* outformat.h->startwrite)(&outformat) == ST_EOF)
+ {
+ st_fail(outformat.st_errstr);
+ }
if (st_checkformat(&outformat))
st_fail("bad output format");
@@ -431,16 +471,14 @@
/* Do the input file first */
ilen = (*informat.h->read)(&informat, ibuf, (LONG) BUFSIZ);
/* Change the volume of this data if needed. */
- if(dovolume && ilen)
- for (i = 0; i < ilen; i++)
- ibuf[i] = volumechange(ibuf[i]);
+ if(dovolume)
+ clipped += volumechange(ibuf, ilen, volume);
/* Now do the mixfile */
mlen = (*mixformat.h->read)(&mixformat, mbuf, (LONG) BUFSIZ);
/* Change the volume of this data if needed. */
- if(dovolume && mlen)
- for (i = 0; i < mlen; i++)
- mbuf[i] = volumechange(mbuf[i]);
+ if(dovolume)
+ clipped += volumechange(mbuf, mlen, volume);
/* mix until both input files are done */
while (ilen || mlen) {
@@ -462,9 +500,8 @@
ibuf, (LONG) BUFSIZ);
/* Change volume of these samples if needed. */
- if(dovolume && ilen)
- for (i = 0; i < ilen; i++)
- ibuf[i] = volumechange(ibuf[i]);
+ if(dovolume)
+ clipped += volumechange(ibuf, ilen, volume);
/* Read another chunk of mix data. */
mlen = (*mixformat.h->read)(&mixformat,
@@ -471,48 +508,61 @@
mbuf, (LONG) BUFSIZ);
/* Change volume of these samples if needed. */
- if(dovolume && mlen)
- for (i = 0; i < mlen; i++)
- mbuf[i] = volumechange(mbuf[i]);
+ if(dovolume)
+ clipped += volumechange(ibuf, ilen, volume);
}
- (* informat.h->stopread)(&informat);
+ /* If closing fails then just warn user instead of exiting.
+ * This is because we are basically done with the files anyways.
+ */
+ if ((* informat.h->stopread)(&informat) == ST_EOF)
+ st_warn(informat.st_errstr);
fclose(informat.fp);
- (* mixformat.h->stopread)(&mixformat);
+ if ((* mixformat.h->stopread)(&mixformat) == ST_EOF)
+ st_warn(mixformat.st_errstr);
fclose(mixformat.fp);
if (writing)
- (* outformat.h->stopwrite)(&outformat);
+ if ((* outformat.h->stopwrite)(&outformat) == ST_EOF)
+ st_warn(outformat.st_errstr);
if (writing)
fclose(outformat.fp);
}
/* Guido Van Rossum fix */
-void statistics() {
+static void statistics() {
if (dovolume && clipped > 0)
st_report("Volume change clipped %d samples", clipped);
}
-LONG volumechange(y)
-LONG y;
+static LONG volumechange(buf, ct, vol)
+LONG *buf;
+LONG ct;
+double vol;
{
- double y1;
+ double y;
+ LONG *p,*top;
+ LONG clips=0;
- y1 = y * volume;
- if (y1 < -2147483647.0) {
- y1 = -2147483647.0;
- clipped++;
+ p = buf;
+ top = buf+ct;
+ while (p < top) {
+ y = vol * *p;
+ if (y < -2147483647.0) {
+ y = -2147483647.0;
+ clips++;
+ }
+ else if (y > 2147483647.0) {
+ y = 2147483647.0;
+ clips++;
+ }
+ *p++ = y + 0.5;
}
- else if (y1 > 2147483647.0) {
- y1 = 2147483647.0;
- clipped++;
- }
-
- return y1;
+ return clips;
}
-int filetype(fd)
+static int filetype(fd)
int fd;
{
struct stat st;
@@ -522,10 +572,10 @@
return st.st_mode & S_IFMT;
}
-char *usagestr =
+static char *usagestr =
"[ gopts ] [ fopts ] ifile [ fopts ] mixfile [ fopts ] ofile";
-void usage(opt)
+static void usage(opt)
char *opt;
{
int i;
--- a/src/sox.c
+++ b/src/sox.c
@@ -136,7 +136,6 @@
/* Get input format options */
ft = &informat;
- clipped = 0;
doopts(argc, argv);
/* Get input file */
if (optind >= argc)
@@ -230,11 +229,9 @@
}
/* Check global arguments */
- if (dovolume && volume == 0.0)
- st_fail("Volume must be non-zero");
/* negative volume is phase-reversal */
- if (volume < 0.0)
+ if (dovolume && 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. */
@@ -259,6 +256,7 @@
/* Default the input comment to the filename.
* The output comment will be assigned when the informat
* structure is copied to the outformat.
+ * FIXME: Should be a memory copy, not a pointer asignment.
*/
informat.comment = informat.filename;
--- a/src/synth.c
+++ b/src/synth.c
@@ -386,12 +386,11 @@
if(n > argn){
/* got here by 'break', scan parms for next chan */
}else{
-
break;
}
}
}
- }
+ } /* if n > argn */
}/* for .. */
/* make some intelligent parameter initialization for channels
@@ -401,7 +400,7 @@
* - if parm for 2 channels were given, copy to channel 1->3, 2->4
* - if parm for 3 channels were given, copy 2->4
*/
- if(c == 0){
+ if(c == 0 || c >= MAXCHAN){
for(c=1;c<MAXCHAN;c++)
parmcopy(synth,0,c);
}else if(c == 1){
@@ -444,9 +443,6 @@
synth->h[i]=0.0;
}
-
-
-
/* parameter adjustment for all channels */
for(c=0;c<MAXCHAN;c++){
/* adjust parameter 0 - 100% to 0..1 */
@@ -454,8 +450,6 @@
synth->par[c][i] /= 100.0;
}
-
-
/* give parameters nice defaults for the different 'type' */
switch(synth->type[c]){
@@ -511,18 +505,6 @@
default:
break;
}
-
-
-#if 0
- st_warn("synth: type=%d, mix=%d, time=%lf, f1=%lf, f2=%lf",
- synth->type[c], synth->mix[c],
- synth->time, synth->freq[c], synth->freq2[c]);
- st_warn("synth: p0=%f, p1=%f, p2=%f, p3=%f, p4=%f",synth->par[c][0],
- synth->par[c][1],synth->par[c][2],synth->par[c][3],synth->par[c][4]);
- st_warn("synth: inchan =%d, rate=%d",
- (int)effp->ininfo.channels,synth->rate
- );
-#endif
}
return (ST_SUCCESS);
}
@@ -562,7 +544,6 @@
sd = fmod(sd+synth->par[c][1],1.0); /* phase einbauen */
-// sd = fmod( (synth->samples_done - synth->h[c])/om + synth->par[c][1],1.0);
switch(synth->type[c]){
case SYNTH_SINE:
r = sin(2.0 * M_PI * sd);