shithub: sox

Download patch

ref: 987af8fb735b57090361b6ecc5a1916cb386c2f6
parent: 0cee7c9348804ae78bb4620fd87222c489b3badb
author: cbagwell <cbagwell>
date: Wed Aug 29 14:16:58 EDT 2001

Changed fade effect to use in parsesamples() function.

--- a/src/fade.c
+++ b/src/fade.c
@@ -1,34 +1,33 @@
 /* This code is based in skel.c
- * Written by Chris Bagwell (cbagwell@sprynet.com) - March 16, 1999 
+ * Written by Chris Bagwell (cbagwell@sprynet.com) - March 16, 1999
  * Non-skel parts written by
  * Ari Moisio <armoi@sci.fi> Aug 29 2000.
- * 
+ *
  * Copyright 1999 Chris Bagwell And Sundry Contributors
  * This source code is freely redistributable and may be used for
- * any purpose.  This copyright notice must be maintained. 
- * Chris Bagwell And Sundry Contributors are not responsible for 
+ * any purpose.  This copyright notice must be maintained.
+ * Chris Bagwell And Sundry Contributors are not responsible for
  * the consequences of using this software.
  */
 
-/* Time resolution one millisecond */
-#define TIMERES 	1000
 /* Fade curves */
-#define FADE_QUARTER 	'q' 	/* Quarter of sine wave, 0 to pi/2 */
-#define FADE_HALF 	'h' 	/* Half of sine wave, pi/2 to 1.5 * pi 
-				* scaled so that -1 means no output
-				* and 1 means 0 db attenuation. */
-#define FADE_LOG 	'l'	/* Logarithmic curve. Fades -100 db 
-				* in given time. */
-#define FADE_TRI 	't'	/* Linear slope. */
-#define FADE_PAR	'p'	/* Inverted parabola. */
+#define FADE_QUARTER    'q'     /* Quarter of sine wave, 0 to pi/2 */
+#define FADE_HALF       'h'     /* Half of sine wave, pi/2 to 1.5 * pi
+                                * scaled so that -1 means no output
+                                * and 1 means 0 db attenuation. */
+#define FADE_LOG        'l'     /* Logarithmic curve. Fades -100 db
+                                * in given time. */
+#define FADE_TRI        't'     /* Linear slope. */
+#define FADE_PAR        'p'     /* Inverted parabola. */
 
 #include <math.h>
 #include "st.h"
 
 /* Private data for fade file */
-typedef struct fadestuff 
+typedef struct fadestuff
 { /* These are measured as samples */
     ULONG in_start,  in_stop, out_start, out_stop, samplesdone;
+    char *in_stop_str, *out_start_str, *out_stop_str;
     char in_fadetype, out_fadetype;
     int endpadwarned;
 } *fade_t;
@@ -45,109 +44,124 @@
  * The 'info' fields are not yet filled in.
  */
 
-int st_fade_getopts(effp, n, argv) 
-eff_t effp;
-int n;
-char **argv;
+int st_fade_getopts(eff_t effp, int n, char **argv)
 {
 
     fade_t fade = (fade_t) effp->priv;
-    double t_double;
     char t_char;
     int t_argno;
 
     if (n < 1 || n > 4)
     { /* Wrong number of arguments. */
-	st_fail(FADE_USAGE);
-	return(ST_EOF);
+        st_fail(FADE_USAGE);
+        return(ST_EOF);
     }
-    
-    /* because sample rate is unavailable at this point we convert time 
-     * values to seconds * TIMERES and convert them to samples later. 
+
+    /* because sample rate is unavailable at this point we store the
+     * string off for later computations.
      */
 
     if (sscanf(argv[0], "%1[qhltp]", &t_char))
     {
-	fade->in_fadetype = t_char;
-	fade->out_fadetype = t_char;
+        fade->in_fadetype = t_char;
+        fade->out_fadetype = t_char;
 
-	argv++;
-	n--;
+        argv++;
+        n--;
     }
     else
     {
-	/* No type given. */
+        /* No type given. */
         fade->in_fadetype = 'l';
         fade->out_fadetype = 'l';
     }
 
-    t_double = st_parsetime(argv[0]);
-    if (t_double >= 0)
-    { /* got something numerical */
-	/* Don't support in_start. Its job is done by trim effect */
-	fade->in_start = 0;
-	fade->in_stop = t_double * TIMERES;
+    fade->in_stop_str = malloc(strlen(argv[0])+1);
+    if (!fade->in_stop_str)
+    {
+        st_fail("Could not allocate memory");
+        return (ST_EOF);
     }
-    else
-    { /* unnumeric value */
-	st_fail(FADE_USAGE);
-	return(ST_EOF);
-    } /* endif numeric fade-in */
+    strcpy(fade->in_stop_str,argv[0]);
 
-    fade->out_start = fade->out_stop = 0;
+    fade->out_start_str = fade->out_stop_str = 0;
 
-    for (t_argno = 1; t_argno < n && t_argno <= 3; t_argno++)	
-    { /* See if there is fade-in/fade-out times/curves specified. */
-	t_double = st_parsetime(argv[t_argno]);
-	if (t_double >= 0)
-	{
-	    if (t_argno == 1)
-	    {
-		fade->out_stop = t_double * TIMERES;
-		/* Zero fade-out too */
-		fade->out_start = fade->out_stop;
-	    }
-	    else
-	    {
-                fade->out_start = fade->out_stop - t_double * TIMERES;
-	    }
-	}
-	else
-	{
-	    st_fail(FADE_USAGE);
-	    return(ST_EOF);
-	}
+    for (t_argno = 1; t_argno < n && t_argno <= 3; t_argno++)
+    {
+        /* See if there is fade-in/fade-out times/curves specified. */
+        if(t_argno == 1)
+        {
+            fade->out_start_str = malloc(strlen(argv[t_argno])+1);
+            fade->out_stop_str = 0;
+            if (!fade->out_start_str)
+            {
+                st_fail("Could not allocate memory");
+                return (ST_EOF);
+            }
+             strcpy(fade->out_start_str,argv[t_argno]);
+        }
+        else
+        {
+            fade->out_stop_str = malloc(strlen(argv[t_argno])+1);
+            if (!fade->out_stop_str)
+            {
+                st_fail("Could not allocate memory");
+                return (ST_EOF);
+            }
+             strcpy(fade->out_stop_str,argv[t_argno]);
+        }
     } /* End for(t_argno) */
 
-    /* Sanity check for fade times vs total time */
-    if (fade->in_stop > fade->out_start && fade->out_start != 0)
-    { /* Fades too long */
-	st_fail("Fade: End of fade-in should not happen before beginning of fade-out");
-	return(ST_EOF);
-    } /* endif fade time sanity */
-
     return(ST_SUCCESS);
-} 
+}
 
 /*
  * Prepare processing.
  * Do all initializations.
  */
-void st_fade_start(effp)
-eff_t effp;
+int st_fade_start(eff_t effp)
 {
     fade_t fade = (fade_t) effp->priv;
 
     /* converting time values to samples */
-    fade->in_start = (double)fade->in_start * effp->ininfo.rate / TIMERES;
-    fade->in_stop =  (double)fade->in_stop * effp->ininfo.rate / TIMERES;
-    fade->out_start =  (double)fade->out_start * effp->ininfo.rate / TIMERES;
-    fade->out_stop = (double)fade->out_stop * effp->ininfo.rate / TIMERES;
+    fade->in_start = 0;
+    if (st_parsesamples(effp->ininfo.rate, fade->in_stop_str,
+                        &fade->in_stop, 't') != ST_SUCCESS)
+    {
+        st_fail(FADE_USAGE);
+        return(ST_EOF);
+    }
+    if (st_parsesamples(effp->ininfo.rate, fade->out_start_str,
+                        &fade->out_start, 't') != ST_SUCCESS)
+    {
+        st_fail(FADE_USAGE);
+        return(ST_EOF);
+    }
+    if (fade->out_stop_str)
+    {
+        if (st_parsesamples(effp->ininfo.rate, fade->out_stop_str,
+                            &fade->out_stop, 't') != ST_SUCCESS)
+        {
+            st_fail(FADE_USAGE);
+            return(ST_EOF);
+        }
+    }
+    else
+        fade->out_stop = fade->out_start;
 
+    /* Sanity check for fade times vs total time */
+    if (fade->in_stop > fade->out_start && fade->out_start != 0)
+    { /* Fades too long */
+        st_fail("Fade: End of fade-in should not happen before beginning of fade-out");
+        return(ST_EOF);
+    } /* endif fade time sanity */
+
     /* If lead-in is required it is handled as negative sample numbers */
     fade->samplesdone = (fade->in_start < 0 ? fade->in_start :0);
 
     fade->endpadwarned = 0;
+
+    return(ST_SUCCESS);
 }
 
 /*
@@ -154,10 +168,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-void st_fade_flow(effp, ibuf, obuf, isamp, osamp)
-eff_t effp;
-LONG *ibuf, *obuf;
-int *isamp, *osamp;
+int st_fade_flow(eff_t effp, LONG *ibuf, LONG *obuf, int *isamp, int *osamp)
 {
     fade_t fade = (fade_t) effp->priv;
     /* len is total samples, chcnt counts channels */
@@ -171,69 +182,67 @@
 
     for(; len; len--)
     {
-	t_ibuf = (fade->samplesdone < 0 ? 0 : *ibuf);
+        t_ibuf = (fade->samplesdone < 0 ? 0 : *ibuf);
 
-	if ((fade->samplesdone >= fade->in_start) && 
-	    (fade->out_stop == 0 || fade->samplesdone < fade->out_stop))
-	{ /* something to generate output */
-	    if (fade->samplesdone < fade->in_stop)
-	    { /* fade-in phase, increase gain */
-		*obuf = t_ibuf * 
-		    fade_gain(fade->samplesdone - fade->in_start, 
-			      fade->in_stop - fade->in_start, 
-			      fade->in_fadetype);
-	    } /* endif fade-in */
+        if ((fade->samplesdone >= fade->in_start) &&
+            (fade->out_stop == 0 || fade->samplesdone < fade->out_stop))
+        { /* something to generate output */
+            if (fade->samplesdone < fade->in_stop)
+            { /* fade-in phase, increase gain */
+                *obuf = t_ibuf *
+                    fade_gain(fade->samplesdone - fade->in_start,
+                              fade->in_stop - fade->in_start,
+                              fade->in_fadetype);
+            } /* endif fade-in */
 
-	    if (fade->samplesdone >= fade->in_stop && 
-		(fade->out_start == 0 || fade->samplesdone < fade->out_start))
-	    { /* steady gain phase */
-		*obuf = t_ibuf;
-	    } /* endif  steady phase */
+            if (fade->samplesdone >= fade->in_stop &&
+                (fade->out_start == 0 || fade->samplesdone < fade->out_start))
+            { /* steady gain phase */
+                *obuf = t_ibuf;
+            } /* endif  steady phase */
 
-	    if (fade->out_start != 0 && fade->samplesdone >= fade->out_start)
-	    { /* fade-out phase, decrease gain */
-		*obuf = t_ibuf * 
-		    fade_gain(fade->out_stop - fade->samplesdone, 
-			      fade->out_stop - fade->out_start, 
-			      fade->out_fadetype);
-	    } /* endif fade-out */
+            if (fade->out_start != 0 && fade->samplesdone >= fade->out_start)
+            { /* fade-out phase, decrease gain */
+                *obuf = t_ibuf *
+                    fade_gain(fade->out_stop - fade->samplesdone,
+                              fade->out_stop - fade->out_start,
+                              fade->out_fadetype);
+            } /* endif fade-out */
 
-	    t_output = 1;
-	}
-	else
-	{ /* No output generated */
-	    t_output = 0;
-	} /* endif something to output */
+            t_output = 1;
+        }
+        else
+        { /* No output generated */
+            t_output = 0;
+        } /* endif something to output */
 
-	if (fade->samplesdone >= 0 )	 
-	{ /* Something to input  */
-	    *isamp += 1;
-	    ibuf++;
-	} /* endif something accepted as input */
+        if (fade->samplesdone >= 0 )
+        { /* Something to input  */
+            *isamp += 1;
+            ibuf++;
+        } /* endif something accepted as input */
 
-	if (t_output) 
-	{ /* Output generated, update pointers and counters */
-	    obuf++;
-	    *osamp += 1;
-	} /* endif t_output */
+        if (t_output)
+        { /* Output generated, update pointers and counters */
+            obuf++;
+            *osamp += 1;
+        } /* endif t_output */
 
-	/* Process next channel */
-	chcnt++;
-	if (chcnt >= effp->ininfo.channels) 
-	{ /* all channels of this sample processed */
-	    chcnt = 0;
-	    fade->samplesdone += 1;
-	} /* endif all channels */
+        /* Process next channel */
+        chcnt++;
+        if (chcnt >= effp->ininfo.channels)
+        { /* all channels of this sample processed */
+            chcnt = 0;
+            fade->samplesdone += 1;
+        } /* endif all channels */
     } /* endfor */
+    return(ST_SUCCESS);
 }
 
 /*
  * Drain out remaining samples if the effect generates any.
  */
-void st_fade_drain(effp, obuf, osamp)
-eff_t effp;
-LONG *obuf;
-int *osamp;
+int st_fade_drain(eff_t effp, LONG *obuf, LONG *osamp)
 {
     fade_t fade = (fade_t) effp->priv;
     int len, t_chan = 0;
@@ -241,45 +250,51 @@
     len = *osamp;
     *osamp = 0;
 
-    if (fade->out_stop != 0 && fade->samplesdone < fade->out_stop && 
-	!(fade->endpadwarned))
+    if (fade->out_stop != 0 && fade->samplesdone < fade->out_stop &&
+        !(fade->endpadwarned))
     { /* Warning about padding silence into end of sample */
-	st_warn("Fade: warning: End time passed end-of-file. Padding with silence");
-	fade->endpadwarned = 1;
+        st_warn("Fade: warning: End time passed end-of-file. Padding with silence");
+        fade->endpadwarned = 1;
     } /* endif endpadwarned */
 
-    for (;len && (fade->out_stop != 0 && 
-		  fade->samplesdone < fade->out_stop); len--)
+    for (;len && (fade->out_stop != 0 &&
+                  fade->samplesdone < fade->out_stop); len--)
     {
-	*obuf = 0;
-	obuf++;
-	*osamp += 1;
+        *obuf = 0;
+        obuf++;
+        *osamp += 1;
 
-	t_chan++;
-	if (t_chan >= effp->ininfo.channels)
-	{
-	    fade->samplesdone += 1;
-	    t_chan = 0;
-	} /* endif channels */
+        t_chan++;
+        if (t_chan >= effp->ininfo.channels)
+        {
+            fade->samplesdone += 1;
+            t_chan = 0;
+        } /* endif channels */
     } /* endfor */
+    return(ST_SUCCESS);
 }
 
 /*
- * Do anything required when you stop reading samples.  
- *	(free allocated memory, etc.)
+ * Do anything required when you stop reading samples.
+ *      (free allocated memory, etc.)
  */
-void st_fade_stop(effp)
-eff_t effp;
+int st_fade_stop(eff_t effp)
 {
-	/* nothing to do */
+    fade_t fade = (fade_t) effp->priv;
+
+    if (fade->in_stop_str)
+        free(fade->in_stop_str);
+    if (fade->out_start_str)
+        free(fade->out_start_str);
+    if (fade->out_stop_str)
+        free(fade->out_stop_str);
+    return (ST_SUCCESS);
 }
 
 /* Function returns gain value 0.0 - 1.0 according index / range ratio
-* and -1.0 if  type is invalid 
+* and -1.0 if  type is invalid
 * todo: to optimize performance calculate gain every now and then and interpolate */
-static double fade_gain(index, range, type)
-ULONG index, range;
-char type;
+static double fade_gain(ULONG index, ULONG range, char type)
 {
     double retval = 0.0, findex = 0.0;
 
@@ -291,32 +306,32 @@
 
     switch (type)
     {
-	case FADE_TRI : /* triangle  */
-	    retval = findex;
-	    break;
+        case FADE_TRI : /* triangle  */
+            retval = findex;
+            break;
 
-	case FADE_QUARTER : /*  quarter of sinewave */
-	    retval = sin(findex * M_PI / 2);
-	    break;
+        case FADE_QUARTER : /*  quarter of sinewave */
+            retval = sin(findex * M_PI / 2);
+            break;
 
-	case FADE_HALF : /* half of sinewave... eh cosine wave */
-	    retval = (1 - cos(findex * M_PI )) / 2 ;
-	    break;
+        case FADE_HALF : /* half of sinewave... eh cosine wave */
+            retval = (1 - cos(findex * M_PI )) / 2 ;
+            break;
 
-	case FADE_LOG : /* logaritmic */
-	    /* 5 means 100 db attenuation. */
-	    /* todo: should this be adopted with bit depth 	  */
-	    retval =  pow(0.1, (1 - findex) * 5);
-	    break;
+        case FADE_LOG : /* logaritmic */
+            /* 5 means 100 db attenuation. */
+            /* todo: should this be adopted with bit depth        */
+            retval =  pow(0.1, (1 - findex) * 5);
+            break;
 
-	case FADE_PAR : /* inverted parabola */
-	    retval = (1 - (1 - findex)  * (1 - findex));
-	    break;
+        case FADE_PAR : /* inverted parabola */
+            retval = (1 - (1 - findex)  * (1 - findex));
+            break;
 
-	    /* todo: more fade curves? */
-	default : /* Error indicating wrong fade curve */
-	    retval = -1.0;
-	    break;
+            /* todo: more fade curves? */
+        default : /* Error indicating wrong fade curve */
+            retval = -1.0;
+            break;
     } /* endswitch */
 
     return retval;
--- a/src/st.h
+++ b/src/st.h
@@ -6,8 +6,8 @@
  * Copyright 1999 Chris Bagwell
  *
  * This source code is freely redistributable and may be used for
- * any purpose.  This copyright notice must be maintained. 
- * Chris Bagwell And Sundry Contributors are not responsible for 
+ * any purpose.  This copyright notice must be maintained.
+ * Chris Bagwell And Sundry Contributors are not responsible for
  * the consequences of using this software.
  */
 
@@ -35,11 +35,11 @@
 /* FIXME: Move to separate header */
 #ifdef __alpha__
 #include <sys/types.h>   /* To get defines for 32-bit integers */
-#define	LONG	int32_t
-#define ULONG	u_int32_t
+#define LONG    int32_t
+#define ULONG   u_int32_t
 #else
-#define	LONG	long
-#define ULONG	unsigned long
+#define LONG    long
+#define ULONG   unsigned long
 #endif
 
 #define MAXLONG 0x7fffffffL
@@ -64,10 +64,10 @@
 
 /* FIXME: Change to typedef */
 typedef struct  st_signalinfo {
-	LONG		rate;		/* sampling rate */
-	int		size;		/* word length of data */
-	int		encoding;	/* format of sample numbers */
-	int		channels;	/* number of sound channels */
+        LONG            rate;           /* sampling rate */
+        int             size;           /* word length of data */
+        int             encoding;       /* format of sample numbers */
+        int             channels;       /* number of sound channels */
 } st_signalinfo_t;
 
 /* Loop parameters */
@@ -74,10 +74,10 @@
 
 /* FIXME: Change to typedef */
 typedef struct  st_loopinfo {
-	int		start;		/* first sample */
-	int		length;		/* length */
-	int		count;		/* number of repeats, 0=forever */
-	int		type;		/* 0=no, 1=forward, 2=forward/back */
+        int             start;          /* first sample */
+        int             length;         /* length */
+        int             count;          /* number of repeats, 0=forever */
+        int             type;           /* 0=no, 1=forward, 2=forward/back */
 }st_loopinfo_t;
 
 /* Instrument parameters */
@@ -86,20 +86,20 @@
 
 /* FIXME: Change to typedef */
 typedef struct  st_instrinfo {
-	char 		MIDInote;	/* for unity pitch playback */
-	char		MIDIlow, MIDIhi;/* MIDI pitch-bend range */
-	char		loopmode;	/* semantics of loop data */
-	char		nloops;		/* number of active loops */
-	unsigned char	smpte[4];	/* SMPTE offset (hour:min:sec:frame) */
-					/* this is a film audio thing */
+        char            MIDInote;       /* for unity pitch playback */
+        char            MIDIlow, MIDIhi;/* MIDI pitch-bend range */
+        char            loopmode;       /* semantics of loop data */
+        char            nloops;         /* number of active loops */
+        unsigned char   smpte[4];       /* SMPTE offset (hour:min:sec:frame) */
+                                        /* this is a film audio thing */
 } st_instrinfo_t;
 
 
-#define ST_MIDI_UNITY 60	/* MIDI note number to play sample at unity */
+#define ST_MIDI_UNITY 60        /* MIDI note number to play sample at unity */
 
 /* Loop modes, upper 4 bits mask the loop blass, lower 4 bits describe */
 /* the loop behaviour, ie. single shot, bidirectional etc. */
-#define ST_LOOP_NONE          0	
+#define ST_LOOP_NONE          0
 #define ST_LOOP_8             32 /* 8 loops: don't know ?? */
 #define ST_LOOP_SUSTAIN_DECAY 64 /* AIFF style: one sustain & one decay loop */
 
@@ -109,11 +109,11 @@
 
 /* FIXME: Change to typedef */
 typedef struct st_fileinfo {
-	char	*buf;			/* Pointer to data buffer */
-	int	size;			/* Size of buffer */
-	int	count;			/* Count read in to buffer */
-	int	pos;			/* Position in buffer */
-	int	eof;			/* Marker that EOF has been reached */
+        char    *buf;                   /* Pointer to data buffer */
+        int     size;                   /* Size of buffer */
+        int     count;                  /* Count read in to buffer */
+        int     pos;                    /* Position in buffer */
+        int     eof;                    /* Marker that EOF has been reached */
 }st_fileinfo_t;
 
 
@@ -121,9 +121,9 @@
  *  Format information for input and output files.
  */
 
-#define	ST_MAX_PRIVSIZE	330
+#define ST_MAX_PRIVSIZE 330
 
-#define ST_MAX_NLOOPS		8
+#define ST_MAX_NLOOPS           8
 
 /*
  * Handler structure for each format.
@@ -132,66 +132,66 @@
 typedef struct st_soundstream *ft_t;
 
 typedef struct st_format {
-	char	**names;	/* file type names */
-	int	flags;		/* details about file type */
-	int	(*startread)(ft_t ft);			
-	LONG	(*read)(ft_t ft, LONG *buf, LONG len);
-	int	(*stopread)(ft_t ft);
-	int	(*startwrite)(ft_t ft);
-	LONG	(*write)(ft_t ft, LONG *buf, LONG len);
-	int	(*stopwrite)(ft_t ft);
-	int	(*seek)(ft_t ft, LONG offset);
+        char    **names;        /* file type names */
+        int     flags;          /* details about file type */
+        int     (*startread)(ft_t ft);
+        LONG    (*read)(ft_t ft, LONG *buf, LONG len);
+        int     (*stopread)(ft_t ft);
+        int     (*startwrite)(ft_t ft);
+        LONG    (*write)(ft_t ft, LONG *buf, LONG len);
+        int     (*stopwrite)(ft_t ft);
+        int     (*seek)(ft_t ft, LONG offset);
 } st_format_t;
 
 struct st_soundstream {
-	st_signalinfo_t info;	/* signal specifications */
-	st_instrinfo_t instr;	/* instrument specification */
-	st_loopinfo_t loops[ST_MAX_NLOOPS]; /* Looping specification */
-	char	swap;			/* do byte- or word-swap */
-	char	seekable;		/* can seek on this file */
-	LONG	length;			/* estimate of total samples in file - for seeking*/
-	char	*filename;		/* file name */
-	char	*filetype;		/* type of file */
-	char	*comment;		/* comment string */
-	FILE	*fp;			/* File stream pointer */
-	st_fileinfo_t file;	/* File data block */
-	int     st_errno;		/* Failure error codes */
-	char	st_errstr[256];		/* Extend Failure text */
-	st_format_t *h;			/* format struct for this file */
-	/* FIXME: I perfer void * or char * */
-	char	priv[ST_MAX_PRIVSIZE]; /* format's private data area */
+        st_signalinfo_t info;   /* signal specifications */
+        st_instrinfo_t instr;   /* instrument specification */
+        st_loopinfo_t loops[ST_MAX_NLOOPS]; /* Looping specification */
+        char    swap;                   /* do byte- or word-swap */
+        char    seekable;               /* can seek on this file */
+        LONG    length;                 /* estimate of total samples in file - for seeking*/
+        char    *filename;              /* file name */
+        char    *filetype;              /* type of file */
+        char    *comment;               /* comment string */
+        FILE    *fp;                    /* File stream pointer */
+        st_fileinfo_t file;     /* File data block */
+        int     st_errno;               /* Failure error codes */
+        char    st_errstr[256];         /* Extend Failure text */
+        st_format_t *h;                 /* format struct for this file */
+        /* FIXME: I perfer void * or char * */
+        char    priv[ST_MAX_PRIVSIZE]; /* format's private data area */
 };
 
 extern st_format_t st_formats[];
 
 /* file flags field */
-#define ST_FILE_STEREO	1	/* does file format support stereo? */
-#define ST_FILE_LOOPS	2	/* does file format support loops? */
-#define ST_FILE_INSTR	4	/* does file format support instrument specificications? */
-#define ST_FILE_SEEK	8	/* does file format support seeking? */
+#define ST_FILE_STEREO  1       /* does file format support stereo? */
+#define ST_FILE_LOOPS   2       /* does file format support loops? */
+#define ST_FILE_INSTR   4       /* does file format support instrument specificications? */
+#define ST_FILE_SEEK    8       /* does file format support seeking? */
 
-/* Size field */ 
+/* Size field */
 /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
-#define	ST_SIZE_BYTE	1
-#define ST_SIZE_8BIT	1
-#define	ST_SIZE_WORD	2
-#define ST_SIZE_16BIT	2
-#define	ST_SIZE_DWORD	4
-#define ST_SIZE_32BIT	4
-#define	ST_SIZE_FLOAT	5
-#define ST_SIZE_DOUBLE	6
-#define ST_SIZE_IEEE	7	/* IEEE 80-bit floats. */
+#define ST_SIZE_BYTE    1
+#define ST_SIZE_8BIT    1
+#define ST_SIZE_WORD    2
+#define ST_SIZE_16BIT   2
+#define ST_SIZE_DWORD   4
+#define ST_SIZE_32BIT   4
+#define ST_SIZE_FLOAT   5
+#define ST_SIZE_DOUBLE  6
+#define ST_SIZE_IEEE    7       /* IEEE 80-bit floats. */
 
 #define ST_SIZE_MAX     7
 
 /* Style field */
-#define ST_ENCODING_UNSIGNED	1 /* unsigned linear: Sound Blaster */
-#define ST_ENCODING_SIGN2	2 /* signed linear 2's comp: Mac */
-#define	ST_ENCODING_ULAW	3 /* U-law signed logs: US telephony, SPARC */
-#define ST_ENCODING_ALAW	4 /* A-law signed logs: non-US telephony */
-#define ST_ENCODING_ADPCM	5 /* Compressed PCM */
-#define ST_ENCODING_IMA_ADPCM	6 /* Compressed PCM */
-#define ST_ENCODING_GSM		7 /* GSM 6.10 33-byte frame lossy compression */
+#define ST_ENCODING_UNSIGNED    1 /* unsigned linear: Sound Blaster */
+#define ST_ENCODING_SIGN2       2 /* signed linear 2's comp: Mac */
+#define ST_ENCODING_ULAW        3 /* U-law signed logs: US telephony, SPARC */
+#define ST_ENCODING_ALAW        4 /* A-law signed logs: non-US telephony */
+#define ST_ENCODING_ADPCM       5 /* Compressed PCM */
+#define ST_ENCODING_IMA_ADPCM   6 /* Compressed PCM */
+#define ST_ENCODING_GSM         7 /* GSM 6.10 33-byte frame lossy compression */
 
 #define ST_ENCODING_MAX         7
 
@@ -199,10 +199,10 @@
 extern const char *st_sizes_str[];
 extern const char *st_encodings_str[];
 
-#define	ST_EFF_CHAN	1		/* Effect can mix channels up/down */
-#define ST_EFF_RATE	2		/* Effect can alter data rate */
-#define ST_EFF_MCHAN	4		/* Effect can handle multi-channel */
-#define ST_EFF_REPORT	8		/* Effect does nothing */
+#define ST_EFF_CHAN     1               /* Effect can mix channels up/down */
+#define ST_EFF_RATE     2               /* Effect can alter data rate */
+#define ST_EFF_MCHAN    4               /* Effect can handle multi-channel */
+#define ST_EFF_REPORT   8               /* Effect does nothing */
 
 /*
  * Handler structure for each effect.
@@ -211,33 +211,33 @@
 typedef struct st_effect *eff_t;
 
 typedef struct {
-	char	*name;			/* effect name */
-	int	flags;			/* this and that */
-					/* process arguments */
-	int	(*getopts)(eff_t effp, int argc, char **argv);
-					/* start off effect */
-	int	(*start)(eff_t effp);
-					/* do a buffer */
-	int	(*flow)(eff_t effp, LONG *ibuf, LONG *obuf,
-			LONG *isamp, LONG *osamp);
-					/* drain out at end */
-	int	(*drain)(eff_t effp, LONG *obuf, LONG *osamp);
-	int	(*stop)(eff_t effp);    /* finish up effect */
+        char    *name;                  /* effect name */
+        int     flags;                  /* this and that */
+                                        /* process arguments */
+        int     (*getopts)(eff_t effp, int argc, char **argv);
+                                        /* start off effect */
+        int     (*start)(eff_t effp);
+                                        /* do a buffer */
+        int     (*flow)(eff_t effp, LONG *ibuf, LONG *obuf,
+                        LONG *isamp, LONG *osamp);
+                                        /* drain out at end */
+        int     (*drain)(eff_t effp, LONG *obuf, LONG *osamp);
+        int     (*stop)(eff_t effp);    /* finish up effect */
 } st_effect_t;
 
 struct st_effect {
-	char		*name;		/* effect name */
-	struct st_signalinfo ininfo;	/* input signal specifications */
-	struct st_loopinfo   loops[8];	/* input loops  specifications */
-	struct st_instrinfo  instr;	/* input instrument  specifications */
-	struct st_signalinfo outinfo;	/* output signal specifications */
-	st_effect_t 	*h;		/* effects driver */
-	LONG		*obuf;		/* output buffer */
-	LONG		odone, olen;	/* consumed, total length */
-	/* FIXME: I perfer void * or char * 
-	* Why was this private area 8 times bigger then the soundstream one?
-	* Someone forget to divide ST_MAX_PRIVSIZE by 8 ? */
-	char		priv[ST_MAX_PRIVSIZE*8]; /* private area for effect */
+        char            *name;          /* effect name */
+        struct st_signalinfo ininfo;    /* input signal specifications */
+        struct st_loopinfo   loops[8];  /* input loops  specifications */
+        struct st_instrinfo  instr;     /* input instrument  specifications */
+        struct st_signalinfo outinfo;   /* output signal specifications */
+        st_effect_t     *h;             /* effects driver */
+        LONG            *obuf;          /* output buffer */
+        LONG            odone, olen;    /* consumed, total length */
+        /* FIXME: I perfer void * or char *
+        * Why was this private area 8 times bigger then the soundstream one?
+        * Someone forget to divide ST_MAX_PRIVSIZE by 8 ? */
+        char            priv[ST_MAX_PRIVSIZE*8]; /* private area for effect */
 };
 
 extern st_effect_t st_effects[]; /* declared in handlers.c */
@@ -271,20 +271,20 @@
  * possible byte swapping.
  */
 /* declared in misc.c */
-LONG	st_read(ft_t ft, void *buf, int size, LONG len);
-LONG	st_write(ft_t ft, void *buf, int size, LONG len);
-int	st_reads(ft_t ft, char *c, int len);
-int	st_writes(ft_t ft, char *c);
-int	st_readb(ft_t ft, unsigned char *uc);
-int	st_writeb(ft_t ft, unsigned char uc);
-int	st_readw(ft_t ft, unsigned short *us);
-int	st_writew(ft_t ft, unsigned short us);
-int	st_readdw(ft_t ft, ULONG *ul);		
-int	st_writedw(ft_t ft, ULONG ul);
-int	st_readf(ft_t ft, float *f);
-int	st_writef(ft_t ft, double f);
-int	st_readdf(ft_t ft, double *d);
-int	st_writedf(ft_t ft, double d);
+LONG    st_read(ft_t ft, void *buf, int size, LONG len);
+LONG    st_write(ft_t ft, void *buf, int size, LONG len);
+int     st_reads(ft_t ft, char *c, int len);
+int     st_writes(ft_t ft, char *c);
+int     st_readb(ft_t ft, unsigned char *uc);
+int     st_writeb(ft_t ft, unsigned char uc);
+int     st_readw(ft_t ft, unsigned short *us);
+int     st_writew(ft_t ft, unsigned short us);
+int     st_readdw(ft_t ft, ULONG *ul);
+int     st_writedw(ft_t ft, ULONG ul);
+int     st_readf(ft_t ft, float *f);
+int     st_writef(ft_t ft, double f);
+int     st_readdf(ft_t ft, double *d);
+int     st_writedf(ft_t ft, double d);
 int st_seek(ft_t ft, LONG offset, int whence);
 LONG st_filelength(ft_t ft);
 
@@ -307,11 +307,11 @@
 #define st_swapl(x) bswap_32(x)
 #define st_swapf(x) (float)bswap_32((ULONG)(x))
 #else
-unsigned short st_swapw(unsigned short us);		/* Swap short */
-ULONG  	       st_swapl(ULONG ul);			/* Swap long */
-float  	       st_swapf(float f);			/* Swap float */
+unsigned short st_swapw(unsigned short us);             /* Swap short */
+ULONG          st_swapl(ULONG ul);                      /* Swap long */
+float          st_swapf(float f);                       /* Swap float */
 #endif
-double 	       st_swapd(double d);			/* Swap double */
+double         st_swapd(double d);                      /* Swap double */
 
 /* util.c */
 void st_report(const char *, ...);
@@ -339,6 +339,7 @@
 void st_copyformat(ft_t, ft_t);
 int st_checkformat(ft_t);
 double st_parsetime(char *);
+int st_parsesamples(ULONG rate, char *str, ULONG *samples, char def);
 
 /* FIXME: Recording hacks shouldn't display a "sigint" style interface.
  * Instead we should provide a function to call when done playing/recording.
@@ -348,7 +349,7 @@
 
 /* export flags */
 /* FIXME: these declared in util.c, inappropriate for lib */
-extern int verbose;	/* be noisy on stderr */
+extern int verbose;     /* be noisy on stderr */
 extern char *myname;
 
 extern int errno;
@@ -355,14 +356,14 @@
 /* Warning, this is a MAX value used in the library.  Each format and
  * effect may have its own limitations of rate.
  */
-#define	ST_MAXRATE	50L * 1024 /* maximum sample rate in library */
+#define ST_MAXRATE      50L * 1024 /* maximum sample rate in library */
 
 /* FIXME: Move to internal st header */
-#define RIGHT(datum, bits)	((datum) >> bits)
-#define LEFT(datum, bits)	((datum) << bits)
+#define RIGHT(datum, bits)      ((datum) >> bits)
+#define LEFT(datum, bits)       ((datum) << bits)
 
-#ifndef	M_PI
-#define M_PI	3.14159265358979323846
+#ifndef M_PI
+#define M_PI    3.14159265358979323846
 #endif
 #ifndef M_PI_2
 #define M_PI_2  1.57079632679489661923  /* pi/2 */
@@ -370,23 +371,23 @@
 
 
 /* FIXME: Move to platform header file */
-#define READBINARY	"rb"
-#define WRITEBINARY	"wb"
+#define READBINARY      "rb"
+#define WRITEBINARY     "wb"
 #define REMOVE unlink
 
 #define ST_EOF (-1)
 #define ST_SUCCESS (0)
 
-const char *st_version(void);			/* return version number */
+const char *st_version(void);                   /* return version number */
 
 /* ST specific error codes.  The rest directly map from errno. */
-#define ST_EHDR 2000		/* Invalid Audio Header */
-#define ST_EFMT 2001		/* Unsupported data format */
-#define ST_ERATE 2002		/* Unsupported rate for format */
-#define ST_ENOMEM 2003		/* Can't alloc memory */
-#define ST_EPERM 2004		/* Operation not permitted */
-#define ST_ENOTSUP 2005		/* Operation not supported */
-#define ST_EINVAL 2006		/* Invalid argument */
+#define ST_EHDR 2000            /* Invalid Audio Header */
+#define ST_EFMT 2001            /* Unsupported data format */
+#define ST_ERATE 2002           /* Unsupported rate for format */
+#define ST_ENOMEM 2003          /* Can't alloc memory */
+#define ST_EPERM 2004           /* Operation not permitted */
+#define ST_ENOTSUP 2005         /* Operation not supported */
+#define ST_EINVAL 2006          /* Invalid argument */
 
 #ifdef __cplusplus
 } /* end of extern "C" */
--- a/src/util.c
+++ b/src/util.c
@@ -482,7 +482,7 @@
  * # of samples.
  * Returns ST_EOF on error.
  */
-int st_parsesamples(ft_t ft, char *str, ULONG *samples, char def)
+int st_parsesamples(ULONG rate, char *str, ULONG *samples, char def)
 {
     int found_samples = 0, found_time = 0;
     int time;
@@ -523,8 +523,8 @@
             frac = time / 1000;
         }
 
-        *samples *= ft->info.rate;
-        *samples += (ft->info.rate * frac);
+        *samples *= rate;
+        *samples += (rate * frac);
         return ST_SUCCESS;
     }
     if (found_samples || (def == 's' && !found_time))