shithub: sox

Download patch

ref: 793a1f4a418744e14db3c95b3751b91decb4f557
parent: bf963ebdb03c67ec78e7a51b2164b3f6cf14575d
author: cbagwell <cbagwell>
date: Sun Aug 1 17:21:00 EDT 2004

Fix vox handler.  Fix OSS rate calcs.  Allow sphere headers > 265.  Make vorbis comments KEY=value.

--- a/Changelog
+++ b/Changelog
@@ -26,6 +26,15 @@
     machines.
   o Tony Seebregts added a file handler for headerless Dialogic/OKI ADPCM
     files (VOX files).
+  o Jan Paul Schmidt added a repeat effect to do loops the brute force way.
+    This is also good for file format that don't support loops as well.
+  o Fix for OSS driver in rate tolerance calcs that were off because
+    of type conversion problems.  Guenter Geiger.
+  o Allow reading sphere files with headers greater then 256 bytes.  Jimen
+    Ching.
+  o Fix for vorbis were comments are displayed in KEY=value format always.
+    Stop printing some info to stdout in case output is a pipe. Guenter
+    Geiger.
 
 sox-12.17.4
 -----------
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -236,6 +236,11 @@
 };
 #endif
 
+static char *voxnames[] = {
+        "vox",
+        (char *) 0
+};
+
 /* Microsoftt RIFF */
 static char *wavnames[] = {
         "wav",
@@ -376,7 +381,7 @@
         st_vorbisstartwrite, st_vorbiswrite, st_vorbisstopwrite,
         st_format_nothing_seek},
 #endif
-    {vorbisnames, 0,
+    {voxnames, 0,
         st_voxstartread, st_voxread, st_voxstopread,
         st_voxstartwrite, st_voxwrite, st_voxstopwrite,
         st_format_nothing_seek},
--- a/src/oss.c
+++ b/src/oss.c
@@ -27,7 +27,7 @@
 
 #include "st_i.h"
 
-#if	defined(HAVE_OSS)
+#if     defined(HAVE_OSS)
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -49,34 +49,34 @@
     if (ft->info.rate == 0.0) ft->info.rate = 8000;
     if (ft->info.size == -1) ft->info.size = ST_SIZE_BYTE;
     if (ft->info.size == ST_SIZE_BYTE) {
-	sampletype = AFMT_U8;
-	samplesize = 8;
-	if (ft->info.encoding == -1)
-	    ft->info.encoding = ST_ENCODING_UNSIGNED;
-	if (ft->info.encoding != ST_ENCODING_UNSIGNED) {
-	    st_report("OSS driver only supports unsigned with bytes");
-	    st_report("Forcing to unsigned");
-	    ft->info.encoding = ST_ENCODING_UNSIGNED;
-	}
+        sampletype = AFMT_U8;
+        samplesize = 8;
+        if (ft->info.encoding == -1)
+            ft->info.encoding = ST_ENCODING_UNSIGNED;
+        if (ft->info.encoding != ST_ENCODING_UNSIGNED) {
+            st_report("OSS driver only supports unsigned with bytes");
+            st_report("Forcing to unsigned");
+            ft->info.encoding = ST_ENCODING_UNSIGNED;
+        }
     }
     else if (ft->info.size == ST_SIZE_WORD) {
-	sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
-	samplesize = 16;
-	if (ft->info.encoding == -1)
-	    ft->info.encoding = ST_ENCODING_SIGN2;
-	if (ft->info.encoding != ST_ENCODING_SIGN2) {
-	    st_report("OSS driver only supports signed with words");
-	    st_report("Forcing to signed linear");
-	    ft->info.encoding = ST_ENCODING_SIGN2;
-	}
+        sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
+        samplesize = 16;
+        if (ft->info.encoding == -1)
+            ft->info.encoding = ST_ENCODING_SIGN2;
+        if (ft->info.encoding != ST_ENCODING_SIGN2) {
+            st_report("OSS driver only supports signed with words");
+            st_report("Forcing to signed linear");
+            ft->info.encoding = ST_ENCODING_SIGN2;
+        }
     }
     else {
-	sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
-	samplesize = 16;
+        sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
+        samplesize = 16;
         ft->info.size = ST_SIZE_WORD;
-	ft->info.encoding = ST_ENCODING_SIGN2;
-	st_report("OSS driver only supports bytes and words");
-	st_report("Forcing to signed linear word");
+        ft->info.encoding = ST_ENCODING_SIGN2;
+        st_report("OSS driver only supports bytes and words");
+        st_report("Forcing to signed linear word");
     }
 
     if (ft->info.channels == -1) ft->info.channels = 1;
@@ -84,8 +84,8 @@
 
     if (ioctl(fileno(ft->fp), SNDCTL_DSP_RESET, 0) < 0)
     {
-	st_fail_errno(ft,ST_EOF,"Unable to reset OSS driver.  Possibly accessing an invalid file/device");
-	return(ST_EOF);
+        st_fail_errno(ft,ST_EOF,"Unable to reset OSS driver.  Possibly accessing an invalid file/device");
+        return(ST_EOF);
     }
 
     /* Query the supported formats and find the best match
@@ -92,47 +92,47 @@
      */
     rc = ioctl(fileno(ft->fp), SNDCTL_DSP_GETFMTS, &tmp);
     if (rc == 0) {
-    	if ((tmp & sampletype) == 0)
-	{
-	    /* is 16-bit supported? */
-	    if (samplesize == 16 && (tmp & (AFMT_S16_LE|AFMT_S16_BE)) == 0)
-	    {
-		/* Must not like 16-bits, try 8-bits */
-		ft->info.size = ST_SIZE_BYTE;
-		ft->info.encoding = ST_ENCODING_UNSIGNED;
-		st_report("OSS driver doesn't like signed words");
-		st_report("Forcing to unsigned bytes");
-		tmp = sampletype = AFMT_U8;
-		samplesize = 8;
-	    }
-	    /* is 8-bit supported */
-	    else if (samplesize == 8 && (tmp & AFMT_U8) == 0)
-	    {
-		ft->info.size = ST_SIZE_WORD;
-		ft->info.encoding = ST_ENCODING_SIGN2;
-		st_report("OSS driver doesn't like unsigned bytes");
-		st_report("Forcing to signed words");
-		sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
-		samplesize = 16;
-	    }
-	    /* determine which 16-bit format to use */
-	    if (samplesize == 16)
-	    {
-	    	if ((tmp & sampletype) == 0)
-		{
-		    sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
-		    ft->swap = ft->swap ? 0 : 1;
-		}
-	    }
-	}
-	tmp = sampletype;
-	rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SETFMT, &tmp);
+        if ((tmp & sampletype) == 0)
+        {
+            /* is 16-bit supported? */
+            if (samplesize == 16 && (tmp & (AFMT_S16_LE|AFMT_S16_BE)) == 0)
+            {
+                /* Must not like 16-bits, try 8-bits */
+                ft->info.size = ST_SIZE_BYTE;
+                ft->info.encoding = ST_ENCODING_UNSIGNED;
+                st_report("OSS driver doesn't like signed words");
+                st_report("Forcing to unsigned bytes");
+                tmp = sampletype = AFMT_U8;
+                samplesize = 8;
+            }
+            /* is 8-bit supported */
+            else if (samplesize == 8 && (tmp & AFMT_U8) == 0)
+            {
+                ft->info.size = ST_SIZE_WORD;
+                ft->info.encoding = ST_ENCODING_SIGN2;
+                st_report("OSS driver doesn't like unsigned bytes");
+                st_report("Forcing to signed words");
+                sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
+                samplesize = 16;
+            }
+            /* determine which 16-bit format to use */
+            if (samplesize == 16)
+            {
+                if ((tmp & sampletype) == 0)
+                {
+                    sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
+                    ft->swap = ft->swap ? 0 : 1;
+                }
+            }
+        }
+        tmp = sampletype;
+        rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SETFMT, &tmp);
     }
     /* Give up and exit */
     if (rc < 0 || tmp != sampletype)
     {
-	st_fail_errno(ft,ST_EOF,"Unable to set the sample size to %d", samplesize);
-	return (ST_EOF);
+        st_fail_errno(ft,ST_EOF,"Unable to set the sample size to %d", samplesize);
+        return (ST_EOF);
     }
 
     if (ft->info.channels == 2) dsp_stereo = 1;
@@ -141,33 +141,33 @@
     tmp = dsp_stereo;
     if (ioctl(fileno(ft->fp), SNDCTL_DSP_STEREO, &tmp) < 0)
     {
-	st_warn("Couldn't set to %s", dsp_stereo?  "stereo":"mono");
-	dsp_stereo = 0;
+        st_warn("Couldn't set to %s", dsp_stereo?  "stereo":"mono");
+        dsp_stereo = 0;
     }
 
     if (tmp != dsp_stereo)
     {
-	st_warn("Sound card appears to only support %d channels.  Overriding format\n", tmp+1);
-	ft->info.channels = tmp + 1;
+        st_warn("Sound card appears to only support %d channels.  Overriding format\n", tmp+1);
+        ft->info.channels = tmp + 1;
     }
 
     tmp = ft->info.rate;
     if (ioctl (fileno(ft->fp), SNDCTL_DSP_SPEED, &tmp) < 0 || 
-    	ft->info.rate != tmp) {
-	/* If the rate the sound card is using is not within 1% of what
-	 * the user specified then override the user setting.
-	 * The only reason not to always override this is because of
-	 * clock-rounding problems. Sound cards will sometimes use
-	 * things like 44101 when you ask for 44100.  No need overriding
-	 * this and having strange output file rates for something that
-	 * we can't hear anyways.
-	 */
-	if (ft->info.rate - tmp > (tmp * .01) || 
-	    tmp - ft->info.rate > (tmp * .01)) {
-	    st_warn("Unable to set audio speed to %d (set to %d)",
-		     ft->info.rate, tmp);
-	    ft->info.rate = tmp;
-	}
+        ft->info.rate != tmp) {
+        /* If the rate the sound card is using is not within 1% of what
+         * the user specified then override the user setting.
+         * The only reason not to always override this is because of
+         * clock-rounding problems. Sound cards will sometimes use
+         * things like 44101 when you ask for 44100.  No need overriding
+         * this and having strange output file rates for something that
+         * we can't hear anyways.
+         */
+        if ((int)ft->info.rate - tmp > (tmp * .01) || 
+            tmp - (int)ft->info.rate > (tmp * .01)) {
+            st_warn("Unable to set audio speed to %d (set to %d)",
+                     ft->info.rate, tmp);
+            ft->info.rate = tmp;
+        }
     }
 
     /* Find out block size to use last because the driver could compute
@@ -176,8 +176,8 @@
     ft->file.size = 0;
     ioctl (fileno(ft->fp), SNDCTL_DSP_GETBLKSIZE, &ft->file.size);
     if (ft->file.size < 4 || ft->file.size > 65536) {
-	    st_fail_errno(ft,ST_EOF,"Invalid audio buffer size %d", ft->file.size);
-	    return (ST_EOF);
+            st_fail_errno(ft,ST_EOF,"Invalid audio buffer size %d", ft->file.size);
+            return (ST_EOF);
     }
     ft->file.count = 0;
     ft->file.pos = 0;
@@ -184,13 +184,13 @@
     ft->file.eof = 0;
 
     if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
-	st_fail_errno(ft,ST_EOF,"Unable to allocate input/output buffer of size %d", ft->file.size);
-	return (ST_EOF);
+        st_fail_errno(ft,ST_EOF,"Unable to allocate input/output buffer of size %d", ft->file.size);
+        return (ST_EOF);
     }
 
     if (ioctl(fileno(ft->fp), SNDCTL_DSP_SYNC, NULL) < 0) {
-	st_fail_errno(ft,ST_EOF,"Unable to sync dsp");
-	return (ST_EOF);
+        st_fail_errno(ft,ST_EOF,"Unable to sync dsp");
+        return (ST_EOF);
     }
 
     /* Change to non-buffered I/O */
@@ -200,15 +200,15 @@
 /*
  * Do anything required before you start reading samples.
  * Read file header.
- *	Find out sampling rate,
- *	size and encoding of samples,
- *	mono/stereo/quad.
+ *      Find out sampling rate,
+ *      size and encoding of samples,
+ *      mono/stereo/quad.
  */
 int st_ossdspstartread(ft_t ft)
 {
     int rc;
     rc = ossdspinit(ft);
-    sigintreg(ft);	/* Prepare to catch SIGINT */
+    sigintreg(ft);      /* Prepare to catch SIGINT */
     return rc;
 }
 
--- a/src/sphere.c
+++ b/src/sphere.c
@@ -33,12 +33,12 @@
 {
 	sphere_t sphere = (sphere_t) ft->priv;
 	int rc;
-	char buf[256];
+	char *buf;
 	char fldname[64], fldtype[16], fldsval[128];
 	int i;
 	int header_size, bytes_read;
 	long rate;
-	
+
 	/* Needed for rawread() */
 	rc = st_rawstartread(ft);
 	if (rc)
@@ -45,7 +45,7 @@
 	    return rc;
 
 	/* Magic header */
-	if (st_reads(ft, buf, 8) == ST_EOF || strncmp(buf, "NIST_1A", 7) != 0)
+	if (st_reads(ft, fldname, 8) == ST_EOF || strncmp(fldname, "NIST_1A", 7) != 0)
 	{
 	    st_fail_errno(ft,ST_EHDR,"Sphere header does not begin with magic mord 'NIST_1A'");
 	    return(ST_EOF);
@@ -57,14 +57,22 @@
 	    return(ST_EOF);
 	}
 
+	/* Determine header size, and allocate a buffer large enough to hold it. */
 	sscanf(fldsval, "%d", &header_size);
+	buf = (char *)malloc(header_size);
+	if (buf == NULL)
+	{
+	    st_fail_errno(ft,ST_ENOMEM,"Unable to allocate memory");
+	    return(ST_ENOMEM);
+	}
 
 	/* Skip what we have read so far */
 	header_size -= 16;
 
-	if (st_reads(ft, buf, 255) == ST_EOF)
+	if (st_reads(ft, buf, header_size) == ST_EOF)
 	{
 	    st_fail_errno(ft,ST_EHDR,"Error reading Sphere header");
+	    free(buf);
 	    return(ST_EOF);
 	}
 
@@ -122,9 +130,10 @@
 		}
 	    }
 
-	    if (st_reads(ft, buf, 255) == ST_EOF)
+	    if (st_reads(ft, buf, header_size) == ST_EOF)
 	    {
 	        st_fail_errno(ft,ST_EHDR,"Error reading Sphere header");
+		free(buf);
 	        return(ST_EOF);
 	    }
 
@@ -148,9 +157,10 @@
 
 	while (header_size)
 	{
-	    bytes_read = st_read(ft, buf, ST_SIZE_BYTE, (header_size > 256) ? 256 : header_size);
+	    bytes_read = st_read(ft, buf, ST_SIZE_BYTE, header_size);
 	    if (bytes_read == 0)
 	    {
+		free(buf);
 		return(ST_EOF);
 	    }
 	    header_size -= bytes_read;
@@ -168,10 +178,12 @@
 	if (!strcmp(sphere->shorten_check,"ajkg"))
 	{
 	    st_fail_errno(ft,ST_EFMT,"File uses shorten compression, can not handle this.\n");
+	    free(buf);
 	    return(ST_EOF);
 	}
 #endif
 
+	free(buf);
 	return (ST_SUCCESS);
 }
 
--- a/src/vorbis.c
+++ b/src/vorbis.c
@@ -15,6 +15,9 @@
  * any purpose.  This copyright notice must be maintained. 
  * Lance Norskog And Sundry Contributors are not responsible for 
  * the consequences of using this software.
+ *
+ * TODO: When reading in comments, it doesn't understand how to read
+ * more then one comment and doesn't know how to parse KEY=value.
  */
 #include "st_i.h"
 
@@ -39,33 +42,33 @@
 
 /* Private data for Ogg Vorbis file */
 typedef struct vorbis_enc {
-	ogg_stream_state os;
-	ogg_page         og;
-	ogg_packet       op;
-	
-	vorbis_dsp_state vd;
-	vorbis_block     vb;
+        ogg_stream_state os;
+        ogg_page         og;
+        ogg_packet       op;
+        
+        vorbis_dsp_state vd;
+        vorbis_block     vb;
         vorbis_info      vi;
 } vorbis_enc_t;
 
 typedef struct vorbisstuff {
 /* Decoding data */
-	OggVorbis_File *vf;
-	char *buf;
-	int buf_len;
-	int start;
-	int end;  /* Unsent data samples in buf[start] through buf[end-1] */
-	int current_section;
-	int eof;
+        OggVorbis_File *vf;
+        char *buf;
+        int buf_len;
+        int start;
+        int end;  /* Unsent data samples in buf[start] through buf[end-1] */
+        int current_section;
+        int eof;
 
-	vorbis_enc_t *vorbis_enc_data;
+        vorbis_enc_t *vorbis_enc_data;
 } *vorbis_t;
 
 /******** Callback functions used in ov_open_callbacks ************/
 int myclose (void *datasource)
 {
-	/* Do nothing so sox can close the file for us */
-	return 0;
+        /* Do nothing so sox can close the file for us */
+        return 0;
 }
 
 /* Taken from vorbisfile.c in libvorbis source code */
@@ -80,105 +83,105 @@
 /*
  * Do anything required before you start reading samples.
  * Read file header. 
- *	Find out sampling rate, 
- *	size and encoding of samples, 
- *	mono/stereo/quad.
+ *      Find out sampling rate, 
+ *      size and encoding of samples, 
+ *      mono/stereo/quad.
  */
 int st_vorbisstartread(ft_t ft) 
 {
-	vorbis_t vb = (vorbis_t) ft->priv;
-	vorbis_info *vi;
-	vorbis_comment *vc;
-	int comment_size;
-	int i, offset;
+        vorbis_t vb = (vorbis_t) ft->priv;
+        vorbis_info *vi;
+        vorbis_comment *vc;
+        int comment_size;
+        int i, offset;
 
-	ov_callbacks callbacks = {
-		(size_t (*)(void *, size_t, size_t, void *))  fread,
-		(int (*)(void *, ogg_int64_t, int))           _fseek64_wrap,
-		(int (*)(void *))                             myclose,
-		(long (*)(void *))                            ftell
-	};
+        ov_callbacks callbacks = {
+                (size_t (*)(void *, size_t, size_t, void *))  fread,
+                (int (*)(void *, ogg_int64_t, int))           _fseek64_wrap,
+                (int (*)(void *))                             myclose,
+                (long (*)(void *))                            ftell
+        };
 
-	
-	
-	/* Allocate space for decoding structure */
-	vb->vf = malloc(sizeof(OggVorbis_File));
-	if (vb->vf == NULL) 
-	{
-	    st_fail_errno(ft, ST_ENOMEM, "Could not allocate memory");
-	    return (ST_EOF);
-	}
+        
+        
+        /* Allocate space for decoding structure */
+        vb->vf = malloc(sizeof(OggVorbis_File));
+        if (vb->vf == NULL) 
+        {
+            st_fail_errno(ft, ST_ENOMEM, "Could not allocate memory");
+            return (ST_EOF);
+        }
 
-	/* Init the decoder */
-	if (ov_open_callbacks((void *)ft->fp,vb->vf,NULL,0,callbacks) < 0)
-	{
-		st_fail_errno(ft,ST_EHDR,
-			      "Input not an Ogg Vorbis audio stream");
-		return (ST_EOF);
-	}
+        /* Init the decoder */
+        if (ov_open_callbacks((void *)ft->fp,vb->vf,NULL,0,callbacks) < 0)
+        {
+                st_fail_errno(ft,ST_EHDR,
+                              "Input not an Ogg Vorbis audio stream");
+                return (ST_EOF);
+        }
 
-	/* Get info about the Ogg Vorbis stream */
-	vi = ov_info(vb->vf, -1);
-	vc = ov_comment(vb->vf, -1);
+        /* Get info about the Ogg Vorbis stream */
+        vi = ov_info(vb->vf, -1);
+        vc = ov_comment(vb->vf, -1);
 
-	/* Record audio info */
-	ft->info.rate = vi->rate;
-	ft->info.size = ST_SIZE_16BIT;
-	ft->info.encoding = ST_ENCODING_SIGN2;
-	ft->info.channels = vi->channels;
-	
-	/* Record comments */
-	if (vc->comments == 0)
-		ft->comment = NULL;
-	else 
-	{
-		comment_size = 0;
+        /* Record audio info */
+        ft->info.rate = vi->rate;
+        ft->info.size = ST_SIZE_16BIT;
+        ft->info.encoding = ST_ENCODING_SIGN2;
+        ft->info.channels = vi->channels;
+        
+        /* Record comments */
+        if (vc->comments == 0)
+                ft->comment = NULL;
+        else 
+        {
+                comment_size = 0;
 
-		for (i = 0; i < vc->comments; i++)
-			comment_size += vc->comment_lengths[i] + 1;
+                for (i = 0; i < vc->comments; i++)
+                        comment_size += vc->comment_lengths[i] + 1;
 
-		if ( (ft->comment = calloc(comment_size, sizeof(char))) 
-		     == NULL)
-		{
-			ov_clear(vb->vf);
-			free(vb->vf);
+                if ( (ft->comment = calloc(comment_size, sizeof(char))) 
+                     == NULL)
+                {
+                        ov_clear(vb->vf);
+                        free(vb->vf);
 
-			st_fail_errno(ft, ST_ENOMEM, 
-				      "Could not allocate memory");
-			return (ST_EOF);
-		}
-		
-		offset = 0;
-		for (i = 0; i < vc->comments; i++)
-		{
-			strncpy(ft->comment + offset, vc->user_comments[i],
-				vc->comment_lengths[i]);
-			offset += vc->comment_lengths[i];
-			ft->comment[offset] = '\n';
-			offset++;
-		}
-		/* On last comment, end string by overwriting last \n */
-		if (offset > 0)
-		    offset--;
-		ft->comment[offset] = 0;
-	}
-
-	/* Setup buffer */
-	vb->buf_len = DEF_BUF_LEN;
-	if ( (vb->buf = calloc(vb->buf_len, sizeof(char))) == NULL )
-	{
-		ov_clear(vb->vf);
-		free(vb->vf);
-		st_fail_errno(ft, ST_ENOMEM, "Could not allocate memory");
-		return (ST_EOF);
-	}
-	vb->start = vb->end = 0;
+                        st_fail_errno(ft, ST_ENOMEM, 
+                                      "Could not allocate memory");
+                        return (ST_EOF);
+                }
+                
+                offset = 0;
+                for (i = 0; i < vc->comments; i++)
+                {
+                        strncpy(ft->comment + offset, vc->user_comments[i],
+                                vc->comment_lengths[i]);
+                        offset += vc->comment_lengths[i];
+                        ft->comment[offset] = '\n';
+                        offset++;
+                }
+                /* On last comment, end string by overwriting last \n */
+                if (offset > 0)
+                    offset--;
+                ft->comment[offset] = 0;
+        }
 
-	/* Fill in other info */
-	vb->eof = 0;
-	vb->current_section = -1;
+        /* Setup buffer */
+        vb->buf_len = DEF_BUF_LEN;
+        if ( (vb->buf = calloc(vb->buf_len, sizeof(char))) == NULL )
+        {
+                ov_clear(vb->vf);
+                free(vb->vf);
+                st_fail_errno(ft, ST_ENOMEM, "Could not allocate memory");
+                return (ST_EOF);
+        }
+        vb->start = vb->end = 0;
 
-	return (ST_SUCCESS);
+        /* Fill in other info */
+        vb->eof = 0;
+        vb->current_section = -1;
+
+        return (ST_SUCCESS);
 }
 
 
@@ -187,29 +190,29 @@
    BUF_ERROR is something bad happens, and BUF_DATA otherwise */
 int refill_buffer (vorbis_t vb)
 {
-	int num_read;
+        int num_read;
 
-	if (vb->start == vb->end) /* Samples all played */
-		vb->start = vb->end = 0;
+        if (vb->start == vb->end) /* Samples all played */
+                vb->start = vb->end = 0;
 
-	while (vb->end < vb->buf_len)
-	{
-		num_read = ov_read(vb->vf, vb->buf + vb->end,
-				   vb->buf_len - vb->end, 0, 2, 1, 
-				   &vb->current_section);
-		
-		if (num_read == 0)
-			return (BUF_EOF);
-		else if (num_read == OV_HOLE)
-			fprintf(stderr, "Warning: hole in stream; probably harmless\n");
-		else if (num_read < 0)
-			return (BUF_ERROR);
-		else
-			vb->end += num_read;
-			
-	}
-
-	return (BUF_DATA);
+        while (vb->end < vb->buf_len)
+        {
+                num_read = ov_read(vb->vf, vb->buf + vb->end,
+                                   vb->buf_len - vb->end, 0, 2, 1, 
+                                   &vb->current_section);
+                
+                if (num_read == 0)
+                        return (BUF_EOF);
+                else if (num_read == OV_HOLE)
+                        st_warn("Warning: hole in stream; probably harmless\n");
+                else if (num_read < 0)
+                        return (BUF_ERROR);
+                else
+                        vb->end += num_read;
+                        
+        }
+
+        return (BUF_DATA);
 }
 
 
@@ -222,33 +225,33 @@
 
 st_ssize_t st_vorbisread(ft_t ft, st_sample_t *buf, st_ssize_t len) 
 {
-	vorbis_t vb = (vorbis_t) ft->priv;
-	int i;
-	int ret;
-	st_sample_t l;
+        vorbis_t vb = (vorbis_t) ft->priv;
+        int i;
+        int ret;
+        st_sample_t l;
 
 
-	for(i = 0; i < len; i++) {
-		if (vb->start == vb->end)
-		{
-			if (vb->eof)
-				break;
-			ret = refill_buffer(vb);
-			if (ret == BUF_EOF || ret == BUF_ERROR)
-			{
-			    vb->eof = 1;
-			    if (vb->end == 0)
-				break;
-			}
-		}
+        for(i = 0; i < len; i++) {
+                if (vb->start == vb->end)
+                {
+                        if (vb->eof)
+                                break;
+                        ret = refill_buffer(vb);
+                        if (ret == BUF_EOF || ret == BUF_ERROR)
+                        {
+                            vb->eof = 1;
+                            if (vb->end == 0)
+                                break;
+                        }
+                }
 
-		l = (vb->buf[vb->start+1]<<24) 
-			| (0xffffff &  (vb->buf[vb->start]<<16));
-		*(buf + i) = l;
-		vb->start += 2;
-	}
+                l = (vb->buf[vb->start+1]<<24) 
+                        | (0xffffff &  (vb->buf[vb->start]<<16));
+                *(buf + i) = l;
+                vb->start += 2;
+        }
 
-	return i;
+        return i;
 }
 
 /*
@@ -257,12 +260,12 @@
  */
 int st_vorbisstopread(ft_t ft) 
 {
-	vorbis_t vb = (vorbis_t) ft->priv;
+        vorbis_t vb = (vorbis_t) ft->priv;
 
-	free(vb->buf);
-	ov_clear(vb->vf);
+        free(vb->buf);
+        ov_clear(vb->vf);
 
-	return (ST_SUCCESS);
+        return (ST_SUCCESS);
 }
 
 /* Write a page of ogg data to a file.  Taken directly from encode.c in 
@@ -281,154 +284,167 @@
    HEADER_OK otherwise. */
 int write_vorbis_header(ft_t ft, vorbis_enc_t *ve)
 {
-	ogg_packet header_main;
-	ogg_packet header_comments;
-	ogg_packet header_codebooks;
-	vorbis_comment vc;
-	int result;
-	int ret;
+        ogg_packet header_main;
+        ogg_packet header_comments;
+        ogg_packet header_codebooks;
+        vorbis_comment vc;
+        int result;
+        int ret;
+        char *comment;
 
-	/* Make the comment structure */
-	vc.user_comments = calloc(1, sizeof(char *));
-	vc.comment_lengths = calloc(1, sizeof(int));
-	vc.comments = 1;
+        /* Make the comment structure */
+        vc.user_comments = calloc(1, sizeof(char *));
+        vc.comment_lengths = calloc(1, sizeof(int));
+        vc.comments = 1;
 
-	vc.user_comments[0] = ft->comment;
-	vc.comment_lengths[0] = strlen(ft->comment);
+        /* We check if there is a FIELD=value pair already in the comment
+         * if not, add one */
+        if (strchr(ft->comment,'=') == NULL) 
+        {
+            comment = calloc(1,strlen(ft->comment)+strlen("COMMENT=")+1);
+            strncpy(comment,"COMMENT=",strlen("COMMENT="));
+        }
+        else
+            comment = calloc(1,strlen(ft->comment)+1);
 
-	/* Build the packets */
-	vorbis_analysis_headerout(&ve->vd,&vc,
-				  &header_main,
-				  &header_comments,
-				  &header_codebooks);
-	
-	/* And stream them out */
-	ogg_stream_packetin(&ve->os,&header_main);
-	ogg_stream_packetin(&ve->os,&header_comments);
-	ogg_stream_packetin(&ve->os,&header_codebooks);
-	
-	while((result = ogg_stream_flush(&ve->os, &ve->og)))
-	{
-		if(!result) break;
-		ret = oe_write_page(&ve->og, ft->fp);
-		if(!ret)
-		{
-			return HEADER_ERROR;
-		}
-	}
+        strcat(comment,ft->comment);
 
-	return HEADER_OK;
-}
+        vc.user_comments[0] = comment;
+        vc.comment_lengths[0] = strlen(comment);
+
+        /* Build the packets */
+        vorbis_analysis_headerout(&ve->vd,&vc,
+                                  &header_main,
+                                  &header_comments,
+                                  &header_codebooks);
+        
+        /* And stream them out */
+        ogg_stream_packetin(&ve->os,&header_main);
+        ogg_stream_packetin(&ve->os,&header_comments);
+        ogg_stream_packetin(&ve->os,&header_codebooks);
+        
+        while((result = ogg_stream_flush(&ve->os, &ve->og)))
+        {
+                if(!result) break;
+                ret = oe_write_page(&ve->og, ft->fp);
+                if(!ret)
+                {
+                    free(comment);
+                    return HEADER_ERROR;
+                }
+        }
 
+        free(comment);
+        return HEADER_OK;
+}
+
 int st_vorbisstartwrite(ft_t ft) 
 {
-	vorbis_t vb = (vorbis_t) ft->priv;
-	vorbis_enc_t *ve;
-	long rate;
+        vorbis_t vb = (vorbis_t) ft->priv;
+        vorbis_enc_t *ve;
+        long rate;
 
-	/* Allocate memory for all of the structures */
-	ve = vb->vorbis_enc_data = malloc(sizeof(vorbis_enc_t));
-	if (ve == NULL)
-	{
-	    st_fail_errno(ft, ST_ENOMEM, "Could not allocate memory");
-	    return (ST_EOF);
-	}
+        /* Allocate memory for all of the structures */
+        ve = vb->vorbis_enc_data = malloc(sizeof(vorbis_enc_t));
+        if (ve == NULL)
+        {
+            st_fail_errno(ft, ST_ENOMEM, "Could not allocate memory");
+            return (ST_EOF);
+        }
 
-	vorbis_info_init(&ve->vi);
+        vorbis_info_init(&ve->vi);
 
-	/* DEBUG */
-	rate = ft->info.rate;
-	fprintf(stdout, "Channels: %d  Rate: %ld\n", ft->info.channels,
-		rate);
+        /* DEBUG */
+        rate = ft->info.rate;
 
-	if (rate)
-	{
-	    st_fail_errno(ft, ST_EHDR, "Error setting up Ogg Vorbis encorder - make sure you've specied a sane rate and number of channels");
-	}
+        if (rate)
+        {
+            st_fail_errno(ft, ST_EHDR, "Error setting up Ogg Vorbis encorder - make sure you've specied a sane rate and number of channels");
+        }
 
-	/* Set encoding to average bit rate of 112kbps VBR */
-	vorbis_encode_init_vbr(&ve->vi, ft->info.channels, ft->info.rate, 0.3f);
+        /* Set encoding to average bit rate of 112kbps VBR */
+        vorbis_encode_init_vbr(&ve->vi, ft->info.channels, ft->info.rate, 0.3f);
 
-	vorbis_analysis_init(&ve->vd, &ve->vi);
-	vorbis_block_init(&ve->vd, &ve->vb);
-	
-	ogg_stream_init(&ve->os, rand()); /* Random serial number */
-	
-	if (write_vorbis_header(ft, ve) == HEADER_ERROR)
-	{
-    	    st_fail_errno(ft,ST_EHDR,
-			  "Error writing headre for Ogg Vorbis audio stream");
-    	    return (ST_EOF);
-	}
-	
-	return(ST_SUCCESS);	
+        vorbis_analysis_init(&ve->vd, &ve->vi);
+        vorbis_block_init(&ve->vd, &ve->vb);
+        
+        ogg_stream_init(&ve->os, rand()); /* Random serial number */
+        
+        if (write_vorbis_header(ft, ve) == HEADER_ERROR)
+        {
+            st_fail_errno(ft,ST_EHDR,
+                          "Error writing headre for Ogg Vorbis audio stream");
+            return (ST_EOF);
+        }
+        
+        return(ST_SUCCESS);     
 }
 
 st_ssize_t st_vorbiswrite(ft_t ft, st_sample_t *buf, st_ssize_t len) 
 {
-	vorbis_t vb = (vorbis_t) ft->priv;
-	vorbis_enc_t *ve = vb->vorbis_enc_data;
-	st_ssize_t samples = len / ft->info.channels;	
-	float **buffer = vorbis_analysis_buffer(&ve->vd, samples);
-	st_ssize_t i, j;
-	int ret;
-	int eos = 0;
+        vorbis_t vb = (vorbis_t) ft->priv;
+        vorbis_enc_t *ve = vb->vorbis_enc_data;
+        st_ssize_t samples = len / ft->info.channels;   
+        float **buffer = vorbis_analysis_buffer(&ve->vd, samples);
+        st_ssize_t i, j;
+        int ret;
+        int eos = 0;
 
-	/* Copy samples into vorbis buffer */
-	for (i = 0; i < samples; i++)
-		for (j = 0; j < ft->info.channels; j++)
-			buffer[j][i] = buf[i*ft->info.channels + j] 
-				/ 2147483648.0f;
+        /* Copy samples into vorbis buffer */
+        for (i = 0; i < samples; i++)
+                for (j = 0; j < ft->info.channels; j++)
+                        buffer[j][i] = buf[i*ft->info.channels + j] 
+                                / 2147483648.0f;
 
-	vorbis_analysis_wrote(&ve->vd, samples);
-	
-	while(vorbis_analysis_blockout(&ve->vd,&ve->vb)==1)
-	{
-		/* Do the main analysis, creating a packet */
-		vorbis_analysis(&ve->vb, &ve->op);
-		vorbis_bitrate_addblock(&ve->vb);
+        vorbis_analysis_wrote(&ve->vd, samples);
+        
+        while(vorbis_analysis_blockout(&ve->vd,&ve->vb)==1)
+        {
+                /* Do the main analysis, creating a packet */
+                vorbis_analysis(&ve->vb, &ve->op);
+                vorbis_bitrate_addblock(&ve->vb);
 
-		/* Add packet to bitstream */
-		while (vorbis_bitrate_flushpacket(&ve->vd, &ve->op)) 
-		{
-		    ogg_stream_packetin(&ve->os,&ve->op);
-		
-    		    /* If we've gone over a page boundary, we can do actual
-		     * output, so do so (for however many pages are available) 
-		     */
-		
-    		    while(!eos)
-    		    {
-			int result = ogg_stream_pageout(&ve->os,&ve->og);
-			if(!result) break;
-			
-			ret = oe_write_page(&ve->og, ft->fp);
-			if(!ret)
-			    return (ST_EOF);
-
-			if(ogg_page_eos(&ve->og))
-			    eos = 1;
-    		    }
-		}
-	}
-
-	return (ST_SUCCESS);	
-}
+                /* Add packet to bitstream */
+                while (vorbis_bitrate_flushpacket(&ve->vd, &ve->op)) 
+                {
+                    ogg_stream_packetin(&ve->os,&ve->op);
+                
+                    /* If we've gone over a page boundary, we can do actual
+                     * output, so do so (for however many pages are available) 
+                     */
+                
+                    while(!eos)
+                    {
+                        int result = ogg_stream_pageout(&ve->os,&ve->og);
+                        if(!result) break;
+                        
+                        ret = oe_write_page(&ve->og, ft->fp);
+                        if(!ret)
+                            return (ST_EOF);
+
+                        if(ogg_page_eos(&ve->og))
+                            eos = 1;
+                    }
+                }
+        }
 
+        return (ST_SUCCESS);    
+}
+
 int st_vorbisstopwrite(ft_t ft) 
 {
-	vorbis_t vb = (vorbis_t) ft->priv;
-	vorbis_enc_t *ve = vb->vorbis_enc_data;
+        vorbis_t vb = (vorbis_t) ft->priv;
+        vorbis_enc_t *ve = vb->vorbis_enc_data;
 
-	/* Close out the remaining data */
-	st_vorbiswrite(ft, NULL, 0);
+        /* Close out the remaining data */
+        st_vorbiswrite(ft, NULL, 0);
 
-	ogg_stream_clear(&ve->os);
-	vorbis_block_clear(&ve->vb);
-	vorbis_dsp_clear(&ve->vd);
-	vorbis_info_clear(&ve->vi);
+        ogg_stream_clear(&ve->os);
+        vorbis_block_clear(&ve->vb);
+        vorbis_dsp_clear(&ve->vd);
+        vorbis_info_clear(&ve->vi);
 
-	return (ST_SUCCESS);
+        return (ST_SUCCESS);
 }
 
 #endif /* HAVE_LIBVORBIS */