ref: 34d83c1c8e6dfa635a57c3cd07b54c222b6f39f7
parent: b91c9d5d7ce73a1b90794fa008fc2dc4cde53886
author: cbagwell <cbagwell>
date: Thu Oct 25 14:08:12 EDT 2001
Fixed size and encoding problem when writing hdrs of 16-bit stereo files
--- a/Changelog
+++ b/Changelog
@@ -24,6 +24,8 @@
forces strictest alignment.
o ima_rw was miscompiling on alpha's because of a header ordering
problem.
+ o Erik de Castro Lopo pointed out that when writing 16-bit VOC files
+ the headers did not contain the correct length or encoding type.
sox-12.17.2
-----------
--- a/src/voc.c
+++ b/src/voc.c
@@ -1,8 +1,8 @@
/*
* 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.
*
* September 8, 1993
@@ -11,7 +11,7 @@
*
* February 22, 1996
* by Chris Bagwell (cbagwell@sprynet.com)
- * Added support for block type 8 (extended) which allows for 8-bit stereo
+ * Added support for block type 8 (extended) which allows for 8-bit stereo
* files. Added support for saving stereo files and 16-bit files.
* Added VOC format info from audio format FAQ so I don't have to keep
* looking around for it.
@@ -111,7 +111,7 @@
Data is stored left, right
-BLOCK 9 - data block that supersedes blocks 1 and 8.
+BLOCK 9 - data block that supersedes blocks 1 and 8.
Used for stereo, 16 bit.
BYTE bBlockID; // = 9
@@ -120,7 +120,7 @@
BYTE bBitsPerSample; // e.g., 8 or 16
BYTE bChannels; // 1 for mono, 2 for stereo
WORD wFormat; // see below
- BYTE reserved[4]; // pad to make block w/o data
+ BYTE reserved[4]; // pad to make block w/o data
// have a size of 16 bytes
Valid values of wFormat are:
@@ -143,148 +143,148 @@
/* Private data for VOC file */
typedef struct vocstuff {
- LONG rest; /* bytes remaining in current block */
- LONG rate; /* rate code (byte) of this chunk */
- int silent; /* sound or silence? */
- LONG srate; /* rate code (byte) of silence */
- LONG blockseek; /* start of current output block */
- LONG samples; /* number of samples output */
- int size; /* word length of data */
- unsigned char channels; /* number of sound channels */
- int extended; /* Has an extended block been read? */
+ LONG rest; /* bytes remaining in current block */
+ LONG rate; /* rate code (byte) of this chunk */
+ int silent; /* sound or silence? */
+ LONG srate; /* rate code (byte) of silence */
+ LONG blockseek; /* start of current output block */
+ LONG samples; /* number of samples output */
+ int size; /* word length of data */
+ unsigned char channels; /* number of sound channels */
+ int extended; /* Has an extended block been read? */
} *vs_t;
-#define VOC_TERM 0
-#define VOC_DATA 1
-#define VOC_CONT 2
-#define VOC_SILENCE 3
-#define VOC_MARKER 4
-#define VOC_TEXT 5
-#define VOC_LOOP 6
-#define VOC_LOOPEND 7
+#define VOC_TERM 0
+#define VOC_DATA 1
+#define VOC_CONT 2
+#define VOC_SILENCE 3
+#define VOC_MARKER 4
+#define VOC_TEXT 5
+#define VOC_LOOP 6
+#define VOC_LOOPEND 7
#define VOC_EXTENDED 8
-#define VOC_DATA_16 9
+#define VOC_DATA_16 9
-#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define min(a, b) (((a) < (b)) ? (a) : (b))
static int getblock(ft_t);
static void blockstart(ft_t);
static void blockstop(ft_t);
-int st_vocstartread(ft)
+int st_vocstartread(ft)
ft_t ft;
{
- char header[20];
- vs_t v = (vs_t) ft->priv;
- unsigned short sbseek;
- int rc;
+ char header[20];
+ vs_t v = (vs_t) ft->priv;
+ unsigned short sbseek;
+ int rc;
- /* VOC is in Little Endian format. Swap bytes read in on */
- /* Big Endian mahcines. */
- if (ST_IS_BIGENDIAN)
- {
- ft->swap = ft->swap ? 0 : 1;
- }
+ /* VOC is in Little Endian format. Swap bytes read in on */
+ /* Big Endian mahcines. */
+ if (ST_IS_BIGENDIAN)
+ {
+ ft->swap = ft->swap ? 0 : 1;
+ }
- if (! ft->seekable)
- {
- st_fail_errno(ft,ST_EOF,"VOC input file must be a file, not a pipe");
- return(ST_EOF);
- }
+ if (! ft->seekable)
+ {
+ st_fail_errno(ft,ST_EOF,"VOC input file must be a file, not a pipe");
+ return(ST_EOF);
+ }
- if (fread(header, 1, 20, ft->fp) != 20)
- {
- st_fail_errno(ft,ST_EHDR,"unexpected EOF in VOC header");
- return(ST_EOF);
- }
- if (strncmp(header, "Creative Voice File\032", 19))
- {
- st_fail_errno(ft,ST_EHDR,"VOC file header incorrect");
- return(ST_EOF);
- }
+ if (fread(header, 1, 20, ft->fp) != 20)
+ {
+ st_fail_errno(ft,ST_EHDR,"unexpected EOF in VOC header");
+ return(ST_EOF);
+ }
+ if (strncmp(header, "Creative Voice File\032", 19))
+ {
+ st_fail_errno(ft,ST_EHDR,"VOC file header incorrect");
+ return(ST_EOF);
+ }
- st_readw(ft, &sbseek);
- fseek(ft->fp, sbseek, 0);
+ st_readw(ft, &sbseek);
+ fseek(ft->fp, sbseek, 0);
- v->rate = -1;
- v->rest = 0;
- v->extended = 0;
- rc = getblock(ft);
- if (rc)
- return rc;
- if (v->rate == -1)
- {
- st_fail_errno(ft,ST_EOF,"Input .voc file had no sound!");
- return(ST_EOF);
- }
+ v->rate = -1;
+ v->rest = 0;
+ v->extended = 0;
+ rc = getblock(ft);
+ if (rc)
+ return rc;
+ if (v->rate == -1)
+ {
+ st_fail_errno(ft,ST_EOF,"Input .voc file had no sound!");
+ return(ST_EOF);
+ }
- ft->info.size = v->size;
- ft->info.encoding = ST_ENCODING_UNSIGNED;
- if (v->size == ST_SIZE_WORD)
- ft->info.encoding = ST_ENCODING_SIGN2;
- if (ft->info.channels == -1)
- ft->info.channels = v->channels;
+ ft->info.size = v->size;
+ ft->info.encoding = ST_ENCODING_UNSIGNED;
+ if (v->size == ST_SIZE_WORD)
+ ft->info.encoding = ST_ENCODING_SIGN2;
+ if (ft->info.channels == -1)
+ ft->info.channels = v->channels;
- return(ST_SUCCESS);
+ return(ST_SUCCESS);
}
-LONG st_vocread(ft, buf, len)
+LONG st_vocread(ft, buf, len)
ft_t ft;
LONG *buf, len;
{
- vs_t v = (vs_t) ft->priv;
- int done = 0;
- int rc;
- unsigned short us;
- unsigned char uc;
-
- if (v->rest == 0)
- {
- rc = getblock(ft);
- if (rc)
- return 0;
- }
+ vs_t v = (vs_t) ft->priv;
+ int done = 0;
+ int rc;
+ unsigned short us;
+ unsigned char uc;
- if (v->rest == 0)
- return 0;
+ if (v->rest == 0)
+ {
+ rc = getblock(ft);
+ if (rc)
+ return 0;
+ }
- if (v->silent) {
- /* Fill in silence */
- for(;v->rest && (done < len); v->rest--, done++)
- *buf++ = 0x80000000L;
- } else {
- for(;v->rest && (done < len); v->rest--, done++) {
- switch(v->size)
- {
- case ST_SIZE_BYTE:
- if (st_readb(ft, &uc) == ST_EOF) {
- st_warn("VOC input: short file");
- v->rest = 0;
- return done;
- }
- uc ^= 0x80; /* convert to signed */
- *buf++ = LEFT(uc, 24);
- break;
- case ST_SIZE_WORD:
- st_readw(ft, &us);
- if (feof(ft->fp))
- {
- st_warn("VOC input: short file");
- v->rest = 0;
- return done;
- }
- *buf++ = LEFT(us, 16);
- v->rest--; /* Processed 2 bytes so update */
- break;
- }
- }
- }
- return done;
-}
+ if (v->rest == 0)
+ return 0;
+
+ if (v->silent) {
+ /* Fill in silence */
+ for(;v->rest && (done < len); v->rest--, done++)
+ *buf++ = 0x80000000L;
+ } else {
+ for(;v->rest && (done < len); v->rest--, done++) {
+ switch(v->size)
+ {
+ case ST_SIZE_BYTE:
+ if (st_readb(ft, &uc) == ST_EOF) {
+ st_warn("VOC input: short file");
+ v->rest = 0;
+ return done;
+ }
+ uc ^= 0x80; /* convert to signed */
+ *buf++ = LEFT(uc, 24);
+ break;
+ case ST_SIZE_WORD:
+ st_readw(ft, &us);
+ if (feof(ft->fp))
+ {
+ st_warn("VOC input: short file");
+ v->rest = 0;
+ return done;
+ }
+ *buf++ = LEFT(us, 16);
+ v->rest--; /* Processed 2 bytes so update */
+ break;
+ }
+ }
+ }
+ return done;
+}
/* nothing to do */
-int st_vocstopread(ft)
+int st_vocstopread(ft)
ft_t ft;
{
return(ST_SUCCESS);
@@ -294,7 +294,7 @@
* If an 8-bit mono sample then use a VOC_DATA header.
* If an 8-bit stereo sample then use a VOC_EXTENDED header followed
* by a VOC_DATA header.
- * If a 16-bit sample (either stereo or mono) then save with a
+ * If a 16-bit sample (either stereo or mono) then save with a
* VOC_DATA_16 header.
*
* This approach will cause the output to be an its most basic format
@@ -301,76 +301,76 @@
* which will work with the oldest software (eg. an 8-bit mono sample
* will be able to be played with a really old SB VOC player.)
*/
-int st_vocstartwrite(ft)
+int st_vocstartwrite(ft)
ft_t ft;
{
- vs_t v = (vs_t) ft->priv;
+ vs_t v = (vs_t) ft->priv;
- /* VOC is in Little Endian format. Swap whats read */
- /* in on Big Endian machines. */
- if (ST_IS_BIGENDIAN)
- {
- ft->swap = ft->swap ? 0 : 1;
- }
+ /* VOC is in Little Endian format. Swap whats read */
+ /* in on Big Endian machines. */
+ if (ST_IS_BIGENDIAN)
+ {
+ ft->swap = ft->swap ? 0 : 1;
+ }
- if (! ft->seekable)
- {
- st_fail_errno(ft,ST_EOF,"Output .voc file must be a file, not a pipe");
- return(ST_EOF);
- }
+ if (! ft->seekable)
+ {
+ st_fail_errno(ft,ST_EOF,"Output .voc file must be a file, not a pipe");
+ return(ST_EOF);
+ }
- v->samples = 0;
+ v->samples = 0;
- /* File format name and a ^Z (aborts printing under DOS) */
- st_writes(ft, "Creative Voice File\032");
- st_writew(ft, 26); /* size of header */
- st_writew(ft, 0x10a); /* major/minor version number */
- st_writew(ft, 0x1129); /* checksum of version number */
+ /* File format name and a ^Z (aborts printing under DOS) */
+ st_writes(ft, "Creative Voice File\032");
+ st_writew(ft, 26); /* size of header */
+ st_writew(ft, 0x10a); /* major/minor version number */
+ st_writew(ft, 0x1129); /* checksum of version number */
- if (ft->info.size == ST_SIZE_BYTE)
- ft->info.encoding = ST_ENCODING_UNSIGNED;
- else
- ft->info.encoding = ST_ENCODING_SIGN2;
- if (ft->info.channels == -1)
- ft->info.channels = 1;
+ if (ft->info.size == ST_SIZE_BYTE)
+ ft->info.encoding = ST_ENCODING_UNSIGNED;
+ else
+ ft->info.encoding = ST_ENCODING_SIGN2;
+ if (ft->info.channels == -1)
+ ft->info.channels = 1;
- return(ST_SUCCESS);
+ return(ST_SUCCESS);
}
-LONG st_vocwrite(ft, buf, len)
+LONG st_vocwrite(ft, buf, len)
ft_t ft;
LONG *buf, len;
{
- vs_t v = (vs_t) ft->priv;
- unsigned char uc;
- int sw;
- LONG done = 0;
-
- if (v->samples == 0) {
- /* No silence packing yet. */
- v->silent = 0;
- blockstart(ft);
- }
- v->samples += len;
- while(done < len) {
- if (ft->info.size == ST_SIZE_BYTE) {
- uc = RIGHT(*buf++, 24);
- uc ^= 0x80;
- st_writeb(ft, uc);
- } else {
- sw = (int) RIGHT(*buf++, 16);
- st_writew(ft,sw);
+ vs_t v = (vs_t) ft->priv;
+ unsigned char uc;
+ int sw;
+ LONG done = 0;
+
+ if (v->samples == 0) {
+ /* No silence packing yet. */
+ v->silent = 0;
+ blockstart(ft);
+ }
+ v->samples += len;
+ while(done < len) {
+ if (ft->info.size == ST_SIZE_BYTE) {
+ uc = RIGHT(*buf++, 24);
+ uc ^= 0x80;
+ st_writeb(ft, uc);
+ } else {
+ sw = (int) RIGHT(*buf++, 16);
+ st_writew(ft,sw);
}
- done++;
- }
- return done;
+ done++;
+ }
+ return done;
}
-int st_vocstopwrite(ft)
+int st_vocstopwrite(ft)
ft_t ft;
{
- blockstop(ft);
- return(ST_SUCCESS);
+ blockstop(ft);
+ return(ST_SUCCESS);
}
/* Voc-file handlers */
@@ -380,271 +380,270 @@
getblock(ft)
ft_t ft;
{
- vs_t v = (vs_t) ft->priv;
- unsigned char uc, block;
- ULONG sblen;
- unsigned short new_rate_short;
- ULONG new_rate_long;
- int i;
- ULONG trash;
+ vs_t v = (vs_t) ft->priv;
+ unsigned char uc, block;
+ ULONG sblen;
+ unsigned short new_rate_short;
+ ULONG new_rate_long;
+ int i;
+ ULONG trash;
- v->silent = 0;
- while (v->rest == 0) {
- if (feof(ft->fp))
- return ST_SUCCESS;
- st_readb(ft, &block);
- if (block == VOC_TERM)
- return ST_SUCCESS;
- if (feof(ft->fp))
- return ST_SUCCESS;
- /*
- * Size is an 24-bit value. Currently there is no util
- * func to read this so do it this cross-platform way
- *
- */
- st_readb(ft, &uc);
- sblen = uc;
- st_readb(ft, &uc);
- sblen |= ((LONG) uc) << 8;
- st_readb(ft, &uc);
- sblen |= ((LONG) uc) << 16;
- switch(block) {
- case VOC_DATA:
- st_readb(ft, &uc);
- /* When DATA block preceeded by an EXTENDED */
- /* block, the DATA blocks rate value is invalid */
- if (!v->extended) {
- if (uc == 0)
- {
- st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?");
- return(ST_EOF);
- }
- if ((v->rate != -1) && (uc != v->rate))
- {
- st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
- ft->filename,v->rate, uc);
- return(ST_EOF);
- }
- v->rate = uc;
- ft->info.rate = 1000000.0/(256 - v->rate);
- v->channels = 1;
- }
- st_readb(ft, &uc);
- if (uc != 0)
- {
- st_fail_errno(ft,ST_EFMT,"File %s: only interpret 8-bit data!",
- ft->filename);
- return(ST_EOF);
- }
- v->extended = 0;
- v->rest = sblen - 2;
- v->size = ST_SIZE_BYTE;
- return (ST_SUCCESS);
- case VOC_DATA_16:
- st_readdw(ft, &new_rate_long);
- if (new_rate_long == 0)
- {
- st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?",ft->filename);
- return(ST_EOF);
- }
- if ((v->rate != -1) && (new_rate_long != v->rate))
- {
- st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
- ft->filename, v->rate, new_rate_long);
- return(ST_EOF);
- }
- v->rate = new_rate_long;
- ft->info.rate = new_rate_long;
- st_readb(ft, &uc);
- switch (uc)
- {
- case 8: v->size = ST_SIZE_BYTE; break;
- case 16: v->size = ST_SIZE_WORD; break;
- default:
- st_fail_errno(ft,ST_EFMT,"Don't understand size %d", uc);
- return(ST_EOF);
- }
- st_readb(ft, &(v->channels));
- st_readb(ft, (unsigned char *)&trash); /* unknown */
- st_readb(ft, (unsigned char *)&trash); /* notused */
- st_readb(ft, (unsigned char *)&trash); /* notused */
- st_readb(ft, (unsigned char *)&trash); /* notused */
- st_readb(ft, (unsigned char *)&trash); /* notused */
- st_readb(ft, (unsigned char *)&trash); /* notused */
- v->rest = sblen - 12;
- return (ST_SUCCESS);
- case VOC_CONT:
- v->rest = sblen;
- return (ST_SUCCESS);
- case VOC_SILENCE:
- {
- unsigned short period;
+ v->silent = 0;
+ while (v->rest == 0) {
+ if (feof(ft->fp))
+ return ST_SUCCESS;
+ st_readb(ft, &block);
+ if (block == VOC_TERM)
+ return ST_SUCCESS;
+ if (feof(ft->fp))
+ return ST_SUCCESS;
+ /*
+ * Size is an 24-bit value. Currently there is no util
+ * func to read this so do it this cross-platform way
+ *
+ */
+ st_readb(ft, &uc);
+ sblen = uc;
+ st_readb(ft, &uc);
+ sblen |= ((LONG) uc) << 8;
+ st_readb(ft, &uc);
+ sblen |= ((LONG) uc) << 16;
+ switch(block) {
+ case VOC_DATA:
+ st_readb(ft, &uc);
+ /* When DATA block preceeded by an EXTENDED */
+ /* block, the DATA blocks rate value is invalid */
+ if (!v->extended) {
+ if (uc == 0)
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?");
+ return(ST_EOF);
+ }
+ if ((v->rate != -1) && (uc != v->rate))
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
+ ft->filename,v->rate, uc);
+ return(ST_EOF);
+ }
+ v->rate = uc;
+ ft->info.rate = 1000000.0/(256 - v->rate);
+ v->channels = 1;
+ }
+ st_readb(ft, &uc);
+ if (uc != 0)
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: only interpret 8-bit data!",
+ ft->filename);
+ return(ST_EOF);
+ }
+ v->extended = 0;
+ v->rest = sblen - 2;
+ v->size = ST_SIZE_BYTE;
+ return (ST_SUCCESS);
+ case VOC_DATA_16:
+ st_readdw(ft, &new_rate_long);
+ if (new_rate_long == 0)
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?",ft->filename);
+ return(ST_EOF);
+ }
+ if ((v->rate != -1) && (new_rate_long != v->rate))
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
+ ft->filename, v->rate, new_rate_long);
+ return(ST_EOF);
+ }
+ v->rate = new_rate_long;
+ ft->info.rate = new_rate_long;
+ st_readb(ft, &uc);
+ switch (uc)
+ {
+ case 8: v->size = ST_SIZE_BYTE; break;
+ case 16: v->size = ST_SIZE_WORD; break;
+ default:
+ st_fail_errno(ft,ST_EFMT,"Don't understand size %d", uc);
+ return(ST_EOF);
+ }
+ st_readb(ft, &(v->channels));
+ st_readb(ft, (unsigned char *)&trash); /* unknown */
+ st_readb(ft, (unsigned char *)&trash); /* notused */
+ st_readb(ft, (unsigned char *)&trash); /* notused */
+ st_readb(ft, (unsigned char *)&trash); /* notused */
+ st_readb(ft, (unsigned char *)&trash); /* notused */
+ st_readb(ft, (unsigned char *)&trash); /* notused */
+ v->rest = sblen - 12;
+ return (ST_SUCCESS);
+ case VOC_CONT:
+ v->rest = sblen;
+ return (ST_SUCCESS);
+ case VOC_SILENCE:
+ {
+ unsigned short period;
- st_readw(ft, &period);
- st_readb(ft, &uc);
- if (uc == 0)
- {
- st_fail_errno(ft,ST_EFMT,"File %s: Silence sample rate is zero");
- return(ST_EOF);
- }
- /*
- * Some silence-packed files have gratuitously
- * different sample rate codes in silence.
- * Adjust period.
- */
- if ((v->rate != -1) && (uc != v->rate))
- period = (period * (256 - uc))/(256 - v->rate);
- else
- v->rate = uc;
- v->rest = period;
- v->silent = 1;
- return (ST_SUCCESS);
- }
- case VOC_MARKER:
- st_readb(ft, &uc);
- st_readb(ft, &uc);
- /* Falling! Falling! */
- case VOC_TEXT:
- {
- int i;
- /* Could add to comment in SF? */
- for(i = 0; i < sblen; i++)
- st_readb(ft, (unsigned char *)&trash);
- }
- continue; /* get next block */
- case VOC_LOOP:
- case VOC_LOOPEND:
- st_report("File %s: skipping repeat loop");
- for(i = 0; i < sblen; i++)
- st_readb(ft, (unsigned char *)&trash);
- break;
- case VOC_EXTENDED:
- /* An Extended block is followed by a data block */
- /* Set this byte so we know to use the rate */
- /* value from the extended block and not the */
- /* data block. */
- v->extended = 1;
- st_readw(ft, &new_rate_short);
- if (new_rate_short == 0)
- {
- st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?");
- return(ST_EOF);
- }
- if ((v->rate != -1) && (new_rate_short != v->rate))
- {
- st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
- ft->filename, v->rate, new_rate_short);
- return(ST_EOF);
- }
- v->rate = new_rate_short;
- st_readb(ft, &uc);
- if (uc != 0)
- {
- st_fail_errno(ft,ST_EFMT,"File %s: only interpret 8-bit data!",
- ft->filename);
- return(ST_EOF);
- }
- st_readb(ft, &uc);
- if (uc)
- ft->info.channels = 2; /* Stereo */
- /* Needed number of channels before finishing
- compute for rate */
- ft->info.rate = (256000000L/(65536L - v->rate))/ft->info.channels;
- /* An extended block must be followed by a data */
- /* block to be valid so loop back to top so it */
- /* can be grabed. */
- continue;
- default:
- st_report("File %s: skipping unknown block code %d",
- ft->filename, block);
- for(i = 0; i < sblen; i++)
- st_readb(ft, (unsigned char *)&trash);
- }
- }
- return ST_SUCCESS;
-}
+ st_readw(ft, &period);
+ st_readb(ft, &uc);
+ if (uc == 0)
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: Silence sample rate is zero");
+ return(ST_EOF);
+ }
+ /*
+ * Some silence-packed files have gratuitously
+ * different sample rate codes in silence.
+ * Adjust period.
+ */
+ if ((v->rate != -1) && (uc != v->rate))
+ period = (period * (256 - uc))/(256 - v->rate);
+ else
+ v->rate = uc;
+ v->rest = period;
+ v->silent = 1;
+ return (ST_SUCCESS);
+ }
+ case VOC_MARKER:
+ st_readb(ft, &uc);
+ st_readb(ft, &uc);
+ /* Falling! Falling! */
+ case VOC_TEXT:
+ {
+ int i;
+ /* Could add to comment in SF? */
+ for(i = 0; i < sblen; i++)
+ st_readb(ft, (unsigned char *)&trash);
+ }
+ continue; /* get next block */
+ case VOC_LOOP:
+ case VOC_LOOPEND:
+ st_report("File %s: skipping repeat loop");
+ for(i = 0; i < sblen; i++)
+ st_readb(ft, (unsigned char *)&trash);
+ break;
+ case VOC_EXTENDED:
+ /* An Extended block is followed by a data block */
+ /* Set this byte so we know to use the rate */
+ /* value from the extended block and not the */
+ /* data block. */
+ v->extended = 1;
+ st_readw(ft, &new_rate_short);
+ if (new_rate_short == 0)
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?");
+ return(ST_EOF);
+ }
+ if ((v->rate != -1) && (new_rate_short != v->rate))
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
+ ft->filename, v->rate, new_rate_short);
+ return(ST_EOF);
+ }
+ v->rate = new_rate_short;
+ st_readb(ft, &uc);
+ if (uc != 0)
+ {
+ st_fail_errno(ft,ST_EFMT,"File %s: only interpret 8-bit data!",
+ ft->filename);
+ return(ST_EOF);
+ }
+ st_readb(ft, &uc);
+ if (uc)
+ ft->info.channels = 2; /* Stereo */
+ /* Needed number of channels before finishing
+ compute for rate */
+ ft->info.rate = (256000000L/(65536L - v->rate))/ft->info.channels;
+ /* An extended block must be followed by a data */
+ /* block to be valid so loop back to top so it */
+ /* can be grabed. */
+ continue;
+ default:
+ st_report("File %s: skipping unknown block code %d",
+ ft->filename, block);
+ for(i = 0; i < sblen; i++)
+ st_readb(ft, (unsigned char *)&trash);
+ }
+ }
+ return ST_SUCCESS;
+}
/* Start an output block. */
static void blockstart(ft)
ft_t ft;
{
- vs_t v = (vs_t) ft->priv;
+ vs_t v = (vs_t) ft->priv;
- v->blockseek = ftell(ft->fp);
- if (v->silent) {
- st_writeb(ft, VOC_SILENCE); /* Silence block code */
- st_writeb(ft, 0); /* Period length */
- st_writeb(ft, 0); /* Period length */
- st_writeb(ft, v->rate); /* Rate code */
- } else {
- if (ft->info.size == ST_SIZE_BYTE) {
- /* 8-bit sample section. By always setting the correct */
- /* rate value in the DATA block (even when its preceeded */
- /* by an EXTENDED block) old software can still play stereo */
- /* files in mono by just skipping over the EXTENDED block. */
- /* Prehaps the rate should be doubled though to make up for */
- /* double amount of samples for a given time???? */
- if (ft->info.channels > 1) {
- st_writeb(ft, VOC_EXTENDED); /* Voice Extended block code */
- st_writeb(ft, 4); /* block length = 4 */
- st_writeb(ft, 0); /* block length = 4 */
- st_writeb(ft, 0); /* block length = 4 */
- v->rate = 65536L - (256000000.0/(2*(float)ft->info.rate));
- st_writew(ft,v->rate); /* Rate code */
- st_writeb(ft, 0); /* File is not packed */
- st_writeb(ft, 1); /* samples are in stereo */
- }
- st_writeb(ft, VOC_DATA); /* Voice Data block code */
- st_writeb(ft, 0); /* block length (for now) */
- st_writeb(ft, 0); /* block length (for now) */
- st_writeb(ft, 0); /* block length (for now) */
- v->rate = 256 - (1000000.0/(float)ft->info.rate);
- st_writeb(ft, (int) v->rate);/* Rate code */
- st_writeb(ft, 0); /* 8-bit raw data */
- } else {
- st_writeb(ft, VOC_DATA_16); /* Voice Data block code */
- st_writeb(ft, 0); /* block length (for now) */
- st_writeb(ft, 0); /* block length (for now) */
- st_writeb(ft, 0); /* block length (for now) */
- v->rate = ft->info.rate;
- st_writedw(ft, v->rate); /* Rate code */
- st_writeb(ft, 16); /* Sample Size */
- st_writeb(ft, ft->info.channels); /* Sample Size */
- st_writeb(ft, 0); /* Unknown */
- st_writeb(ft, 0); /* Unused */
- st_writeb(ft, 0); /* Unused */
- st_writeb(ft, 0); /* Unused */
- st_writeb(ft, 0); /* Unused */
- st_writeb(ft, 0); /* Unused */
- }
- }
+ v->blockseek = ftell(ft->fp);
+ if (v->silent) {
+ st_writeb(ft, VOC_SILENCE); /* Silence block code */
+ st_writeb(ft, 0); /* Period length */
+ st_writeb(ft, 0); /* Period length */
+ st_writeb(ft, v->rate); /* Rate code */
+ } else {
+ if (ft->info.size == ST_SIZE_BYTE) {
+ /* 8-bit sample section. By always setting the correct */
+ /* rate value in the DATA block (even when its preceeded */
+ /* by an EXTENDED block) old software can still play stereo */
+ /* files in mono by just skipping over the EXTENDED block. */
+ /* Prehaps the rate should be doubled though to make up for */
+ /* double amount of samples for a given time???? */
+ if (ft->info.channels > 1) {
+ st_writeb(ft, VOC_EXTENDED); /* Voice Extended block code */
+ st_writeb(ft, 4); /* block length = 4 */
+ st_writeb(ft, 0); /* block length = 4 */
+ st_writeb(ft, 0); /* block length = 4 */
+ v->rate = 65536L - (256000000.0/(2*(float)ft->info.rate));
+ st_writew(ft,v->rate); /* Rate code */
+ st_writeb(ft, 0); /* File is not packed */
+ st_writeb(ft, 1); /* samples are in stereo */
+ }
+ st_writeb(ft, VOC_DATA); /* Voice Data block code */
+ st_writeb(ft, 0); /* block length (for now) */
+ st_writeb(ft, 0); /* block length (for now) */
+ st_writeb(ft, 0); /* block length (for now) */
+ v->rate = 256 - (1000000.0/(float)ft->info.rate);
+ st_writeb(ft, (int) v->rate);/* Rate code */
+ st_writeb(ft, 0); /* 8-bit raw data */
+ } else {
+ st_writeb(ft, VOC_DATA_16); /* Voice Data block code */
+ st_writeb(ft, 0); /* block length (for now) */
+ st_writeb(ft, 0); /* block length (for now) */
+ st_writeb(ft, 0); /* block length (for now) */
+ v->rate = ft->info.rate;
+ st_writedw(ft, v->rate); /* Rate code */
+ st_writeb(ft, 16); /* Sample Size */
+ st_writeb(ft, ft->info.channels); /* Sample Size */
+ st_writew(ft, 0x0004); /* Encoding */
+ st_writeb(ft, 0); /* Unused */
+ st_writeb(ft, 0); /* Unused */
+ st_writeb(ft, 0); /* Unused */
+ st_writeb(ft, 0); /* Unused */
+ }
+ }
}
/* End the current data or silence block. */
-static void blockstop(ft)
+static void blockstop(ft)
ft_t ft;
{
- vs_t v = (vs_t) ft->priv;
- LONG datum;
+ vs_t v = (vs_t) ft->priv;
+ LONG datum;
- st_writeb(ft, 0); /* End of file block code */
- fseek(ft->fp, v->blockseek, 0); /* seek back to block length */
- fseek(ft->fp, 1, 1); /* seek forward one */
- if (v->silent) {
- st_writew(ft, v->samples);
- } else {
- if (ft->info.size == ST_SIZE_BYTE) {
- if (ft->info.channels > 1) {
- fseek(ft->fp, 8, 1); /* forward 7 + 1 for new block header */
- }
- }
- v->samples += 2; /* adjustment: SBDK pp. 3-5 */
- datum = (v->samples) & 0xff;
- st_writeb(ft, (int)datum); /* low byte of length */
- datum = (v->samples >> 8) & 0xff;
- st_writeb(ft, (int)datum); /* middle byte of length */
- datum = (v->samples >> 16) & 0xff;
- st_writeb(ft, (int)datum); /* high byte of length */
- }
+ st_writeb(ft, 0); /* End of file block code */
+ fseek(ft->fp, v->blockseek, 0); /* seek back to block length */
+ fseek(ft->fp, 1, 1); /* seek forward one */
+ if (v->silent) {
+ st_writew(ft, v->samples);
+ } else {
+ if (ft->info.size == ST_SIZE_BYTE) {
+ if (ft->info.channels > 1) {
+ fseek(ft->fp, 8, 1); /* forward 7 + 1 for new block header */
+ }
+ }
+ v->samples += 2; /* adjustment: SBDK pp. 3-5 */
+ datum = (v->samples * ft->info.size) & 0xff;
+ st_writeb(ft, (int)datum); /* low byte of length */
+ datum = ((v->samples * ft->info.size) >> 8) & 0xff;
+ st_writeb(ft, (int)datum); /* middle byte of length */
+ datum = ((v->samples * ft->info.size)>> 16) & 0xff;
+ st_writeb(ft, (int)datum); /* high byte of length */
+ }
}