ref: e1bb8ea335d3517f9b3153bdc56b237847e2c7cd
parent: 269fe345e41fbff0ef56c8095e3f1d752517345c
author: cbagwell <cbagwell>
date: Wed Feb 21 15:57:01 EST 2001
Major updates to error checking code to use errno. Added file seeking support.
--- a/Changelog
+++ b/Changelog
@@ -6,6 +6,10 @@
sox-12.17.2
-----------
+ o Darrick Servis has made major cleanups in the code in regards
+ to error conditions. Helps people using libst.
+ o Darrick Servis has added added optional seek functionality sox.
+ Several formats have been modified to make use of this.
o Geoff Kuenning rewrote the average effect into a general-purpose
parametric mapping from N channels to M channels.
o Geoff Kuenning added an optional delay-time parameter to the compander
--- a/src/8svx.c
+++ b/src/8svx.c
@@ -15,10 +15,10 @@
#include "st.h"
/* Private data used by writer */
-struct svxpriv {
+typedef struct svxpriv {
ULONG nsamples;
FILE *ch[4];
-};
+}*svx_t;
static void svxwriteheader(ft_t, LONG);
@@ -29,7 +29,7 @@
int st_svxstartread(ft)
ft_t ft;
{
- struct svxpriv *p = (struct svxpriv *) ft->priv;
+ svx_t p = (svx_t ) ft->priv;
char buf[12];
char *chunk_buf;
@@ -43,6 +43,11 @@
ULONG chan1_pos;
+ if (! ft->seekable)
+ {
+ st_fail_errno(ft,ST_EINVAL,"8svx input file must be a file, not a pipe");
+ return (ST_EOF);
+ }
/* 8svx is in big endian format. Swap whats
* read in on little endian machines.
*/
@@ -215,7 +220,7 @@
int done = 0;
int i;
- struct svxpriv *p = (struct svxpriv *) ft->priv;
+ svx_t p = (svx_t ) ft->priv;
while (done < nsamp) {
for (i = 0; i < ft->info.channels; i++) {
@@ -239,7 +244,7 @@
{
int i;
- struct svxpriv *p = (struct svxpriv *) ft->priv;
+ svx_t p = (svx_t ) ft->priv;
/* close channel files */
for (i = 1; i < ft->info.channels; i++) {
@@ -254,7 +259,7 @@
int st_svxstartwrite(ft)
ft_t ft;
{
- struct svxpriv *p = (struct svxpriv *) ft->priv;
+ svx_t p = (svx_t ) ft->priv;
int i;
/* 8svx is in big endian format. Swaps wahst
@@ -292,7 +297,7 @@
ft_t ft;
LONG *buf, len;
{
- struct svxpriv *p = (struct svxpriv *) ft->priv;
+ svx_t p = (svx_t ) ft->priv;
unsigned char datum;
int done = 0;
@@ -318,7 +323,7 @@
int st_svxstopwrite(ft)
ft_t ft;
{
- struct svxpriv *p = (struct svxpriv *) ft->priv;
+ svx_t p = (svx_t ) ft->priv;
int i;
int len;
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -53,9 +53,11 @@
#include "st.h"
/* Private data used by writer */
-struct aiffpriv {
+typedef struct aiffpriv {
ULONG nsamples; /* number of 1-channel samples read or written */
-};
+ /*Decrements for read increments for write */
+ LONG dataStart; /* need to for seeking */
+} *aiff_t;
/* forward declarations */
static double read_ieee_extended(ft_t);
@@ -67,10 +69,24 @@
static int commentChunk(char **text, char *chunkDescription, ft_t ft);
static void reportInstrument(ft_t ft);
+int st_aiffseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ aiff_t aiff = (aiff_t ) ft->priv;
+
+ ft->st_errno = st_seek(ft,offset*ft->info.size + aiff->dataStart,SEEK_SET);
+
+ if( ft->st_errno == ST_SUCCESS )
+ aiff->nsamples = ft->length - offset;
+
+ return(ft->st_errno);
+}
+
int st_aiffstartread(ft)
ft_t ft;
{
- struct aiffpriv *p = (struct aiffpriv *) ft->priv;
+ aiff_t aiff = (aiff_t ) ft->priv;
char buf[5];
ULONG totalsize;
LONG chunksize;
@@ -100,11 +116,6 @@
int rc;
- /* Needed because of st_rawread() */
- rc = st_rawstartread(ft);
- if (rc)
- return rc;
-
/* AIFF is in Big Endian format. Swap whats read in on Little */
/* Endian machines. */
if (ST_IS_LITTLEENDIAN)
@@ -115,7 +126,7 @@
/* FORM chunk */
if (st_reads(ft, buf, 4) == ST_EOF || strncmp(buf, "FORM", 4) != 0)
{
- st_fail("AIFF header does not begin with magic word 'FORM'");
+ st_fail_errno(ft,ST_EHDR,"AIFF header does not begin with magic word 'FORM'");
return(ST_EOF);
}
st_readdw(ft, &totalsize);
@@ -122,7 +133,7 @@
if (st_reads(ft, buf, 4) == ST_EOF || (strncmp(buf, "AIFF", 4) != 0 &&
strncmp(buf, "AIFC", 4) != 0))
{
- st_fail("AIFF 'FORM' chunk does not specify 'AIFF' or 'AIFC' as type");
+ st_fail_errno(ft,ST_EHDR,"AIFF 'FORM' chunk does not specify 'AIFF' or 'AIFC' as type");
return(ST_EOF);
}
@@ -136,7 +147,7 @@
break;
else
{
- st_fail("Missing SSND chunk in AIFF file");
+ st_fail_errno(ft,ST_EHDR,"Missing SSND chunk in AIFF file");
return(ST_EOF);
}
}
@@ -155,7 +166,7 @@
if (strncmp(buf, "NONE", 4) != 0)
{
buf[4] = 0;
- st_fail("Can not support AIFC files that contain compressed data: %s",buf);
+ st_fail_errno(ft,ST_EHDR,"Can not support AIFC files that contain compressed data: %s",buf);
return(ST_EOF);
}
}
@@ -338,7 +349,7 @@
fseek(ft->fp, seekto, SEEK_SET);
else
{
- st_fail("AIFF: no sound data on input file");
+ st_fail_errno(ft,ST_EOF,"AIFF: no sound data on input file");
return(ST_EOF);
}
}
@@ -345,13 +356,13 @@
/* SSND chunk just read */
if (blocksize != 0)
{
- st_fail("AIFF header specifies nonzero blocksize?!?!");
+ st_fail_errno(ft,ST_EHDR,"AIFF header specifies nonzero blocksize?!?!");
return(ST_EOF);
}
while ((LONG) (--offset) >= 0) {
if (st_readb(ft, (unsigned char *)&trash) == ST_EOF)
{
- st_fail("unexpected EOF while skipping AIFF offset");
+ st_fail_errno(ft,errno,"unexpected EOF while skipping AIFF offset");
return(ST_EOF);
}
}
@@ -368,7 +379,7 @@
ft->info.size = ST_SIZE_WORD;
break;
default:
- st_fail("unsupported sample size in AIFF header: %d", bits);
+ st_fail_errno(ft,ST_EFMT,"unsupported sample size in AIFF header: %d", bits);
return(ST_EOF);
/*NOTREACHED*/
}
@@ -379,22 +390,22 @@
|| (ft->info.size == -1)) {
st_report("You must specify # channels, sample rate, signed/unsigned,\n");
st_report("and 8/16 on the command line.");
- st_fail("Bogus AIFF file: no COMM section.");
+ st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: no COMM section.");
return(ST_EOF);
}
}
- p->nsamples = ssndsize / ft->info.size; /* leave out channels */
+ aiff->nsamples = ssndsize / ft->info.size; /* leave out channels */
if (foundmark && !foundinstr)
{
- st_fail("Bogus AIFF file: MARKers but no INSTrument.");
+ st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: MARKers but no INSTrument.");
return(ST_EOF);
}
if (!foundmark && foundinstr)
{
- st_fail("Bogus AIFF file: INSTrument but no MARKers.");
+ st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: INSTrument but no MARKers.");
return(ST_EOF);
}
if (foundmark && foundinstr) {
@@ -437,6 +448,14 @@
if (verbose)
reportInstrument(ft);
+ /* Needed because of st_rawread() */
+ rc = st_rawstartread(ft);
+ if (rc)
+ return rc;
+
+ ft->length = aiff->nsamples; /* for seeking */
+ aiff->dataStart = ftell(ft->fp);
+
return(ST_SUCCESS);
}
@@ -479,12 +498,12 @@
*text = (char *) malloc((size_t) chunksize + 1);
if (*text == NULL)
{
- st_fail("AIFF: Couldn't allocate %s header", chunkDescription);
+ st_fail_errno(ft,ST_ENOMEM,"AIFF: Couldn't allocate %s header", chunkDescription);
return(ST_EOF);
}
if (fread(*text, 1, chunksize, ft->fp) != chunksize)
{
- st_fail("AIFF: Unexpected EOF in %s header", chunkDescription);
+ st_fail_errno(ft,ST_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
return(ST_EOF);
}
*(*text + chunksize) = '\0';
@@ -494,7 +513,7 @@
char c;
if (fread(&c, 1, 1, ft->fp) != 1)
{
- st_fail("AIFF: Unexpected EOF in %s header", chunkDescription);
+ st_fail_errno(ft,ST_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
return(ST_EOF);
}
}
@@ -537,11 +556,11 @@
}
if (*text == NULL) {
- st_fail("AIFF: Couldn't allocate %s header", chunkDescription);
+ st_fail_errno(ft,ST_ENOMEM,"AIFF: Couldn't allocate %s header", chunkDescription);
return(ST_EOF);
}
if (fread(*text + totalCommentLength - commentLength, 1, commentLength, ft->fp) != commentLength) {
- st_fail("AIFF: Unexpected EOF in %s header", chunkDescription);
+ st_fail_errno(ft,ST_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
return(ST_EOF);
}
*(*text + totalCommentLength) = '\0';
@@ -549,7 +568,7 @@
/* Read past pad byte */
char c;
if (fread(&c, 1, 1, ft->fp) != 1) {
- st_fail("AIFF: Unexpected EOF in %s header", chunkDescription);
+ st_fail_errno(ft,ST_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
return(ST_EOF);
}
}
@@ -564,14 +583,17 @@
ft_t ft;
LONG *buf, len;
{
- struct aiffpriv *p = (struct aiffpriv *) ft->priv;
+ aiff_t aiff = (aiff_t ) ft->priv;
+ LONG done;
/* just read what's left of SSND chunk */
- if (len > p->nsamples)
- len = p->nsamples;
- st_rawread(ft, buf, len);
- p->nsamples -= len;
- return len;
+ if (len > aiff->nsamples)
+ len = aiff->nsamples;
+ done = st_rawread(ft, buf, len);
+ if (done == 0 && aiff->nsamples != 0)
+ st_warn("Premature EOF on AIFF input file");
+ aiff->nsamples -= done;
+ return done;
}
int st_aiffstopread(ft)
@@ -621,7 +643,7 @@
int st_aiffstartwrite(ft)
ft_t ft;
{
- struct aiffpriv *p = (struct aiffpriv *) ft->priv;
+ aiff_t aiff = (aiff_t ) ft->priv;
int rc;
/* Needed because st_rawwrite() */
@@ -636,7 +658,7 @@
ft->swap = ft->swap ? 0 : 1;
}
- p->nsamples = 0;
+ aiff->nsamples = 0;
if ((ft->info.encoding == ST_ENCODING_ULAW ||
ft->info.encoding == ST_ENCODING_ALAW) &&
ft->info.size == ST_SIZE_BYTE) {
@@ -658,8 +680,8 @@
ft_t ft;
LONG *buf, len;
{
- struct aiffpriv *p = (struct aiffpriv *) ft->priv;
- p->nsamples += len;
+ aiff_t aiff = (aiff_t ) ft->priv;
+ aiff->nsamples += len;
st_rawwrite(ft, buf, len);
return(len);
}
@@ -667,7 +689,7 @@
int st_aiffstopwrite(ft)
ft_t ft;
{
- struct aiffpriv *p = (struct aiffpriv *) ft->priv;
+ aiff_t aiff = (aiff_t ) ft->priv;
int rc;
/* Needed because of st_rawwrite(). Call now to flush
@@ -679,15 +701,15 @@
if (!ft->seekable)
{
- st_fail("Non-seekable file.");
+ st_fail_errno(ft,ST_EOF,"Non-seekable file.");
return(ST_EOF);
}
if (fseek(ft->fp, 0L, SEEK_SET) != 0)
{
- st_fail("can't rewind output file to rewrite AIFF header");
+ st_fail_errno(ft,errno,"can't rewind output file to rewrite AIFF header");
return(ST_EOF);
}
- return(aiffwriteheader(ft, p->nsamples / ft->info.channels));
+ return(aiffwriteheader(ft, aiff->nsamples / ft->info.channels));
}
static int aiffwriteheader(ft, nframes)
@@ -717,7 +739,7 @@
bits = 16;
else
{
- st_fail("unsupported output encoding/size for AIFF header");
+ st_fail_errno(ft,ST_EFMT,"unsupported output encoding/size for AIFF header");
return(ST_EOF);
}
@@ -834,7 +856,7 @@
char buf[10];
if (fread(buf, 1, 10, ft->fp) != 10)
{
- st_fail("EOF while reading IEEE extended number");
+ st_fail_errno(ft,ST_EOF,"EOF while reading IEEE extended number");
return(ST_EOF);
}
return ConvertFromIeeeExtended(buf);
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -45,7 +45,7 @@
ft->file.eof = 0;
ft->file.size = c_info.buffer_size;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("unable to allocate output buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
return(ST_EOF);
}
if (ft->info.rate < c_info.min_rate) ft->info.rate = 2 * c_info.min_rate;
@@ -94,7 +94,7 @@
ft->file.eof = 0;
ft->file.size = p_info.buffer_size;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("unable to allocate output buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
return(ST_EOF);
}
if (ft->info.rate < p_info.min_rate) ft->info.rate = 2 * p_info.min_rate;
@@ -144,7 +144,7 @@
ft->file.eof = 0;
ft->file.size = c_info.buffer_size;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("unable to allocate output buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
return(ST_EOF);
}
if (ft->info.rate < c_info.min_rate) ft->info.rate = 2 * c_info.min_rate;
@@ -194,7 +194,7 @@
ft->file.eof = 0;
ft->file.size = p_info.buffer_size;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("unable to allocate output buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
return(ST_EOF);
}
if (ft->info.rate < p_info.min_rate) ft->info.rate = 2 * p_info.min_rate;
@@ -252,21 +252,21 @@
{
case ST_ENCODING_SIGN2:
if (!(formats & SND_PCM_FMT_S8)) {
- st_fail("ALSA driver does not support signed byte samples");
- return -1;
+ st_fail_errno(ft,ST_EFMT,"ALSA driver does not support signed byte samples");
+ return ST_EOF;
}
*fmt = SND_PCM_SFMT_S8;
break;
case ST_ENCODING_UNSIGNED:
if (!(formats & SND_PCM_FMT_U8)) {
- st_fail("ALSA driver does not support unsigned byte samples");
- return -1;
+ st_fail_errno(ft,ST_EFMT,"ALSA driver does not support unsigned byte samples");
+ return ST_EOF;
}
*fmt = SND_PCM_SFMT_U8;
break;
default:
- st_fail("Hardware does not support %s output", st_encodings_str[ft->info.encoding]);
- return -1;
+ st_fail_errno(ft,ST_EFMT,"Hardware does not support %s output", st_encodings_str[ft->info.encoding]);
+ return ST_EOF;
break;
}
}
@@ -275,21 +275,21 @@
{
case ST_ENCODING_SIGN2:
if (!(formats & SND_PCM_FMT_S16)) {
- st_fail("ALSA driver does not support signed word samples");
- return -1;
+ st_fail_errno(ft,ST_EFMT,"ALSA driver does not support signed word samples");
+ return ST_EOF;
}
*fmt = SND_PCM_SFMT_S16_LE;
break;
case ST_ENCODING_UNSIGNED:
if (!(formats & SND_PCM_FMT_U16)) {
- st_fail("ALSA driver does not support unsigned word samples");
- return -1;
+ st_fail_errno(ft,ST_EFMT,"ALSA driver does not support unsigned word samples");
+ return ST_EOF;
}
*fmt = SND_PCM_SFMT_U16_LE;
break;
default:
- st_fail("Hardware does not support %s output", st_encodings_str[ft->info.encoding]);
- return -1;
+ st_fail_errno(ft,ST_EFMT,"Hardware does not support %s output", st_encodings_str[ft->info.encoding]);
+ return ST_EOF;
break;
}
}
--- a/src/au.c
+++ b/src/au.c
@@ -45,9 +45,11 @@
/* The other formats are not supported by sox at the moment */
/* Private data */
-struct aupriv {
- /* For writer: */
+typedef struct aupriv {
+ /* For writer: size in bytes */
ULONG data_size;
+ /* For seeking */
+ LONG dataStart;
/* For G72x decoding: */
struct g72x_state state;
int (*dec_routine)();
@@ -54,7 +56,7 @@
int dec_bits;
unsigned int in_buffer;
int in_bits;
-};
+} *au_t;
static void auwriteheader(ft_t ft, ULONG data_size);
@@ -93,12 +95,25 @@
break;
default:
st_report("encoding: 0x%lx", encoding);
- st_fail("Unsupported encoding in Sun/NeXT header.\nOnly U-law, signed bytes, signed words, and ADPCM are supported.");
return(ST_EOF);
}
return(ST_SUCCESS);
}
+int st_auseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ au_t au = (au_t ) ft->priv;
+
+ if (au->dec_routine != NULL)
+ st_fail_errno(ft,ST_ENOTSUP,"Sorry, DEC unsupported");
+ else
+ return st_seek(ft,offset*ft->info.size + au->dataStart,SEEK_SET);
+
+ return(ft->st_errno);
+}
+
int st_austartread(ft)
ft_t ft;
{
@@ -116,15 +131,10 @@
register int i;
char *buf;
- struct aupriv *p = (struct aupriv *) ft->priv;
+ au_t p = (au_t ) ft->priv;
int rc;
- /* Needed for rawread() */
- rc = st_rawstartread(ft);
- if (rc)
- return rc;
-
/* AU is in big endian format. Swap whats read
* in onlittle endian machines.
*/
@@ -155,7 +165,7 @@
}
else
{
- st_fail("Sun/NeXT/DEC header doesn't start with magic word\nTry the '.ul' file type with '-t ul -r 8000 filename'");
+ st_fail_errno(ft,ST_EHDR,"Sun/NeXT/DEC header doesn't start with magic word\nTry the '.ul' file type with '-t ul -r 8000 filename'");
return(ST_EOF);
}
@@ -163,8 +173,8 @@
st_readdw(ft, &hdr_size);
if (hdr_size < SUN_HDRSIZE)
{
- st_fail("Sun/NeXT header size too small.");
- return(0);
+ st_fail_errno(ft,ST_EHDR,"Sun/NeXT header size too small.");
+ return(ST_EOF);
}
/* Read the data size; may be ~0 meaning unspecified */
@@ -181,7 +191,10 @@
p->in_bits = 0;
if(st_auencodingandsize(encoding, &(ft->info.encoding),
&(ft->info.size)) == ST_EOF)
+ {
+ st_fail_errno(ft,ST_EFMT,"Unsupported encoding in Sun/NeXT header.\nOnly U-law, signed bytes, signed words, and ADPCM are supported.");
return(ST_EOF);
+ }
switch (encoding) {
case SUN_G721:
g72x_init_state(&p->state);
@@ -217,7 +230,7 @@
st_readb(ft, &(buf[i]));
if (feof(ft->fp))
{
- st_fail("Unexpected EOF in Sun/NeXT header info.");
+ st_fail_errno(ft,ST_EOF,"Unexpected EOF in Sun/NeXT header info.");
return(ST_EOF);
}
}
@@ -232,6 +245,16 @@
ft->comment = buf;
st_report("Input file %s: Sun header info: %s", ft->filename, buf);
}
+ /* Needed for seeking */
+ ft->length = data_size/ft->info.size;
+ if(ft->seekable)
+ p->dataStart = ftell(ft->fp);
+
+ /* Needed for rawread() */
+ rc = st_rawstartread(ft);
+ if (rc)
+ return rc;
+
return(ST_SUCCESS);
}
@@ -247,7 +270,7 @@
int st_austartwrite(ft)
ft_t ft;
{
- struct aupriv *p = (struct aupriv *) ft->priv;
+ au_t p = (au_t ) ft->priv;
int rc;
/* Needed because of rawwrite(); */
@@ -278,7 +301,7 @@
ft_t ft;
unsigned char *code;
{
- struct aupriv *p = (struct aupriv *) ft->priv;
+ au_t p = (au_t ) ft->priv;
unsigned char in_byte;
if (p->in_bits < p->dec_bits) {
@@ -299,7 +322,7 @@
ft_t ft;
LONG *buf, samp;
{
- struct aupriv *p = (struct aupriv *) ft->priv;
+ au_t p = (au_t ) ft->priv;
unsigned char code;
int done;
if (p->dec_routine == NULL)
@@ -319,7 +342,7 @@
ft_t ft;
LONG *buf, samp;
{
- struct aupriv *p = (struct aupriv *) ft->priv;
+ au_t p = (au_t ) ft->priv;
p->data_size += samp * ft->info.size;
return(st_rawwrite(ft, buf, samp));
}
@@ -327,7 +350,7 @@
int st_austopwrite(ft)
ft_t ft;
{
- struct aupriv *p = (struct aupriv *) ft->priv;
+ au_t p = (au_t ) ft->priv;
int rc;
/* Needed because of rawwrite(). Do now to flush
@@ -342,7 +365,7 @@
{
if (fseek(ft->fp, 0L, 0) != 0)
{
- st_fail("Can't rewind output file to rewrite Sun header.");
+ st_fail_errno(ft,errno,"Can't rewind output file to rewrite Sun header.");
return(ST_EOF);
}
auwriteheader(ft, p->data_size);
--- a/src/auto.c
+++ b/src/auto.c
@@ -22,14 +22,15 @@
{
char *type;
char header[132];
+ int rc;
if (!ft->seekable)
{
- st_fail("Type AUTO input must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"Type AUTO input must be a file, not a pipe");
return(ST_EOF);
}
if (fread(header, 1, sizeof(header), ft->fp) != sizeof(header))
{
- st_fail("Type AUTO detects short file");
+ st_fail_errno(ft,ST_EOF,"Type AUTO detects short file");
return(ST_EOF);
}
fseek(ft->fp, 0L - sizeof header, 1); /* Seek back */
@@ -69,8 +70,8 @@
}
if (type == 0) {
- printf("Type AUTO doesn't recognize this header\n");
- printf("Trying: -t raw -r 44100 -s -w\n\n");
+ st_warn("Type AUTO doesn't recognize this header\n");
+ st_warn("Trying: -t raw -r 44100 -s -w\n\n");
type = "raw";
ft->info.rate = 44100;
ft->info.size = ST_SIZE_WORD;
@@ -78,7 +79,9 @@
}
st_report("Type AUTO changed to %s", type);
ft->filetype = type;
- st_gettype(ft); /* Change ft->h to the new format */
+ rc = st_gettype(ft); /* Change ft->h to the new format */
+ if(rc)
+ return (rc);
(* ft->h->startread)(ft);
return(ST_SUCCESS);
}
@@ -86,6 +89,6 @@
int st_autostartwrite(ft)
ft_t ft;
{
- st_fail("Type AUTO can only be used for input!");
+ st_fail_errno(ft,ST_EFMT,"Type AUTO can only be used for input!");
return(ST_EOF);
}
--- a/src/avr.c
+++ b/src/avr.c
@@ -76,14 +76,10 @@
ft->swap = ft->swap ? 0 : 1;
}
- rc = st_rawstartread (ft);
- if (rc)
- return rc;
-
st_reads(ft, avr->magic, 4);
if (strncmp (avr->magic, AVR_MAGIC, 4)) {
- st_fail("AVR: unknown header");
+ st_fail_errno(ft,ST_EHDR,"AVR: unknown header");
return(ST_EOF);
}
@@ -105,8 +101,8 @@
ft->info.size = ST_SIZE_WORD;
}
else {
- st_fail("AVR: unsupported sample resolution");
- return(0);
+ st_fail_errno(ft,ST_EFMT,"AVR: unsupported sample resolution");
+ return(ST_EOF);
}
st_readw (ft, &(avr->sign));
@@ -146,6 +142,10 @@
fread(avr->user, 1, sizeof(avr->user), ft->fp);
+ rc = st_rawstartread (ft);
+ if (rc)
+ return rc;
+
return(ST_SUCCESS);
}
@@ -163,7 +163,7 @@
}
if (!ft->seekable) {
- st_fail("AVR: file is not seekable");
+ st_fail_errno(ft,ST_EOF,"AVR: file is not seekable");
return(ST_EOF);
}
@@ -192,7 +192,7 @@
st_writew (ft, 0xffff);
}
else {
- st_fail("AVR: number of channels not supported");
+ st_fail_errno(ft,ST_EFMT,"AVR: number of channels not supported");
return(0);
}
@@ -204,7 +204,7 @@
st_writew (ft, 16);
}
else {
- st_fail("AVR: unsupported sample resolution");
+ st_fail_errno(ft,ST_EFMT,"AVR: unsupported sample resolution");
return(ST_EOF);
}
@@ -216,7 +216,7 @@
st_writew (ft, 0);
}
else {
- st_fail("AVR: unsupported encoding");
+ st_fail_errno(ft,ST_EFMT,"AVR: unsupported encoding");
return(ST_EOF);
}
--- a/src/cdr.c
+++ b/src/cdr.c
@@ -62,6 +62,13 @@
ft->info.channels = 2;
ft->comment = NULL;
+/* Need length for seeking */
+ if(ft->seekable){
+ ft->length = st_filelength(ft)/2;
+ } else {
+ ft->length = 0;
+ }
+
return(ST_SUCCESS);
}
--- a/src/cvsd.c
+++ b/src/cvsd.c
@@ -263,7 +263,7 @@
if (!dbg.f1) {
if (!(dbg.f1 = fopen("dbg1", "w")))
{
- st_fail("debugging");
+ st_fail_errno(ft,errno,"debugging");
return (0);
}
fprintf(dbg.f1, "\"input\"\n");
@@ -271,7 +271,7 @@
if (!dbg.f2) {
if (!(dbg.f2 = fopen("dbg2", "w")))
{
- st_fail("debugging");
+ st_fail_errno(ft,errno,"debugging");
return (0);
}
fprintf(dbg.f2, "\"recon\"\n");
@@ -345,7 +345,7 @@
if (!dbg.f1) {
if (!(dbg.f1 = fopen("dbg1", "w")))
{
- st_fail("debugging");
+ st_fail_errno(ft,errno,"debugging");
return (0);
}
fprintf(dbg.f1, "\"input\"\n");
@@ -353,7 +353,7 @@
if (!dbg.f2) {
if (!(dbg.f2 = fopen("dbg2", "w")))
{
- st_fail("debugging");
+ st_fail_errno(ft,errno,"debugging");
return (0);
}
fprintf(dbg.f2, "\"recon\"\n");
@@ -490,7 +490,6 @@
if (fread(hdrbuf, sizeof(hdrbuf), 1, f) != 1)
{
- st_fail("unable to read DVMS header\n");
return (ST_EOF);
}
for(i = sizeof(hdrbuf), sum = 0; i > /*2*/3; i--) /* Deti bug */
@@ -515,7 +514,7 @@
hdr->Crc = get16(&pch);
if (sum != hdr->Crc)
{
- st_fail("DVMS header checksum error, read %u, calculated %u\n",
+ st_report("DVMS header checksum error, read %u, calculated %u\n",
hdr->Crc, sum);
return (ST_EOF);
}
@@ -559,12 +558,12 @@
put16(&pch, hdr->Crc);
if (fseek(f, 0, SEEK_SET) < 0)
{
- st_fail("cannot write DVMS header, seek failed\n");
+ st_report("seek failed\n: %s",strerror(errno));
return (ST_EOF);
}
if (fwrite(hdrbuf, sizeof(hdrbuf), 1, f) != 1)
{
- st_fail("cannot write DVMS header\n");
+ st_report("%s\n",strerror(errno));
return (ST_EOF);
}
return (ST_SUCCESS);
@@ -608,8 +607,10 @@
int rc;
rc = dvms_read_header(ft->fp, &hdr);
- if (rc)
+ if (rc){
+ st_fail_errno(ft,ST_EHDR,"unable to read DVMS header\n");
return rc;
+ }
st_report("DVMS header of source file \"%s\":");
st_report(" filename \"%.14s\"",ft->filename);
@@ -651,8 +652,10 @@
make_dvms_hdr(ft, &hdr);
rc = dvms_write_header(ft->fp, &hdr);
- if (rc)
+ if (rc){
+ st_fail_errno(ft,rc,"cannot write DVMS header\n");
return rc;
+ }
if (!ft->seekable)
st_warn("Length in output .DVMS header will wrong since can't seek to fix it");
@@ -677,11 +680,15 @@
}
if (fseek(ft->fp, 0L, 0) != 0)
{
- st_fail("Can't rewind output file to rewrite DVMS header.");
+ st_fail_errno(ft,errno,"Can't rewind output file to rewrite DVMS header.");
return(ST_EOF);
}
make_dvms_hdr(ft, &hdr);
rc = dvms_write_header(ft->fp, &hdr);
+ if(rc){
+ st_fail_errno(ft,rc,"cannot write DVMS header\n");
+ return rc;
+ }
return rc;
}
--- a/src/dat.c
+++ b/src/dat.c
@@ -47,7 +47,7 @@
sscanf(inpstr," %c",&sc);
if (sc != ';')
{
- st_fail("Cannot determine sample rate.");
+ st_fail_errno(ft,ST_EHDR,"Cannot determine sample rate.");
return (ST_EOF);
}
#ifdef __alpha__
@@ -116,7 +116,7 @@
retc = sscanf(inpstr,"%*s %lg",&sampval);
if (retc != 1)
{
- st_fail("Unable to read sample.");
+ st_fail_errno(ft,ST_EOF,"Unable to read sample.");
return (0);
}
*buf++ = roundoff(sampval * 2.147483648e9);
--- a/src/gsm.c
+++ b/src/gsm.c
@@ -66,7 +66,7 @@
p->channels = ft->info.channels;
if (p->channels > MAXCHANS || p->channels <= 0)
{
- st_fail("gsm: channels(%d) must be in 1-16", ft->info.channels);
+ st_fail_errno(ft,ST_EFMT,"gsm: channels(%d) must be in 1-16", ft->info.channels);
return(ST_EOF);
}
@@ -74,7 +74,7 @@
p->handle[ch] = gsm_create();
if (!p->handle[ch])
{
- st_fail("unable to create GSM stream");
+ st_fail_errno(ft,errno,"unable to create GSM stream");
return (ST_EOF);
}
}
@@ -133,7 +133,7 @@
gbuff = p->sampleTop;
if (gsm_decode(p->handle[ch], p->frames + ch*FRAMESIZE, gbuff) < 0)
{
- st_fail("error during GSM decode");
+ st_fail_errno(ft,errno,"error during GSM decode");
return (0);
}
@@ -175,7 +175,7 @@
r = fwrite(p->frames, FRAMESIZE, 1, ft->fp);
if (r != 1)
{
- st_fail("write error");
+ st_fail_errno(ft,errno,"write error");
return(ST_EOF);
}
}
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -27,6 +27,7 @@
extern int st_aiffstartwrite();
extern LONG st_aiffwrite();
extern int st_aiffstopwrite();
+extern int st_aiffseek();
static char *alnames[] = {
"al",
@@ -57,6 +58,7 @@
extern int st_austartwrite();
extern LONG st_auwrite();
extern int st_austopwrite();
+extern int st_auseek();
static char *autonames[] = {
"auto",
@@ -191,6 +193,7 @@
extern int st_sfstartread();
extern int st_sfstartwrite();
+extern int st_sfseek();
static char *slnames[] = {
"sl",
@@ -210,6 +213,7 @@
extern LONG st_smpwrite();
extern int st_smpstartwrite();
extern int st_smpstopwrite();
+extern int st_smpseek();
static char *sndtnames[] = {
"sndt",
@@ -223,6 +227,7 @@
extern int st_sndtstartwrite();
extern LONG st_sndtwrite();
extern int st_sndtstopwrite();
+extern int st_sndseek();
static char *spherenames[] = {
"sph",
@@ -328,6 +333,7 @@
extern int st_wavstartwrite();
extern LONG st_wavwrite();
extern int st_wavstopwrite();
+extern int st_wavseek();
static char *wvenames[] = {
"wve",
@@ -339,112 +345,113 @@
extern int st_wvestartwrite();
extern LONG st_wvewrite();
extern int st_wvestopwrite();
+extern int st_wveseek();
extern int st_nothing();
extern LONG st_nothing_success();
st_format_t st_formats[] = {
- {aiffnames, ST_FILE_STEREO, /* SGI/Apple AIFF */
+ {aiffnames, ST_FILE_STEREO | ST_FILE_SEEK, /* SGI/Apple AIFF */
st_aiffstartread, st_aiffread, st_aiffstopread,
- st_aiffstartwrite, st_aiffwrite, st_aiffstopwrite},
+ st_aiffstartwrite, st_aiffwrite, st_aiffstopwrite, st_aiffseek},
{alnames, ST_FILE_STEREO, /* a-law byte raw */
st_alstartread, st_rawread, st_rawstopread,
- st_alstartwrite, st_rawwrite, st_rawstopwrite},
+ st_alstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
#if defined(ALSA_PLAYER)
{alsanames, ST_FILE_STEREO, /* /dev/snd/pcmXX */
st_alsastartread, st_rawread, st_rawstopread,
- st_alsastartwrite, st_rawwrite, st_rawstopwrite},
+ st_alsastartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
#endif
- {aunames, ST_FILE_STEREO, /* SPARC .au w/header */
+ {aunames, ST_FILE_STEREO | ST_FILE_SEEK, /* SPARC .au w/header */
st_austartread, st_auread, st_rawstopread,
- st_austartwrite, st_auwrite, st_austopwrite},
+ st_austartwrite, st_auwrite, st_austopwrite, st_auseek},
{autonames, ST_FILE_STEREO, /* Guess from header */
st_autostartread, st_nothing_success, st_nothing,
- st_autostartwrite, st_nothing_success, st_nothing},
+ st_autostartwrite, st_nothing_success, st_nothing, st_nothing},
{avrnames, ST_FILE_STEREO, /* AVR format */
st_avrstartread, st_rawread, st_nothing,
- st_avrstartwrite, st_avrwrite, st_avrstopwrite},
- {cdrnames, ST_FILE_STEREO, /* CD-R format */
+ st_avrstartwrite, st_avrwrite, st_avrstopwrite, st_nothing},
+ {cdrnames, ST_FILE_STEREO | ST_FILE_SEEK, /* CD-R format */
st_cdrstartread, st_cdrread, st_cdrstopread,
- st_cdrstartwrite, st_cdrwrite, st_cdrstopwrite},
+ st_cdrstartwrite, st_cdrwrite, st_cdrstopwrite, st_rawseek},
{cvsdnames, 0, /* Cont. Variable Slope Delta */
st_cvsdstartread, st_cvsdread, st_cvsdstopread,
- st_cvsdstartwrite, st_cvsdwrite, st_cvsdstopwrite},
+ st_cvsdstartwrite, st_cvsdwrite, st_cvsdstopwrite, st_nothing},
{datnames, 0, /* Text data samples */
st_datstartread, st_datread, st_nothing,
- st_datstartwrite, st_datwrite, st_nothing},
+ st_datstartwrite, st_datwrite, st_nothing, st_nothing},
{dvmsnames, 0, /* Cont. Variable Solot Delta */
st_dvmsstartread, st_cvsdread, st_cvsdstopread,
- st_dvmsstartwrite, st_cvsdwrite, st_dvmsstopwrite},
+ st_dvmsstartwrite, st_cvsdwrite, st_dvmsstopwrite, st_nothing},
#ifdef HAVE_LIBGSM
{gsmnames, 0, /* GSM 06.10 */
st_gsmstartread, st_gsmread, st_gsmstopread,
- st_gsmstartwrite, st_gsmwrite, st_gsmstopwrite},
+ st_gsmstartwrite, st_gsmwrite, st_gsmstopwrite, st_nothing},
#endif
{hcomnames, 0, /* Mac FSSD/HCOM */
st_hcomstartread, st_hcomread, st_hcomstopread,
- st_hcomstartwrite, st_hcomwrite, st_hcomstopwrite},
+ st_hcomstartwrite, st_hcomwrite, st_hcomstopwrite, st_nothing},
{maudnames, ST_FILE_STEREO, /* Amiga MAUD */
st_maudstartread, st_maudread, st_maudstopread,
- st_maudstartwrite, st_maudwrite, st_maudstopwrite},
+ st_maudstartwrite, st_maudwrite, st_maudstopwrite, st_nothing},
#if defined(OSS_PLAYER)
{ossdspnames, ST_FILE_STEREO, /* OSS /dev/dsp player */
st_ossdspstartread, st_rawread, st_rawstopread,
- st_ossdspstartwrite, st_rawwrite, st_rawstopwrite},
+ st_ossdspstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
#endif
- {rawnames, ST_FILE_STEREO, /* Raw format */
+ {rawnames, ST_FILE_STEREO | ST_FILE_SEEK, /* Raw format */
st_rawstartread, st_rawread, st_rawstopread,
- st_rawstartwrite, st_rawwrite, st_rawstopwrite},
+ st_rawstartwrite, st_rawwrite, st_rawstopwrite, st_rawseek},
{sbnames, ST_FILE_STEREO, /* signed byte raw */
st_sbstartread, st_rawread, st_rawstopread,
- st_sbstartwrite, st_rawwrite, st_rawstopwrite},
- {sfnames, ST_FILE_STEREO, /* IRCAM Sound File */
+ st_sbstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
+ {sfnames, ST_FILE_STEREO | ST_FILE_SEEK, /* IRCAM Sound File */
st_sfstartread, st_rawread, st_rawstopread,
- st_sfstartwrite, st_rawwrite, st_rawstopwrite},
+ st_sfstartwrite, st_rawwrite, st_rawstopwrite, st_sfseek},
{ slnames, ST_FILE_STEREO, /* signed long raw */
st_slstartread, st_rawread, st_rawstopread,
- st_slstartwrite, st_rawwrite, st_rawstopwrite },
- {smpnames, ST_FILE_STEREO | ST_FILE_LOOPS,/* SampleVision sound */
+ st_slstartwrite, st_rawwrite, st_rawstopwrite, st_nothing },
+ {smpnames, ST_FILE_STEREO | ST_FILE_LOOPS | ST_FILE_SEEK,/* SampleVision sound */
st_smpstartread, st_smpread, st_nothing,
- st_smpstartwrite, st_smpwrite, st_smpstopwrite},
- {sndtnames, ST_FILE_STEREO, /* Sndtool Sound File */
+ st_smpstartwrite, st_smpwrite, st_smpstopwrite, st_smpseek},
+ {sndtnames, ST_FILE_STEREO | ST_FILE_SEEK, /* Sndtool Sound File */
st_sndtstartread, st_rawread, st_rawstopread,
- st_sndtstartwrite, st_sndtwrite, st_sndtstopwrite},
+ st_sndtstartwrite, st_sndtwrite, st_sndtstopwrite, st_sndseek},
{spherenames, ST_FILE_STEREO, /* NIST Sphere File */
st_spherestartread, st_sphereread, st_rawstopread,
- st_spherestartwrite, st_spherewrite, st_spherestopwrite},
+ st_spherestartwrite, st_spherewrite, st_spherestopwrite, st_nothing},
#if defined(SUNAUDIO_PLAYER)
{sunnames, ST_FILE_STEREO, /* Sun /dev/audio player */
st_sunstartread, st_rawread, st_rawstopread,
- st_sunstartwrite, st_rawwrite, st_rawstopwrite},
+ st_sunstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
#endif
{svxnames, ST_FILE_STEREO, /* Amiga 8SVX */
st_svxstartread, st_svxread, st_svxstopread,
- st_svxstartwrite, st_svxwrite, st_svxstopwrite},
+ st_svxstartwrite, st_svxwrite, st_svxstopwrite, st_nothing},
{swnames, ST_FILE_STEREO, /* signed word raw */
st_swstartread, st_rawread, st_rawstopread,
- st_swstartwrite, st_rawwrite, st_rawstopwrite},
+ st_swstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
{txwnames, 0, /* Yamaha TX16W and SY99 waves */
st_txwstartread, st_txwread, st_txwstopread,
- st_txwstartwrite, st_txwwrite, st_txwstopwrite},
+ st_txwstartwrite, st_txwwrite, st_txwstopwrite, st_nothing},
{ubnames, ST_FILE_STEREO, /* unsigned byte raw */
st_ubstartread, st_rawread, st_rawstopread,
- st_ubstartwrite, st_rawwrite, st_rawstopwrite},
+ st_ubstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
{ulnames, ST_FILE_STEREO, /* u-law byte raw */
st_ulstartread, st_rawread, st_rawstopread,
- st_ulstartwrite, st_rawwrite, st_rawstopwrite},
+ st_ulstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
{uwnames, ST_FILE_STEREO, /* unsigned word raw */
st_uwstartread, st_rawread, st_rawstopread,
- st_uwstartwrite, st_rawwrite, st_rawstopwrite},
+ st_uwstartwrite, st_rawwrite, st_rawstopwrite, st_nothing},
{vocnames, ST_FILE_STEREO, /* Sound Blaster .VOC */
st_vocstartread, st_vocread, st_vocstopread,
- st_vocstartwrite, st_vocwrite, st_vocstopwrite},
- {wavnames, ST_FILE_STEREO, /* Microsoftt RIFF */
+ st_vocstartwrite, st_vocwrite, st_vocstopwrite, st_nothing},
+ {wavnames, ST_FILE_STEREO | ST_FILE_SEEK, /* Microsoftt RIFF */
st_wavstartread, st_wavread, st_nothing,
- st_wavstartwrite, st_wavwrite, st_wavstopwrite},
- {wvenames, 0, /* Psion .wve */
+ st_wavstartwrite, st_wavwrite, st_wavstopwrite, st_wavseek},
+ {wvenames, ST_FILE_SEEK, /* Psion .wve */
st_wvestartread, st_wveread, st_rawstopread,
- st_wvestartwrite, st_wvewrite, st_wvestopwrite},
+ st_wvestartwrite, st_wvewrite, st_wvestopwrite, st_wveseek},
{0, 0,
0, 0, 0, 0, 0, 0}
};
@@ -660,7 +667,7 @@
{"null", 0, /* stand-in, never gets called */
st_nothing, st_nothing, st_nothing,
st_null_drain, st_nothing},
- {"avg", ST_EFF_MCHAN,
+ {"avg", ST_EFF_CHAN,
st_avg_getopts, st_avg_start, st_avg_flow,
st_null_drain, st_avg_stop},
{"band", 0,
--- a/src/hcom.c
+++ b/src/hcom.c
@@ -77,7 +77,7 @@
/* Check the file type (bytes 65-68) */
if (st_reads(ft, buf, 4) == ST_EOF || strncmp(buf, "FSSD", 4) != 0)
{
- st_fail("Mac header type is not FSSD");
+ st_fail_errno(ft,ST_EHDR,"Mac header type is not FSSD");
return (ST_EOF);
}
@@ -98,7 +98,7 @@
/* The data fork must contain a "HCOM" header */
if (st_reads(ft, buf, 4) == ST_EOF || strncmp(buf, "HCOM", 4) != 0)
{
- st_fail("Mac data fork is not HCOM");
+ st_fail_errno(ft,ST_EHDR,"Mac data fork is not HCOM");
return (ST_EOF);
}
@@ -108,13 +108,13 @@
st_readdw(ft, &compresstype);
if (compresstype > 1)
{
- st_fail("Bad compression type in HCOM header");
+ st_fail_errno(ft,ST_EHDR,"Bad compression type in HCOM header");
return (ST_EOF);
}
st_readdw(ft, &divisor);
if (divisor == 0 || divisor > 4)
{
- st_fail("Bad sampling rate divisor in HCOM header");
+ st_fail_errno(ft,ST_EHDR,"Bad sampling rate divisor in HCOM header");
return (ST_EOF);
}
st_readw(ft, &dictsize);
@@ -129,8 +129,8 @@
p->dictionary = (dictent *) malloc(511 * sizeof(dictent));
if (p->dictionary == NULL)
{
- st_fail("can't malloc memory for Huffman dictionary");
- return (0);
+ st_fail_errno(ft,ST_ENOMEM,"can't malloc memory for Huffman dictionary");
+ return (ST_EOF);
}
/* Read dictionary */
@@ -169,7 +169,7 @@
while (--n >= 0) {
if (st_readb(ft, &trash) == ST_EOF)
{
- st_fail("unexpected EOF in Mac header");
+ st_fail_errno(ft,ST_EOF,"unexpected EOF in Mac header");
return(ST_EOF);
}
}
@@ -190,7 +190,7 @@
return 0; /* Don't know if this can happen... */
if (st_readb(ft, &sample_rate) == ST_EOF)
{
- st_fail("unexpected EOF at start of HCOM data");
+ st_fail_errno(ft,ST_EOF,"unexpected EOF at start of HCOM data");
return (0);
}
p->sample = sample_rate;
@@ -208,7 +208,7 @@
st_readdw(ft, &(p->current));
if (feof(ft->fp))
{
- st_fail("unexpected EOF in HCOM data");
+ st_fail_errno(ft,ST_EOF,"unexpected EOF in HCOM data");
return (0);
}
p->cksum += p->current;
@@ -252,12 +252,12 @@
if (p->huffcount != 0)
{
- st_fail("not all HCOM data read");
+ st_fail_errno(ft,ST_EFMT,"not all HCOM data read");
return (ST_EOF);
}
if(p->cksum != p->checksum)
{
- st_fail("checksum error in HCOM data");
+ st_fail_errno(ft,ST_EFMT,"checksum error in HCOM data");
return (ST_EOF);
}
free((char *)p->dictionary);
@@ -293,7 +293,7 @@
case 22050/4:
break;
default:
- st_fail("unacceptable output rate for HCOM: try 5512, 7350, 11025 or 22050 hertz");
+ st_fail_errno(ft,ST_EFMT,"unacceptable output rate for HCOM: try 5512, 7350, 11025 or 22050 hertz");
return (ST_EOF);
}
ft->info.size = ST_SIZE_BYTE;
@@ -305,7 +305,7 @@
p->data = (unsigned char *) malloc(p->size);
if (p->data == NULL)
{
- st_fail("can't malloc buffer for uncompressed HCOM data");
+ st_fail_errno(ft,ST_ENOMEM,"can't malloc buffer for uncompressed HCOM data");
return (ST_EOF);
}
return (ST_SUCCESS);
@@ -327,7 +327,7 @@
p->data = (unsigned char *) realloc(p->data, p->size);
if (p->data == NULL)
{
- st_fail("can't realloc buffer for uncompressed HCOM data");
+ st_fail_errno(ft,ST_ENOMEM,"can't realloc buffer for uncompressed HCOM data");
return (0);
}
}
@@ -495,8 +495,7 @@
st_report("Compressed size: %6d bytes", l);
if((datafork = (unsigned char *)malloc((unsigned)l)) == NULL)
{
- st_fail("can't malloc buffer for compressed HCOM data");
- return (ST_EOF);
+ return (ST_ENOMEM);
}
ddf = datafork + 22;
for(i = 0; i < dictsize; i++) {
@@ -553,8 +552,10 @@
rc = compress(&compressed_data, &compressed_len, (double) ft->info.rate);
free((char *) p->data);
- if (rc)
+ if (rc){
+ st_fail_errno(ft, rc,"can't malloc buffer for compressed HCOM data");
return 0;
+ }
/* Write the header */
fwrite("\000\001A", 1, 3, ft->fp); /* Dummy file name "A" */
@@ -566,7 +567,7 @@
padbytes(ft, 128 - 91);
if (ferror(ft->fp))
{
- st_fail("write error in HCOM header");
+ st_fail_errno(ft,errno,"write error in HCOM header");
return (ST_EOF);
}
@@ -573,7 +574,7 @@
/* Write the compressed_data fork */
if (fwrite((char *) compressed_data, 1, (int)compressed_len, ft->fp) != compressed_len)
{
- st_fail("can't write compressed HCOM data");
+ st_fail_errno(ft,errno,"can't write compressed HCOM data");
rc = ST_EOF;
}
else
--- a/src/maud.c
+++ b/src/maud.c
@@ -73,7 +73,7 @@
/* read FORM chunk */
if (st_reads(ft, buf, 4) == ST_EOF || strncmp(buf, "FORM", 4) != 0)
{
- st_fail("MAUD: header does not begin with magic word 'FORM'");
+ st_fail_errno(ft,ST_EHDR,"MAUD: header does not begin with magic word 'FORM'");
return (ST_EOF);
}
@@ -81,7 +81,7 @@
if (st_reads(ft, buf, 4) == ST_EOF || strncmp(buf, "MAUD", 4) != 0)
{
- st_fail("MAUD: 'FORM' chunk does not specify 'MAUD' as type");
+ st_fail_errno(ft,ST_EHDR,"MAUD: 'FORM' chunk does not specify 'MAUD' as type");
return(ST_EOF);
}
@@ -99,8 +99,8 @@
st_readdw(ft, &chunksize);
if (chunksize != 8*4)
{
- st_fail("MAUD: MHDR chunk has bad size");
- return(0);
+ st_fail_errno(ft,ST_EHDR,"MAUD: MHDR chunk has bad size");
+ return(ST_EOF);
}
/* fseek(ft->fp,12,SEEK_CUR); */
@@ -118,7 +118,7 @@
st_readw(ft, &denom); /* clock devide */
if (denom == 0)
{
- st_fail("MAUD: frequency denominator == 0, failed");
+ st_fail_errno(ft,ST_EHDR,"MAUD: frequency denominator == 0, failed");
return (ST_EOF);
}
@@ -133,7 +133,7 @@
ft->info.channels = 2;
break;
default:
- st_fail("MAUD: unsupported number of channels in file");
+ st_fail_errno(ft,ST_EFMT,"MAUD: unsupported number of channels in file");
return (ST_EOF);
}
@@ -140,7 +140,7 @@
st_readw(ft, &chaninf); /* number of channels (mono: 1, stereo: 2, ...) */
if (chaninf != ft->info.channels)
{
- st_fail("MAUD: unsupported number of channels in file");
+ st_fail_errno(ft,ST_EFMT,"MAUD: unsupported number of channels in file");
return(ST_EOF);
}
@@ -168,7 +168,7 @@
}
else
{
- st_fail("MAUD: unsupported compression type detected");
+ st_fail_errno(ft,ST_EFMT,"MAUD: unsupported compression type detected");
return(ST_EOF);
}
@@ -184,13 +184,13 @@
chunk_buf = (char *) malloc(chunksize + 1);
if (!chunk_buf)
{
- st_fail("Couldn't alloc resources");
+ st_fail_errno(ft,ST_ENOMEM,"Couldn't alloc resources");
return(ST_EOF);
}
if (fread(chunk_buf,1,(int)chunksize,ft->fp)
!= chunksize)
{
- st_fail("MAUD: Unexpected EOF in ANNO header");
+ st_fail_errno(ft,ST_EOF,"MAUD: Unexpected EOF in ANNO header");
return(ST_EOF);
}
chunk_buf[chunksize] = '\0';
@@ -211,7 +211,7 @@
if (strncmp(buf,"MDAT",4) != 0)
{
- st_fail("MAUD: MDAT chunk not found");
+ st_fail_errno(ft,ST_EFMT,"MAUD: MDAT chunk not found");
return(ST_EOF);
}
st_readdw(ft, &(p->nsamples));
@@ -265,12 +265,12 @@
/* If you have to seek around the output file */
if (! ft->seekable)
{
- st_fail("Output .maud file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"Output .maud file must be a file, not a pipe");
return (ST_EOF);
}
if (ft->info.channels != 1 && ft->info.channels != 2) {
- st_fail("MAUD: unsupported number of channels, unable to store");
+ st_fail_errno(ft,ST_EFMT,"MAUD: unsupported number of channels, unable to store");
return(ST_EOF);
}
if (ft->info.size == ST_SIZE_WORD) ft->info.encoding = ST_ENCODING_SIGN2;
@@ -311,7 +311,7 @@
if (fseek(ft->fp, 0L, 0) != 0)
{
- st_fail("can't rewind output file to rewrite MAUD header");
+ st_fail_errno(ft,errno,"can't rewind output file to rewrite MAUD header");
return(ST_EOF);
}
--- a/src/misc.c
+++ b/src/misc.c
@@ -18,6 +18,10 @@
#include <time.h>
#include <string.h>
+/* for fstat */
+#include <sys/stat.h>
+#include <unistd.h>
+
const char *st_sizes_str[] = {
"NONSENSE!",
"bytes",
@@ -92,6 +96,7 @@
if (fread(&in, 1, 1, ft->fp) != 1)
{
*sc = 0;
+ st_fail_errno(ft,errno,readerr);
return (ST_EOF);
}
if (in == 0 || in == '\n')
@@ -114,7 +119,7 @@
{
if (fwrite(c, 1, strlen(c), ft->fp) != strlen(c))
{
- st_fail(writerr);
+ st_fail_errno(ft,errno,writerr);
return(ST_EOF);
}
return(ST_SUCCESS);
@@ -128,6 +133,7 @@
{
if (fread(uc, 1, 1, ft->fp) != 1)
{
+ st_fail_errno(ft,errno,readerr);
return(ST_EOF);
}
return ST_SUCCESS;
@@ -141,7 +147,7 @@
{
if (fwrite(&uc, 1, 1, ft->fp) != 1)
{
- st_fail(writerr);
+ st_fail_errno(ft,errno,writerr);
return(ST_EOF);
}
return(ST_SUCCESS);
@@ -155,6 +161,7 @@
{
if (fread(us, 2, 1, ft->fp) != 1)
{
+ st_fail_errno(ft,errno,readerr);
return (ST_EOF);
}
if (ft->swap)
@@ -172,7 +179,7 @@
us = st_swapw(us);
if (fwrite(&us, 2, 1, ft->fp) != 1)
{
- st_fail(writerr);
+ st_fail_errno(ft,errno,writerr);
return (ST_EOF);
}
return(ST_SUCCESS);
@@ -186,6 +193,7 @@
{
if (fread(ul, 4, 1, ft->fp) != 1)
{
+ st_fail_errno(ft,errno,readerr);
return (ST_EOF);
}
if (ft->swap)
@@ -203,7 +211,7 @@
ul = st_swapl(ul);
if (fwrite(&ul, 4, 1, ft->fp) != 1)
{
- st_fail(writerr);
+ st_fail_errno(ft,errno,writerr);
return (ST_EOF);
}
return(ST_SUCCESS);
@@ -236,7 +244,7 @@
t = st_swapf(t);
if (fwrite(&t, sizeof(float), 1, ft->fp) != 1)
{
- st_fail(writerr);
+ st_fail_errno(ft,errno,writerr);
return (ST_EOF);
}
return (ST_SUCCESS);
@@ -267,7 +275,7 @@
d = st_swapd(d);
if (fwrite(&d, sizeof(double), 1, ft->fp) != 1)
{
- st_fail(writerr);
+ st_fail_errno(ft,errno,writerr);
return (ST_EOF);
}
return (ST_SUCCESS);
@@ -468,3 +476,61 @@
}
}
#endif
+
+/* Sets file offset
+ * offset in bytes
+ */
+int st_seek(ft,offset,whence)
+ft_t ft;
+LONG offset;
+int whence;
+{
+ if( ft->seekable == 0 ){
+/*
+ * If a stream peel off chars else
+ * EPERM "Operation not permitted"
+ */
+ if(whence == SEEK_CUR ){
+ if( offset < 0 ){
+ st_fail_errno(ft,ST_EINVAL,"Can't seek backwards in pipe");
+ } else {
+ while ( offset > 0 && !feof(ft->fp) )
+ {
+ getc(ft->fp);
+ offset--;
+ }
+ if(offset)
+ st_fail_errno(ft,ST_EOF,"offset past eof");
+ else
+ ft->st_errno = ST_SUCCESS;
+ }
+ } else {
+ st_fail_errno(ft,ST_EPERM,"File not seekable");
+ }
+ } else {
+ if( fseek(ft->fp,offset,whence) == -1 )
+ st_fail_errno(ft,errno,strerror(errno));
+ else
+ ft->st_errno = ST_SUCCESS;
+ }
+
+/* Empty the st file buffer */
+ if( ft->st_errno == ST_SUCCESS ){
+ ft->file.count = 0;
+ ft->file.pos = 0;
+ ft->file.eof = 0;
+ }
+
+ return(ft->st_errno);
+}
+
+LONG st_filelength(ft)
+ft_t ft;
+{
+
+ struct stat st;
+
+ fstat(fileno(ft->fp), &st);
+
+ return (LONG)st.st_size;
+}
--- a/src/oss.c
+++ b/src/oss.c
@@ -84,12 +84,12 @@
if (ioctl(fileno(ft->fp), SNDCTL_DSP_RESET, 0) < 0)
{
- st_fail("Unable to reset OSS driver. Possibly accessing an invalid file/device");
+ st_fail_errno(ft,ST_EOF,"Unable to reset OSS driver. Possibly accessing an invalid file/device");
return(ST_EOF);
}
if (ioctl(fileno(ft->fp), SNDCTL_DSP_SYNC, NULL) < 0) {
- st_fail("Unable to sync dsp");
+ st_fail_errno(ft,ST_EOF,"Unable to sync dsp");
return (ST_EOF);
}
@@ -136,7 +136,7 @@
/* Give up and exit */
if (rc < 0 || tmp != sampletype)
{
- st_fail("Unable to set the sample size to %d", samplesize);
+ st_fail_errno(ft,ST_EOF,"Unable to set the sample size to %d", samplesize);
return (ST_EOF);
}
@@ -181,7 +181,7 @@
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("Invalid audio buffer size %d", ft->file.size);
+ st_fail_errno(ft,ST_EOF,"Invalid audio buffer size %d", ft->file.size);
return (ST_EOF);
}
ft->file.count = 0;
@@ -189,7 +189,7 @@
ft->file.eof = 0;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("Unable to allocate input/output buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_EOF,"Unable to allocate input/output buffer of size %d", ft->file.size);
return (ST_EOF);
}
--- a/src/raw.c
+++ b/src/raw.c
@@ -33,6 +33,36 @@
static void rawdefaults(ft_t ft);
+
+int st_rawseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ int sample_size = 0;
+
+ switch(ft->info.size) {
+ case ST_SIZE_BYTE:
+ sample_size = 1;
+ break;
+ case ST_SIZE_WORD:
+ sample_size = sizeof(short);
+ break;
+ case ST_SIZE_DWORD:
+ sample_size = sizeof(LONG);
+ break;
+ case ST_SIZE_FLOAT:
+ sample_size = sizeof(float);
+ break;
+ default:
+ st_fail_errno(ft,ST_ENOTSUP,"Can't seek this data size");
+ return(ft->st_errno);
+ }
+
+ ft->st_errno = st_seek(ft,offset*sample_size,SEEK_SET);
+
+ return(ft->st_errno);
+}
+
int st_rawstartread(ft)
ft_t ft;
{
@@ -39,7 +69,7 @@
ft->file.buf = malloc(BUFSIZ);
if (!ft->file.buf)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_ENOMEM,"Unable to alloc resources");
return(ST_EOF);
}
ft->file.size = BUFSIZ;
@@ -56,7 +86,7 @@
ft->file.buf = malloc(BUFSIZ);
if (!ft->file.buf)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_ENOMEM,"Unable to alloc resources");
return(ST_EOF);
}
ft->file.size = BUFSIZ;
@@ -241,10 +271,10 @@
}
return done;
case ST_ENCODING_ULAW:
- st_fail("No U-Law support for shorts");
+ st_fail_errno(ft,ST_EFMT,"No U-Law support for shorts");
return 0;
case ST_ENCODING_ALAW:
- st_fail("No A-Law support for shorts");
+ st_fail_errno(ft,ST_EFMT,"No A-Law support for shorts");
return 0;
}
break;
@@ -276,7 +306,11 @@
default:
break;
}
- st_fail("Sorry, don't have code to read %s, %s",
+/* Someone could send a really bad ft. i.e. ft->info.encoding = -145677
+ * i should know I've done this. It will segment fault st_fail_errno.
+ */
+
+ st_fail_errno(ft,ST_EFMT,"Sorry, don't have code to read %s, %s",
st_encodings_str[ft->info.encoding], st_sizes_str[ft->info.size]);
return(0);
}
@@ -294,7 +328,7 @@
{
if (fwrite(ft->file.buf, 1, ft->file.pos, ft->fp) != ft->file.pos)
{
- st_fail("Error writing data to file");
+ st_fail_errno(ft,errno,"Error writing data to file");
}
ft->file.pos = 0;
}
@@ -452,10 +486,10 @@
}
return done;
case ST_ENCODING_ULAW:
- st_fail("No U-Law support for shorts");
+ st_fail_errno(ft,ST_EFMT,"No U-Law support for shorts");
return 0;
case ST_ENCODING_ALAW:
- st_fail("No A-Law support for shorts");
+ st_fail_errno(ft,ST_EFMT,"No A-Law support for shorts");
return 0;
}
break;
@@ -484,7 +518,8 @@
default:
break;
}
- st_fail("Sorry, don't have code to write %s, %s",
+ /* Possible overflow */
+ st_fail_errno(ft,ST_EFMT,"Sorry, don't have code to write %s, %s",
st_encodings_str[ft->info.encoding], st_sizes_str[ft->info.size]);
return 0;
}
--- a/src/sf.c
+++ b/src/sf.c
@@ -26,6 +26,8 @@
/* Private data for SF file */
typedef struct sfstuff {
struct sfinfo info;
+ /* needed for seek */
+ LONG dataStart;
} *sf_t;
/*
@@ -68,6 +70,16 @@
ft->comment = commentbuf;
}
+int st_sfseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ sf_t sf = (sf_t ) ft->priv;
+
+ return st_seek(ft,offset*ft->info.size + sf->dataStart,SEEK_SET);
+
+}
+
/*
* Do anything required before you start reading samples.
* Read file header.
@@ -81,12 +93,8 @@
sf_t sf = (sf_t) ft->priv;
SFHEADER sfhead;
int rc;
+ int samplesize = 0;
- /* Needed for rawread() */
- rc = st_rawstartread(ft);
- if (rc)
- return rc;
-
if (fread(&sfhead, 1, sizeof(sfhead), ft->fp) != sizeof(sfhead))
{
st_fail("unexpected EOF in SF header");
@@ -114,10 +122,12 @@
case SF_SHORT:
ft->info.size = ST_SIZE_WORD;
ft->info.encoding = ST_ENCODING_SIGN2;
+ samplesize = ft->info.size;
break;
case SF_FLOAT:
ft->info.size = ST_SIZE_FLOAT;
ft->info.encoding = ST_ENCODING_SIGN2;
+ samplesize = sizeof(float);
break;
default:
st_fail("Soundfile input: unknown format 0x%x\n",
@@ -129,7 +139,18 @@
/* Read codes and print as comments. */
readcodes(ft, &sfhead);
- return(ST_SUCCESS);
+ /* Needed for rawread() */
+ rc = st_rawstartread(ft);
+
+/* Need length for seeking */
+ if(ft->seekable){
+ ft->length = st_filelength(ft)/samplesize;
+ sf->dataStart = ftell(ft->fp);
+ } else {
+ ft->length = 0;
+ }
+
+ return(rc);
}
int st_sfstartwrite(ft)
--- a/src/skel.c
+++ b/src/skel.c
@@ -34,7 +34,7 @@
/* If you need to seek around the input file. */
if (! ft->seekable)
{
- st_fail("SKEL input file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EVALUE,"SKEL input file must be a file, not a pipe");
return (ST_EOF);
}
@@ -103,7 +103,7 @@
/* If you have to seek around the output file */
if (! ft->seekable)
{
- st_fail("Output .skel file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EVALUE,"Output .skel file must be a file, not a pipe");
return (ST_EOF);
}
@@ -130,7 +130,7 @@
while(len--)
st_writeb(ft, (*buf++ >> 24) ^ 0x80);
/* If you cannot write out all of the supplied samples, */
- /* st_fail("SKEL: Can't write all samples to %s", ft->filename); */
+ /* st_fail_errno(ft,ST_EVALUE,"SKEL: Can't write all samples to %s", ft->filename); */
/* return (ST_EOF); */
return (ST_SUCCESS);
--- a/src/smp.c
+++ b/src/smp.c
@@ -60,6 +60,7 @@
/* Private data for SMP file */
typedef struct smpstuff {
ULONG NoOfSamps; /* Sample data count in words */
+ LONG dataStart;
/* comment memory resides in private data because it's small */
char comment[COMMENTLEN + NAMELEN + 3];
} *smp_t;
@@ -92,7 +93,7 @@
for(i = 0; i < 8; i++) { /* read the 8 markers */
if (fread(trailer->markers[i].name, 1, 10, ft->fp) != 10)
{
- st_fail("EOF in SMP");
+ st_fail_errno(ft,ST_EHDR,"EOF in SMP");
return(ST_EOF);
}
st_readdw(ft, &(trailer->markers[i].position));
@@ -160,7 +161,7 @@
for(i = 0; i < 8; i++) { /* write the 8 markers */
if (st_writes(ft, trailer->markers[i].name) == ST_EOF)
{
- st_fail("EOF in SMP");
+ st_fail_errno(ft,ST_EHDR,"EOF in SMP");
return(ST_EOF);
}
st_writedw(ft, trailer->markers[i].position);
@@ -172,6 +173,19 @@
return(ST_SUCCESS);
}
+int st_smpseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ smp_t smp = (smp_t) ft->priv;
+
+ ft->st_errno = st_seek(ft,offset*ft->info.size + smp->dataStart,SEEK_SET);
+
+ if( ft->st_errno == ST_SUCCESS )
+ smp->NoOfSamps = ft->length - offset;
+
+ return(ft->st_errno);
+}
/*
* Do anything required before you start reading samples.
* Read file header.
@@ -199,7 +213,7 @@
/* If you need to seek around the input file. */
if (! ft->seekable)
{
- st_fail("SMP input file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"SMP input file must be a file, not a pipe");
return(ST_EOF);
}
@@ -206,17 +220,17 @@
/* Read SampleVision header */
if (fread((char *) &header, 1, HEADERSIZE, ft->fp) != HEADERSIZE)
{
- st_fail("unexpected EOF in SMP header");
+ st_fail_errno(ft,ST_EHDR,"unexpected EOF in SMP header");
return(ST_EOF);
}
if (strncmp(header.Id, SVmagic, 17) != 0)
{
- st_fail("SMP header does not begin with magic word %s\n", SVmagic);
+ st_fail_errno(ft,ST_EHDR,"SMP header does not begin with magic word %s\n", SVmagic);
return(ST_EOF);
}
if (strncmp(header.version, SVvers, 4) != 0)
{
- st_fail("SMP header is not version %s\n", SVvers);
+ st_fail_errno(ft,ST_EHDR,"SMP header is not version %s\n", SVvers);
return(ST_EOF);
}
@@ -243,12 +257,12 @@
/* NoOfSamps * 2 */
if (fseek(ft->fp, smp->NoOfSamps * 2L, 1) == -1)
{
- st_fail("SMP unable to seek to trailer");
+ st_fail_errno(ft,errno,"SMP unable to seek to trailer");
return(ST_EOF);
}
if (readtrailer(ft, &trailer))
{
- st_fail("unexpected EOF in SMP trailer");
+ st_fail_errno(ft,ST_EHDR,"unexpected EOF in SMP trailer");
return(ST_EOF);
}
@@ -255,7 +269,7 @@
/* seek back to the beginning of the data */
if (fseek(ft->fp, samplestart, 0) == -1)
{
- st_fail("SMP unable to seek back to start of sample data");
+ st_fail_errno(ft,errno,"SMP unable to seek back to start of sample data");
return(ST_EOF);
}
@@ -263,6 +277,8 @@
ft->info.size = ST_SIZE_WORD;
ft->info.encoding = ST_ENCODING_SIGN2;
ft->info.channels = 1;
+ smp->dataStart = samplestart;
+ ft->length = smp->NoOfSamps;
st_report("SampleVision trailer:\n");
for(i = 0; i < 8; i++) if (1 || trailer.loops[i].count) {
@@ -351,7 +367,7 @@
/* If you have to seek around the output file */
if (! ft->seekable)
{
- st_fail("Output .smp file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"Output .smp file must be a file, not a pipe");
return(ST_EOF);
}
@@ -368,7 +384,7 @@
/* Write file header */
if(fwrite(&header, 1, HEADERSIZE, ft->fp) != HEADERSIZE)
{
- st_fail("SMP: Can't write header completely");
+ st_fail_errno(ft,errno,"SMP: Can't write header completely");
return(ST_EOF);
}
st_writedw(ft, 0); /* write as zero length for now, update later */
@@ -406,7 +422,7 @@
writetrailer(ft, &trailer);
if (fseek(ft->fp, 112, 0) == -1)
{
- st_fail("SMP unable to seek back to save size");
+ st_fail_errno(ft,errno,"SMP unable to seek back to save size");
return(ST_EOF);
}
st_writedw(ft, smp->NoOfSamps);
--- a/src/sndrtool.c
+++ b/src/sndrtool.c
@@ -18,9 +18,10 @@
#include "st.h"
/* Private data used by writer */
-struct sndpriv {
+typedef struct sndpriv {
ULONG nsamples;
-};
+ LONG dataStart;
+} *snd_t;
#ifndef SEEK_CUR
#define SEEK_CUR 1
@@ -28,6 +29,15 @@
static void sndtwriteheader(ft_t ft,LONG nsamples);
+int st_sndseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ snd_t snd = (snd_t ) ft->priv;
+
+ return st_seek(ft,offset*ft->info.size + snd->dataStart,SEEK_SET);
+
+}
/*======================================================================*/
/* SNDSTARTREAD */
/*======================================================================*/
@@ -35,6 +45,8 @@
int st_sndtstartread(ft)
ft_t ft;
{
+ snd_t snd = (snd_t ) ft->priv;
+
char buf[97];
unsigned short rate;
@@ -63,7 +75,7 @@
if (fread(buf, 1, 2, ft->fp) != 2)
{
- st_fail("SND: unexpected EOF");
+ st_fail_errno(ft,errno,"SND: unexpected EOF");
return(ST_EOF);
}
if (strncmp(buf,"\0\0",2) == 0)
@@ -72,7 +84,7 @@
st_readw(ft, &rate);
if (rate < 4000 || rate > 25000 )
{
- st_fail("SND: sample rate out of range");
+ st_fail_errno(ft,ST_EFMT,"SND: sample rate out of range");
return(ST_EOF);
}
fseek(ft->fp,4,SEEK_CUR);
@@ -83,7 +95,7 @@
fread(&buf[2], 1, 6, ft->fp);
if (strncmp(buf,"SOUND",5))
{
- st_fail("SND: unrecognized SND format");
+ st_fail_errno(ft,ST_EFMT,"SND: unrecognized SND format");
return(ST_EOF);
}
fseek(ft->fp,12,SEEK_CUR);
@@ -91,7 +103,7 @@
fseek(ft->fp,6,SEEK_CUR);
if (st_reads(ft, buf, 96) == ST_EOF)
{
- st_fail("SND: unexpected EOF in SND header");
+ st_fail_errno(ft,ST_EHDR,"SND: unexpected EOF in SND header");
return(ST_EOF);
}
st_report("%s",buf);
@@ -102,6 +114,9 @@
ft->info.encoding = ST_ENCODING_UNSIGNED;
ft->info.size = ST_SIZE_BYTE;
+snd->dataStart = ftell(ft->fp);
+ft->length = st_filelength(ft) - snd->dataStart;
+
return (ST_SUCCESS);
}
@@ -111,7 +126,7 @@
int st_sndtstartwrite(ft)
ft_t ft;
{
- struct sndpriv *p = (struct sndpriv *) ft->priv;
+ snd_t p = (snd_t ) ft->priv;
int rc;
/* Needed for rawwrite() */
@@ -179,7 +194,7 @@
ft_t ft;
LONG *buf, len;
{
- struct sndpriv *p = (struct sndpriv *) ft->priv;
+ snd_t p = (snd_t ) ft->priv;
p->nsamples += len;
return st_rawwrite(ft, buf, len);
}
@@ -191,7 +206,7 @@
int st_sndtstopwrite(ft)
ft_t ft;
{
- struct sndpriv *p = (struct sndpriv *) ft->priv;
+ snd_t p = (snd_t ) ft->priv;
int rc;
/* Flush remaining buffer out */
@@ -200,9 +215,13 @@
return rc;
/* fixup file sizes in header */
- if (fseek(ft->fp, 0L, 0) != 0)
- st_fail("can't rewind output file to rewrite SND header");
+ if (fseek(ft->fp, 0L, 0) != 0){
+ st_fail_errno(ft,errno,"can't rewind output file to rewrite SND header");
+ return ST_EOF;
+ }
+
sndtwriteheader(ft, p->nsamples);
+
return(ST_SUCCESS);
}
--- a/src/sox.c
+++ b/src/sox.c
@@ -414,9 +414,11 @@
static void process(void) {
int e, f, havedata, flowstatus;
- st_gettype(&informat);
+ if( st_gettype(&informat) )
+ st_fail("bad input format");
if (writing)
- st_gettype(&outformat);
+ if ( st_gettype(&outformat) )
+ st_fail("bad output format");
/* Read and write starters can change their formats. */
if ((* informat.h->startread)(&informat) == ST_EOF)
@@ -423,7 +425,8 @@
{
st_fail(informat.st_errstr);
}
- st_checkformat(&informat);
+ if ( st_checkformat(&informat) )
+ st_fail("bad input format");
if (dovolume)
st_report("Volume factor: %f\n", volume);
@@ -479,7 +482,8 @@
{
st_fail(outformat.st_errstr);
}
- st_checkformat(&outformat);
+ if (st_checkformat(&outformat))
+ st_fail("bad output format");
st_cmpformats(&informat, &outformat);
st_report("Output file: using sample rate %lu\n\tsize %s, encoding %s, %d %s",
outformat.info.rate, st_sizes_str[outformat.info.size],
@@ -528,6 +532,7 @@
/* Prime while() loop by reading initial chunk of input data. */
efftab[0].olen = (*informat.h->read)(&informat,
efftab[0].obuf, (LONG) BUFSIZ);
+
efftab[0].odone = 0;
/* Change the volume of this initial input data if needed. */
--- a/src/sphere.c
+++ b/src/sphere.c
@@ -43,14 +43,13 @@
/* Magic header */
if (st_reads(ft, buf, 8) == ST_EOF || strncmp(buf, "NIST_1A", 7) != 0)
{
- st_fail("Sphere header does not begin with magic mord 'NIST_1A'");
+ st_fail_errno(ft,ST_EHDR,"Sphere header does not begin with magic mord 'NIST_1A'");
return(ST_EOF);
}
if (st_reads(ft, fldsval, 8) == ST_EOF)
{
- printf("%s\n",fldsval);
- st_fail("Error reading Sphere header");
+ st_fail_errno(ft,ST_EHDR,"Error reading Sphere header %s",fldsval);
return(ST_EOF);
}
@@ -61,7 +60,7 @@
if (st_reads(ft, buf, 255) == ST_EOF)
{
- st_fail("Error reading Sphere header");
+ st_fail_errno(ft,ST_EHDR,"Error reading Sphere header");
return(ST_EOF);
}
@@ -122,7 +121,7 @@
if (st_reads(ft, buf, 255) == ST_EOF)
{
- st_fail("Error reading Sphere header");
+ st_fail_errno(ft,ST_EHDR,"Error reading Sphere header");
return(ST_EOF);
}
@@ -165,7 +164,7 @@
if (!strcmp(sphere->shorten_check,"ajkg"))
{
- st_fail("File uses shorten compression, can not handle this.\n");
+ st_fail_errno(ft,ST_EFMT,"File uses shorten compression, can not handle this.\n");
return(ST_EOF);
}
#endif
@@ -205,7 +204,7 @@
if (!ft->seekable)
{
- st_fail("File must be seekable for sphere file output");
+ st_fail_errno(ft,ST_EOF,"File must be seekable for sphere file output");
return (ST_EOF);
}
@@ -216,7 +215,7 @@
case ST_ENCODING_UNSIGNED:
break;
default:
- st_fail("SPHERE format only supports ulaw and PCM data.");
+ st_fail_errno(ft,ST_EFMT,"SPHERE format only supports ulaw and PCM data.");
return(ST_EOF);
}
@@ -259,7 +258,7 @@
if (fseek(ft->fp, 0L, 0) != 0)
{
- st_fail("Could not rewird output file to rewrite sphere header.\n");
+ st_fail_errno(ft,errno,"Could not rewird output file to rewrite sphere header.\n");
return (ST_EOF);
}
--- a/src/st.h
+++ b/src/st.h
@@ -63,22 +63,22 @@
/* Signal parameters */
/* FIXME: Change to typedef */
-struct st_signalinfo {
+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 */
-};
+} st_signalinfo_t;
/* Loop parameters */
/* FIXME: Change to typedef */
-struct st_loopinfo {
+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 */
-};
+}st_loopinfo_t;
/* Instrument parameters */
@@ -85,7 +85,7 @@
/* vague attempt at generic information for sampler-specific info */
/* FIXME: Change to typedef */
-struct st_instrinfo {
+typedef struct st_instrinfo {
char MIDInote; /* for unity pitch playback */
char MIDIlow, MIDIhi;/* MIDI pitch-bend range */
char loopmode; /* semantics of loop data */
@@ -92,7 +92,7 @@
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 */
@@ -108,13 +108,13 @@
*/
/* FIXME: Change to typedef */
-struct st_fileinfo {
+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 */
-};
+}st_fileinfo_t;
/*
@@ -140,24 +140,26 @@
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 {
- struct st_signalinfo info; /* signal specifications */
- struct st_instrinfo instr; /* instrument specification */
- struct st_loopinfo loops[ST_MAX_NLOOPS]; /* Looping specification */
+ 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 */
- struct st_fileinfo file; /* File data block */
+ 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 * */
- double priv[ST_MAX_PRIVSIZE/8]; /* format's private data area */
+ char priv[ST_MAX_PRIVSIZE]; /* format's private data area */
};
extern st_format_t st_formats[];
@@ -166,6 +168,7 @@
#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 */
/* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
@@ -227,8 +230,10 @@
st_effect_t *h; /* effects driver */
LONG *obuf; /* output buffer */
LONG odone, olen; /* consumed, total length */
- /* FIXME: I perfer void * or char * */
- double priv[ST_MAX_PRIVSIZE]; /* private area for effect */
+ /* 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 */
@@ -276,6 +281,8 @@
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);
/* FIXME: raw routines are used by so many formats their prototypes are defined
* here for convience. This wont last for long so application software
@@ -286,6 +293,7 @@
int st_rawstartwrite(ft_t ft);
int st_rawstopread(ft_t ft);
int st_rawstopwrite(ft_t ft);
+int st_rawseek(ft_t ft, LONG offset);
LONG st_rawread(ft_t ft, LONG *buf, LONG nsamp);
LONG st_rawwrite(ft_t ft, LONG *buf, LONG nsamp);
@@ -321,8 +329,8 @@
int st_geteffect_opt(eff_t, int, char **);
int st_geteffect(eff_t, char *);
int st_updateeffect(eff_t, ft_t, ft_t, int);
-void st_gettype(ft_t);
-void st_checkformat(ft_t);
+int st_gettype(ft_t);
+int st_checkformat(ft_t);
void st_copyformat(ft_t, ft_t);
void st_cmpformats(ft_t, ft_t);
double st_parsetime(char *);
@@ -338,6 +346,7 @@
extern int verbose; /* be noisy on stderr */
extern char *myname;
+extern int errno;
/* Warning, this is a MAX value used in the library. Each format and
* effect may have its own limitations of rate.
*/
@@ -368,8 +377,11 @@
/* 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 20002 /* Unsupported rate for 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/sunaudio.c
+++ b/src/sunaudio.c
@@ -55,7 +55,7 @@
ft->file.eof = 0;
ft->file.size = 1024;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("unable to allocate input buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_ENOMEM,"unable to allocate input buffer of size %d", ft->file.size);
return ST_EOF;
}
@@ -66,7 +66,7 @@
#ifdef __SVR4
/* Read in old values, change to what we need and then send back */
if (ioctl(fileno(ft->fp), AUDIO_GETDEV, &audio_dev) < 0) {
- st_fail("Unable to get device information.");
+ st_fail_errno(ft,errno,"Unable to get device information.");
return(ST_EOF);
}
st_report("Hardware detected: %s\n",audio_dev.name);
@@ -101,7 +101,8 @@
if (ft->info.encoding != ST_ENCODING_ULAW &&
ft->info.encoding != ST_ENCODING_ALAW &&
ft->info.encoding != ST_ENCODING_SIGN2) {
- st_fail("Sun Audio driver only supports ULAW, ALAW, and Signed Linear for bytes.");
+ st_fail_errno(ft,ST_EFMT,"Sun Audio driver only supports ULAW, ALAW, and Signed Linear for bytes.");
+ return (ST_EOF);
}
if ((ft->info.encoding == ST_ENCODING_ULAW ||
ft->info.encoding == ST_ENCODING_ALAW) && ft->info.channels == 2)
@@ -113,12 +114,12 @@
else if (ft->info.size == ST_SIZE_WORD) {
samplesize = 16;
if (ft->info.encoding != ST_ENCODING_SIGN2) {
- st_fail("Sun Audio driver only supports Signed Linear for words.");
+ st_fail_errno(ft,ST_EFMT,"Sun Audio driver only supports Signed Linear for words.");
return(ST_EOF);
}
}
else {
- st_fail("Sun Audio driver only supports bytes and words");
+ st_fail_errno(ft,ST_EFMT,"Sun Audio driver only supports bytes and words");
return(ST_EOF);
}
@@ -134,7 +135,7 @@
/* Read in old values, change to what we need and then send back */
if (ioctl(fileno(ft->fp), AUDIO_GETINFO, &audio_if) < 0) {
- st_fail("Unable to initialize /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize /dev/audio");
return(ST_EOF);
}
audio_if.record.precision = samplesize;
@@ -150,19 +151,19 @@
ioctl(fileno(ft->fp), AUDIO_SETINFO, &audio_if);
if (audio_if.record.precision != samplesize) {
- st_fail("Unable to initialize sample size for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize sample size for /dev/audio");
return(ST_EOF);
}
if (audio_if.record.channels != ft->info.channels) {
- st_fail("Unable to initialize number of channels for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize number of channels for /dev/audio");
return(ST_EOF);
}
if (audio_if.record.sample_rate != ft->info.rate) {
- st_fail("Unable to initialize rate for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize rate for /dev/audio");
return(ST_EOF);
}
if (audio_if.record.encoding != encoding) {
- st_fail("Unable to initialize encoding for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize encoding for /dev/audio");
return(ST_EOF);
}
/* Change to non-buffered I/O*/
@@ -188,7 +189,7 @@
ft->file.eof = 0;
ft->file.size = 1024;
if ((ft->file.buf = malloc (ft->file.size)) == NULL) {
- st_fail("unable to allocate output buffer of size %d", ft->file.size);
+ st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
return(ST_EOF);
}
@@ -195,7 +196,7 @@
#ifdef __SVR4
/* Read in old values, change to what we need and then send back */
if (ioctl(fileno(ft->fp), AUDIO_GETDEV, &audio_dev) < 0) {
- st_fail("Unable to get device information.");
+ st_fail_errno(ft,errno,"Unable to get device information.");
return(ST_EOF);
}
st_report("Hardware detected: %s\n",audio_dev.name);
@@ -264,7 +265,7 @@
/* Read in old values, change to what we need and then send back */
if (ioctl(fileno(ft->fp), AUDIO_GETINFO, &audio_if) < 0) {
- st_fail("Unable to initialize /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize /dev/audio");
return(ST_EOF);
}
audio_if.play.precision = samplesize;
@@ -280,19 +281,19 @@
ioctl(fileno(ft->fp), AUDIO_SETINFO, &audio_if);
if (audio_if.play.precision != samplesize) {
- st_fail("Unable to initialize sample size for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize sample size for /dev/audio");
return(ST_EOF);
}
if (audio_if.play.channels != ft->info.channels) {
- st_fail("Unable to initialize number of channels for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize number of channels for /dev/audio");
return(ST_EOF);
}
if (audio_if.play.sample_rate != ft->info.rate) {
- st_fail("Unable to initialize rate for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize rate for /dev/audio");
return(ST_EOF);
}
if (audio_if.play.encoding != encoding) {
- st_fail("Unable to initialize encoding for /dev/audio");
+ st_fail_errno(ft,errno,"Unable to initialize encoding for /dev/audio");
return(ST_EOF);
}
/* Change to non-buffered I/O */
--- a/src/tx16w.c
+++ b/src/tx16w.c
@@ -90,7 +90,7 @@
/* If you need to seek around the input file. */
if (! ft->seekable)
{
- st_fail("txw input file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"txw input file must be a file, not a pipe");
return(ST_EOF);
}
@@ -127,7 +127,7 @@
st_report("Found header filetype %s",filetype);
if(strcmp(filetype,"LM8953"))
{
- st_fail("Invalid filetype ID in input file header, != LM8953");
+ st_fail_errno(ft,ST_EHDR,"Invalid filetype ID in input file header, != LM8953");
return(ST_EOF);
}
/*
@@ -267,7 +267,7 @@
/* If you have to seek around the output file */
if (! ft->seekable)
{
- st_fail("Output .txw file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"Output .txw file must be a file, not a pipe");
return(ST_EOF);
}
@@ -331,7 +331,7 @@
else WH.sample_rate = 2;
if (tx16w_len >= TXMAXLEN) {
- fprintf(stderr,"Sound too large for TX16W. Truncating, Loop Off\n");
+ st_warn("Sound too large for TX16W. Truncating, Loop Off\n");
AttackLength = TXMAXLEN/2;
LoopLength = TXMAXLEN/2;
}
--- a/src/util.c
+++ b/src/util.c
@@ -83,6 +83,8 @@
/* Warning: no error checking is done with errstr. Be sure not to
* go over the array limit ourself!
+ * Note: Changing vsprintf to vsnprintf should help that but bad
+ * references to strings can still cause overflow.
*/
void
st_fail_errno(ft_t ft, int st_errno, const char *fmt, ...)
@@ -92,8 +94,9 @@
ft->st_errno = st_errno;
va_start(args, fmt);
- vsprintf(ft->st_errstr, fmt, args);
+ vsnprintf(ft->st_errstr, 255,fmt, args);
va_end(args);
+ ft->st_errstr[255] = '\0';
}
int st_is_bigendian(void)
@@ -133,7 +136,7 @@
/*
* Check that we have a known format suffix string.
*/
-void
+int
st_gettype(formp)
ft_t formp;
{
@@ -140,9 +143,11 @@
char **list;
int i;
- if (! formp->filetype)
-st_fail("Must give file type for %s file, either as suffix or with -t option",
+ if (! formp->filetype){
+st_fail_errno(formp,ST_EFMT,"Must give file type for %s file, either as suffix or with -t option",
formp->filename);
+ return(ST_EFMT);
+ }
for(i = 0; st_formats[i].names; i++) {
for(list = st_formats[i].names; *list; list++) {
char *s1 = *list, *s2 = formp->filetype;
@@ -153,7 +158,7 @@
continue;
/* Found it! */
formp->h = &st_formats[i];
- return;
+ return ST_SUCCESS;
}
if (! strcmpcase(formp->filetype, "snd")) {
verbose = 1;
@@ -164,10 +169,12 @@
st_report("If it came from a PC, it's probably a Soundtool file.");
st_report("Use the sequence '-t .sndt file.snd'");
st_report("If it came from a NeXT, it's probably a .au file.");
- st_fail("Use the sequence '-t .au file.snd'\n");
+ st_fail_errno(formp,ST_EFMT,"Use the sequence '-t .au file.snd'\n");
+ return ST_EFMT;
}
- st_fail("File type '%s' of %s file is not known!",
+ st_fail_errno(formp,ST_EFMT,"File type '%s' of %s file is not known!",
formp->filetype, formp->filename);
+ return ST_EFMT;
}
/*
@@ -371,23 +378,37 @@
}
/* check that all settings have been given */
-void st_checkformat(ft)
+int st_checkformat(ft)
ft_t ft;
{
+
+ ft->st_errno = ST_SUCCESS;
+
if (ft->info.rate == 0)
- st_fail("Sampling rate for %s file was not given\n", ft->filename);
+ st_fail_errno(ft,ST_EFMT,"Sampling rate for %s file was not given\n", ft->filename);
if ((ft->info.rate < 100) || (ft->info.rate > 999999L))
- st_fail("Sampling rate %lu for %s file is bogus\n",
+ st_fail_errno(ft,ST_EFMT,"Sampling rate %lu for %s file is bogus\n",
ft->info.rate, ft->filename);
if (ft->info.size == -1)
- st_fail("Data size was not given for %s file\nUse one of -b/-w/-l/-f/-d/-D", ft->filename);
+ st_fail_errno(ft,ST_EFMT,"Data size was not given for %s file\nUse one of -b/-w/-l/-f/-d/-D", ft->filename);
if (ft->info.encoding == -1 && ft->info.size != ST_SIZE_FLOAT)
- st_fail("Data encoding was not given for %s file\nUse one of -s/-u/-U/-A", ft->filename);
+ st_fail_errno(ft,ST_EFMT,"Data encoding was not given for %s file\nUse one of -s/-u/-U/-A", ft->filename);
+/* I put these here because some modules call st_fail_errno with
+ * st_sizes_str[ft->info.size] etc. I don't think the library should
+ * seg fault even if the app using doesn't init ft properly or overflows
+ * into it.
+ * anyway to check length on st_sizes_str[] ? */
+ if ((ft->info.size < 0) || (ft->info.size > 7))
+ st_fail_errno(ft,ST_EFMT,"Data size %i for %s file is bogus\n", ft->filename,ft->info.size);
+ /* anyway to check length on st_encoding_str[] ? */
+ if (ft->info.encoding < -1 || ft->info.encoding > 7)
+ st_fail_errno(ft,ST_EFMT,"Data encoding %i for %s file is bogus\n", ft->filename,ft->info.encoding);
/* it's so common, might as well default */
if (ft->info.channels == -1)
ft->info.channels = 1;
/* st_fail("Number of output channels was not given for %s file",
ft->filename); */
+ return ft->st_errno;
}
static ft_t ft_queue[2];
--- a/src/voc.c
+++ b/src/voc.c
@@ -186,19 +186,21 @@
ft->swap = ft->swap ? 0 : 1;
}
+
if (! ft->seekable)
{
- st_fail("VOC input file must be a file, not a pipe");
+ 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("unexpected EOF in VOC header");
+ st_fail_errno(ft,ST_EHDR,"unexpected EOF in VOC header");
return(ST_EOF);
}
if (strncmp(header, "Creative Voice File\032", 19))
{
- st_fail("VOC file header incorrect");
+ st_fail_errno(ft,ST_EHDR,"VOC file header incorrect");
return(ST_EOF);
}
@@ -213,7 +215,7 @@
return rc;
if (v->rate == -1)
{
- st_fail("Input .voc file had no sound!");
+ st_fail_errno(ft,ST_EOF,"Input .voc file had no sound!");
return(ST_EOF);
}
@@ -313,7 +315,7 @@
if (! ft->seekable)
{
- st_fail("Output .voc file must be a file, not a pipe");
+ st_fail_errno(ft,ST_EOF,"Output .voc file must be a file, not a pipe");
return(ST_EOF);
}
@@ -414,12 +416,12 @@
if (!v->extended) {
if (uc == 0)
{
- st_fail("File %s: Sample rate is zero?");
+ st_fail_errno(ft,ST_EFMT,"File %s: Sample rate is zero?");
return(ST_EOF);
}
if ((v->rate != -1) && (uc != v->rate))
{
- st_fail("File %s: sample rate codes differ: %d != %d",
+ st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
ft->filename,v->rate, uc);
return(ST_EOF);
}
@@ -430,7 +432,7 @@
st_readb(ft, &uc);
if (uc != 0)
{
- st_fail("File %s: only interpret 8-bit data!",
+ st_fail_errno(ft,ST_EFMT,"File %s: only interpret 8-bit data!",
ft->filename);
return(ST_EOF);
}
@@ -442,12 +444,12 @@
st_readdw(ft, &new_rate_long);
if (new_rate_long == 0)
{
- st_fail("File %s: Sample rate is zero?",ft->filename);
+ 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("File %s: sample rate codes differ: %d != %d",
+ st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
ft->filename, v->rate, new_rate_long);
return(ST_EOF);
}
@@ -459,7 +461,7 @@
case 8: v->size = ST_SIZE_BYTE; break;
case 16: v->size = ST_SIZE_WORD; break;
default:
- st_fail("Don't understand size %d", uc);
+ st_fail_errno(ft,ST_EFMT,"Don't understand size %d", uc);
return(ST_EOF);
}
st_readb(ft, &(v->channels));
@@ -482,7 +484,7 @@
st_readb(ft, &uc);
if (uc == 0)
{
- st_fail("File %s: Silence sample rate is zero");
+ st_fail_errno(ft,ST_EFMT,"File %s: Silence sample rate is zero");
return(ST_EOF);
}
/*
@@ -525,12 +527,12 @@
st_readw(ft, &new_rate_short);
if (new_rate_short == 0)
{
- st_fail("File %s: Sample rate is zero?");
+ 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("File %s: sample rate codes differ: %d != %d",
+ st_fail_errno(ft,ST_EFMT,"File %s: sample rate codes differ: %d != %d",
ft->filename, v->rate, new_rate_short);
return(ST_EOF);
}
@@ -538,7 +540,7 @@
st_readb(ft, &uc);
if (uc != 0)
{
- st_fail("File %s: only interpret 8-bit data!",
+ st_fail_errno(ft,ST_EFMT,"File %s: only interpret 8-bit data!",
ft->filename);
return(ST_EOF);
}
--- a/src/wav.c
+++ b/src/wav.c
@@ -80,12 +80,13 @@
/* Private data for .wav file */
typedef struct wavstuff {
- LONG numSamples; /* reading: starts at total count and decremented */
+ LONG numSamples; /* samples/channel reading: starts at total count and decremented */
/* writing: starts at 0 and counts samples written */
LONG dataLength; /* needed for ADPCM writing */
unsigned short formatTag; /* What type of encoding file is using */
unsigned short samplesPerBlock;
unsigned short blockAlign;
+ LONG dataStart; /* need to for seeking */
/* following used by *ADPCM wav files */
unsigned short nCoefs; /* ADPCM: number of coef sets */
@@ -225,7 +226,7 @@
/* write the compressed packet */
if (fwrite(wav->packet, wav->blockAlign, 1, ft->fp) != 1)
{
- st_fail("write error");
+ st_fail_errno(ft,ST_EOF,"write error");
return (ST_EOF);
}
/* update lengths and samplePtr */
@@ -254,18 +255,18 @@
wav->gsmhandle=gsm_create();
if (!wav->gsmhandle)
{
- st_fail("cannot create GSM object");
+ st_fail_errno(ft,ST_EOF,"cannot create GSM object");
return (ST_EOF);
}
if(gsm_option(wav->gsmhandle,GSM_OPT_WAV49,&valueP) == -1){
- st_fail("error setting gsm_option for WAV49 format. Recompile gsm library with -DWAV49 option and relink sox");
+ st_fail_errno(ft,ST_EOF,"error setting gsm_option for WAV49 format. Recompile gsm library with -DWAV49 option and relink sox");
return (ST_EOF);
}
wav->gsmsample=malloc(sizeof(gsm_signal)*160*2);
if (wav->gsmsample == NULL){
- st_fail("error allocating memory for gsm buffer");
+ st_fail_errno(ft,ST_ENOMEM,"error allocating memory for gsm buffer");
return (ST_EOF);
}
wav->gsmindex=0;
@@ -290,6 +291,8 @@
int bytes;
gsm_byte frame[65];
+ ft->st_errno = ST_SUCCESS;
+
/* copy out any samples left from the last call */
while(wav->gsmindex && (wav->gsmindex<160*2) && (done < len))
buf[done++]=LEFT(wav->gsmsample[wav->gsmindex++],16);
@@ -307,13 +310,13 @@
/* decode the long 33 byte half */
if(gsm_decode(wav->gsmhandle,frame, wav->gsmsample)<0)
{
- st_fail("error during gsm decode");
+ st_fail_errno(ft,ST_EOF,"error during gsm decode");
return 0;
}
/* decode the short 32 byte half */
if(gsm_decode(wav->gsmhandle,frame+33, wav->gsmsample+160)<0)
{
- st_fail("error during gsm decode");
+ st_fail_errno(ft,ST_EOF,"error during gsm decode");
return 0;
}
@@ -342,7 +345,7 @@
gsm_encode(wav->gsmhandle, wav->gsmsample+160, frame+32);
if (fwrite(frame, 1, 65, ft->fp) != 65)
{
- st_fail("write error");
+ st_fail_errno(ft,ST_EOF,"write error");
return (ST_EOF);
}
wav->gsmbytecount += 65;
@@ -353,7 +356,7 @@
/* pad output to an even number of bytes */
if(st_writeb(ft, 0))
{
- st_fail("write error");
+ st_fail_errno(ft,ST_EOF,"write error");
return (ST_EOF);
}
wav->gsmbytecount += 1;
@@ -369,6 +372,8 @@
int done = 0;
int rc;
+ ft->st_errno = ST_SUCCESS;
+
while (done < len) {
while ((wav->gsmindex < 160*2) && (done < len))
wav->gsmsample[(wav->gsmindex)++] = RIGHT(buf[done++], 16);
@@ -389,6 +394,8 @@
{
wav_t wav = (wav_t) ft->priv;
+ ft->st_errno = ST_SUCCESS;
+
if (wav->gsmindex)
wavgsmflush(ft, 1);
@@ -399,7 +406,10 @@
/* General Sox WAV file code */
/****************************************************************************/
-/* FIXME: Use common misc.c skip code */
+/* FIXME: Use common misc.c skip code
+
+moved to misc.c using st_seek(ft,len,SEEK_CUR) instead
+
static void fSkip(FILE *fp, ULONG len)
{
while (len > 0 && !feof(fp))
@@ -408,7 +418,7 @@
len--;
}
}
-
+*/
static ULONG findChunk(ft_t ft, const char *Label)
{
char magic[5];
@@ -417,14 +427,16 @@
{
if (st_reads(ft, magic, 4) == ST_EOF)
{
- st_fail("WAVE file has missing %s chunk", Label);
- return 0;
+ st_fail_errno(ft,ST_EHDR,"WAVE file has missing %s chunk", Label);
+ return ST_EOF;
}
st_readdw(ft, &len);
+ st_report("Chunk %s",magic);
if (strncmp(Label, magic, 4) == 0)
break; /* Found the data chunk */
+
- fSkip(ft->fp, len); /* skip to next chunk */
+ st_seek(ft, len, SEEK_CUR); /* skip to next chunk */
}
return len;
}
@@ -456,12 +468,15 @@
ULONG wDataLength; /* length of sound data in bytes */
ULONG bytesPerBlock = 0;
ULONG bytespersample; /* bytes per sample (per channel */
+ char text[256];
+ ft->st_errno = ST_SUCCESS;
+
if (ST_IS_BIGENDIAN) ft->swap = ft->swap ? 0 : 1;
if (st_reads(ft, magic, 4) == ST_EOF || strncmp("RIFF", magic, 4))
{
- st_fail("WAVE: RIFF header not found");
+ st_fail_errno(ft,ST_EHDR,"WAVE: RIFF header not found");
return ST_EOF;
}
@@ -469,7 +484,7 @@
if (st_reads(ft, magic, 4) == ST_EOF || strncmp("WAVE", magic, 4))
{
- st_fail("WAVE header not found");
+ st_fail_errno(ft,ST_EHDR,"WAVE header not found");
return ST_EOF;
}
@@ -479,7 +494,7 @@
if (wFmtSize < 16)
{
- st_fail("WAVE file fmt chunk is too short");
+ st_fail_errno(ft,ST_EHDR,"WAVE file fmt chunk is too short");
return ST_EOF;
}
@@ -494,7 +509,7 @@
switch (wav->formatTag)
{
case WAVE_FORMAT_UNKNOWN:
- st_fail("WAVE file is in unsupported Microsoft Official Unknown format.");
+ st_fail_errno(ft,ST_EHDR,"WAVE file is in unsupported Microsoft Official Unknown format.");
return ST_EOF;
case WAVE_FORMAT_PCM:
@@ -525,7 +540,7 @@
break;
case WAVE_FORMAT_IEEE_FLOAT:
- st_fail("Sorry, this WAV file is in IEEE Float format.");
+ st_fail_errno(ft,ST_EHDR,"Sorry, this WAV file is in IEEE Float format.");
return ST_EOF;
case WAVE_FORMAT_ALAW:
@@ -555,16 +570,16 @@
break;
case WAVE_FORMAT_OKI_ADPCM:
- st_fail("Sorry, this WAV file is in OKI ADPCM format.");
+ st_fail_errno(ft,ST_EHDR,"Sorry, this WAV file is in OKI ADPCM format.");
return ST_EOF;
case WAVE_FORMAT_DIGISTD:
- st_fail("Sorry, this WAV file is in Digistd format.");
+ st_fail_errno(ft,ST_EHDR,"Sorry, this WAV file is in Digistd format.");
return ST_EOF;
case WAVE_FORMAT_DIGIFIX:
- st_fail("Sorry, this WAV file is in Digifix format.");
+ st_fail_errno(ft,ST_EHDR,"Sorry, this WAV file is in Digifix format.");
return ST_EOF;
case WAVE_FORMAT_DOLBY_AC2:
- st_fail("Sorry, this WAV file is in Dolby AC2 format.");
+ st_fail_errno(ft,ST_EHDR,"Sorry, this WAV file is in Dolby AC2 format.");
return ST_EOF;
case WAVE_FORMAT_GSM610:
#ifdef HAVE_LIBGSM
@@ -574,34 +589,34 @@
st_warn("User options overriding encoding read in .wav header");
break;
#else
- st_fail("Sorry, this WAV file is in GSM6.10 format and no GSM support present, recompile sox with gsm library");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in GSM6.10 format and no GSM support present, recompile sox with gsm library");
return ST_EOF;
#endif
case WAVE_FORMAT_ROCKWELL_ADPCM:
- st_fail("Sorry, this WAV file is in Rockwell ADPCM format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in Rockwell ADPCM format.");
return ST_EOF;
case WAVE_FORMAT_ROCKWELL_DIGITALK:
- st_fail("Sorry, this WAV file is in Rockwell DIGITALK format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in Rockwell DIGITALK format.");
return ST_EOF;
case WAVE_FORMAT_G721_ADPCM:
- st_fail("Sorry, this WAV file is in G.721 ADPCM format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in G.721 ADPCM format.");
return ST_EOF;
case WAVE_FORMAT_G728_CELP:
- st_fail("Sorry, this WAV file is in G.728 CELP format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in G.728 CELP format.");
return ST_EOF;
case WAVE_FORMAT_MPEG:
- st_fail("Sorry, this WAV file is in MPEG format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in MPEG format.");
return ST_EOF;
case WAVE_FORMAT_MPEGLAYER3:
- st_fail("Sorry, this WAV file is in MPEG Layer 3 format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in MPEG Layer 3 format.");
return ST_EOF;
case WAVE_FORMAT_G726_ADPCM:
- st_fail("Sorry, this WAV file is in G.726 ADPCM format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in G.726 ADPCM format.");
return ST_EOF;
case WAVE_FORMAT_G722_ADPCM:
- st_fail("Sorry, this WAV file is in G.722 ADPCM format.");
+ st_fail_errno(ft,ST_EOF,"Sorry, this WAV file is in G.722 ADPCM format.");
return ST_EOF;
- default: st_fail("WAV file has unknown format type of %x",wav->formatTag);
+ default: st_fail_errno(ft,ST_EOF,"WAV file has unknown format type of %x",wav->formatTag);
return ST_EOF;
}
@@ -633,7 +648,7 @@
if (wExtSize > len)
{
- st_fail("wave header error: wExtSize inconsistent with wFmtLen");
+ st_fail_errno(ft,ST_EOF,"wave header error: wExtSize inconsistent with wFmtLen");
return ST_EOF;
}
@@ -643,7 +658,7 @@
case WAVE_FORMAT_ADPCM:
if (wExtSize < 4)
{
- st_fail("format[%s]: expects wExtSize >= %d",
+ st_fail_errno(ft,ST_EOF,"format[%s]: expects wExtSize >= %d",
wav_format_str(wav->formatTag), 4);
return ST_EOF;
}
@@ -650,7 +665,7 @@
if (wBitsPerSample != 4)
{
- st_fail("Can only handle 4-bit MS ADPCM in wav files");
+ st_fail_errno(ft,ST_EOF,"Can only handle 4-bit MS ADPCM in wav files");
return ST_EOF;
}
@@ -658,7 +673,7 @@
bytesPerBlock = AdpcmBytesPerBlock(ft->info.channels, wav->samplesPerBlock);
if (bytesPerBlock > wav->blockAlign)
{
- st_fail("format[%s]: samplesPerBlock(%d) incompatible with blockAlign(%d)",
+ st_fail_errno(ft,ST_EOF,"format[%s]: samplesPerBlock(%d) incompatible with blockAlign(%d)",
wav_format_str(wav->formatTag), wav->samplesPerBlock, wav->blockAlign);
return ST_EOF;
}
@@ -665,13 +680,13 @@
st_readw(ft, &(wav->nCoefs));
if (wav->nCoefs < 7 || wav->nCoefs > 0x100) {
- st_fail("ADPCM file nCoefs (%.4hx) makes no sense\n", wav->nCoefs);
+ st_fail_errno(ft,ST_EOF,"ADPCM file nCoefs (%.4hx) makes no sense\n", wav->nCoefs);
return ST_EOF;
}
wav->packet = (unsigned char *)malloc(wav->blockAlign);
if (!wav->packet)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_EOF,"Unable to alloc resources");
return ST_EOF;
}
@@ -679,7 +694,7 @@
if (wExtSize < 4 + 4*wav->nCoefs)
{
- st_fail("wave header error: wExtSize(%d) too small for nCoefs(%d)", wExtSize, wav->nCoefs);
+ st_fail_errno(ft,ST_EOF,"wave header error: wExtSize(%d) too small for nCoefs(%d)", wExtSize, wav->nCoefs);
return ST_EOF;
}
@@ -686,7 +701,7 @@
wav->samples = (short *)malloc(wChannels*wav->samplesPerBlock*sizeof(short));
if (!wav->samples)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_EOF,"Unable to alloc resources");
return ST_EOF;
}
@@ -694,7 +709,7 @@
wav->iCoefs = (short *)malloc(wav->nCoefs * 2 * sizeof(short));
if (!wav->iCoefs)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_EOF,"Unable to alloc resources");
return ST_EOF;
}
{
@@ -714,7 +729,7 @@
case WAVE_FORMAT_IMA_ADPCM:
if (wExtSize < 2)
{
- st_fail("format[%s]: expects wExtSize >= %d",
+ st_fail_errno(ft,ST_EOF,"format[%s]: expects wExtSize >= %d",
wav_format_str(wav->formatTag), 2);
return ST_EOF;
}
@@ -721,7 +736,7 @@
if (wBitsPerSample != 4)
{
- st_fail("Can only handle 4-bit IMA ADPCM in wav files");
+ st_fail_errno(ft,ST_EOF,"Can only handle 4-bit IMA ADPCM in wav files");
return ST_EOF;
}
@@ -729,7 +744,7 @@
bytesPerBlock = ImaBytesPerBlock(ft->info.channels, wav->samplesPerBlock);
if (bytesPerBlock > wav->blockAlign || wav->samplesPerBlock%8 != 1)
{
- st_fail("format[%s]: samplesPerBlock(%d) incompatible with blockAlign(%d)",
+ st_fail_errno(ft,ST_EOF,"format[%s]: samplesPerBlock(%d) incompatible with blockAlign(%d)",
wav_format_str(wav->formatTag), wav->samplesPerBlock, wav->blockAlign);
return ST_EOF;
}
@@ -737,7 +752,7 @@
wav->packet = (unsigned char *)malloc(wav->blockAlign);
if (!wav->packet)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_EOF,"Unable to alloc resources");
return ST_EOF;
}
len -= 2;
@@ -745,7 +760,7 @@
wav->samples = (short *)malloc(wChannels*wav->samplesPerBlock*sizeof(short));
if (!wav->samples)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_EOF,"Unable to alloc resources");
return ST_EOF;
}
@@ -757,7 +772,7 @@
case WAVE_FORMAT_GSM610:
if (wExtSize < 2)
{
- st_fail("format[%s]: expects wExtSize >= %d",
+ st_fail_errno(ft,ST_EOF,"format[%s]: expects wExtSize >= %d",
wav_format_str(wav->formatTag), 2);
return ST_EOF;
}
@@ -765,13 +780,13 @@
bytesPerBlock = 65;
if (wav->blockAlign != 65)
{
- st_fail("format[%s]: expects blockAlign(%d) = %d",
+ st_fail_errno(ft,ST_EOF,"format[%s]: expects blockAlign(%d) = %d",
wav_format_str(wav->formatTag), wav->blockAlign, 65);
return ST_EOF;
}
if (wav->samplesPerBlock != 320)
{
- st_fail("format[%s]: expects samplesPerBlock(%d) = %d",
+ st_fail_errno(ft,ST_EOF,"format[%s]: expects samplesPerBlock(%d) = %d",
wav_format_str(wav->formatTag), wav->samplesPerBlock, 320);
return ST_EOF;
}
@@ -823,12 +838,12 @@
break;
default:
- st_fail("Sorry, don't understand .wav size");
+ st_fail_errno(ft,ST_EOF,"Sorry, don't understand .wav size");
return ST_EOF;
}
/* Skip anything left over from fmt chunk */
- fSkip(ft->fp, len);
+ st_seek(ft, len, SEEK_CUR);
/* for non-PCM formats, there's a 'fact' chunk before
* the upcoming 'data' chunk */
@@ -837,6 +852,9 @@
wDataLength = len = findChunk(ft, "data");
/* findChunk() only returns if chunk was found */
+ /* Data starts here */
+ wav->dataStart = ftell(ft->fp);
+
switch (wav->formatTag)
{
@@ -845,6 +863,7 @@
AdpcmSamplesIn(wDataLength, ft->info.channels, wav->blockAlign, wav->samplesPerBlock);
/*st_report("datalen %d, numSamples %d",wDataLength, wav->numSamples);*/
wav->blockSamplesRemaining = 0; /* Samples left in buffer */
+ ft->length = wav->numSamples*ft->info.channels;
break;
case WAVE_FORMAT_IMA_ADPCM:
@@ -855,6 +874,7 @@
/*st_report("datalen %d, numSamples %d",wDataLength, wav->numSamples);*/
wav->blockSamplesRemaining = 0; /* Samples left in buffer */
initImaTable();
+ ft->length = wav->numSamples*ft->info.channels;
break;
#ifdef HAVE_LIBGSM
@@ -861,11 +881,13 @@
case WAVE_FORMAT_GSM610:
wav->numSamples = (((wDataLength / wav->blockAlign) * wav->samplesPerBlock) * ft->info.channels);
wavgsminit(ft);
+ ft->length = wav->numSamples;
break;
#endif
default:
wav->numSamples = wDataLength/ft->info.size; /* total samples */
+ ft->length = wav->numSamples;
}
@@ -898,6 +920,60 @@
default:
break;
}
+/* Horrible way to find Cool Edit marker points. Taken from Quake source*/
+ ft->loops[0].start = -1;
+ if(ft->seekable){
+ /* Skip over data */
+/*Got this from the quake source. I think it 32bit aligns the chunks
+ * doubt any machine writing Cool Edit Chunks writes them at an odd
+ * offset */
+ len = (len + 1) & ~1;
+ st_seek(ft, len, SEEK_CUR);
+ if( findChunk(ft, "LIST") != ST_EOF){
+ ft->comment = (char*)malloc(256);
+ while(!feof(ft->fp)){
+ st_reads(ft,magic,4);
+ if(strncmp(magic,"INFO",4) == 0){
+ /*Skip*/
+ } else if(strncmp(magic,"ICRD",4) == 0){
+ st_readdw(ft,&len);
+ len = (len + 1) & ~1;
+ st_reads(ft,text,len);
+ strcat(ft->comment,text);
+ strcat(ft->comment,"\n");
+ } else if(strncmp(magic,"ISFT",4) == 0){
+ st_readdw(ft,&len);
+ len = (len + 1) & ~1;
+ st_reads(ft,text,len);
+ strcat(ft->comment,text);
+ strcat(ft->comment,"\n");
+ } else if(strncmp(magic,"cue ",4) == 0){
+ st_readdw(ft,&len);
+ len = (len + 1) & ~1;
+ st_seek(ft,len-4,SEEK_CUR);
+ st_readdw(ft,(ULONG*)&ft->loops[0].start);
+ } else if(strncmp(magic,"note",4) == 0){
+ /*Skip*/
+ st_readdw(ft,&len);
+ len = (len + 1) & ~1;
+ st_seek(ft,len-4,SEEK_CUR);
+ } else if(strncmp(magic,"adtl",4) == 0){
+ /*Skip*/
+ } else if(strncmp(magic,"ltxt",4) == 0){
+ st_seek(ft,4,SEEK_CUR);
+ st_readdw(ft,(ULONG*)&ft->loops[0].length);
+ ft->loops[0].length = ft->loops[0].length - ft->loops[0].start;
+ } else if(strncmp(magic,"labl",4) == 0){
+ /*Skip*/
+ st_readdw(ft,&len);
+ len = (len + 1) & ~1;
+ st_seek(ft,len-4,SEEK_CUR);
+ }
+ }
+ }
+ clearerr(ft->fp);
+ st_seek(ft,wav->dataStart,SEEK_SET);
+ }
return ST_SUCCESS;
}
@@ -915,6 +991,8 @@
{
wav_t wav = (wav_t) ft->priv;
LONG done;
+
+ ft->st_errno = ST_SUCCESS;
/* If file is in ADPCM encoding then read in multiple blocks else */
/* read as much as possible and return quickly. */
@@ -1009,6 +1087,8 @@
wav_t wav = (wav_t) ft->priv;
int rc = ST_SUCCESS;
+ ft->st_errno = ST_SUCCESS;
+
if (wav->packet) free(wav->packet);
if (wav->samples) free(wav->samples);
if (wav->iCoefs) free(wav->iCoefs);
@@ -1036,6 +1116,8 @@
wav_t wav = (wav_t) ft->priv;
int rc;
+ ft->st_errno = ST_SUCCESS;
+
if (ST_IS_BIGENDIAN) ft->swap = ft->swap ? 0 : 1;
wav->numSamples = 0;
@@ -1063,7 +1145,7 @@
wav->samples = (short *)malloc(sbsize*sizeof(short));
if (!wav->packet || !wav->samples)
{
- st_fail("Unable to alloc resources");
+ st_fail_errno(ft,ST_EOF,"Unable to alloc resources");
return ST_EOF;
}
wav->sampleTop = wav->samples + sbsize;
@@ -1260,7 +1342,7 @@
case ST_ENCODING_IMA_ADPCM:
if (wChannels>16)
{
- st_fail("Channels(%d) must be <= 16\n",wChannels);
+ st_fail_errno(ft,ST_EOF,"Channels(%d) must be <= 16\n",wChannels);
return ST_EOF;
}
wFormatTag = WAVE_FORMAT_IMA_ADPCM;
@@ -1272,7 +1354,7 @@
case ST_ENCODING_ADPCM:
if (wChannels>16)
{
- st_fail("Channels(%d) must be <= 16\n",wChannels);
+ st_fail_errno(ft,ST_EOF,"Channels(%d) must be <= 16\n",wChannels);
return ST_EOF;
}
wFormatTag = WAVE_FORMAT_ADPCM;
@@ -1285,7 +1367,7 @@
#ifdef HAVE_LIBGSM
if (wChannels!=1)
{
- st_fail("Channels(%d) must be == 1\n",wChannels);
+ st_fail_errno(ft,ST_EOF,"Channels(%d) must be == 1\n",wChannels);
return ST_EOF;
}
wFormatTag = WAVE_FORMAT_GSM610;
@@ -1295,7 +1377,7 @@
wExtSize=2; /* length of format extension */
wSamplesPerBlock = 320;
#else
- st_fail("sorry, no GSM6.10 support, recompile sox with gsm library");
+ st_fail_errno(ft,ST_EOF,"sorry, no GSM6.10 support, recompile sox with gsm library");
return ST_EOF;
#endif
break;
@@ -1422,6 +1504,8 @@
wav_t wav = (wav_t) ft->priv;
LONG save_len = len;
+ ft->st_errno = ST_SUCCESS;
+
switch (wav->formatTag)
{
case WAVE_FORMAT_IMA_ADPCM:
@@ -1459,14 +1543,16 @@
ft_t ft;
{
wav_t wav = (wav_t) ft->priv;
- int rc = ST_SUCCESS;
+ ft->st_errno = ST_SUCCESS;
+
+
/* Call this to flush out any remaining data. */
switch (wav->formatTag)
{
case WAVE_FORMAT_IMA_ADPCM:
case WAVE_FORMAT_ADPCM:
- rc = xxxAdpcmWriteBlock(ft);
+ xxxAdpcmWriteBlock(ft);
break;
#ifdef HAVE_LIBGSM
case WAVE_FORMAT_GSM610:
@@ -1474,7 +1560,7 @@
break;
#endif
default:
- rc = st_rawstopwrite(ft);
+ st_rawstopwrite(ft);
}
if (wav->packet) free(wav->packet);
if (wav->samples) free(wav->samples);
@@ -1481,8 +1567,8 @@
if (wav->iCoefs) free(wav->iCoefs);
/* Now that we've free()'d memory, return with errors if needed */
- if (rc)
- return rc;
+ if (ft->st_errno)
+ return ST_EOF;
/* All samples are already written out. */
/* If file header needs fixing up, for example it needs the */
@@ -1492,7 +1578,7 @@
if (fseek(ft->fp, 0L, SEEK_SET) != 0)
{
- st_fail("Sorry, can't rewind output file to rewrite .wav header.");
+ st_fail_errno(ft,ST_EOF,"Sorry, can't rewind output file to rewrite .wav header.");
return ST_EOF;
}
wavwritehdr(ft, 1);
@@ -1551,4 +1637,29 @@
default:
return "Unknown";
}
+}
+
+int st_wavseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ wav_t wav = (wav_t) ft->priv;
+
+ switch (wav->formatTag)
+ {
+ case WAVE_FORMAT_IMA_ADPCM:
+ case WAVE_FORMAT_ADPCM:
+#ifdef HAVE_LIBGSM
+ case WAVE_FORMAT_GSM610:
+#endif
+ st_fail_errno(ft,ST_ENOTSUP,"Only PCM Supported");
+ break;
+ default:
+ ft->st_errno = st_seek(ft,offset*ft->info.size + wav->dataStart, SEEK_SET);
+ }
+
+ if( ft->st_errno == ST_SUCCESS )
+ wav->numSamples = ft->length - offset;
+
+ return(ft->st_errno);
}
--- a/src/wve.c
+++ b/src/wve.c
@@ -13,19 +13,30 @@
#define PSION_INV_VERSION ((short)4111)
#define PSION_HDRSIZE 32
-struct wvepriv
+typedef struct wvepriv
{
ULONG length;
short padding;
short repeats;
- };
+/* For seeking */
+ LONG dataStart;
+ } *wve_t;
static void wvewriteheader(ft_t ft);
+int st_wveseek(ft,offset)
+ft_t ft;
+LONG offset;
+{
+ wve_t wve = (wve_t ) ft->priv;
+
+ return st_seek(ft,offset*ft->info.size + wve->dataStart,SEEK_SET);
+}
+
int st_wvestartread(ft)
ft_t ft;
{
- struct wvepriv *p = (struct wvepriv *) ft->priv;
+ wve_t p = (wve_t ) ft->priv;
char magic[16];
short version;
int rc;
@@ -52,7 +63,7 @@
}
else
{
- st_fail("Psion header doesn't start with magic word\nTry the '.al' file type with '-t al -r 8000 filename'");
+ st_fail_errno(ft,ST_EHDR,"Psion header doesn't start with magic word\nTry the '.al' file type with '-t al -r 8000 filename'");
return (ST_EOF);
}
@@ -74,7 +85,7 @@
}
else
{
- st_fail("Wrong version in Psion header");
+ st_fail_errno(ft,ST_EHDR,"Wrong version in Psion header");
return(ST_EOF);
}
@@ -94,6 +105,10 @@
ft->info.rate = 8000;
ft->info.channels = 1;
+
+ p->dataStart = ftell(ft->fp);
+ ft->length = p->length/ft->info.size;
+
return (ST_SUCCESS);
}
@@ -109,7 +124,7 @@
int st_wvestartwrite(ft)
ft_t ft;
{
- struct wvepriv *p = (struct wvepriv *) ft->priv;
+ wve_t p = (wve_t ) ft->priv;
int rc;
/* Needed for rawwrite() */
@@ -148,7 +163,7 @@
ft_t ft;
LONG *buf, samp;
{
- struct wvepriv *p = (struct wvepriv *) ft->priv;
+ wve_t p = (wve_t ) ft->priv;
p->length += samp * ft->info.size;
return st_rawwrite(ft, buf, samp);
}
@@ -164,7 +179,7 @@
if (fseek(ft->fp, 0L, 0) != 0)
{
- st_fail("Can't rewind output file to rewrite Psion header.");
+ st_fail_errno(ft,errno,"Can't rewind output file to rewrite Psion header.");
return(ST_EOF);
}
wvewriteheader(ft);
@@ -180,7 +195,7 @@
char magic[16];
short version;
short zero;
- struct wvepriv *p = (struct wvepriv *) ft->priv;
+ wve_t p = (wve_t ) ft->priv;
strcpy(magic,PSION_MAGIC);
version=PSION_VERSION;