ref: 788e9abe05be565060286f9ee1a9cbd7ed18d367
parent: 2502bcd9b570012e34e34166aefca9c116f06026
author: robs <robs>
date: Sat Dec 20 11:07:58 EST 2008
--ignore-length
--- a/src/aifc-fmt.c
+++ b/src/aifc-fmt.c
@@ -26,9 +26,9 @@
static sox_format_handler_t const sox_aifc_format = {SOX_LIB_VERSION_CODE,
"AIFF-C (not compressed, linear), defined in DAVIC 1.4 Part 9 Annex B",
names, SOX_FILE_BIG_END,
- lsx_aiffstartread, lsx_aiffread, lsx_aiffstopread,
- lsx_aifcstartwrite, lsx_aiffwrite, lsx_aifcstopwrite,
- lsx_aiffseek, write_encodings, NULL, sizeof(aiff_priv_t)
+ lsx_aiffstartread, lsx_rawread, lsx_aiffstopread,
+ lsx_aifcstartwrite, lsx_rawwrite, lsx_aifcstopwrite,
+ lsx_rawseek, write_encodings, NULL, 0
};
return &sox_aifc_format;
}
--- a/src/aiff-fmt.c
+++ b/src/aiff-fmt.c
@@ -25,9 +25,9 @@
SOX_ENCODING_SIGN2, 32, 24, 16, 8, 0, 0};
static sox_format_handler_t const sox_aiff_format = {SOX_LIB_VERSION_CODE,
"AIFF files used on Apple IIc/IIgs and SGI", names, SOX_FILE_BIG_END,
- lsx_aiffstartread, lsx_aiffread, lsx_aiffstopread,
- lsx_aiffstartwrite, lsx_aiffwrite, lsx_aiffstopwrite,
- lsx_aiffseek, write_encodings, NULL, sizeof(aiff_priv_t)
+ lsx_aiffstartread, lsx_rawread, lsx_aiffstopread,
+ lsx_aiffstartwrite, lsx_rawwrite, lsx_aiffstopwrite,
+ lsx_rawseek, write_encodings, NULL, 0
};
return &sox_aiff_format;
}
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -35,446 +35,382 @@
static int commentChunk(char **text, char *chunkDescription, sox_format_t * ft);
static void reportInstrument(sox_format_t * ft);
-/* Private data used by writer */
-typedef aiff_priv_t priv_t;
-
-int lsx_aiffseek(sox_format_t * ft, uint64_t offset)
-{
- priv_t * aiff = (priv_t *) ft->priv;
- size_t new_offset, channel_block, alignment;
- size_t size = ft->encoding.bits_per_sample >> 3;
-
- new_offset = offset * size;
- /* Make sure request aligns to a channel block (ie left+right) */
- channel_block = ft->signal.channels * size;
- alignment = new_offset % channel_block;
- /* Most common mistaken is to compute something like
- * "skip everthing upto and including this sample" so
- * advance to next sample block in this case.
- */
- if (alignment != 0)
- new_offset += (channel_block - alignment);
- new_offset += aiff->dataStart;
-
- ft->sox_errno = lsx_seeki(ft, (off_t)new_offset, SEEK_SET);
-
- if (ft->sox_errno == SOX_SUCCESS)
- aiff->nsamples = ft->signal.length - (new_offset / size);
-
- return(ft->sox_errno);
-}
-
int lsx_aiffstartread(sox_format_t * ft)
{
- priv_t * aiff = (priv_t *) ft->priv;
- char buf[5];
- uint32_t totalsize;
- uint32_t chunksize;
- unsigned short channels = 0;
- uint32_t frames;
- unsigned short bits = 0;
- double rate = 0.0;
- uint32_t offset = 0;
- uint32_t blocksize = 0;
- int foundcomm = 0, foundmark = 0, foundinstr = 0, is_sowt = 0;
- struct mark {
- unsigned short id;
- uint32_t position;
- char name[40];
- } marks[32];
- unsigned short looptype;
- int i, j;
- unsigned short nmarks = 0;
- unsigned short sustainLoopBegin = 0, sustainLoopEnd = 0,
- releaseLoopBegin = 0, releaseLoopEnd = 0;
- off_t seekto = 0;
- size_t ssndsize = 0;
- char *annotation;
- char *author;
- char *comment = NULL;
- char *copyright;
- char *nametext;
+ char buf[5];
+ uint32_t totalsize;
+ uint32_t chunksize;
+ unsigned short channels = 0;
+ uint32_t frames;
+ unsigned short bits = 0;
+ double rate = 0.0;
+ uint32_t offset = 0;
+ uint32_t blocksize = 0;
+ int foundcomm = 0, foundmark = 0, foundinstr = 0, is_sowt = 0;
+ struct mark {
+ unsigned short id;
+ uint32_t position;
+ char name[40];
+ } marks[32];
+ unsigned short looptype;
+ int i, j;
+ unsigned short nmarks = 0;
+ unsigned short sustainLoopBegin = 0, sustainLoopEnd = 0,
+ releaseLoopBegin = 0, releaseLoopEnd = 0;
+ off_t seekto = 0;
+ size_t ssndsize = 0;
+ char *annotation;
+ char *author;
+ char *comment = NULL;
+ char *copyright;
+ char *nametext;
- uint8_t trash8;
- uint16_t trash16;
- uint32_t trash32;
+ uint8_t trash8;
+ uint16_t trash16;
+ uint32_t trash32;
- int rc;
+ int rc;
- /* FORM chunk */
- if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF || strncmp(buf, "FORM", (size_t)4) != 0)
- {
- lsx_fail_errno(ft,SOX_EHDR,"AIFF header does not begin with magic word 'FORM'");
- return(SOX_EOF);
- }
- lsx_readdw(ft, &totalsize);
- if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF || (strncmp(buf, "AIFF", (size_t)4) != 0 &&
- strncmp(buf, "AIFC", (size_t)4) != 0))
- {
- lsx_fail_errno(ft,SOX_EHDR,"AIFF 'FORM' chunk does not specify 'AIFF' or 'AIFC' as type");
- return(SOX_EOF);
- }
+ /* FORM chunk */
+ if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF || strncmp(buf, "FORM", (size_t)4) != 0) {
+ lsx_fail_errno(ft,SOX_EHDR,"AIFF header does not begin with magic word 'FORM'");
+ return(SOX_EOF);
+ }
+ lsx_readdw(ft, &totalsize);
+ if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF || (strncmp(buf, "AIFF", (size_t)4) != 0 &&
+ strncmp(buf, "AIFC", (size_t)4) != 0)) {
+ lsx_fail_errno(ft,SOX_EHDR,"AIFF 'FORM' chunk does not specify 'AIFF' or 'AIFC' as type");
+ return(SOX_EOF);
+ }
- /* Skip everything but the COMM chunk and the SSND chunk */
- /* The SSND chunk must be the last in the file */
- while (1) {
- if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF)
- {
- if (ssndsize > 0)
- {
- break;
- }
- else
- {
- lsx_fail_errno(ft,SOX_EHDR,"Missing SSND chunk in AIFF file");
- return(SOX_EOF);
- }
- }
- if (strncmp(buf, "COMM", (size_t)4) == 0) {
- /* COMM chunk */
- lsx_readdw(ft, &chunksize);
- lsx_readw(ft, &channels);
- lsx_readdw(ft, &frames);
- lsx_readw(ft, &bits);
- rate = read_ieee_extended(ft);
- chunksize -= 18;
- if (chunksize > 0)
- {
- lsx_reads(ft, buf, (size_t)4);
- chunksize -= 4;
- if (strncmp(buf, "sowt", (size_t)4) == 0)
- {
- /* CD audio as read on Mac OS machines */
- /* Need to endian swap all the data */
- is_sowt = 1;
- }
- else if (strncmp(buf, "NONE", (size_t)4) != 0 &&
- strncmp(buf, "twos", (size_t)4) != 0)
- {
- buf[4] = 0;
- lsx_fail_errno(ft,SOX_EHDR,"AIFC files that contain compressed data are not supported: %s",buf);
- return(SOX_EOF);
- }
- }
- while(chunksize-- > 0)
- lsx_readb(ft, &trash8);
- foundcomm = 1;
- }
- else if (strncmp(buf, "SSND", (size_t)4) == 0) {
- /* SSND chunk */
- lsx_readdw(ft, &chunksize);
- lsx_readdw(ft, &offset);
- lsx_readdw(ft, &blocksize);
- chunksize -= 8;
- ssndsize = chunksize;
- /* word-align chunksize in case it wasn't
- * done by writing application already.
- */
- chunksize += (chunksize % 2);
- /* if can't seek, just do sound now */
- if (!ft->seekable)
- break;
- /* else, seek to end of sound and hunt for more */
- seekto = lsx_tell(ft);
- lsx_seeki(ft, (off_t)chunksize, SEEK_CUR);
- }
- else if (strncmp(buf, "MARK", (size_t)4) == 0) {
- /* MARK chunk */
- lsx_readdw(ft, &chunksize);
- if (chunksize >= sizeof(nmarks)) {
- lsx_readw(ft, &nmarks);
- chunksize -= sizeof(nmarks);
- }
- else nmarks = 0;
+ /* Skip everything but the COMM chunk and the SSND chunk */
+ /* The SSND chunk must be the last in the file */
+ while (1) {
+ if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF) {
+ if (ssndsize > 0)
+ break;
+ else {
+ lsx_fail_errno(ft,SOX_EHDR,"Missing SSND chunk in AIFF file");
+ return(SOX_EOF);
+ }
+ }
+ if (strncmp(buf, "COMM", (size_t)4) == 0) {
+ /* COMM chunk */
+ lsx_readdw(ft, &chunksize);
+ lsx_readw(ft, &channels);
+ lsx_readdw(ft, &frames);
+ lsx_readw(ft, &bits);
+ rate = read_ieee_extended(ft);
+ chunksize -= 18;
+ if (chunksize > 0) {
+ lsx_reads(ft, buf, (size_t)4);
+ chunksize -= 4;
+ if (strncmp(buf, "sowt", (size_t)4) == 0) {
+ /* CD audio as read on Mac OS machines */
+ /* Need to endian swap all the data */
+ is_sowt = 1;
+ }
+ else if (strncmp(buf, "NONE", (size_t)4) != 0 &&
+ strncmp(buf, "twos", (size_t)4) != 0) {
+ buf[4] = 0;
+ lsx_fail_errno(ft,SOX_EHDR,"AIFC files that contain compressed data are not supported: %s",buf);
+ return(SOX_EOF);
+ }
+ }
+ while(chunksize-- > 0)
+ lsx_readb(ft, &trash8);
+ foundcomm = 1;
+ }
+ else if (strncmp(buf, "SSND", (size_t)4) == 0) {
+ /* SSND chunk */
+ lsx_readdw(ft, &chunksize);
+ lsx_readdw(ft, &offset);
+ lsx_readdw(ft, &blocksize);
+ chunksize -= 8;
+ ssndsize = chunksize;
+ /* word-align chunksize in case it wasn't
+ * done by writing application already.
+ */
+ chunksize += (chunksize % 2);
+ /* if can't seek, just do sound now */
+ if (!ft->seekable)
+ break;
+ /* else, seek to end of sound and hunt for more */
+ seekto = lsx_tell(ft);
+ lsx_seeki(ft, (off_t)chunksize, SEEK_CUR);
+ }
+ else if (strncmp(buf, "MARK", (size_t)4) == 0) {
+ /* MARK chunk */
+ lsx_readdw(ft, &chunksize);
+ if (chunksize >= sizeof(nmarks)) {
+ lsx_readw(ft, &nmarks);
+ chunksize -= sizeof(nmarks);
+ }
+ else nmarks = 0;
- /* Some programs like to always have a MARK chunk
- * but will set number of marks to 0 and force
- * software to detect and ignore it.
- */
- if (nmarks == 0)
- foundmark = 0;
- else
- foundmark = 1;
+ /* Some programs like to always have a MARK chunk
+ * but will set number of marks to 0 and force
+ * software to detect and ignore it.
+ */
+ if (nmarks == 0)
+ foundmark = 0;
+ else
+ foundmark = 1;
- /* Make sure its not larger then we support */
- if (nmarks > 32)
- nmarks = 32;
+ /* Make sure its not larger then we support */
+ if (nmarks > 32)
+ nmarks = 32;
- for(i = 0; i < nmarks && chunksize; i++) {
- unsigned char len, read_len, tmp_c;
+ for(i = 0; i < nmarks && chunksize; i++) {
+ unsigned char len, read_len, tmp_c;
- if (chunksize < 6)
- break;
- lsx_readw(ft, &(marks[i].id));
- lsx_readdw(ft, &(marks[i].position));
- chunksize -= 6;
- /* If error reading length then
- * don't try to read more bytes
- * based on that value.
- */
- if (lsx_readb(ft, &len) != SOX_SUCCESS)
- break;
- --chunksize;
- if (len > chunksize)
- len = chunksize;
- read_len = len;
- if (read_len > 39)
- read_len = 39;
- for(j = 0; j < len && chunksize; j++)
- {
- lsx_readb(ft, &tmp_c);
- if (j < read_len)
- marks[i].name[j] = tmp_c;
- chunksize--;
- }
- marks[i].name[read_len] = 0;
- if ((len & 1) == 0 && chunksize) {
- chunksize--;
- lsx_readb(ft, &trash8);
- }
- }
- /* HA HA! Sound Designer (and others) makes */
- /* bogus files. It spits out bogus chunksize */
- /* for MARK field */
- while(chunksize-- > 0)
- lsx_readb(ft, &trash8);
- }
- else if (strncmp(buf, "INST", (size_t)4) == 0) {
- /* INST chunk */
- lsx_readdw(ft, &chunksize);
- lsx_readsb(ft, &(ft->oob.instr.MIDInote));
- lsx_readb(ft, &trash8);
- lsx_readsb(ft, &(ft->oob.instr.MIDIlow));
- lsx_readsb(ft, &(ft->oob.instr.MIDIhi));
- /* Low velocity */
- lsx_readb(ft, &trash8);
- /* Hi velocity */
- lsx_readb(ft, &trash8);
- lsx_readw(ft, &trash16);/* gain */
- lsx_readw(ft, &looptype); /* sustain loop */
- ft->oob.loops[0].type = looptype;
- lsx_readw(ft, &sustainLoopBegin); /* begin marker */
- lsx_readw(ft, &sustainLoopEnd); /* end marker */
- lsx_readw(ft, &looptype); /* release loop */
- ft->oob.loops[1].type = looptype;
- lsx_readw(ft, &releaseLoopBegin); /* begin marker */
- lsx_readw(ft, &releaseLoopEnd); /* end marker */
-
- foundinstr = 1;
- }
- else if (strncmp(buf, "APPL", (size_t)4) == 0) {
- lsx_readdw(ft, &chunksize);
- /* word-align chunksize in case it wasn't
- * done by writing application already.
- */
- chunksize += (chunksize % 2);
- while(chunksize-- > 0)
- lsx_readb(ft, &trash8);
- }
- else if (strncmp(buf, "ALCH", (size_t)4) == 0) {
- /* I think this is bogus and gets grabbed by APPL */
- /* INST chunk */
- lsx_readdw(ft, &trash32); /* ENVS - jeez! */
- lsx_readdw(ft, &chunksize);
- while(chunksize-- > 0)
- lsx_readb(ft, &trash8);
- }
- else if (strncmp(buf, "ANNO", (size_t)4) == 0) {
- rc = textChunk(&annotation, "Annotation:", ft);
- if (rc)
- {
- /* Fail already called in function */
- return(SOX_EOF);
- }
- if (annotation)
- sox_append_comments(&ft->oob.comments, annotation);
- free(annotation);
- }
- else if (strncmp(buf, "COMT", (size_t)4) == 0) {
- rc = commentChunk(&comment, "Comment:", ft);
- if (rc) {
- /* Fail already called in function */
- return(SOX_EOF);
- }
- if (comment)
- sox_append_comments(&ft->oob.comments, comment);
- free(comment);
- }
- else if (strncmp(buf, "AUTH", (size_t)4) == 0) {
- /* Author chunk */
- rc = textChunk(&author, "Author:", ft);
- if (rc)
- {
- /* Fail already called in function */
- return(SOX_EOF);
- }
- free(author);
- }
- else if (strncmp(buf, "NAME", (size_t)4) == 0) {
- /* Name chunk */
- rc = textChunk(&nametext, "Name:", ft);
- if (rc)
- {
- /* Fail already called in function */
- return(SOX_EOF);
- }
- free(nametext);
- }
- else if (strncmp(buf, "(c) ", (size_t)4) == 0) {
- /* Copyright chunk */
- rc = textChunk(©right, "Copyright:", ft);
- if (rc)
- {
- /* Fail already called in function */
- return(SOX_EOF);
- }
- free(copyright);
- }
- else {
- if (lsx_eof(ft))
- break;
- buf[4] = 0;
- lsx_debug("AIFFstartread: ignoring '%s' chunk", buf);
- lsx_readdw(ft, &chunksize);
- if (lsx_eof(ft))
- break;
- /* Skip the chunk using lsx_readb() so we may read
- from a pipe */
- while (chunksize-- > 0) {
- if (lsx_readb(ft, &trash8) == SOX_EOF)
- break;
- }
- }
- if (lsx_eof(ft))
- break;
- }
+ if (chunksize < 6)
+ break;
+ lsx_readw(ft, &(marks[i].id));
+ lsx_readdw(ft, &(marks[i].position));
+ chunksize -= 6;
+ /* If error reading length then
+ * don't try to read more bytes
+ * based on that value.
+ */
+ if (lsx_readb(ft, &len) != SOX_SUCCESS)
+ break;
+ --chunksize;
+ if (len > chunksize)
+ len = chunksize;
+ read_len = len;
+ if (read_len > 39)
+ read_len = 39;
+ for(j = 0; j < len && chunksize; j++) {
+ lsx_readb(ft, &tmp_c);
+ if (j < read_len)
+ marks[i].name[j] = tmp_c;
+ chunksize--;
+ }
+ marks[i].name[read_len] = 0;
+ if ((len & 1) == 0 && chunksize) {
+ chunksize--;
+ lsx_readb(ft, &trash8);
+ }
+ }
+ /* HA HA! Sound Designer (and others) makes */
+ /* bogus files. It spits out bogus chunksize */
+ /* for MARK field */
+ while(chunksize-- > 0)
+ lsx_readb(ft, &trash8);
+ }
+ else if (strncmp(buf, "INST", (size_t)4) == 0) {
+ /* INST chunk */
+ lsx_readdw(ft, &chunksize);
+ lsx_readsb(ft, &(ft->oob.instr.MIDInote));
+ lsx_readb(ft, &trash8);
+ lsx_readsb(ft, &(ft->oob.instr.MIDIlow));
+ lsx_readsb(ft, &(ft->oob.instr.MIDIhi));
+ /* Low velocity */
+ lsx_readb(ft, &trash8);
+ /* Hi velocity */
+ lsx_readb(ft, &trash8);
+ lsx_readw(ft, &trash16);/* gain */
+ lsx_readw(ft, &looptype); /* sustain loop */
+ ft->oob.loops[0].type = looptype;
+ lsx_readw(ft, &sustainLoopBegin); /* begin marker */
+ lsx_readw(ft, &sustainLoopEnd); /* end marker */
+ lsx_readw(ft, &looptype); /* release loop */
+ ft->oob.loops[1].type = looptype;
+ lsx_readw(ft, &releaseLoopBegin); /* begin marker */
+ lsx_readw(ft, &releaseLoopEnd); /* end marker */
+
+ foundinstr = 1;
+ }
+ else if (strncmp(buf, "APPL", (size_t)4) == 0) {
+ lsx_readdw(ft, &chunksize);
+ /* word-align chunksize in case it wasn't
+ * done by writing application already.
+ */
+ chunksize += (chunksize % 2);
+ while(chunksize-- > 0)
+ lsx_readb(ft, &trash8);
+ }
+ else if (strncmp(buf, "ALCH", (size_t)4) == 0) {
+ /* I think this is bogus and gets grabbed by APPL */
+ /* INST chunk */
+ lsx_readdw(ft, &trash32); /* ENVS - jeez! */
+ lsx_readdw(ft, &chunksize);
+ while(chunksize-- > 0)
+ lsx_readb(ft, &trash8);
+ }
+ else if (strncmp(buf, "ANNO", (size_t)4) == 0) {
+ rc = textChunk(&annotation, "Annotation:", ft);
+ if (rc) {
+ /* Fail already called in function */
+ return(SOX_EOF);
+ }
+ if (annotation)
+ sox_append_comments(&ft->oob.comments, annotation);
+ free(annotation);
+ }
+ else if (strncmp(buf, "COMT", (size_t)4) == 0) {
+ rc = commentChunk(&comment, "Comment:", ft);
+ if (rc) {
+ /* Fail already called in function */
+ return(SOX_EOF);
+ }
+ if (comment)
+ sox_append_comments(&ft->oob.comments, comment);
+ free(comment);
+ }
+ else if (strncmp(buf, "AUTH", (size_t)4) == 0) {
+ /* Author chunk */
+ rc = textChunk(&author, "Author:", ft);
+ if (rc) {
+ /* Fail already called in function */
+ return(SOX_EOF);
+ }
+ free(author);
+ }
+ else if (strncmp(buf, "NAME", (size_t)4) == 0) {
+ /* Name chunk */
+ rc = textChunk(&nametext, "Name:", ft);
+ if (rc) {
+ /* Fail already called in function */
+ return(SOX_EOF);
+ }
+ free(nametext);
+ }
+ else if (strncmp(buf, "(c) ", (size_t)4) == 0) {
+ /* Copyright chunk */
+ rc = textChunk(©right, "Copyright:", ft);
+ if (rc) {
+ /* Fail already called in function */
+ return(SOX_EOF);
+ }
+ free(copyright);
+ }
+ else {
+ if (lsx_eof(ft))
+ break;
+ buf[4] = 0;
+ lsx_debug("AIFFstartread: ignoring '%s' chunk", buf);
+ lsx_readdw(ft, &chunksize);
+ if (lsx_eof(ft))
+ break;
+ /* Skip the chunk using lsx_readb() so we may read
+ from a pipe */
+ while (chunksize-- > 0) {
+ if (lsx_readb(ft, &trash8) == SOX_EOF)
+ break;
+ }
+ }
+ if (lsx_eof(ft))
+ break;
+ }
+
+ /*
+ * if a pipe, we lose all chunks after sound.
+ * Like, say, instrument loops.
+ */
+ if (ft->seekable) {
+ if (seekto > 0)
+ lsx_seeki(ft, seekto, SEEK_SET);
+ else {
+ lsx_fail_errno(ft,SOX_EOF,"AIFF: no sound data on input file");
+ return(SOX_EOF);
+ }
+ }
+ /* SSND chunk just read */
+ if (blocksize != 0)
+ lsx_warn("AIFF header has invalid blocksize. Ignoring but expect a premature EOF");
+
+ ssndsize -= offset;
+ while (offset-- > 0) {
+ if (lsx_readb(ft, &trash8) == SOX_EOF) {
+ lsx_fail_errno(ft,errno,"unexpected EOF while skipping AIFF offset");
+ return(SOX_EOF);
+ }
+ }
- /*
- * if a pipe, we lose all chunks after sound.
- * Like, say, instrument loops.
- */
- if (ft->seekable)
- {
- if (seekto > 0)
- lsx_seeki(ft, seekto, SEEK_SET);
- else
- {
- lsx_fail_errno(ft,SOX_EOF,"AIFF: no sound data on input file");
- return(SOX_EOF);
- }
- }
- /* SSND chunk just read */
- if (blocksize != 0)
- lsx_warn("AIFF header has invalid blocksize. Ignoring but expect a premature EOF");
-
- ssndsize -= offset;
- while (offset-- > 0) {
- if (lsx_readb(ft, &trash8) == SOX_EOF)
- {
- lsx_fail_errno(ft,errno,"unexpected EOF while skipping AIFF offset");
- return(SOX_EOF);
- }
- }
-
- if (foundcomm) {
- ft->signal.channels = channels;
- ft->signal.rate = rate;
- if (ft->encoding.encoding != SOX_ENCODING_UNKNOWN && ft->encoding.encoding != SOX_ENCODING_SIGN2)
- lsx_report("AIFF only supports signed data. Forcing to signed.");
- ft->encoding.encoding = SOX_ENCODING_SIGN2;
- if (bits <= 8)
- ft->encoding.bits_per_sample = 8;
- else if (bits <= 16)
- ft->encoding.bits_per_sample = 16;
- else if (bits <= 24)
- ft->encoding.bits_per_sample = 24;
- else if (bits <= 32)
- ft->encoding.bits_per_sample = 32;
- else
- {
- lsx_fail_errno(ft,SOX_EFMT,"unsupported sample size in AIFF header: %d", bits);
- return(SOX_EOF);
- }
- } else {
- if ((ft->signal.channels == 0)
- || (ft->signal.rate == 0)
- || (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
- || (ft->encoding.bits_per_sample == 0)) {
- lsx_report("You must specify # channels, sample rate, signed/unsigned,");
- lsx_report("and 8/16 on the command line.");
- lsx_fail_errno(ft,SOX_EFMT,"Bogus AIFF file: no COMM section.");
- return(SOX_EOF);
- }
+ if (foundcomm) {
+ if (ft->encoding.encoding != SOX_ENCODING_UNKNOWN && ft->encoding.encoding != SOX_ENCODING_SIGN2)
+ lsx_report("AIFF only supports signed data. Forcing to signed.");
+ ft->encoding.encoding = SOX_ENCODING_SIGN2;
+ if (bits <= 8) bits = 8;
+ else if (bits <= 16) bits = 16;
+ else if (bits <= 24) bits = 24;
+ else if (bits <= 32) bits = 32;
+ else {
+ lsx_fail_errno(ft,SOX_EFMT,"unsupported sample size in AIFF header: %d", bits);
+ return(SOX_EOF);
+ }
+ } else {
+ if ((ft->signal.channels == SOX_UNSPEC)
+ || (ft->signal.rate == SOX_UNSPEC)
+ || (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
+ || (ft->encoding.bits_per_sample == 0)) {
+ lsx_report("You must specify # channels, sample rate, signed/unsigned,");
+ lsx_report("and 8/16 on the command line.");
+ lsx_fail_errno(ft,SOX_EFMT,"Bogus AIFF file: no COMM section.");
+ return(SOX_EOF);
+ }
- }
+ }
+ ssndsize /= bits >> 3;
- aiff->nsamples = ssndsize / (ft->encoding.bits_per_sample >> 3);
+ /* Cope with 'sowt' CD tracks as read on Macs */
+ if (is_sowt)
+ ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
- /* Cope with 'sowt' CD tracks as read on Macs */
- if (is_sowt)
- ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
+ if (foundmark && !foundinstr) {
+ lsx_debug("Ignoring MARK chunk since no INSTR found.");
+ foundmark = 0;
+ }
+ if (!foundmark && foundinstr) {
+ lsx_debug("Ignoring INSTR chunk since no MARK found.");
+ foundinstr = 0;
+ }
+ if (foundmark && foundinstr) {
+ int i;
+ int slbIndex = 0, sleIndex = 0;
+ int rlbIndex = 0, rleIndex = 0;
- if (foundmark && !foundinstr)
- {
- lsx_debug("Ignoring MARK chunk since no INSTR found.");
- foundmark = 0;
- }
- if (!foundmark && foundinstr)
- {
- lsx_debug("Ignoring INSTR chunk since no MARK found.");
- foundinstr = 0;
- }
- if (foundmark && foundinstr) {
- int i;
- int slbIndex = 0, sleIndex = 0;
- int rlbIndex = 0, rleIndex = 0;
+ /* find our loop markers and save their marker indexes */
+ for(i = 0; i < nmarks; i++) {
+ if(marks[i].id == sustainLoopBegin)
+ slbIndex = i;
+ if(marks[i].id == sustainLoopEnd)
+ sleIndex = i;
+ if(marks[i].id == releaseLoopBegin)
+ rlbIndex = i;
+ if(marks[i].id == releaseLoopEnd)
+ rleIndex = i;
+ }
- /* find our loop markers and save their marker indexes */
- for(i = 0; i < nmarks; i++) {
- if(marks[i].id == sustainLoopBegin)
- slbIndex = i;
- if(marks[i].id == sustainLoopEnd)
- sleIndex = i;
- if(marks[i].id == releaseLoopBegin)
- rlbIndex = i;
- if(marks[i].id == releaseLoopEnd)
- rleIndex = i;
- }
+ ft->oob.instr.nloops = 0;
+ if (ft->oob.loops[0].type != 0) {
+ ft->oob.loops[0].start = marks[slbIndex].position;
+ ft->oob.loops[0].length =
+ marks[sleIndex].position - marks[slbIndex].position;
+ /* really the loop count should be infinite */
+ ft->oob.loops[0].count = 1;
+ ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[0].type;
+ ft->oob.instr.nloops++;
+ }
+ if (ft->oob.loops[1].type != 0) {
+ ft->oob.loops[1].start = marks[rlbIndex].position;
+ ft->oob.loops[1].length =
+ marks[rleIndex].position - marks[rlbIndex].position;
+ /* really the loop count should be infinite */
+ ft->oob.loops[1].count = 1;
+ ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[1].type;
+ ft->oob.instr.nloops++;
+ }
+ }
+ reportInstrument(ft);
- ft->oob.instr.nloops = 0;
- if (ft->oob.loops[0].type != 0) {
- ft->oob.loops[0].start = marks[slbIndex].position;
- ft->oob.loops[0].length =
- marks[sleIndex].position - marks[slbIndex].position;
- /* really the loop count should be infinite */
- ft->oob.loops[0].count = 1;
- ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[0].type;
- ft->oob.instr.nloops++;
- }
- if (ft->oob.loops[1].type != 0) {
- ft->oob.loops[1].start = marks[rlbIndex].position;
- ft->oob.loops[1].length =
- marks[rleIndex].position - marks[rlbIndex].position;
- /* really the loop count should be infinite */
- ft->oob.loops[1].count = 1;
- ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[1].type;
- ft->oob.instr.nloops++;
- }
- }
- reportInstrument(ft);
+ return lsx_check_read_params(
+ ft, channels, rate, SOX_ENCODING_SIGN2, bits, (off_t)ssndsize, sox_false);
+}
- /* Needed because of lsx_rawread() */
- rc = lsx_rawstartread(ft);
- if (rc)
- return rc;
-
- ft->signal.length = aiff->nsamples; /* for seeking */
- aiff->dataStart = lsx_tell(ft);
-
- return(SOX_SUCCESS);
-}
-
/* print out the MIDI key allocations, loop points, directions etc */
static void reportInstrument(sox_format_t * ft)
{
@@ -590,20 +526,6 @@
return(SOX_SUCCESS);
}
-size_t lsx_aiffread(sox_format_t * ft, sox_sample_t *buf, size_t len)
-{
- priv_t * aiff = (priv_t *) ft->priv;
- off_t done;
-
- if ((size_t)len > aiff->nsamples)
- len = aiff->nsamples;
- done = lsx_rawread(ft, buf, len);
- if (done == 0 && aiff->nsamples != 0)
- lsx_warn("Premature EOF on AIFF input file");
- aiff->nsamples -= done;
- return done;
-}
-
int lsx_aiffstopread(sox_format_t * ft)
{
char buf[5];
@@ -647,7 +569,6 @@
int lsx_aiffstartwrite(sox_format_t * ft)
{
- priv_t * aiff = (priv_t *) ft->priv;
int rc;
/* Needed because lsx_rawwrite() */
@@ -655,8 +576,6 @@
if (rc)
return rc;
- aiff->nsamples = 0;
-
/* Compute the "very large number" so that a maximum number
of samples can be transmitted through a pipe without the
risk of causing overflow when calculating the number of bytes.
@@ -666,21 +585,11 @@
return(aiffwriteheader(ft, (size_t) 0x7f000000 / ((ft->encoding.bits_per_sample>>3)*ft->signal.channels)));
}
-size_t lsx_aiffwrite(sox_format_t * ft, const sox_sample_t *buf, size_t len)
-{
- priv_t * aiff = (priv_t *) ft->priv;
- aiff->nsamples += len;
- lsx_rawwrite(ft, buf, len);
- return(len);
-}
-
int lsx_aiffstopwrite(sox_format_t * ft)
{
- priv_t * aiff = (priv_t *) ft->priv;
-
/* If we've written an odd number of bytes, write a padding
NUL */
- if (aiff->nsamples % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
+ if (ft->olength % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
{
sox_sample_t buf = 0;
lsx_rawwrite(ft, &buf, (size_t) 1);
@@ -696,7 +605,7 @@
lsx_fail_errno(ft,errno,"can't rewind output file to rewrite AIFF header");
return(SOX_EOF);
}
- return(aiffwriteheader(ft, aiff->nsamples / ft->signal.channels));
+ return(aiffwriteheader(ft, ft->olength / ft->signal.channels));
}
static int aiffwriteheader(sox_format_t * ft, size_t nframes)
@@ -844,7 +753,6 @@
int lsx_aifcstartwrite(sox_format_t * ft)
{
- priv_t * aiff = (priv_t *) ft->priv;
int rc;
/* Needed because lsx_rawwrite() */
@@ -852,8 +760,6 @@
if (rc)
return rc;
- aiff->nsamples = 0;
-
/* Compute the "very large number" so that a maximum number
of samples can be transmitted through a pipe without the
risk of causing overflow when calculating the number of bytes.
@@ -865,11 +771,9 @@
int lsx_aifcstopwrite(sox_format_t * ft)
{
- priv_t * aiff = (priv_t *) ft->priv;
-
/* If we've written an odd number of bytes, write a padding
NUL */
- if (aiff->nsamples % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
+ if (ft->olength % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
{
sox_sample_t buf = 0;
lsx_rawwrite(ft, &buf, (size_t) 1);
@@ -885,7 +789,7 @@
lsx_fail_errno(ft,errno,"can't rewind output file to rewrite AIFC header");
return(SOX_EOF);
}
- return(aifcwriteheader(ft, aiff->nsamples / ft->signal.channels));
+ return(aifcwriteheader(ft, ft->olength / ft->signal.channels));
}
static int aifcwriteheader(sox_format_t * ft, size_t nframes)
--- a/src/aiff.h
+++ b/src/aiff.h
@@ -14,18 +14,9 @@
* (usable for japanese-data-broadcasting, specified by ARIB STD-B24.)
*/
-typedef struct {
- size_t nsamples; /* number of 1-channel samples read or written */
- /* Decrements for read increments for write */
- size_t dataStart; /* need to for seeking */
-} aiff_priv_t;
-
-int lsx_aiffseek(sox_format_t * ft, uint64_t offset);
int lsx_aiffstartread(sox_format_t * ft);
-size_t lsx_aiffread(sox_format_t * ft, sox_sample_t *buf, size_t len);
int lsx_aiffstopread(sox_format_t * ft);
int lsx_aiffstartwrite(sox_format_t * ft);
-size_t lsx_aiffwrite(sox_format_t * ft, const sox_sample_t *buf, size_t len);
int lsx_aiffstopwrite(sox_format_t * ft);
int lsx_aifcstartwrite(sox_format_t * ft);
int lsx_aifcstopwrite(sox_format_t * ft);
--- a/src/au.c
+++ b/src/au.c
@@ -187,9 +187,9 @@
free(buf);
}
if (data_size == SUN_UNSPEC)
- data_size = 0; /* libSoX uses 0 for unspecified */
- return lsx_check_read_params(ft, channels, (sox_rate_t)rate,
- encoding, bits_per_sample, div_bits(data_size, bits_per_sample));
+ data_size = SOX_UNSPEC;
+ return lsx_check_read_params(ft, channels, (sox_rate_t)rate, encoding,
+ bits_per_sample, div_bits(data_size, bits_per_sample), sox_true);
}
static int write_header(sox_format_t * ft)
@@ -202,7 +202,7 @@
sox_bool error = sox_false
||lsx_writechars(ft, id[i].str, sizeof(id[i].str))
||lsx_writedw(ft, FIXED_HDR + (unsigned)info_len)
- ||lsx_writedw(ft, (unsigned) (size? size*(ft->encoding.bits_per_sample >> 3) : SUN_UNSPEC))
+ ||lsx_writedw(ft, (unsigned) (size != SOX_UNSPEC? size*(ft->encoding.bits_per_sample >> 3) : SUN_UNSPEC))
||lsx_writedw(ft, ft_enc(ft->encoding.bits_per_sample, ft->encoding.encoding))
||lsx_writedw(ft, (unsigned)(ft->signal.rate + .5))
||lsx_writedw(ft, ft->signal.channels)
--- a/src/cdr.c
+++ b/src/cdr.c
@@ -20,7 +20,7 @@
static int start(sox_format_t * ft)
{
- return lsx_check_read_params(ft, 2, 44100., SOX_ENCODING_SIGN2, 16, (off_t)0);
+ return lsx_check_read_params(ft, 2, 44100., SOX_ENCODING_SIGN2, 16, (off_t)0, sox_false);
}
static int stopwrite(sox_format_t * ft)
--- a/src/formats.c
+++ b/src/formats.c
@@ -808,15 +808,20 @@
size_t sox_read(sox_format_t * ft, sox_sample_t * buf, size_t len)
{
- size_t actual = ft->handler.read? (*ft->handler.read)(ft, buf, len) : 0;
- return (actual > len? 0 : actual);
+ size_t actual;
+ if (ft->signal.length != SOX_UNSPEC)
+ len = min(len, ft->signal.length - ft->olength);
+ actual = ft->handler.read? (*ft->handler.read)(ft, buf, len) : 0;
+ actual = actual > len? 0 : actual;
+ ft->olength += actual;
+ return actual;
}
size_t sox_write(sox_format_t * ft, const sox_sample_t *buf, size_t len)
{
- size_t ret = ft->handler.write? (*ft->handler.write)(ft, buf, len) : 0;
- ft->olength += ret;
- return ret;
+ size_t actual = ft->handler.write? (*ft->handler.write)(ft, buf, len) : 0;
+ ft->olength += actual;
+ return actual;
}
int sox_close(sox_format_t * ft)
--- a/src/formats_i.c
+++ b/src/formats_i.c
@@ -47,9 +47,10 @@
}
int lsx_check_read_params(sox_format_t * ft, unsigned channels,
- sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, off_t length)
+ sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
+ off_t num_samples, sox_bool check_length)
{
- ft->signal.length = length;
+ ft->signal.length = ft->signal.length == SOX_IGNORE_LENGTH? SOX_UNSPEC : num_samples;
if (ft->seekable)
ft->data_start = lsx_tell(ft);
@@ -70,12 +71,12 @@
lsx_warn("`%s': overriding encoding size", ft->filename);
ft->encoding.bits_per_sample = bits_per_sample;
- if (ft->encoding.bits_per_sample && lsx_filelength(ft)) {
+ if (check_length && ft->encoding.bits_per_sample && lsx_filelength(ft)) {
off_t calculated_length = div_bits(lsx_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample);
if (!ft->signal.length)
ft->signal.length = calculated_length;
- else if (length != calculated_length)
- lsx_warn("`%s': file header gives the total number of samples as %u but file length indicates the number is in fact %u", ft->filename, (unsigned)length, (unsigned)calculated_length); /* FIXME: casts */
+ else if (num_samples != calculated_length)
+ lsx_warn("`%s': file header gives the total number of samples as %u but file length indicates the number is in fact %u", ft->filename, (unsigned)num_samples, (unsigned)calculated_length); /* FIXME: casts */
}
if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample))
@@ -171,6 +172,7 @@
void lsx_rewind(sox_format_t * ft)
{
rewind(ft->fp);
+ ft->tell_off = 0;
}
void lsx_clearerr(sox_format_t * ft)
--- a/src/htk.c
+++ b/src/htk.c
@@ -42,8 +42,8 @@
lsx_fail_errno(ft, SOX_EFMT, "unsupported HTK type `%s' (0%o)", str[n], parmKind);
return SOX_EOF;
}
- return lsx_check_read_params(ft, 1, 1e7 / period_100ns,
- SOX_ENCODING_SIGN2, (unsigned)bytes_per_sample << 3, (off_t)num_samples);
+ return lsx_check_read_params(ft, 1, 1e7 / period_100ns, SOX_ENCODING_SIGN2,
+ (unsigned)bytes_per_sample << 3, (off_t)num_samples, sox_true);
}
static int write_header(sox_format_t * ft)
--- a/src/lpc10.c
+++ b/src/lpc10.c
@@ -131,7 +131,7 @@
return SOX_EOF;
}
lpc->samples = LPC10_SAMPLES_PER_FRAME;
- return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_LPC10, 0, (off_t)0);
+ return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_LPC10, 0, (off_t)0, sox_false);
}
static int startwrite(sox_format_t * ft)
--- a/src/sf.c
+++ b/src/sf.c
@@ -112,7 +112,7 @@
if (lsx_skipbytes(ft, FIXED_HDR - (size_t)lsx_tell(ft)))
return SOX_EOF;
- return lsx_check_read_params(ft, channels, rate, encoding, bits_per_sample, (off_t)0);
+ return lsx_check_read_params(ft, channels, rate, encoding, bits_per_sample, (off_t)0, sox_false);
}
static int write_header(sox_format_t * ft)
--- a/src/sounder.c
+++ b/src/sounder.c
@@ -28,7 +28,7 @@
lsx_fail_errno(ft, SOX_EHDR, "invalid Sounder header");
return SOX_EOF;
}
- return lsx_check_read_params(ft, 1, (sox_rate_t)rate, SOX_ENCODING_UNSIGNED, 8, (off_t)0);
+ return lsx_check_read_params(ft, 1, (sox_rate_t)rate, SOX_ENCODING_UNSIGNED, 8, (off_t)0, sox_false);
}
static int write_header(sox_format_t * ft)
--- a/src/soundtool.c
+++ b/src/soundtool.c
@@ -39,7 +39,7 @@
}
comments[text_field_len] = '\0'; /* Be defensive against incorrect files */
sox_append_comments(&ft->oob.comments, comments);
- return lsx_check_read_params(ft, 1, (sox_rate_t)rate, SOX_ENCODING_UNSIGNED, 8, (off_t)0);
+ return lsx_check_read_params(ft, 1, (sox_rate_t)rate, SOX_ENCODING_UNSIGNED, 8, (off_t)nsamples, sox_true);
}
static int write_header(sox_format_t * ft)
--- a/src/sox-fmt.c
+++ b/src/sox-fmt.c
@@ -68,7 +68,7 @@
lsx_seeki(ft, (off_t)(headers_bytes - FIXED_HDR - comments_bytes), SEEK_CUR);
return lsx_check_read_params(
- ft, num_channels, rate, SOX_ENCODING_SIGN2, 32, (off_t)num_samples);
+ ft, num_channels, rate, SOX_ENCODING_SIGN2, 32, (off_t)num_samples, sox_true);
}
static int write_header(sox_format_t * ft)
--- a/src/sox.c
+++ b/src/sox.c
@@ -1641,6 +1641,7 @@
"overriden by any of various means including providing output format options.",
"",
"-v|--volume FACTOR Input file volume adjustment factor (real number)",
+"--ignore-length Ignore input file length given in header; read to EOF",
"-t|--type FILETYPE File type of audio",
"-s/-u/-f/-U/-A/-i/-a/-g Encoding type=signed-integer/unsigned-integer/floating-",
" point/mu-law/a-law/ima-adpcm/ms-adpcm/gsm-full-rate",
@@ -1830,6 +1831,7 @@
{"effects-file" , required_argument, NULL, 0},
{"temp" , required_argument, NULL, 0},
{"single-threaded" , no_argument, NULL, 0},
+ {"ignore-length" , no_argument, NULL, 0},
{"bits" , required_argument, NULL, 'b'},
{"channels" , required_argument, NULL, 'c'},
@@ -2020,6 +2022,10 @@
case 17:
single_threaded = sox_true;
+ break;
+
+ case 18:
+ f->signal.length = SOX_IGNORE_LENGTH;
break;
}
--- a/src/sox.h
+++ b/src/sox.h
@@ -191,11 +191,13 @@
typedef double sox_rate_t;
-typedef struct { /* Signal parameters; 0 if unknown */
+#define SOX_UNSPEC 0
+#define SOX_IGNORE_LENGTH (size_t)(-1)
+typedef struct { /* Signal parameters; SOX_UNSPEC if unknown */
sox_rate_t rate; /* sampling rate */
unsigned channels; /* number of sound channels */
unsigned precision; /* in bits */
- size_t length; /* samples * chans in file; 0 if unknown */
+ size_t length; /* samples * chans in file */
} sox_signalinfo_t;
typedef enum {
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -215,7 +215,7 @@
int lsx_check_read_params(sox_format_t * ft, unsigned channels,
sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
- off_t num_samples);
+ off_t num_samples, sox_bool check_length);
sox_sample_t lsx_sample_max(sox_encodinginfo_t const * encoding);
#define SOX_FORMAT_HANDLER(name) \
sox_format_handler_t const * sox_##name##_format_fn(void); \
--- a/src/sphere.c
+++ b/src/sphere.c
@@ -133,7 +133,7 @@
num_samples = num_samples_ul;
return lsx_check_read_params(ft, channels, (sox_rate_t)rate, encoding,
- bytes_per_sample << 3, (off_t)(num_samples * channels));
+ bytes_per_sample << 3, (off_t)(num_samples * channels), sox_true);
}
static int write_header(sox_format_t * ft)
--- a/src/wav.c
+++ b/src/wav.c
@@ -439,7 +439,7 @@
uint32_t dwLoopPos;
ft->sox_errno = SOX_SUCCESS;
- wav->ignoreSize = 0;
+ wav->ignoreSize = ft->signal.length == SOX_IGNORE_LENGTH;
if (lsx_reads(ft, magic, (size_t)4) == SOX_EOF || (strncmp("RIFF", magic, (size_t)4) != 0 &&
strncmp("RIFX", magic, (size_t)4) != 0))
@@ -844,7 +844,7 @@
* not mistakenly depend on it.
*/
if (wav->ignoreSize)
- ft->signal.length = 0;
+ ft->signal.length = SOX_UNSPEC;
lsx_debug("Reading Wave file: %s format, %d channel%s, %d samp/sec",
wav_format_str(wav->formatTag), ft->signal.channels,
--- a/src/wve.c
+++ b/src/wve.c
@@ -35,7 +35,7 @@
lsx_fail_errno(ft, SOX_EHDR, "wve: can't find Psion identifier");
return SOX_EOF;
}
- return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_ALAW, 8, (off_t)num_samples);
+ return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_ALAW, 8, (off_t)num_samples, sox_true);
}
static int write_header(sox_format_t * ft)