shithub: sox

Download patch

ref: 0cee7c9348804ae78bb4620fd87222c489b3badb
parent: 00246a9fe1c6a6242a1db68db1be619556a74fbe
author: cbagwell <cbagwell>
date: Mon Aug 27 13:59:55 EDT 2001

Adding parsesamples function that will replace parsetime.
It doesn't use floats but requires knowledge of sample rate
when called.

--- a/src/util.c
+++ b/src/util.c
@@ -2,8 +2,8 @@
  * 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 
+ * any purpose.  This copyright notice must be maintained.
+ * Lance Norskog And Sundry Contributors are not responsible for
  * the consequences of using this software.
  */
 
@@ -28,52 +28,52 @@
 
 /* export flags */
 /* FIXME: To be moved inside of fileop structure per handler. */
-int verbose = 0;	/* be noisy on stderr */
+int verbose = 0;        /* be noisy on stderr */
 
 /* FIXME:  These functions are user level concepts.  Move them outside
- * the ST library. 
+ * the ST library.
  */
 char *myname = 0;
 
-void st_report(const char *fmt, ...) 
+void st_report(const char *fmt, ...)
 {
-	va_list args;
+        va_list args;
 
-	if (! verbose)
-		return;
+        if (! verbose)
+                return;
 
-	fprintf(stderr, "%s: ", myname);
-	va_start(args, fmt);
-	vfprintf(stderr, fmt, args);
-	va_end(args);
-	fprintf(stderr, "\n");
+        fprintf(stderr, "%s: ", myname);
+        va_start(args, fmt);
+        vfprintf(stderr, fmt, args);
+        va_end(args);
+        fprintf(stderr, "\n");
 }
 
-void st_warn(const char *fmt, ...) 
+void st_warn(const char *fmt, ...)
 {
-	va_list args;
+        va_list args;
 
-	fprintf(stderr, "%s: ", myname);
-	va_start(args, fmt);
+        fprintf(stderr, "%s: ", myname);
+        va_start(args, fmt);
 
-	vfprintf(stderr, fmt, args);
-	va_end(args);
-	fprintf(stderr, "\n");
+        vfprintf(stderr, fmt, args);
+        va_end(args);
+        fprintf(stderr, "\n");
 }
 
-void st_fail(const char *fmt, ...) 
+void st_fail(const char *fmt, ...)
 {
-	va_list args;
-	extern void cleanup();
+        va_list args;
+        extern void cleanup();
 
-	fprintf(stderr, "%s: ", myname);
+        fprintf(stderr, "%s: ", myname);
 
-	va_start(args, fmt);
-	vfprintf(stderr, fmt, args);
-	va_end(args);
-	fprintf(stderr, "\n");
-	cleanup();
-	exit(2);
+        va_start(args, fmt);
+        vfprintf(stderr, fmt, args);
+        va_end(args);
+        fprintf(stderr, "\n");
+        cleanup();
+        exit(2);
 }
 
 
@@ -84,14 +84,14 @@
  */
 void st_fail_errno(ft_t ft, int st_errno, const char *fmt, ...)
 {
-	va_list args;
+        va_list args;
 
-	ft->st_errno = st_errno;
+        ft->st_errno = st_errno;
 
-	va_start(args, fmt);
-	vsnprintf(ft->st_errstr, 255,fmt, args);
-	va_end(args);
-	ft->st_errstr[255] = '\0';
+        va_start(args, fmt);
+        vsnprintf(ft->st_errstr, 255,fmt, args);
+        va_end(args);
+        ft->st_errstr[255] = '\0';
 }
 
 int st_is_bigendian(void)
@@ -102,9 +102,9 @@
     b = 1;
     p = (char *) &b;
     if (!*p)
-	return 1;
+        return 1;
     else
-	return 0;
+        return 0;
 }
 
 int st_is_littleendian(void)
@@ -115,16 +115,16 @@
     b = 1;
     p = (char *) &b;
     if (*p)
-	return 1;
+        return 1;
     else
-	return 0;
+        return 0;
 }
 
 int strcmpcase(char *s1, char *s2)
 {
-	while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
-		s1++, s2++;
-	return *s1 - *s2;
+        while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
+                s1++, s2++;
+        return *s1 - *s2;
 }
 
 /*
@@ -132,44 +132,44 @@
  */
 int st_gettype(ft_t formp)
 {
-	char **list;
-	int i;
+        char **list;
+        int i;
 
-	if (! formp->filetype){
+        if (! formp->filetype){
             st_fail_errno(formp,
-		          ST_EFMT,
-			  "Must give file type for %s file, either as suffix or with -t option",
-			  formp->filename);
-		return(ST_EFMT);
-	}
-	for(i = 0; st_formats[i].names; i++) {
-		for(list = st_formats[i].names; *list; list++) {
-			char *s1 = *list, *s2 = formp->filetype;
-			if (! strcmpcase(s1, s2))
-				break;	/* not a match */
-		}
-		if (! *list)
-			continue;
-		/* Found it! */
-		formp->h = &st_formats[i];
-		return ST_SUCCESS;
-	}
-	if (! strcmpcase(formp->filetype, "snd")) {
-		verbose = 1;
-		st_report("File type '%s' is used to name several different formats.", formp->filetype);
-		st_report("If the file came from a Macintosh, it is probably");
-		st_report("a .ub file with a sample rate of 11025 (or possibly 5012 or 22050).");
-		st_report("Use the sequence '-t .ub -r 11025 file.snd'");
-		st_report("If it came from a PC, it's probably a Soundtool file.");
-		st_report("Use the sequence '-t .sndt file.snd'");
-		st_report("If it came from a NeXT, it's probably a .au file.");
-		st_fail_errno(formp,ST_EFMT,"Use the sequence '-t .au file.snd'\n");
-		return ST_EFMT;
-	}
-	st_fail_errno(formp,ST_EFMT,"File type '%s' of %s file is not known!",
-		formp->filetype, formp->filename);
-	return ST_EFMT;
-}
+                          ST_EFMT,
+                          "Must give file type for %s file, either as suffix or with -t option",
+                          formp->filename);
+                return(ST_EFMT);
+        }
+        for(i = 0; st_formats[i].names; i++) {
+                for(list = st_formats[i].names; *list; list++) {
+                        char *s1 = *list, *s2 = formp->filetype;
+                        if (! strcmpcase(s1, s2))
+                                break;  /* not a match */
+                }
+                if (! *list)
+                        continue;
+                /* Found it! */
+                formp->h = &st_formats[i];
+                return ST_SUCCESS;
+        }
+        if (! strcmpcase(formp->filetype, "snd")) {
+                verbose = 1;
+                st_report("File type '%s' is used to name several different formats.", formp->filetype);
+                st_report("If the file came from a Macintosh, it is probably");
+                st_report("a .ub file with a sample rate of 11025 (or possibly 5012 or 22050).");
+                st_report("Use the sequence '-t .ub -r 11025 file.snd'");
+                st_report("If it came from a PC, it's probably a Soundtool file.");
+                st_report("Use the sequence '-t .sndt file.snd'");
+                st_report("If it came from a NeXT, it's probably a .au file.");
+                st_fail_errno(formp,ST_EFMT,"Use the sequence '-t .au file.snd'\n");
+                return ST_EFMT;
+        }
+        st_fail_errno(formp,ST_EFMT,"File type '%s' of %s file is not known!",
+                formp->filetype, formp->filename);
+        return ST_EFMT;
+}
 
 /*
  * Check that we have a known effect name.  If found, copy name of
@@ -179,47 +179,47 @@
  */
 int st_geteffect_opt(eff_t effp, int argc, char **argv)
 {
-	int i, optind;
+        int i, optind;
 
-	for(i = 0; st_effects[i].name; i++) 
-	{
-	    char *s1 = st_effects[i].name, *s2 = argv[0];
+        for(i = 0; st_effects[i].name; i++)
+        {
+            char *s1 = st_effects[i].name, *s2 = argv[0];
 
-	    while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
-		s1++, s2++;
-	    if (*s1 || *s2)
-		continue;	/* not a match */
+            while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
+                s1++, s2++;
+            if (*s1 || *s2)
+                continue;       /* not a match */
 
-	    /* Found it! */
-	    effp->name = st_effects[i].name;
-	    effp->h = &st_effects[i];
+            /* Found it! */
+            effp->name = st_effects[i].name;
+            effp->h = &st_effects[i];
 
-	    optind = 1;
+            optind = 1;
 
-	    while (optind < argc)
-	    {
-	        for (i = 0; st_effects[i].name; i++)
-	        {
-		    char *s1 = st_effects[i].name, *s2 = argv[optind];
-		    while (*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
-		    s1++, s2++;
-		    if (*s1 || *s2)
-		        continue;
+            while (optind < argc)
+            {
+                for (i = 0; st_effects[i].name; i++)
+                {
+                    char *s1 = st_effects[i].name, *s2 = argv[optind];
+                    while (*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
+                    s1++, s2++;
+                    if (*s1 || *s2)
+                        continue;
 
-		    /* Found it! */
-		    return (optind - 1);
-	        }
-		/* Didn't find a match, try the next argument. */
-		optind++;
-	    }
-	    /* 
-	     * No matches found, all the following arguments are
-	     * for this effect passed in.
-	     */
-	    return (optind - 1);
-	}
+                    /* Found it! */
+                    return (optind - 1);
+                }
+                /* Didn't find a match, try the next argument. */
+                optind++;
+            }
+            /*
+             * No matches found, all the following arguments are
+             * for this effect passed in.
+             */
+            return (optind - 1);
+        }
 
-	return (ST_EOF);
+        return (ST_EOF);
 }
 
 /*
@@ -230,24 +230,24 @@
 
 int st_geteffect(eff_t effp, char *effect_name)
 {
-	int i;
+        int i;
 
-	for(i = 0; st_effects[i].name; i++) {
-		char *s1 = st_effects[i].name, *s2 = effect_name;
+        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 */
+                while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
+                        s1++, s2++;
+                if (*s1 || *s2)
+                        continue;       /* not a match */
 
-		/* Found it! */
-		effp->name = st_effects[i].name;
-		effp->h = &st_effects[i];
+                /* Found it! */
+                effp->name = st_effects[i].name;
+                effp->h = &st_effects[i];
 
-		return ST_SUCCESS;
-	}
+                return ST_SUCCESS;
+        }
 
-	return (ST_EOF);
+        return (ST_EOF);
 }
 
 /*
@@ -257,23 +257,23 @@
 
 int st_checkeffect(char *effect_name)
 {
-	int i;
+        int i;
 
-	for(i = 0; st_effects[i].name; i++) {
-		char *s1 = st_effects[i].name, *s2 = effect_name;
+        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 */
+                while(*s1 && *s2 && (tolower(*s1) == tolower(*s2)))
+                        s1++, s2++;
+                if (*s1 || *s2)
+                        continue;       /* not a match */
 
-		return ST_SUCCESS;
-	}
+                return ST_SUCCESS;
+        }
 
-	return (ST_EOF);
+        return (ST_EOF);
 }
 
-/* 
+/*
  * Copy input and output signal info into effect structures.
  * Must pass in a bitmask containing info of wheither ST_EFF_CHAN
  * or ST_EFF_RATE has been used previously on this effect stream.
@@ -297,7 +297,7 @@
 
     for(i = 0; i < 8; i++) {
         memcpy(&effp->loops[i], &in->loops[i], sizeof(struct st_loopinfo));
-	memcpy(&effp->loops[i], &in->loops[i], sizeof(struct st_loopinfo));
+        memcpy(&effp->loops[i], &in->loops[i], sizeof(struct st_loopinfo));
     }
     effp->instr = in->instr;
     effp->instr = in->instr;
@@ -304,48 +304,48 @@
 
     if (in->info.channels != out->info.channels)
     {
-	/* Only effects with ST_EFF_CHAN flag can actually handle
-	 * outputing a different number of channels then the input.
-	 */
-	if (!(effp->h->flags & ST_EFF_CHAN))
-	{
-	    /* If this effect is being ran before a ST_EFF_CHAN effect
-	     * then effect's output is the same as the input file. Else its
-	     * input contains same number of channels as the output
-	     * file.
-	     */
-	    if (effect_mask & ST_EFF_CHAN)
-		effp->ininfo.channels = out->info.channels;
-	    else
-		effp->outinfo.channels = in->info.channels;
+        /* Only effects with ST_EFF_CHAN flag can actually handle
+         * outputing a different number of channels then the input.
+         */
+        if (!(effp->h->flags & ST_EFF_CHAN))
+        {
+            /* If this effect is being ran before a ST_EFF_CHAN effect
+             * then effect's output is the same as the input file. Else its
+             * input contains same number of channels as the output
+             * file.
+             */
+            if (effect_mask & ST_EFF_CHAN)
+                effp->ininfo.channels = out->info.channels;
+            else
+                effp->outinfo.channels = in->info.channels;
 
-	}
+        }
     }
 
     if (in->info.rate != out->info.rate)
     {
-	/* Only the ST_EFF_RATE effect can handle an input that
-	 * is a different sample rate then the output.
-	 */
-	if (!(effp->h->flags & ST_EFF_RATE))
-	{
-	    if (effect_mask & ST_EFF_RATE)
-		effp->ininfo.rate = out->info.rate;
-	    else
-		effp->outinfo.rate = in->info.rate;
-	}
+        /* Only the ST_EFF_RATE effect can handle an input that
+         * is a different sample rate then the output.
+         */
+        if (!(effp->h->flags & ST_EFF_RATE))
+        {
+            if (effect_mask & ST_EFF_RATE)
+                effp->ininfo.rate = out->info.rate;
+            else
+                effp->outinfo.rate = in->info.rate;
+        }
     }
 
     if (effp->h->flags & ST_EFF_CHAN)
-	effect_mask |= ST_EFF_CHAN;
+        effect_mask |= ST_EFF_CHAN;
     if (effp->h->flags & ST_EFF_RATE)
-	effect_mask |= ST_EFF_RATE;
+        effect_mask |= ST_EFF_RATE;
 
     return effect_mask;
 }
 
 /*
- * File format routines 
+ * File format routines
  */
 
 void st_initformat(ft_t ft)
@@ -367,87 +367,87 @@
 
 void st_copyformat(ft_t ft, ft_t ft2)
 {
-	int noise = 0, i;
-	double factor;
+        int noise = 0, i;
+        double factor;
 
-	if (ft2->info.rate == 0) {
-		ft2->info.rate = ft->info.rate;
-		noise = 1;
-	}
-	if (ft2->info.size == -1) {
-		ft2->info.size = ft->info.size;
-		noise = 1;
-	}
-	if (ft2->info.encoding == -1) {
-		ft2->info.encoding = ft->info.encoding;
-		noise = 1;
-	}
-	if (ft2->info.channels == -1) {
-		ft2->info.channels = ft->info.channels;
-		noise = 1;
-	}
+        if (ft2->info.rate == 0) {
+                ft2->info.rate = ft->info.rate;
+                noise = 1;
+        }
+        if (ft2->info.size == -1) {
+                ft2->info.size = ft->info.size;
+                noise = 1;
+        }
+        if (ft2->info.encoding == -1) {
+                ft2->info.encoding = ft->info.encoding;
+                noise = 1;
+        }
+        if (ft2->info.channels == -1) {
+                ft2->info.channels = ft->info.channels;
+                noise = 1;
+        }
 
-	/* FIXME: Do not copy pointers!  This should be at least
-	 * a malloc+strcpy.
-	 */
-	if (ft2->comment == NULL) {
-		ft2->comment = ft->comment;
-		noise = 1;
-	}
+        /* FIXME: Do not copy pointers!  This should be at least
+         * a malloc+strcpy.
+         */
+        if (ft2->comment == NULL) {
+                ft2->comment = ft->comment;
+                noise = 1;
+        }
 
-	/* 
-	 * copy loop info, resizing appropriately 
-	 * it's in samples, so # channels don't matter
-	 */
-	factor = (double) ft2->info.rate / (double) ft->info.rate;
-	for(i = 0; i < ST_MAX_NLOOPS; i++) {
-		ft2->loops[i].start = ft->loops[i].start * factor;
-		ft2->loops[i].length = ft->loops[i].length * factor;
-		ft2->loops[i].count = ft->loops[i].count;
-		ft2->loops[i].type = ft->loops[i].type;
-	}
-	/* leave SMPTE # alone since it's absolute */
-	ft2->instr = ft->instr;
+        /*
+         * copy loop info, resizing appropriately
+         * it's in samples, so # channels don't matter
+         */
+        factor = (double) ft2->info.rate / (double) ft->info.rate;
+        for(i = 0; i < ST_MAX_NLOOPS; i++) {
+                ft2->loops[i].start = ft->loops[i].start * factor;
+                ft2->loops[i].length = ft->loops[i].length * factor;
+                ft2->loops[i].count = ft->loops[i].count;
+                ft2->loops[i].type = ft->loops[i].type;
+        }
+        /* leave SMPTE # alone since it's absolute */
+        ft2->instr = ft->instr;
 }
 
 /* check that all settings have been given */
-int st_checkformat(ft_t ft) 
+int st_checkformat(ft_t ft)
 {
 
-	ft->st_errno = ST_SUCCESS;
+        ft->st_errno = ST_SUCCESS;
 
-	if (ft->info.rate == 0)
-	{
-		st_fail_errno(ft,ST_EFMT,"Sampling rate for %s file was not given\n", ft->filename);
-		return ST_EOF;
-	}
+        if (ft->info.rate == 0)
+        {
+                st_fail_errno(ft,ST_EFMT,"Sampling rate for %s file was not given\n", ft->filename);
+                return ST_EOF;
+        }
 
-	if (ft->info.size == -1)
-	{
-		st_fail_errno(ft,ST_EFMT,"Data size was not given for %s file\nUse one of -b/-w/-l/-f/-d/-D", ft->filename);
-		return ST_EOF;
-	}
+        if (ft->info.size == -1)
+        {
+                st_fail_errno(ft,ST_EFMT,"Data size was not given for %s file\nUse one of -b/-w/-l/-f/-d/-D", ft->filename);
+                return ST_EOF;
+        }
 
-	if (ft->info.encoding == -1 && ft->info.size != ST_SIZE_FLOAT)
-	{
-		st_fail_errno(ft,ST_EFMT,"Data encoding was not given for %s file\nUse one of -s/-u/-U/-A", ft->filename);
-		return ST_EOF;
-	}
+        if (ft->info.encoding == -1 && ft->info.size != ST_SIZE_FLOAT)
+        {
+                st_fail_errno(ft,ST_EFMT,"Data encoding was not given for %s file\nUse one of -s/-u/-U/-A", ft->filename);
+                return ST_EOF;
+        }
 
-	if ((ft->info.size <= 0) || (ft->info.size > ST_SIZE_MAX))
-	{
-		st_fail_errno(ft,ST_EFMT,"Data size %i for %s file is bogus\n", ft->info.size, ft->filename);
-		return ST_EOF;
-	}
+        if ((ft->info.size <= 0) || (ft->info.size > ST_SIZE_MAX))
+        {
+                st_fail_errno(ft,ST_EFMT,"Data size %i for %s file is bogus\n", ft->info.size, ft->filename);
+                return ST_EOF;
+        }
 
-	/* anyway to check length on st_encoding_str[] ? */ 
-	if (ft->info.encoding <= 0  || ft->info.encoding > ST_ENCODING_MAX)
-	{
-		st_fail_errno(ft,ST_EFMT,"Data encoding %i for %s file is bogus\n", ft->info.encoding, ft->filename);
-		return ST_EOF;
-	}
+        /* anyway to check length on st_encoding_str[] ? */
+        if (ft->info.encoding <= 0  || ft->info.encoding > ST_ENCODING_MAX)
+        {
+                st_fail_errno(ft,ST_EFMT,"Data encoding %i for %s file is bogus\n", ft->info.encoding, ft->filename);
+                return ST_EOF;
+        }
 
-	return ST_SUCCESS;
+        return ST_SUCCESS;
 }
 
 static ft_t ft_queue[2] = {0, 0};
@@ -455,10 +455,10 @@
 static void sigint(int s)
 {
     if (s == SIGINT) {
-	if (ft_queue[0])
-	    ft_queue[0]->file.eof = 1;
-	if (ft_queue[1])
-	    ft_queue[1]->file.eof = 1;
+        if (ft_queue[0])
+            ft_queue[0]->file.eof = 1;
+        if (ft_queue[1])
+            ft_queue[1]->file.eof = 1;
     }
 }
 
@@ -465,12 +465,78 @@
 void sigintreg(ft_t ft)
 {
     if (ft_queue[0] == 0)
-	ft_queue[0] = ft;
+        ft_queue[0] = ft;
     else
-	ft_queue[1] = ft;
+        ft_queue[1] = ft;
     signal(SIGINT, sigint);
 }
 
+/*
+ * st_parsesamples
+ *
+ * Parse a string for # of samples.  If string ends with a 's'
+ * then string is interrepted as a user calculated # of samples.
+ * If string contains ':' or '.' or if it ends with a 't' then its
+ * treated as an amount of time.  This is converted into seconds and
+ * fraction of seconds and then use the sample rate to calculate
+ * # of samples.
+ * Returns ST_EOF on error.
+ */
+int st_parsesamples(ft_t ft, char *str, ULONG *samples, char def)
+{
+    int found_samples = 0, found_time = 0;
+    int time;
+    long long_samples;
+    float frac = 0;
+
+    if (strchr(str, ':') || strchr(str, '.') || str[strlen(str)-1] == 't')
+        found_time = 0;
+    else if (str[strlen(str)-1] == 's')
+        found_samples = 1;
+
+    if (found_time || (def == 't' && !found_samples))
+    {
+        *samples = 0;
+
+        while(1)
+        {
+            if (sscanf(str, "%d", &time) != 1)
+                return ST_EOF;
+            samples += time;
+
+            while (*str != ':' && *str != '.' && str != NULL)
+                str++;
+
+            if (*str == '.' || str == NULL)
+                break;
+
+            /* Skip past ':' */
+            str++;
+            *samples *= 60;
+        }
+
+        if (*str == '.')
+        {
+            str++;
+            if (sscanf(str, "%d", &time) != 1)
+                return ST_EOF;
+            frac = time / 1000;
+        }
+
+        *samples *= ft->info.rate;
+        *samples += (ft->info.rate * frac);
+        return ST_SUCCESS;
+    }
+    if (found_samples || (def == 's' && !found_time))
+    {
+        if (sscanf(str, "%ld", &long_samples) != 1)
+            return ST_EOF;
+        *samples = long_samples;
+        return ST_SUCCESS;
+    }
+    return ST_EOF;
+}
+
 /* Parse a time specification in hh:mm:ss.frac format.  Returns -1 */
 /* on failure. */
 double st_parsetime(char *str)
@@ -477,21 +543,21 @@
 {
     double time, moretime;
     if (sscanf(str, "%lf", &time) != 1)
-	return -1;
+        return -1;
     str = strchr(str, ':');
     if (str == NULL)
-	return time;
-    str++;				/* Skip colon */
+        return time;
+    str++;                              /* Skip colon */
     time *= 60.0;
     if (sscanf(str, "%lf", &moretime) != 1)
-	return -1;
+        return -1;
     time += moretime;
     str = strchr(str, ':');
     if (str == NULL)
-	return time;
-    str++;				/* Skip colon */
+        return time;
+    str++;                              /* Skip colon */
     time *= 60.0;
     if (sscanf(str, "%lf", &moretime) != 1)
-	return -1;
+        return -1;
     return time + moretime;
 }