ref: 51927c478136cb53d12d1017e1842e3d4050b7c8
parent: 44dc2abe48eaded6e27f4a1ae92fa2666d38993b
author: robs <robs>
date: Sun Nov 19 15:46:56 EST 2006
Add support for 24-bit PCM raw, wav, & flac files. Needed to fix-up some const-correctness in other function headers.
--- a/src/raw.c
+++ b/src/raw.c
@@ -88,6 +88,7 @@
switch(ft->info.size) {
case ST_SIZE_BYTE:
case ST_SIZE_WORD:
+ case ST_SIZE_24BIT:
case ST_SIZE_DWORD:
case ST_SIZE_DDWORD:
break;
@@ -143,7 +144,7 @@
return ST_SUCCESS;
}
-void st_ub_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_ub_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -157,7 +158,7 @@
}
}
-void st_sb_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_sb_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -171,7 +172,7 @@
}
}
-void st_ulaw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len,
+void st_ulaw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -186,7 +187,7 @@
}
}
-void st_alaw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len,
+void st_alaw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -201,7 +202,7 @@
}
}
-void st_inv_ulaw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len,
+void st_inv_ulaw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -216,7 +217,7 @@
}
}
-void st_inv_alaw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len,
+void st_inv_alaw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -232,7 +233,7 @@
}
-void st_uw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_uw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -248,7 +249,7 @@
}
}
-void st_sw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_sw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -264,8 +265,50 @@
}
}
-void st_udw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+
+
+static int24_t st_24_read_one(char const * * buffer, char swap)
{
+ /* N.B. overreads an extra byte; however SoX buffers are 2^n bytes long and
+ * since 2^n != 0 (mod 3), there will always be an extra byte to read from. */
+ int24_t datum = *(int24_t const *)*buffer;
+
+ *buffer += 3;
+
+ if (ST_IS_BIGENDIAN)
+ {
+ datum >>= 8;
+ }
+
+ return swap? st_swap24(datum) : datum;
+}
+
+
+
+void st_u24_read_buf(st_sample_t * buf1, char const * buf2, st_ssize_t len, char const swap)
+{
+ while (len--)
+ {
+ int24_t datum = st_24_read_one(&buf2, swap);
+ *buf1++ = ST_UNSIGNED_24BIT_TO_SAMPLE(datum);
+ }
+}
+
+
+
+void st_s24_read_buf(st_sample_t * buf1, char const * buf2, st_ssize_t len, char const swap)
+{
+ while (len--)
+ {
+ int24_t datum = st_24_read_one(&buf2, swap);
+ *buf1++ = ST_SIGNED_24BIT_TO_SAMPLE(datum);
+ }
+}
+
+
+
+void st_udw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
+{
while (len)
{
uint32_t datum;
@@ -280,7 +323,7 @@
}
}
-void st_dw_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_dw_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -296,7 +339,7 @@
}
}
-void st_f32_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_f32_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -312,7 +355,7 @@
}
}
-void st_f64_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
+void st_f64_read_buf(st_sample_t *buf1, char const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -340,7 +383,7 @@
st_ssize_t st_rawread(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
{
st_ssize_t len, done = 0;
- void (*read_buf)(st_sample_t *, char *, st_ssize_t, char) = 0;
+ void (*read_buf)(st_sample_t *, char const *, st_ssize_t, char) = 0;
size_t i;
if (nsamp < 0)
@@ -392,6 +435,21 @@
}
break;
+ case ST_SIZE_24BIT:
+ switch(ft->info.encoding)
+ {
+ case ST_ENCODING_SIGN2:
+ read_buf = st_s24_read_buf;
+ break;
+ case ST_ENCODING_UNSIGNED:
+ read_buf = st_u24_read_buf;
+ break;
+ default:
+ st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
+ return ST_EOF;
+ }
+ break;
+
case ST_SIZE_DWORD:
switch(ft->info.encoding)
{
@@ -483,7 +541,7 @@
return ST_SUCCESS;
}
-void st_ub_write_buf(char* buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_ub_write_buf(char* buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -492,7 +550,7 @@
}
}
-void st_sb_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_sb_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -501,7 +559,7 @@
}
}
-void st_ulaw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len,
+void st_ulaw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -511,7 +569,7 @@
}
}
-void st_alaw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len,
+void st_alaw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -521,7 +579,7 @@
}
}
-void st_inv_ulaw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len,
+void st_inv_ulaw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -531,7 +589,7 @@
}
}
-void st_inv_alaw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len,
+void st_inv_alaw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len,
char swap)
{
while (len)
@@ -541,7 +599,7 @@
}
}
-void st_uw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_uw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -557,7 +615,7 @@
}
}
-void st_sw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_sw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -573,8 +631,52 @@
}
}
-void st_udw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+
+
+static void st_24_write_one(char * * const buf1, int24_t datum, char const swap)
{
+ if (swap)
+ {
+ datum = st_swap24(datum);
+ }
+ if (ST_IS_BIGENDIAN)
+ {
+ datum <<= 8;
+ }
+
+ /* N.B. overwrites an extra byte; however SoX buffers are 2^n bytes long and
+ * since 2^n != 0 (mod 3), there will always be an extra byte to write to. */
+ *(int24_t *)*buf1 = datum;
+
+ *buf1 += 3;
+}
+
+
+
+void st_u24_write_buf(char * buf1, st_sample_t const * buf2, st_ssize_t len, char const swap)
+{
+ while (len--)
+ {
+ int24_t datum = ST_SAMPLE_TO_UNSIGNED_24BIT(*buf2++);
+ st_24_write_one(&buf1, datum, swap);
+ }
+}
+
+
+
+void st_s24_write_buf(char * buf1, st_sample_t const * buf2, st_ssize_t len, char const swap)
+{
+ while (len--)
+ {
+ int24_t datum = ST_SAMPLE_TO_SIGNED_24BIT(*buf2++);
+ st_24_write_one(&buf1, datum, swap);
+ }
+}
+
+
+
+void st_udw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
+{
while (len)
{
uint32_t datum;
@@ -589,7 +691,7 @@
}
}
-void st_dw_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_dw_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -605,7 +707,7 @@
}
}
-void st_f32_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_f32_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -621,7 +723,7 @@
}
}
-void st_f64_write_buf(char *buf1, st_sample_t *buf2, st_ssize_t len, char swap)
+void st_f64_write_buf(char *buf1, st_sample_t const * buf2, st_ssize_t len, char swap)
{
while (len)
{
@@ -659,7 +761,7 @@
st_ssize_t st_rawwrite(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
{
st_ssize_t len, done = 0;
- void (*write_buf)(char *, st_sample_t *, st_ssize_t, char) = 0;
+ void (*write_buf)(char *, st_sample_t const *, st_ssize_t, char) = 0;
switch(ft->info.size) {
case ST_SIZE_BYTE:
@@ -704,6 +806,21 @@
}
break;
+ case ST_SIZE_24BIT:
+ switch(ft->info.encoding)
+ {
+ case ST_ENCODING_SIGN2:
+ write_buf = st_s24_write_buf;
+ break;
+ case ST_ENCODING_UNSIGNED:
+ write_buf = st_u24_write_buf;
+ break;
+ default:
+ st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
+ return ST_EOF;
+ }
+ break;
+
case ST_SIZE_DWORD:
switch(ft->info.encoding)
{
@@ -799,6 +916,15 @@
STARTREAD(st_swstartread,ST_SIZE_WORD,ST_ENCODING_SIGN2)
STARTWRITE(st_swstartwrite,ST_SIZE_WORD,ST_ENCODING_SIGN2)
+STARTREAD(st_u3startread,ST_SIZE_24BIT,ST_ENCODING_UNSIGNED)
+STARTWRITE(st_u3startwrite,ST_SIZE_24BIT,ST_ENCODING_UNSIGNED)
+
+STARTREAD(st_s3startread,ST_SIZE_24BIT,ST_ENCODING_SIGN2)
+STARTWRITE(st_s3startwrite,ST_SIZE_24BIT,ST_ENCODING_SIGN2)
+
+STARTREAD(st_u4startread,ST_SIZE_DWORD,ST_ENCODING_UNSIGNED)
+STARTWRITE(st_u4startwrite,ST_SIZE_DWORD,ST_ENCODING_UNSIGNED)
+
STARTREAD(st_slstartread,ST_SIZE_DWORD,ST_ENCODING_SIGN2)
STARTWRITE(st_slstartwrite,ST_SIZE_DWORD,ST_ENCODING_SIGN2)
@@ -940,6 +1066,35 @@
return &st_sb_format;
}
+
+
+/* Unsigned 3 byte raw; used for testing only; not documented in the man page */
+
+static char *u4names[] = {
+ "u4",
+ NULL,
+};
+
+static st_format_t st_u4_format = {
+ u4names,
+ NULL,
+ ST_FILE_STEREO,
+ st_u4startread,
+ st_rawread,
+ st_rawstopread,
+ st_u4startwrite,
+ st_rawwrite,
+ st_rawstopwrite,
+ st_format_nothing_seek
+};
+
+const st_format_t *st_u4_format_fn(void)
+{
+ return &st_u4_format;
+}
+
+
+
static char *slnames[] = {
"sl",
NULL,
@@ -986,6 +1141,35 @@
return &st_sw_format;
}
+
+
+/* Signed 3 byte raw; used for testing only; not documented in the man page */
+
+static char *s3names[] = {
+ "s3",
+ NULL
+};
+
+static st_format_t st_s3_format = {
+ s3names,
+ NULL,
+ ST_FILE_STEREO,
+ st_s3startread,
+ st_rawread,
+ st_rawstopread,
+ st_s3startwrite,
+ st_rawwrite,
+ st_rawstopwrite,
+ st_format_nothing_seek
+};
+
+const st_format_t *st_s3_format_fn(void)
+{
+ return &st_s3_format;
+}
+
+
+
static char *ubnames[] = {
"ub",
"sou",
@@ -1055,4 +1239,31 @@
const st_format_t *st_uw_format_fn(void)
{
return &st_uw_format;
+}
+
+
+
+/* Unsigned 3 byte raw; used for testing only; not documented in the man page */
+
+static char *u3names[] = {
+ "u3",
+ NULL
+};
+
+static st_format_t st_u3_format = {
+ u3names,
+ NULL,
+ ST_FILE_STEREO,
+ st_u3startread,
+ st_rawread,
+ st_rawstopread,
+ st_u3startwrite,
+ st_rawwrite,
+ st_rawstopwrite,
+ st_format_nothing_seek
+};
+
+const st_format_t *st_u3_format_fn(void)
+{
+ return &st_u3_format;
}