|
From: robs <ro...@us...> - 2008-03-16 07:53:05
|
Update of /cvsroot/sox/sox/src In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv15459/src Modified Files: 8svx.c au.c CMakeLists.txt formats.h Makefile.am misc.c mp3.c raw.c sf.c sox.c sox.h sox_i.h test-comments tests.sh wav.c wve.c Log Message: Can now write Sounder files Can now write DEC-variant au files (with -x) Comments support for SoundTool files Fix IRCAM SF header processing; support all (modern) variants Fix 24-bit read/write on big-endian systems For some file-types, warn if file size seems too short Added auto-detect for caf, sndr, txw & sf files Fix endian selection (-B, -L, -x) in some circumstances Reimplement (separately) SoundTool & Sounder format handlers Index: test-comments =================================================================== RCS file: /cvsroot/sox/sox/src/test-comments,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- test-comments 16 Feb 2008 16:43:23 -0000 1.2 +++ test-comments 16 Mar 2008 07:52:57 -0000 1.3 @@ -27,17 +27,10 @@ cp $tmp.au $tmp.comment.au cat > $tmp.i << . -TITLE=The First Track -ARTIST=A Band Of Musicians +TITLE=First Track +ARTIST=A Band ALBUM=A Collection Of Songs -DATE=2008 TRACKNUMBER=01 -TRACKTOTAL=14 -GENRE=Music -REPLAYGAIN_TRACK_PEAK=1.00515676 -REPLAYGAIN_TRACK_GAIN=-3.97 dB -REPLAYGAIN_ALBUM_PEAK=1.00515676 -REPLAYGAIN_ALBUM_GAIN=-2.88 dB . ./sox monkey.au --comment-file $tmp.i $tmp.comments.au @@ -77,7 +70,8 @@ ./sox $tmp.comments.au $tmp.flac ./sox $tmp.flac $tmp.sf ./sox $tmp.sf $tmp.ogg -./sox $tmp.ogg $tmp.au +./sox $tmp.ogg $tmp.sndt +./sox $tmp.sndt $tmp.au check_file $tmp.au $tmp.i rm -f $tmp.* Index: au.c =================================================================== RCS file: /cvsroot/sox/sox/src/au.c,v retrieving revision 1.87 retrieving revision 1.88 diff -u -d -r1.87 -r1.88 --- au.c 9 Mar 2008 20:38:29 -0000 1.87 +++ au.c 16 Mar 2008 07:52:57 -0000 1.88 @@ -14,7 +14,6 @@ * We support only the common formats, plus * CCITT G.721 (32 kbit/s) and G.723 (24/40 kbit/s), * courtesy of Sun's public domain implementation. - * Output is always in big-endian (Sun/NeXT) order. */ #include "sox_i.h" @@ -22,11 +21,14 @@ #include <string.h> /* Magic numbers used in Sun and NeXT audio files */ -#define SUN_MAGIC 0x2e736e64 /* Really '.snd' */ -#define SUN_INV_MAGIC 0x646e732e /* '.snd' reversed bytes */ -#define DEC_MAGIC 0x2e736400 /* Really '\0ds.' (for DEC) */ -#define DEC_INV_MAGIC 0x0064732e /* '\0ds.' reversed bytes */ -#define SUN_HDRSIZE 24 /* Size of minimal header */ +static struct {char str[4]; sox_bool reverse_bytes; char const * desc;} id[] = { + {"\x2e\x73\x6e\x64", SOX_IS_LITTLEENDIAN, "Big-endian .snd"}, + {"\x64\x6e\x73\x2e", SOX_IS_BIGENDIAN , "Little-endian .snd"}, + {"\x00\x64\x73\x2e", SOX_IS_BIGENDIAN , "Little-endian '\0ds.' (for DEC)"}, + {"\x2e\x73\x64\x00", SOX_IS_LITTLEENDIAN, "Big-endian '\0ds.'"}, + {" ", 0, NULL} +}; +#define FIXED_HDR 24 #define SUN_UNSPEC ~0u /* Unspecified data size (this is legal) */ typedef enum { @@ -34,7 +36,7 @@ Double, Indirect, Nested, Dsp_core, Dsp_data_8, Dsp_data_16, Dsp_data_24, Dsp_data_32, Unknown, Display, Mulaw_squelch, Emphasized, Compressed, Compressed_emphasized, Dsp_commands, Dsp_commands_samples, Adpcm_g721, - Adpcm_g722, Adpcm_g723_3, Adpcm_g723_5, Alaw_8, Unknown_other} sun_encoding_t; + Adpcm_g722, Adpcm_g723_3, Adpcm_g723_5, Alaw_8, Unknown_other} ft_encoding_t; static char const * const str[] = { "Unspecified", "8-bit mu-law", "8-bit signed linear", "16-bit signed linear", "24-bit signed linear", "32-bit signed linear", "Floating-point", @@ -46,40 +48,35 @@ "Music Kit DSP samples", "4-bit G.721 ADPCM", "G.722 ADPCM", "3-bit G.723 ADPCM", "5-bit G.723 ADPCM", "8-bit a-law", "Unknown"}; -static sun_encoding_t sun_enc(unsigned size, sox_encoding_t sox_enc) +static ft_encoding_t ft_enc(unsigned size, sox_encoding_t encoding) { - sun_encoding_t result = Unspecified; - if (sox_enc == SOX_ENCODING_ULAW && size == 8) result = Mulaw_8; - else if (sox_enc == SOX_ENCODING_ALAW && size == 8) result = Alaw_8; - else if (sox_enc == SOX_ENCODING_SIGN2 && size == 8) result = Linear_8; - else if (sox_enc == SOX_ENCODING_SIGN2 && size == 16) result = Linear_16; - else if (sox_enc == SOX_ENCODING_SIGN2 && size == 24) result = Linear_24; - else if (sox_enc == SOX_ENCODING_SIGN2 && size == 32) result = Linear_32; - else if (sox_enc == SOX_ENCODING_FLOAT && size == 32) result = Float; - else if (sox_enc == SOX_ENCODING_FLOAT && size == 64) result = Double; - return result; + if (encoding == SOX_ENCODING_ULAW && size == 8) return Mulaw_8; + if (encoding == SOX_ENCODING_ALAW && size == 8) return Alaw_8; + if (encoding == SOX_ENCODING_SIGN2 && size == 8) return Linear_8; + if (encoding == SOX_ENCODING_SIGN2 && size == 16) return Linear_16; + if (encoding == SOX_ENCODING_SIGN2 && size == 24) return Linear_24; + if (encoding == SOX_ENCODING_SIGN2 && size == 32) return Linear_32; + if (encoding == SOX_ENCODING_FLOAT && size == 32) return Float; + if (encoding == SOX_ENCODING_FLOAT && size == 64) return Double; + return Unspecified; } -static int sox_enc( - uint32_t sun_encoding, sox_encoding_t * encoding, unsigned * size) +static sox_encoding_t sox_enc(uint32_t ft_encoding, unsigned * size) { - switch (sun_encoding) { - case Mulaw_8 : *encoding = SOX_ENCODING_ULAW ; *size = 8; break; - case Alaw_8 : *encoding = SOX_ENCODING_ALAW ; *size = 8; break; - case Linear_8 : *encoding = SOX_ENCODING_SIGN2; *size = 8; break; - case Linear_16 : *encoding = SOX_ENCODING_SIGN2; *size = 16; break; - case Linear_24 : *encoding = SOX_ENCODING_SIGN2; *size = 24; break; - case Linear_32 : *encoding = SOX_ENCODING_SIGN2; *size = 32; break; - case Float : *encoding = SOX_ENCODING_FLOAT; *size = 32; break; - case Double : *encoding = SOX_ENCODING_FLOAT; *size = 64; break; - /* Sun encodings that SoX can read, but not write: */ - case Adpcm_g721 : *encoding = SOX_ENCODING_G721 ; *size = 4; break; - case Adpcm_g723_3: *encoding = SOX_ENCODING_G723 ; *size = 3; break; - case Adpcm_g723_5: *encoding = SOX_ENCODING_G723 ; *size = 5; break; - - default: sox_debug("encoding: 0x%x", sun_encoding); return SOX_EOF; + switch (ft_encoding) { + case Mulaw_8 : *size = 8; return SOX_ENCODING_ULAW; + case Alaw_8 : *size = 8; return SOX_ENCODING_ALAW; + case Linear_8 : *size = 8; return SOX_ENCODING_SIGN2; + case Linear_16 : *size = 16; return SOX_ENCODING_SIGN2; + case Linear_24 : *size = 24; return SOX_ENCODING_SIGN2; + case Linear_32 : *size = 32; return SOX_ENCODING_SIGN2; + case Float : *size = 32; return SOX_ENCODING_FLOAT; + case Double : *size = 64; return SOX_ENCODING_FLOAT; + case Adpcm_g721 : *size = 4; return SOX_ENCODING_G721; /* read-only */ + case Adpcm_g723_3: *size = 3; return SOX_ENCODING_G723; /* read-only */ + case Adpcm_g723_5: *size = 5; return SOX_ENCODING_G723; /* read-only */ + default: return SOX_ENCODING_UNKNOWN; } - return SOX_SUCCESS; } typedef struct { /* For G72x decoding: */ @@ -128,57 +125,47 @@ static int startread(sox_format_t * ft) { priv_t * p = (priv_t * ) ft->priv; - uint32_t magic; /* These 6 uint32_t variables represent a Sun sound */ - uint32_t hdr_size; /* header on disk. The numbers are written as */ - uint32_t data_size; /* big-endians. Any extra bytes (totalling */ - uint32_t sun_encoding; /* hdr_size - 24) are an "info" field of */ - uint32_t sample_rate; /* unspecified nature, usually a string. By */ + char magic[4]; /* These 6 variables represent a Sun sound */ + uint32_t hdr_size; /* header on disk. The uint32_t are written as */ + uint32_t data_size; /* big-endians. At least extra bytes (totalling */ + uint32_t ft_encoding; /* hdr_size - FIXED_HDR) are an "info" field of */ + uint32_t rate; /* unspecified nature, usually a string. By */ uint32_t channels; /* convention the header size is a multiple of 4. */ - unsigned bits_per_sample; - sox_encoding_t sox_encoding; + unsigned i, bits_per_sample; + sox_encoding_t encoding; - sox_readdw(ft, &magic); - if (magic == DEC_INV_MAGIC) { - sox_debug("Found inverted DEC magic word."); - /* Inverted headers are not standard. Code was probably - * left over from pre-standardize period of testing for - * endianess. Its not hurting though. - */ - ft->encoding.reverse_bytes = SOX_IS_BIGENDIAN; - } - else if (magic == SUN_INV_MAGIC) { - sox_debug("Found inverted Sun/NeXT magic word."); - ft->encoding.reverse_bytes = SOX_IS_BIGENDIAN; - } - else if (magic == SUN_MAGIC) { - sox_debug("Found Sun/NeXT magic word"); - ft->encoding.reverse_bytes = SOX_IS_LITTLEENDIAN; - } - else if (magic == DEC_MAGIC) { - sox_debug("Found DEC magic word"); - ft->encoding.reverse_bytes = SOX_IS_LITTLEENDIAN; - } - else { - sox_fail_errno(ft,SOX_EHDR,"Did not detect valid Sun/NeXT/DEC magic number in header."); + if (sox_readchars(ft, magic, sizeof(magic))) + return SOX_EOF; + + for (i = 0; id[i].desc && memcmp(magic, id[i].str, sizeof(magic)); ++i); + if (!id[i].desc) { + sox_fail_errno(ft, SOX_EHDR, "au: can't find Sun/NeXT/DEC identifier"); return SOX_EOF; } + sox_report("found %s identifier", id[i].desc); + ft->encoding.reverse_bytes = id[i].reverse_bytes; - sox_readdw(ft, &hdr_size); - if (hdr_size < SUN_HDRSIZE) { - sox_fail_errno(ft, SOX_EHDR, "Sun/NeXT header size too small."); + if (sox_readdw(ft, &hdr_size) || + sox_readdw(ft, &data_size) || /* Can be SUN_UNSPEC */ + sox_readdw(ft, &ft_encoding) || + sox_readdw(ft, &rate) || + sox_readdw(ft, &channels)) + return SOX_EOF; + + if (hdr_size < FIXED_HDR) { + sox_fail_errno(ft, SOX_EHDR, "header size %u is too small", hdr_size); return SOX_EOF; } - sox_readdw(ft, &data_size); /* Can be SUN_UNSPEC */ - sox_readdw(ft, &sun_encoding); - sox_readdw(ft, &sample_rate); - sox_readdw(ft, &channels); + if (hdr_size < FIXED_HDR + 4) + sox_warn("header size %u is too small", hdr_size); - if (sox_enc(sun_encoding, &sox_encoding, &bits_per_sample) == SOX_EOF) { - int n = min(sun_encoding, Unknown_other); - sox_fail_errno(ft, SOX_EFMT, "unsupported encoding `%s' (%u)", str[n], sun_encoding); + if (!(encoding = sox_enc(ft_encoding, &bits_per_sample))) { + int n = min(ft_encoding, Unknown_other); + sox_fail_errno(ft, SOX_EFMT, "unsupported encoding `%s' (%#x)", str[n], ft_encoding); return SOX_EOF; } - switch (sun_encoding) { + + switch (ft_encoding) { case Adpcm_g721 : p->dec_routine = g721_decoder ; break; case Adpcm_g723_3: p->dec_routine = g723_24_decoder; break; case Adpcm_g723_5: p->dec_routine = g723_40_decoder; break; @@ -189,11 +176,10 @@ ft->handler.read = dec_read; } - hdr_size -= SUN_HDRSIZE; /* # bytes already read */ - if (hdr_size > 0) { - char * buf = xcalloc(1, hdr_size + 1); /* +1 ensures null-terminated */ - if (sox_readbuf(ft, buf, hdr_size) != hdr_size) { - sox_fail_errno(ft, SOX_EOF, "Unexpected EOF in Sun/NeXT header info."); + if (hdr_size > FIXED_HDR) { + size_t info_size = hdr_size - FIXED_HDR; + char * buf = xcalloc(1, info_size + 1); /* +1 ensures null-terminated */ + if (sox_readchars(ft, buf, info_size) != SOX_SUCCESS) { free(buf); return SOX_EOF; } @@ -201,25 +187,26 @@ free(buf); } if (data_size == SUN_UNSPEC) - data_size = 0; /* SoX uses 0 for unspecified */ - return sox_check_read_params( ft, channels, (sox_rate_t)sample_rate, - sox_encoding, bits_per_sample, div_bits(data_size, bits_per_sample)); + data_size = 0; /* libSoX uses 0 for unspecified */ + return sox_check_read_params(ft, channels, (sox_rate_t)rate, + encoding, bits_per_sample, div_bits(data_size, bits_per_sample)); } static int write_header(sox_format_t * ft) { - char *comment = cat_comments(ft->comments); + char * comment = cat_comments(ft->comments); size_t len = strlen(comment) + 1; /* Write out null-terminated */ size_t info_len = max(4, (len + 3) & ~3u); /* Minimum & multiple of 4 bytes */ size_t size = ft->olength? ft->olength : ft->length; + int i = ft->encoding.reverse_bytes == SOX_IS_BIGENDIAN? 2 : 0; sox_bool error = sox_false - ||sox_writedw(ft, SUN_MAGIC) - ||sox_writedw(ft, SUN_HDRSIZE + info_len) + ||sox_writechars(ft, id[i].str, sizeof(id[i].str)) + ||sox_writedw(ft, FIXED_HDR + info_len) ||sox_writedw(ft, size? size*(ft->encoding.bits_per_sample >> 3) : SUN_UNSPEC) - ||sox_writedw(ft, sun_enc(ft->encoding.bits_per_sample,ft->encoding.encoding)) + ||sox_writedw(ft, ft_enc(ft->encoding.bits_per_sample, ft->encoding.encoding)) ||sox_writedw(ft, (unsigned)(ft->signal.rate + .5)) ||sox_writedw(ft, ft->signal.channels) - ||sox_writebuf(ft, comment, len) != len + ||sox_writechars(ft, comment, len) ||sox_padbytes(ft, info_len - len); free(comment); return error? SOX_EOF: SOX_SUCCESS; @@ -234,8 +221,7 @@ SOX_ENCODING_SIGN2, 8, 16, 24, 32, 0, SOX_ENCODING_FLOAT, 32, 64, 0, 0}; - static sox_format_handler_t const handler = { - SOX_LIB_VERSION_CODE, + static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE, "PCM file format used widely on Sun systems", names, SOX_FILE_BIG_END | SOX_FILE_REWIND, startread, sox_rawread, NULL, Index: wav.c =================================================================== RCS file: /cvsroot/sox/sox/src/wav.c,v retrieving revision 1.133 retrieving revision 1.134 diff -u -d -r1.133 -r1.134 --- wav.c 9 Mar 2008 20:38:30 -0000 1.133 +++ wav.c 16 Mar 2008 07:52:57 -0000 1.134 @@ -1324,7 +1324,7 @@ /* If user specified opposite swap than we think, assume they are * asking to write a RIFX file. */ - if (ft->encoding.reverse_bytes && SOX_IS_LITTLEENDIAN) + if (ft->encoding.reverse_bytes == SOX_IS_LITTLEENDIAN) { if (!second_header) sox_report("Requested to swap bytes so writing RIFX header"); Index: tests.sh =================================================================== RCS file: /cvsroot/sox/sox/src/tests.sh,v retrieving revision 1.58 retrieving revision 1.59 diff -u -d -r1.58 -r1.59 --- tests.sh 9 Mar 2008 20:38:30 -0000 1.58 +++ tests.sh 16 Mar 2008 07:52:57 -0000 1.59 @@ -158,7 +158,7 @@ convertToAndFrom ima s2 u2 s3 u3 s4 u4 raw Raw dat au aiff aifc flac caf # FIXME: vox wav format1=wav1u - convertToAndFrom smp s1 s1X s1N s1XN sndt + convertToAndFrom smp s1 s1X s1N s1XN sndt sndr #(rate=50000; convertToAndFrom txw) || exit 1 # FIXME (rate=11025; convertToAndFrom hcom) || exit 1 # Fixed rates Index: mp3.c =================================================================== RCS file: /cvsroot/sox/sox/src/mp3.c,v retrieving revision 1.56 retrieving revision 1.57 diff -u -d -r1.56 -r1.57 --- mp3.c 9 Mar 2008 20:38:30 -0000 1.56 +++ mp3.c 16 Mar 2008 07:52:57 -0000 1.57 @@ -196,9 +196,7 @@ */ ReadSize = sox_readbuf(ft, p->InputBuffer, INPUT_BUFFER_SIZE); if (ReadSize < INPUT_BUFFER_SIZE) { - if (sox_error(ft)) - sox_fail_errno(ft, SOX_EOF, "error reading input file"); - else if (sox_eof(ft)) + if (sox_eof(ft)) sox_fail_errno(ft, SOX_EOF, "input file too short"); return SOX_EOF; } Index: wve.c =================================================================== RCS file: /cvsroot/sox/sox/src/wve.c,v retrieving revision 1.64 retrieving revision 1.65 diff -u -d -r1.64 -r1.65 --- wve.c 9 Mar 2008 20:38:31 -0000 1.64 +++ wve.c 16 Mar 2008 07:52:58 -0000 1.65 @@ -29,8 +29,8 @@ char buf[sizeof(ID1)]; uint32_t num_samples; - if (sox_readbuf(ft, buf, sizeof(buf)) != sizeof(buf) || - sox_readdw(ft, &num_samples) || sox_skipbytes(ft, sizeof(ID2))) + if (sox_readchars(ft, buf, sizeof(buf)) || sox_readdw(ft, &num_samples) || + sox_skipbytes(ft, sizeof(ID2))) return SOX_EOF; if (memcmp(ID1, buf, sizeof(buf))) { sox_fail_errno(ft, SOX_EHDR, "wve: can't find Psion identifier"); @@ -41,9 +41,9 @@ static int write_header(sox_format_t * ft) { - return sox_writebuf(ft, ID1, sizeof(ID1)) != sizeof(ID1) + return sox_writechars(ft, ID1, sizeof(ID1)) || sox_writedw(ft, ft->olength? ft->olength:ft->length) - || sox_writebuf(ft, ID2, sizeof(ID2)) != sizeof(ID2)? SOX_EOF:SOX_SUCCESS; + || sox_writechars(ft, ID2, sizeof(ID2))? SOX_EOF:SOX_SUCCESS; } SOX_FORMAT_HANDLER(wve) Index: misc.c =================================================================== RCS file: /cvsroot/sox/sox/src/misc.c,v retrieving revision 1.121 retrieving revision 1.122 diff -u -d -r1.121 -r1.122 --- misc.c 9 Mar 2008 20:38:29 -0000 1.121 +++ misc.c 16 Mar 2008 07:52:57 -0000 1.122 @@ -156,8 +156,13 @@ sox_warn("'%s': overriding encoding size", ft->filename); ft->encoding.bits_per_sample = bits_per_sample; - if (!ft->length && ft->encoding.bits_per_sample && sox_filelength(ft)) - ft->length = div_bits(sox_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample); + if (ft->encoding.bits_per_sample && sox_filelength(ft)) { + off_t calculated_length = div_bits(sox_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample); + if (!ft->length) + ft->length = calculated_length; + else if (length != calculated_length) + sox_warn("file header gives the total number of samples as %u but file length indicates the number is in fact %u", (unsigned)length, (unsigned)calculated_length); /* FIXME: casts */ + } if ( sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample)) return SOX_SUCCESS; @@ -173,8 +178,6 @@ return (SOX_SAMPLE_MAX >> shift) << shift; } -const char sox_readerr[] = "Premature EOF while reading sample file"; - /* Lookup table to reverse the bit order of a byte. ie MSB become LSB */ uint8_t const cswap[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, @@ -209,7 +212,9 @@ size_t sox_readbuf(sox_format_t * ft, void *buf, sox_size_t len) { size_t ret = fread(buf, 1, len, ft->fp); - return (ferror(ft->fp) || (feof(ft->fp) && ret == 0)) ? 0 : ret; + if (ret != len && ferror(ft->fp)) + sox_fail_errno(ft, errno, "sox_readbuf"); + return ret; } /* Skip input without seeking. */ @@ -238,7 +243,7 @@ * Returns number of bytes written. */ -size_t sox_writebuf(sox_format_t * ft, void const *buf, sox_size_t len) +size_t sox_writebuf(sox_format_t * ft, void const * buf, sox_size_t len) { size_t ret = fwrite(buf, 1, len, ft->fp); if (ret != len) { @@ -303,8 +308,6 @@ if (sox_readbuf(ft, &in, 1) != 1) { *sc = 0; - if (sox_error(ft)) - sox_fail_errno(ft, errno, sox_readerr); return (SOX_EOF); } if (in == 0 || in == '\n') Index: sox.h =================================================================== RCS file: /cvsroot/sox/sox/src/sox.h,v retrieving revision 1.49 retrieving revision 1.50 diff -u -d -r1.49 -r1.50 --- sox.h 9 Mar 2008 20:38:30 -0000 1.49 +++ sox.h 16 Mar 2008 07:52:57 -0000 1.50 @@ -232,6 +232,7 @@ * indicate to the libSoX core if they have a preference using * SOX_FILE_xxx flags. */ + sox_bool opposite_endian; sox_option_t reverse_bytes; /* endiannesses... */ sox_option_t reverse_nibbles; sox_option_t reverse_bits; Index: raw.c =================================================================== RCS file: /cvsroot/sox/sox/src/raw.c,v retrieving revision 1.90 retrieving revision 1.91 diff -u -d -r1.90 -r1.91 --- raw.c 9 Mar 2008 20:38:30 -0000 1.90 +++ raw.c 16 Mar 2008 07:52:57 -0000 1.91 @@ -65,8 +65,7 @@ { \ sox_size_t n, nread; \ ctype *data = xmalloc(sizeof(ctype) * len); \ - if ((nread = sox_read_ ## type ## _buf(ft, (uctype *)data, len)) != len && sox_error(ft)) \ - sox_fail_errno(ft, errno, sox_readerr); \ + nread = sox_read_ ## type ## _buf(ft, (uctype *)data, len); \ for (n = 0; n < nread; n++) \ *buf++ = cast(data[n], ft->clips); \ free(data); \ Index: sox_i.h =================================================================== RCS file: /cvsroot/sox/sox/src/sox_i.h,v retrieving revision 1.49 retrieving revision 1.50 diff -u -d -r1.49 -r1.50 --- sox_i.h 14 Mar 2008 07:29:19 -0000 1.49 +++ sox_i.h 16 Mar 2008 07:52:57 -0000 1.50 @@ -149,6 +149,7 @@ int sox_reads(sox_format_t * ft, char *c, sox_size_t len); int sox_writes(sox_format_t * ft, char const * c); void set_signal_defaults(sox_signalinfo_t * signal); +#define sox_writechars(ft, chars, len) (sox_writebuf(ft, chars, len) == len? SOX_SUCCESS : SOX_EOF) sox_size_t sox_read_b_buf(sox_format_t * ft, uint8_t *buf, sox_size_t len); sox_size_t sox_read_w_buf(sox_format_t * ft, uint16_t *buf, sox_size_t len); @@ -164,20 +165,23 @@ sox_size_t sox_write_f_buf(sox_format_t * ft, float *buf, sox_size_t len); sox_size_t sox_write_df_buf(sox_format_t * ft, double *buf, sox_size_t len); -#define sox_readb(ft, ub) (sox_read_b_buf(ft, ub, 1) == 1 ? SOX_SUCCESS : SOX_EOF) +int sox_read3(sox_format_t * ft, uint24_t * u3); +int sox_readb(sox_format_t * ft, uint8_t * ub); +int sox_readdf(sox_format_t * ft, double * d); +int sox_readdw(sox_format_t * ft, uint32_t * udw); +int sox_readf(sox_format_t * ft, float * f); +int sox_readw(sox_format_t * ft, uint16_t * uw); +int sox_readchars(sox_format_t * ft, char * chars, sox_size_t len); + +int sox_write3(sox_format_t * ft, unsigned u3); int sox_writeb(sox_format_t * ft, unsigned ub); -#define sox_readw(ft, uw) (sox_read_w_buf(ft, uw, 1) == 1 ? SOX_SUCCESS : SOX_EOF) -int sox_writew(sox_format_t * ft, unsigned uw); +int sox_writedw(sox_format_t * ft, unsigned udw); +int sox_writef(sox_format_t * ft, double f); int sox_writesb(sox_format_t * ft, signed); int sox_writesw(sox_format_t * ft, signed); -#define sox_read3(ft, u3) (sox_read_3_buf(ft, u3, 1) == 1 ? SOX_SUCCESS : SOX_EOF) -int sox_write3(sox_format_t * ft, unsigned u3); -#define sox_readdw(ft, udw) (sox_read_dw_buf(ft, udw, 1) == 1 ? SOX_SUCCESS : SOX_EOF) -int sox_writedw(sox_format_t * ft, unsigned udw); -#define sox_readf(ft, f) (sox_read_f_buf(ft, f, 1) == 1 ? SOX_SUCCESS : SOX_EOF) -int sox_writef(sox_format_t * ft, float f); -#define sox_readdf(ft, d) (sox_read_df_buf(ft, d, 1) == 1 ? SOX_SUCCESS : SOX_EOF) +int sox_writew(sox_format_t * ft, unsigned uw); int sox_writedf(sox_format_t * ft, double d); + int sox_seeki(sox_format_t * ft, sox_ssize_t to_sample, int whence); int sox_offset_seek(sox_format_t * ft, off_t byte_offset, sox_size_t to_sample); sox_size_t sox_filelength(sox_format_t * ft); @@ -296,8 +300,6 @@ extern sox_globals_t sox_globals; extern sox_effects_globals_t sox_effects_globals; - -extern const char sox_readerr[]; extern uint8_t const cswap[256]; Index: Makefile.am =================================================================== RCS file: /cvsroot/sox/sox/src/Makefile.am,v retrieving revision 1.129 retrieving revision 1.130 diff -u -d -r1.129 -r1.130 --- Makefile.am 12 Mar 2008 01:13:24 -0000 1.129 +++ Makefile.am 16 Mar 2008 07:52:57 -0000 1.130 @@ -40,11 +40,11 @@ libsox_fmt_cdr.la libsox_fmt_cvsd.la libsox_fmt_dvms.la \ libsox_fmt_dat.la libsox_fmt_gsm.la libsox_fmt_hcom.la \ libsox_fmt_lpc10.la libsox_fmt_maud.la libsox_fmt_prc.la \ - libsox_fmt_sf.la libsox_fmt_smp.la libsox_fmt_sndrtool.la \ + libsox_fmt_sf.la libsox_fmt_smp.la \ libsox_fmt_sphere.la libsox_fmt_txw.la libsox_fmt_voc.la \ libsox_fmt_vox.la libsox_fmt_ima.la libsox_fmt_wav.la \ libsox_fmt_wve.la libsox_fmt_xa.la libsox_fmt_nul.la \ - libsox_fmt_htk.la + libsox_fmt_htk.la libsox_fmt_sounder.la libsox_fmt_soundtool.la # File formats libsox_fmt_raw_la_SOURCES = raw-fmt.c @@ -103,12 +103,14 @@ libsox_fmt_maud_la_LIBADD = libsox.la libsox_fmt_prc_la_SOURCES = prc.c libsox_fmt_prc_la_LIBADD = libsox.la -libsox_fmt_sf_la_SOURCES = sf.c sfircam.h +libsox_fmt_sf_la_SOURCES = sf.c libsox_fmt_sf_la_LIBADD = libsox.la libsox_fmt_smp_la_SOURCES = smp.c libsox_fmt_smp_la_LIBADD = libsox.la -libsox_fmt_sndrtool_la_SOURCES = sndrtool.c -libsox_fmt_sndrtool_la_LIBADD = libsox.la +libsox_fmt_sounder_la_SOURCES = sounder.c +libsox_fmt_sounder_la_LIBADD = libsox.la +libsox_fmt_soundtool_la_SOURCES = soundtool.c +libsox_fmt_soundtool_la_LIBADD = libsox.la libsox_fmt_sphere_la_SOURCES = sphere.c libsox_fmt_sphere_la_LIBADD = libsox.la libsox_fmt_txw_la_SOURCES = tx16w.c @@ -218,8 +220,8 @@ libsox_la_SOURCES += raw-fmt.c s1-fmt.c s2-fmt.c s3-fmt.c \ s4-fmt.c u1-fmt.c u2-fmt.c u3-fmt.c u4-fmt.c al-fmt.c la-fmt.c ul-fmt.c \ lu-fmt.c 8svx.c aiff-fmt.c aifc-fmt.c au.c avr.c cdr.c cvsd-fmt.c \ - dvms-fmt.c dat.c gsm.c hcom.c htk.c lpc10.c maud.c prc.c sf.c sfircam.h smp.c \ - sndrtool.c sphere.c tx16w.c voc.c vox-fmt.c ima-fmt.c adpcm.c adpcm.h \ + dvms-fmt.c dat.c gsm.c hcom.c htk.c lpc10.c maud.c prc.c sf.c smp.c \ + sounder.c soundtool.c sphere.c tx16w.c voc.c vox-fmt.c ima-fmt.c adpcm.c adpcm.h \ ima_rw.c ima_rw.h wav.c wav.h wve.c xa.c nulfile.c libsox_la_LIBADD = @GSM_LIBS@ @LIBGSM_LIBADD@ libsox_la_LIBADD += ../lpc10/liblpc10.la Index: CMakeLists.txt =================================================================== RCS file: /cvsroot/sox/sox/src/CMakeLists.txt,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- CMakeLists.txt 11 Mar 2008 00:08:31 -0000 1.23 +++ CMakeLists.txt 16 Mar 2008 07:52:57 -0000 1.24 @@ -30,17 +30,17 @@ dither key pitch speed vol ) set(formats_srcs - 8svx cvsd-fmt htk s1-fmt u2-fmt - adpcm dat ima-fmt s2-fmt u3-fmt - adpcms dvms-fmt ima_rw s3-fmt u4-fmt - aifc-fmt formats la-fmt s4-fmt ul-fmt - aiff g711 lpc10.c sf voc - aiff-fmt g721 lu-fmt skelform vox - al-fmt g723_24 maud smp vox-fmt - au g723_40 nulfile sndrtool wav - avr g72x prc sphere wve - cdr gsm.c raw tx16w xa - cvsd hcom raw-fmt u1-fmt + 8svx cvsd-fmt htk s1-fmt u1-fmt + adpcm dat ima-fmt s2-fmt u2-fmt + adpcms dvms-fmt ima_rw s3-fmt u3-fmt + aifc-fmt formats la-fmt s4-fmt u4-fmt + aiff g711 lpc10.c sf ul-fmt + aiff-fmt g721 lu-fmt skelform voc + al-fmt g723_24 maud smp vox + au g723_40 nulfile sounder vox-fmt + avr g72x prc soundtool wav + cdr gsm.c raw sphere wve + cvsd hcom raw-fmt tx16w xa ) add_library(lib${PROJECT_NAME} ${effects_srcs} misc util Index: 8svx.c =================================================================== RCS file: /cvsroot/sox/sox/src/8svx.c,v retrieving revision 1.61 retrieving revision 1.62 diff -u -d -r1.61 -r1.62 --- 8svx.c 9 Mar 2008 20:38:29 -0000 1.61 +++ 8svx.c 16 Mar 2008 07:52:57 -0000 1.62 @@ -341,7 +341,7 @@ sox_writedw(ft, nsamples/ft->signal.channels); /* samples, 1-shot */ sox_writedw(ft, 0); /* samples, repeat */ sox_writedw(ft, 0); /* samples per repeat cycle */ - sox_writew(ft, (uint16_t)ft->signal.rate); /* samples per second */ + sox_writew(ft, min(65535, (unsigned)(ft->signal.rate + .5))); sox_writeb(ft,1); /* number of octabes */ sox_writeb(ft,0); /* data compression (none) */ sox_writew(ft,1); sox_writew(ft,0); /* volume */ Index: sox.c =================================================================== RCS file: /cvsroot/sox/sox/src/sox.c,v retrieving revision 1.308 retrieving revision 1.309 diff -u -d -r1.308 -r1.309 --- sox.c 9 Mar 2008 21:46:49 -0000 1.308 +++ sox.c 16 Mar 2008 07:52:57 -0000 1.309 @@ -288,7 +288,7 @@ } if (full) { - if (ft->encoding.bits_per_sample > 8) + if (ft->encoding.bits_per_sample > 8 || (ft->handler.flags & SOX_FILE_ENDIAN)) fprintf(output, "Endian Type : %s\n", ft->encoding.reverse_bytes != SOX_IS_BIGENDIAN ? "big" : "little"); if (ft->encoding.bits_per_sample) @@ -1266,11 +1266,11 @@ static sox_bool parse_gopts_and_fopts(file_t f, int argc, char **argv) { while (sox_true) { - int option_index; + int c, option_index; int i; /* sscanf silently accepts negative numbers for %u :( */ char dummy; /* To check for extraneous chars in optarg. */ - switch (getopt_long(argc, argv, getoptstr, long_options, &option_index)) { + switch (c=getopt_long(argc, argv, getoptstr, long_options, &option_index)) { case -1: /* @ one of: file-name, effect name, end of arg-list. */ return sox_false; /* i.e. not null file. */ @@ -1306,10 +1306,12 @@ break; case 5: + if (f->encoding.reverse_bytes != SOX_OPTION_DEFAULT || f->encoding.opposite_endian) + usage("only one endian option per file is allowed"); switch (enum_option(option_index, endian_options)) { case ENDIAN_little: f->encoding.reverse_bytes = SOX_IS_BIGENDIAN; break; case ENDIAN_big: f->encoding.reverse_bytes = SOX_IS_LITTLEENDIAN; break; - case ENDIAN_swap: f->encoding.reverse_bytes = sox_true; break; + case ENDIAN_swap: f->encoding.opposite_endian = sox_true; break; } break; @@ -1419,9 +1421,15 @@ f->encoding.bits_per_sample = 8; break; - case 'L': f->encoding.reverse_bytes = SOX_IS_BIGENDIAN; break; - case 'B': f->encoding.reverse_bytes = SOX_IS_LITTLEENDIAN; break; - case 'x': f->encoding.reverse_bytes = SOX_OPTION_YES; break; + case 'L': case 'B': case 'x': + if (f->encoding.reverse_bytes != SOX_OPTION_DEFAULT || f->encoding.opposite_endian) + usage("only one endian option per file is allowed"); + switch (c) { + case 'L': f->encoding.reverse_bytes = SOX_IS_BIGENDIAN; break; + case 'B': f->encoding.reverse_bytes = SOX_IS_LITTLEENDIAN; break; + case 'x': f->encoding.opposite_endian = sox_true; break; + } + break; case 'X': f->encoding.reverse_bits = SOX_OPTION_YES; break; case 'N': f->encoding.reverse_nibbles = SOX_OPTION_YES; break; Index: formats.h =================================================================== RCS file: /cvsroot/sox/sox/src/formats.h,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- formats.h 8 Mar 2008 10:54:37 -0000 1.7 +++ formats.h 16 Mar 2008 07:52:57 -0000 1.8 @@ -26,7 +26,8 @@ FORMAT(s4) FORMAT(sf) FORMAT(smp) - FORMAT(sndrtool) + FORMAT(sounder) + FORMAT(soundtool) FORMAT(sphere) FORMAT(svx) FORMAT(txw) Index: sf.c =================================================================== RCS file: /cvsroot/sox/sox/src/sf.c,v retrieving revision 1.55 retrieving revision 1.56 diff -u -d -r1.55 -r1.56 --- sf.c 9 Mar 2008 20:38:30 -0000 1.55 +++ sf.c 16 Mar 2008 07:52:57 -0000 1.56 @@ -1,232 +1,155 @@ /* - * July 5, 1991 - * Copyright 1991 Lance Norskog And Sundry Contributors - * This source code is freely redistributable and may be used for - * any purpose. This copyright notice must be maintained. - * Lance Norskog And Sundry Contributors are not responsible for - * the consequences of using this software. - */ - -/* - * libSoX IRCAM SoundFile format handler. + * File format: IRCAM SoundFile (c) 2008 ro...@us... * - * Derived from: libSoX skeleton handler file. + * See http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/IRCAM/IRCAM.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, write to the Free Software Foundation, + * Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA. */ #include "sox_i.h" -#include "sfircam.h" - #include <string.h> -#include <stdlib.h> -/* Private data for SF file */ -typedef struct sfstuff { - struct sfinfo info; - /* needed for seek */ - sox_size_t dataStart; -} *sf_t; +/* Magic numbers used in IRCAM audio files */ +static struct {char str[4]; sox_bool reverse_bytes; char const * desc;} id[] = { + {"\144\243\001\0", SOX_IS_BIGENDIAN , "Little-endian VAX (native)"}, + {"\0\001\243\144", SOX_IS_LITTLEENDIAN, "Big-endian VAX"}, + {"\144\243\002\0", SOX_IS_LITTLEENDIAN, "Big-endian Sun (native)"}, + {"\0\002\243\144", SOX_IS_BIGENDIAN , "Little-endian Sun"}, + {"\144\243\003\0", SOX_IS_BIGENDIAN , "Little-endian MIPS (DEC)"}, + {"\0\003\243\144", SOX_IS_LITTLEENDIAN, "Big-endian MIPS (SGI)"}, + {"\144\243\004\0", SOX_IS_LITTLEENDIAN, "Big-endian NeXT"}, + {" ", 0, NULL} +}; +#define FIXED_HDR 1024 +#define SF_COMMENT 2 /* code for "comment line" */ -/* - * Read the codes from the sound file, allocate space for the comment and - * assign its pointer to the comment field in ft. - */ -static void readcodes(sox_format_t * ft, SFHEADER *sfhead) -{ - char *commentbuf = NULL, *sfcharp; - sox_size_t bsize; - sox_bool finished = sox_false; - SFCODE *sfcodep; +typedef enum {Unspecified, + Linear_8 = 0x00001, Alaw_8 = 0x10001, Mulaw_8 = 0x20001, Linear_16 = 0x00002, + Linear_24 = 0x00003, Linear_32 = 0x40004, Float = 0x00004, Double = 0x00008 +} ft_encoding_t; - sfcodep = (SFCODE *) (&sfhead->sfinfo + 1); - do { - sfcharp = (char *) sfcodep + sizeof(SFCODE); - if (ft->encoding.reverse_bytes) { - sfcodep->bsize = sox_swapdw(sfcodep->bsize); - sfcodep->code = sox_swapdw(sfcodep->code); - } - bsize = sfcodep->bsize - sizeof(SFCODE); - switch(sfcodep->code) { - case SF_END: - finished = sox_true; - break; - case SF_COMMENT: - commentbuf = (char *) xmalloc(bsize + 1); - memcpy(commentbuf, sfcharp, bsize); - commentbuf[bsize] = '\0'; - break; - } - sfcodep = (SFCODE *) (sfcharp + bsize); - } while(!finished); - append_comments(&ft->comments, commentbuf); - free(commentbuf); +static ft_encoding_t ft_enc(unsigned size, sox_encoding_t encoding) +{ + if (encoding == SOX_ENCODING_ULAW && size == 8) return Mulaw_8; + if (encoding == SOX_ENCODING_ALAW && size == 8) return Alaw_8; + if (encoding == SOX_ENCODING_SIGN2 && size == 8) return Linear_8; + if (encoding == SOX_ENCODING_SIGN2 && size == 16) return Linear_16; + if (encoding == SOX_ENCODING_SIGN2 && size == 24) return Linear_24; + if (encoding == SOX_ENCODING_SIGN2 && size == 32) return Linear_32; + if (encoding == SOX_ENCODING_FLOAT && size == 32) return Float; + if (encoding == SOX_ENCODING_FLOAT && size == 64) return Double; + return Unspecified; } -static int seek(sox_format_t * ft, sox_size_t offset) +static sox_encoding_t sox_enc(uint32_t ft_encoding, unsigned * size) { - sox_size_t new_offset, channel_block, alignment; - - sf_t sf = (sf_t ) ft->priv; - new_offset = offset * (ft->encoding.bits_per_sample >> 3); - /* Make sure request aligns to a channel block (ie left+right) */ - channel_block = ft->signal.channels * (ft->encoding.bits_per_sample >> 3); - 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 += sf->dataStart; - - return sox_seeki(ft, (sox_ssize_t)new_offset, SEEK_SET); + switch (ft_encoding) { + case Mulaw_8 : *size = 8; return SOX_ENCODING_ULAW; + case Alaw_8 : *size = 8; return SOX_ENCODING_ALAW; + case Linear_8 : *size = 8; return SOX_ENCODING_SIGN2; + case Linear_16 : *size = 16; return SOX_ENCODING_SIGN2; + case Linear_24 : *size = 24; return SOX_ENCODING_SIGN2; + case Linear_32 : *size = 32; return SOX_ENCODING_SIGN2; + case Float : *size = 32; return SOX_ENCODING_FLOAT; + case Double : *size = 64; return SOX_ENCODING_FLOAT; + default: return SOX_ENCODING_UNKNOWN; + } } -/* - * Do anything required before you start reading samples. - * Read file header. - * Find out sampling rate, - * size and encoding of samples, - * mono/stereo/quad. - */ static int startread(sox_format_t * ft) { - sf_t sf = (sf_t) ft->priv; - SFHEADER sfhead; - int rc; - int samplesize = 0; - - if (sox_readbuf(ft, &sfhead, sizeof(sfhead)) != sizeof(sfhead)) - { - sox_fail("unexpected EOF in SF header"); - return(SOX_EOF); - } - memcpy(&sf->info, &sfhead.sfinfo, sizeof(struct sfinfo)); - if (ft->encoding.reverse_bytes) { - sox_swapf(&sf->info.sf_srate); - sf->info.sf_packmode = sox_swapdw(sf->info.sf_packmode); - sf->info.sf_chans = sox_swapdw(sf->info.sf_chans); - } - if ((sfmagic1(&sfhead) != SF_MAGIC1) || - (sfmagic2(&sfhead) != SF_MAGIC2)) { - sox_fail_errno(ft, SOX_EHDR, "sf: can't find IRCAM identifier"); - return SOX_EOF; - } - - /* - * If your format specifies or your file header contains - * any of the following information. - */ - ft->signal.rate = sf->info.sf_srate; - switch(sf->info.sf_packmode) { - case SF_SHORT: - ft->encoding.bits_per_sample = 16; - ft->encoding.encoding = SOX_ENCODING_SIGN2; - samplesize = 2; - break; - case SF_FLOAT: - ft->encoding.bits_per_sample = 16; - ft->encoding.encoding = SOX_ENCODING_FLOAT; - samplesize = sizeof(float); - break; - default: - sox_fail("Soundfile input: unknown format 0x%x", - sf->info.sf_packmode); - return(SOX_EOF); - } - ft->signal.channels = (int) sf->info.sf_chans; - - if (ft->signal.channels == 0) - ft->signal.channels = 1; - - /* Read codes and print as comments. */ - readcodes(ft, &sfhead); - - /* Needed for rawread() */ - rc = sox_rawstartread(ft); + char magic[4]; + float rate; + uint32_t channels, ft_encoding; + unsigned i, bits_per_sample; + sox_encoding_t encoding; + uint16_t code, size; -/* Need length for seeking */ - if(ft->seekable){ - ft->length = sox_filelength(ft)/samplesize; - sf->dataStart = sox_tell(ft); - } else { - ft->length = 0; - } + if (sox_readchars(ft, magic, sizeof(magic))) + return SOX_EOF; + + for (i = 0; id[i].desc && memcmp(magic, id[i].str, sizeof(magic)); ++i); + if (!id[i].desc) { + sox_fail_errno(ft, SOX_EHDR, "sf: can't find IRCAM identifier"); + return SOX_EOF; + } + sox_report("found %s identifier", id[i].desc); + ft->encoding.reverse_bytes = id[i].reverse_bytes; - return(rc); + if (sox_readf(ft, &rate) || sox_readdw(ft, &channels) || sox_readdw(ft, &ft_encoding)) + return SOX_EOF; + + if (!(encoding = sox_enc(ft_encoding, &bits_per_sample))) { + sox_fail_errno(ft, SOX_EFMT, "sf: unsupported encoding %#x)", ft_encoding); + return SOX_EOF; + } + do { + if (sox_readw(ft, &code) || sox_readw(ft, &size)) + return SOX_EOF; + if (code == SF_COMMENT) { + char * buf = xcalloc(1, (size_t)size + 1); /* +1 ensures null-terminated */ + if (sox_readchars(ft, buf, size) != SOX_SUCCESS) { + free(buf); + return SOX_EOF; + } + append_comments(&ft->comments, buf); + free(buf); + } + else if (sox_skipbytes(ft, size)) + return SOX_EOF; + } while (code); + if (sox_skipbytes(ft, FIXED_HDR - (sox_size_t)sox_tell(ft))) + return SOX_EOF; + + return sox_check_read_params(ft, channels, rate, encoding, bits_per_sample, (off_t)0); } -static int startwrite(sox_format_t * ft) +static int write_header(sox_format_t * ft) { - sf_t sf = (sf_t) ft->priv; - SFHEADER sfhead; - SFCODE *sfcodep; - char *sfcharp; - int rc; - char * comment = cat_comments(ft->comments); - - /* Needed for rawwrite() */ - rc = sox_rawstartwrite(ft); - if (rc) - return rc; - - sf->info.magic_union._magic_bytes.sf_magic1 = SF_MAGIC1; - sf->info.magic_union._magic_bytes.sf_magic2 = SF_MAGIC2; - sf->info.magic_union._magic_bytes.sf_param = 0; - - /* This file handler can handle both big and little endian data */ - if (SOX_IS_LITTLEENDIAN) - sf->info.magic_union._magic_bytes.sf_machine = SF_VAX; - else - sf->info.magic_union._magic_bytes.sf_machine = SF_SUN; - - sf->info.sf_srate = ft->signal.rate; - if (ft->encoding.bits_per_sample == 32 && - ft->encoding.encoding == SOX_ENCODING_FLOAT) { - sf->info.sf_packmode = SF_FLOAT; - } else { - sf->info.sf_packmode = SF_SHORT; - /* Default to signed words */ - ft->encoding.bits_per_sample = 16; - ft->encoding.encoding = SOX_ENCODING_SIGN2; - } - - sf->info.sf_chans = ft->signal.channels; - - /* Clean out structure so unused areas will remain constain */ - /* between different coverts and not rely on memory contents */ - memset (&sfhead, 0, sizeof(SFHEADER)); - memcpy(&sfhead.sfinfo, &sf->info, sizeof(struct sfinfo)); - sfcodep = (SFCODE *) (&sfhead.filler[SF_INFO_LEN+1]); - sfcodep->code = SF_COMMENT; - sfcodep->bsize = strlen(comment) + sizeof(SFCODE); - while (sfcodep->bsize % 4) - sfcodep->bsize++; - sfcharp = (char *) sfcodep; - strcpy(sfcharp + sizeof(SFCODE), comment); - free(comment); - sfcodep = (SFCODE *) (sfcharp + sfcodep->bsize); - sfcodep->code = SF_END; - sfcodep->bsize = sizeof(SFCODE); - sfcharp = (char *) sfcodep + sizeof(SFCODE); - sox_writebuf(ft, &sfhead, sizeof(SFHEADER)); - - return(SOX_SUCCESS); + char * comment = cat_comments(ft->comments); + size_t len = min(FIXED_HDR - 26, strlen(comment)) + 1; /* null-terminated */ + size_t info_len = max(4, (len + 3) & ~3u); /* Minimum & multiple of 4 bytes */ + int i = ft->encoding.reverse_bytes == SOX_IS_BIGENDIAN? 0 : 2; + sox_bool error = sox_false + ||sox_writechars(ft, id[i].str, sizeof(id[i].str)) + ||sox_writef(ft, ft->signal.rate) + ||sox_writedw(ft, ft->signal.channels) + ||sox_writedw(ft, ft_enc(ft->encoding.bits_per_sample, ft->encoding.encoding)) + ||sox_writew(ft, SF_COMMENT) + ||sox_writew(ft, info_len) + ||sox_writechars(ft, comment, len) + ||sox_padbytes(ft, FIXED_HDR - 20 - len); + free(comment); + return error? SOX_EOF: SOX_SUCCESS; } SOX_FORMAT_HANDLER(sf) { static char const * const names[] = {"sf", "ircam", NULL}; - static unsigned const encodings[] = { - SOX_ENCODING_SIGN2, 16, 0, - SOX_ENCODING_FLOAT, 32, 0, + static unsigned const write_encodings[] = { + SOX_ENCODING_ULAW, 8, 0, + SOX_ENCODING_ALAW, 8, 0, + SOX_ENCODING_SIGN2, 8, 16, 24, 32, 0, + SOX_ENCODING_FLOAT, 32, 64, 0, 0}; - static sox_format_handler_t const handler = { - SOX_LIB_VERSION_CODE, - "Institut de Recherche et Coordination Acoustique/Musique Sound Description Interchange Format", - names, 0, - startread, sox_rawread, sox_rawstopread, - startwrite, sox_rawwrite, sox_rawstopwrite, - seek, encodings, NULL + static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE, + "Institut de Recherche et Coordination Acoustique/Musique", + names, SOX_FILE_LIT_END, + startread, sox_rawread, NULL, + write_header, sox_rawwrite, NULL, + sox_rawseek, write_encodings, NULL }; return &handler; } |