shithub: sox

Download patch

ref: d413c73ca2c43f879fa14afd5cc3186a7c4d8dd5
parent: 3b1fd9df8568594a3b324e276f1e110a7a01f664
author: cbagwell <cbagwell>
date: Sun Mar 4 00:43:51 EST 2001

Cleaning up sox command parser to get ready for allowing multiple
input filenames to be specified.

--- a/src/dat.c
+++ b/src/dat.c
@@ -57,7 +57,8 @@
 #endif
       }
 
-   /* size and encoding are really not necessary except to satisfy caller. */
+   if (ft->info.channels == -1)
+       ft->info.channels = 1;
 
    ft->info.size = ST_SIZE_DOUBLE;
    ft->info.encoding = ST_ENCODING_SIGN2;
--- a/src/sf.c
+++ b/src/sf.c
@@ -136,6 +136,9 @@
 	}
 	ft->info.channels = (int) sf->info.sf_chans;
 
+	if (ft->info.channels == -1)
+	    ft->info.channels = 1;
+
 	/* Read codes and print as comments. */
 	readcodes(ft, &sfhead);
 
--- a/src/sox.c
+++ b/src/sox.c
@@ -77,8 +77,7 @@
 static LONG obufr[BUFSIZ/2];
 
 /* local forward declarations */
-static void init(void);
-static void doopts(int, char **);
+static void doopts(ft_t, int, char **);
 static void usage(char *) NORET;
 static int filetype(int);
 static void process(void);
@@ -88,10 +87,8 @@
 static int flow_effect(int);
 static int drain_effect(int);
 
-static struct st_soundstream informat, outformat;
+static ft_t informat = 0, outformat = 0;
 
-static ft_t ft;
-
 /* We parse effects into a temporary effects table and then place into
  * the real effects table.  This makes it easier to reorder some effects
  * as needed.  For instance, we can run a resampling effect before
@@ -119,8 +116,6 @@
 static struct st_effect user_efftab[MAX_USER_EFF];
 static int nuser_effects;
 
-static char *ifile, *ofile;
-
 int main(argc, argv)
 int argc;
 char **argv;
@@ -127,71 +122,83 @@
 {
 
         int argc_effect;
+	ft_t ft;
 
 	myname = argv[0];
 
-	init();
+	/* Loop over arguments and filenames, stop when an effect name is found */
+	while (optind < argc && st_checkeffect(argv[optind]) != ST_SUCCESS)
+	{
 	
-	ifile = ofile = NULL;
+	    /* 
+	     * Its possible to not specify the output filename by using "-e" option.
+	     * This allows effects to be ran on data but no output file to be
+	     * written.  This loop basically ingores the "-e" option for input files.
+	     */
+	    if (strcmp(argv[optind], "-e"))
+		writing = 1;
+	    else {
+		writing = 0;
+		optind++;  /* Move passed -e */
+	    }
 
-	/* Get input format options */
-	ft = &informat;
-	doopts(argc, argv);
-	/* Get input file */
-	if (optind >= argc)
-		usage("No input file?");
-	
-	ifile = argv[optind];
-	if (! strcmp(ifile, "-"))
-		ft->fp = stdin;
-	else if ((ft->fp = fopen(ifile, READBINARY)) == NULL)
-		st_fail("Can't open input file '%s': %s", 
-			ifile, strerror(errno));
-	ft->filename = ifile;
+	    ft = (ft_t)malloc(sizeof(struct st_soundstream));
+	    st_initformat(ft);
+
+	    doopts(ft, argc, argv);
+
+	    if (optind < argc && writing)
+	    {
+		ft->filename = argv[optind];
+		optind++;
+	    }
+	    else
+	    {
+		ft->filename = 0;
+	    }
+
+	    /* 
+	     * Determine if we will need to loop around again.  If we don't
+	     * then we know we just grabbed the output file information.
+	     */
+	    if (optind < argc && st_checkeffect(argv[optind]) != ST_SUCCESS)
+	    {
+		informat = ft;
+
+		if (! strcmp(informat->filename, "-"))
+		    informat->fp = stdin;
+		else if ((informat->fp = fopen(informat->filename, READBINARY)) == NULL)
+		    st_fail("Can't open input file '%s': %s", 
+			    informat->filename, strerror(errno));
 #if	defined(DUMB_FILESYSTEM)
-	ft->seekable = 0;
+		informat->seekable = 0;
 #else
-	ft->seekable  = (filetype(fileno(informat.fp)) == S_IFREG);
+		informat->seekable  = (filetype(fileno(informat->fp)) == S_IFREG);
 #endif
-
-	optind++;
-
-	/* If more arguments are left then look for -e to see if */
-	/* no output file is used, then just do an effect */
-	if (optind < argc && strcmp(argv[optind], "-e"))
-	    writing = 1;
-	else if (optind < argc) {
-	    writing = 0;
-	    optind++;  /* Move passed -e */
+	    }
+	    else
+	    {
+		outformat = ft;
+		if (writing)
+		{
+		    /* 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.
+		     */
+		}
+	    }
 	}
-	else
-	    writing = 1;  /* No arguments left but let next check fail */
-	    
-	/* Get output format options */
-	ft = &outformat;
-	doopts(argc, argv);
 
-	/* Find and save output filename, if writing to file */
-	if (writing) {
-	    /* Get output file */
-	    if (optind >= argc)
-		usage("No output file?");
-	    ofile = argv[optind];
-	    ft->filename = ofile;
+	/* Make sure we got all required filenames */
+	if (!informat || !informat->filename)
+	    usage("No input file?");
 
-	    /* Move passed filename */
-	    optind++;
+	if (!outformat || (!outformat->filename && writing))
+	    usage("No output file?");
 
-	    /* 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.
-	     */
-	}
-
-
 	/* Loop through the reset of the arguments looking for effects */
 	nuser_effects = 0;
 
@@ -235,23 +242,23 @@
 	    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)
-			informat.filetype++;
+	if (! informat->filetype) {
+		if ((informat->filetype = strrchr(informat->filename, LASTCHAR)) != NULL)
+			informat->filetype++;
 		else
-			informat.filetype = ifile;
-		if ((informat.filetype = strrchr(informat.filetype, '.')) != NULL)
-			informat.filetype++;
+			informat->filetype = informat->filename;
+		if ((informat->filetype = strrchr(informat->filetype, '.')) != NULL)
+			informat->filetype++;
 		else /* Default to "auto" */
-			informat.filetype = "auto";
+			informat->filetype = "auto";
 	}
-	if (writing && ! outformat.filetype) {
-		if ((outformat.filetype = strrchr(ofile, LASTCHAR)) != NULL)
-			outformat.filetype++;
+	if (writing && ! outformat->filetype) {
+		if ((outformat->filetype = strrchr(outformat->filename, LASTCHAR)) != NULL)
+			outformat->filetype++;
 		else
-			outformat.filetype = ofile;
-		if ((outformat.filetype = strrchr(outformat.filetype, '.')) != NULL)
-			outformat.filetype++;
+			outformat->filetype = outformat->filename;
+		if ((outformat->filetype = strrchr(outformat->filetype, '.')) != NULL)
+			outformat->filetype++;
 	}
 	/* Default the input comment to the filename. 
 	 * The output comment will be assigned when the informat 
@@ -258,7 +265,7 @@
 	 * structure is copied to the outformat. 
 	 * FIXME: Should be a memory copy, not a pointer asignment.
 	 */
-	informat.comment = informat.filename;
+	informat->comment = informat->filename;
 
 	process();
 	statistics();
@@ -271,9 +278,7 @@
 static char *getoptstr = "r:v:t:c:phsuUAaigbwlfdDxV";
 #endif
 
-static void doopts(argc, argv)
-int argc;
-char **argv;
+static void doopts(ft_t ft, int argc, char **argv)
 {
 	int c;
 	char *str;
@@ -388,18 +393,6 @@
 	}
 }
 
-static void init(void) {
-
-    /* init files */
-    st_initformat(&informat);
-    st_initformat(&outformat);
-
-    informat.fp        = stdin;
-    outformat.fp       = stdout;
-    informat.filename  = "input";
-    outformat.filename = "output";
-}
-
 /* 
  * Process input file -> effect table -> output file
  *	one buffer at a time
@@ -408,19 +401,23 @@
 static void process(void) {
     int e, f, havedata, flowstatus;
 
-    if( st_gettype(&informat) )
+    if( st_gettype(informat) )
 		st_fail("bad input format");	
     if (writing)
-	if ( st_gettype(&outformat) )
+	if ( st_gettype(outformat) )
 		st_fail("bad output format");	
     
     /* Read and write starters can change their formats. */
-    if ((* informat.h->startread)(&informat) == ST_EOF)
+    if ((* informat->h->startread)(informat) == ST_EOF)
     {
-        st_fail(informat.st_errstr);
+        st_fail(informat->st_errstr);
     }
 
-    if ( st_checkformat(&informat) )
+    /* Go a head and assume 1 channel audio if nothing is detected. */
+    if (informat->info.channels == -1)
+	informat->info.channels = 1;
+
+    if ( st_checkformat(informat) )
 		st_fail("bad input format");
     
     if (dovolume)
@@ -427,11 +424,11 @@
 	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], 
-	   st_encodings_str[informat.info.encoding], informat.info.channels, 
-	   (informat.info.channels > 1) ? "channels" : "channel");
-    if (informat.comment)
-	st_report("Input file: comment \"%s\"\n", informat.comment);
+	   informat->info.rate, st_sizes_str[informat->info.size], 
+	   st_encodings_str[informat->info.encoding], informat->info.channels, 
+	   (informat->info.channels > 1) ? "channels" : "channel");
+    if (informat->comment)
+	st_report("Input file: comment \"%s\"\n", informat->comment);
 	
     if (writing) {
         /*
@@ -439,13 +436,13 @@
 	 *	1) stomp the old file - normal shell "> file" behavior
 	 *	2) fail if the old file already exists - csh mode
 	 */
-	 if (! strcmp(ofile, "-"))
+	 if (! strcmp(outformat->filename, "-"))
 	 {
-	    ft->fp = stdout;
+	    outformat->fp = stdout;
 
 	    /* stdout tends to be line-buffered.  Override this */
 	    /* to be Full Buffering. */
-	    if (setvbuf (ft->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
+	    if (setvbuf (outformat->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
 	    {
 	        st_fail("Can't set write buffer");
 	    }
@@ -452,15 +449,15 @@
 	 }
          else {
 
-	     ft->fp = fopen(ofile, WRITEBINARY);
+	     outformat->fp = fopen(outformat->filename, WRITEBINARY);
 
-	     if (ft->fp == NULL)
+	     if (outformat->fp == NULL)
 	         st_fail("Can't open output file '%s': %s", 
-		      ofile, strerror(errno));
+		      outformat->filename, strerror(errno));
 
 	     /* stdout tends to be line-buffered.  Override this */
 	     /* to be Full Buffering. */
-	     if (setvbuf (ft->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
+	     if (setvbuf (outformat->fp,NULL,_IOFBF,sizeof(char)*BUFSIZ))
 	     {
 	         st_fail("Can't set write buffer");
 	     }
@@ -467,25 +464,25 @@
 
         } /* end of else != stdout */
 #if	defined(DUMB_FILESYSTEM)
-	outformat.seekable = 0;
+	outformat->seekable = 0;
 #else
-	outformat.seekable  = (filetype(fileno(outformat.fp)) == S_IFREG);
+	outformat->seekable  = (filetype(fileno(outformat->fp)) == S_IFREG);
 #endif
 
-	st_copyformat(&informat, &outformat);
-	if ((* outformat.h->startwrite)(&outformat) == ST_EOF)
+	st_copyformat(informat, outformat);
+	if ((* outformat->h->startwrite)(outformat) == ST_EOF)
 	{
-	    st_fail(outformat.st_errstr);
+	    st_fail(outformat->st_errstr);
 	}
-	if (st_checkformat(&outformat))
+	if (st_checkformat(outformat))
 		st_fail("bad output format");
 
 	st_report("Output file: using sample rate %lu\n\tsize %s, encoding %s, %d %s",
-	       outformat.info.rate, st_sizes_str[outformat.info.size], 
-	       st_encodings_str[outformat.info.encoding], outformat.info.channels, 
-	       (outformat.info.channels > 1) ? "channels" : "channel");
-	if (outformat.comment)
-	    st_report("Output file: comment \"%s\"\n", outformat.comment);
+	       outformat->info.rate, st_sizes_str[outformat->info.size], 
+	       st_encodings_str[outformat->info.encoding], outformat->info.channels, 
+	       (outformat->info.channels > 1) ? "channels" : "channel");
+	if (outformat->comment)
+	    st_report("Output file: comment \"%s\"\n", outformat->comment);
     }
 
     /* build efftab */
@@ -521,11 +518,11 @@
      * Just like errno, we must set st_errno to known values before
      * calling I/O operations.
      */
-    informat.st_errno = 0;
-    outformat.st_errno = 0;
+    informat->st_errno = 0;
+    outformat->st_errno = 0;
 
     /* Prime while() loop by reading initial chunk of input data. */
-    efftab[0].olen = (*informat.h->read)(&informat, 
+    efftab[0].olen = (*informat->h->read)(informat, 
                                          efftab[0].obuf, (LONG) BUFSIZ);
 
     efftab[0].odone = 0;
@@ -558,14 +555,14 @@
 	    /* 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, 
+		w = (* outformat->h->write)(outformat, 
 			                   efftab[neffects-1].obuf, 
 				           (LONG) efftab[neffects-1].olen);
 	        efftab[neffects-1].odone = efftab[neffects-1].olen;
 	    }
 
-	    if (outformat.st_errno)
-		st_fail(outformat.st_errstr);
+	    if (outformat->st_errno)
+		st_fail(outformat->st_errstr);
 
 	    /* If any effect will never again produce data, give up.  This */
 	    /* works because of the pull status: the effect won't be able to */
@@ -587,7 +584,7 @@
 	    break;
 
         /* Read another chunk of input data. */
-        efftab[0].olen = (*informat.h->read)(&informat, 
+        efftab[0].olen = (*informat->h->read)(informat, 
                                              efftab[0].obuf, (LONG) BUFSIZ);
         efftab[0].odone = 0;
 
@@ -597,8 +594,8 @@
 		                    volume);
     }
 
-    if (informat.st_errno)
-	st_fail(informat.st_errstr);
+    if (informat->st_errno)
+	st_fail(informat->st_errstr);
 
     /* Drain the effects out first to last, 
      * pushing residue through subsequent effects */
@@ -611,7 +608,7 @@
 		break;		/* out of while (1) */
 	
 	    if (writing&&efftab[neffects-1].olen > 0)
-		(* outformat.h->write)(&outformat, efftab[neffects-1].obuf,
+		(* outformat->h->write)(outformat, efftab[neffects-1].obuf,
 				       (LONG) efftab[neffects-1].olen);
 
 	    if (efftab[f].olen != BUFSIZ)
@@ -631,17 +628,17 @@
 	    (* efftabR[e].h->stop)(&efftabR[e]);
     }
 
-    if ((* informat.h->stopread)(&informat) == ST_EOF)
-	st_fail(informat.st_errstr);
-    fclose(informat.fp);
+    if ((* informat->h->stopread)(informat) == ST_EOF)
+	st_fail(informat->st_errstr);
+    fclose(informat->fp);
 
     if (writing)
     {
-        if ((* outformat.h->stopwrite)(&outformat) == ST_EOF)
-	    st_fail(outformat.st_errstr);
+        if ((* outformat->h->stopwrite)(outformat) == ST_EOF)
+	    st_fail(outformat->st_errstr);
     }
     if (writing)
-        fclose(outformat.fp);
+        fclose(outformat->fp);
 }
 
 static int flow_effect(e)
@@ -760,8 +757,8 @@
 	int needchan = 0, needrate = 0, haschan = 0, hasrate = 0;
 	int effects_mask = 0;
 
-	needrate = (informat.info.rate != outformat.info.rate);
-	needchan = (informat.info.channels != outformat.info.channels);
+	needrate = (informat->info.rate != outformat->info.rate);
+	needchan = (informat->info.channels != outformat->info.channels);
 
 	for (i = 0; i < nuser_effects; i++)
 	{
@@ -803,7 +800,7 @@
 	 * after the avg effect.
 	 */
         if (needchan && !(haschan) &&
-	    (informat.info.channels > outformat.info.channels))
+	    (informat->info.channels > outformat->info.channels))
         {
 	    /* Find effect and update initial pointers */
 	    st_geteffect(&efftab[neffects], "avg");
@@ -813,8 +810,8 @@
 					    (char **)0);
 
 	    /* Copy format info to effect table */
-	    effects_mask = st_updateeffect(&efftab[neffects], &informat, 
-		                           &outformat, effects_mask);
+	    effects_mask = st_updateeffect(&efftab[neffects], informat, 
+		                           outformat, effects_mask);
 
 	    neffects++;
 	}
@@ -823,7 +820,7 @@
 	 * after the resample effect.
 	 */
 	if (needrate && !(hasrate) &&
-	    (informat.info.rate > outformat.info.rate))
+	    (informat->info.rate > outformat->info.rate))
 	{
 	    if (soxpreview)
 	        st_geteffect(&efftab[neffects], "rate");
@@ -835,8 +832,8 @@
 					    (char **)0);
 
 	    /* Copy format info to effect table */
-	    effects_mask = st_updateeffect(&efftab[neffects], &informat, 
-		                           &outformat, effects_mask);
+	    effects_mask = st_updateeffect(&efftab[neffects], informat, 
+		                           outformat, effects_mask);
 
 	    /* Rate can't handle multiple channels so be sure and
 	     * account for that.
@@ -857,8 +854,8 @@
 		   sizeof(struct st_effect));
 
 	    /* Copy format info to effect table */
-	    effects_mask = st_updateeffect(&efftab[neffects], &informat, 
-		                           &outformat, effects_mask);
+	    effects_mask = st_updateeffect(&efftab[neffects], informat, 
+		                           outformat, effects_mask);
 
 	    /* If this effect can't handle multiple channels then
 	     * account for this.
@@ -889,8 +886,8 @@
 					    (char **)0);
 
 	    /* Copy format info to effect table */
-	    effects_mask = st_updateeffect(&efftab[neffects], &informat, 
-		                           &outformat, effects_mask);
+	    effects_mask = st_updateeffect(&efftab[neffects], informat, 
+		                           outformat, effects_mask);
 
 	    /* Rate can't handle multiple channels so be sure and
 	     * account for that.
@@ -916,8 +913,8 @@
 					    (char **)0);
 
 	    /* Copy format info to effect table */
-	    effects_mask = st_updateeffect(&efftab[neffects], &informat, 
-		                           &outformat, effects_mask);
+	    effects_mask = st_updateeffect(&efftab[neffects], informat, 
+		                           outformat, effects_mask);
 
 	    neffects++;
 	}
@@ -1000,13 +997,13 @@
 /* called from util.c:fail */
 void cleanup(void) {
 	/* Close the input file and outputfile before exiting*/
-	if (informat.fp)
-		fclose(informat.fp);
-	if (outformat.fp) {
-		fclose(outformat.fp);
+	if (informat->fp)
+		fclose(informat->fp);
+	if (outformat->fp) {
+		fclose(outformat->fp);
 		/* remove the output file because we failed, if it's ours. */
 		/* Don't if its not a regular file. */
-		if (filetype(fileno(outformat.fp)) == S_IFREG)
-		    REMOVE(outformat.filename);
+		if (filetype(fileno(outformat->fp)) == S_IFREG)
+		    REMOVE(outformat->filename);
 	}
 }
--- a/src/st.h
+++ b/src/st.h
@@ -332,6 +332,7 @@
 
 int st_geteffect_opt(eff_t, int, char **);
 int st_geteffect(eff_t, char *);
+int st_checkeffect(char *);
 int st_updateeffect(eff_t, ft_t, ft_t, int);
 int st_gettype(ft_t);
 void st_initformat(ft_t ft);
--- a/src/tests.sh
+++ b/src/tests.sh
@@ -30,7 +30,7 @@
 ./sox $noise ub2.aiff ub3.sf
 echo Comparing ub2.sf to ub3.sf, ignoring Comment field
 cmp -l ub2.sf ub3.sf | grep -v '^    2[3456789]'
-rm -f ub2.sf ub2.aiff ub3.sf
+#rm -f ub2.sf ub2.aiff ub3.sf
 #
 # Cmp -l of stop.raw and stop2.raw will show that most of the 
 # bytes are 1 apart.  This is quantization error.
--- a/src/util.c
+++ b/src/util.c
@@ -250,6 +250,29 @@
 	return (ST_EOF);
 }
 
+/*
+ * Check that we have a known effect name.  Return ST_SUCESS if found, else
+ * return ST_EOF.
+ */
+
+int st_checkeffect(char *effect_name)
+{
+	int i;
+
+	for(i = 0; st_effects[i].name; i++) {
+		char *s1 = st_effects[i].name, *s2 = effect_name;
+
+		while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
+			s1++, s2++;
+		if (*s1 || *s2)
+			continue;	/* not a match */
+
+		return ST_SUCCESS;
+	}
+
+	return (ST_EOF);
+}
+
 /* 
  * Copy input and output signal info into effect structures.
  * Must pass in a bitmask containing info of wheither ST_EFF_CHAN