ref: a8635acb1f82f062e4ce39340866d8d2d5e0fa5d
parent: 1636c7a43cff83f077710aaa2d37605f18d51c81
author: cbagwell <cbagwell>
date: Sun May 20 19:49:29 EDT 2001
Unified the raw read routines for all datatypes. This reduces bugs being introduced for specific data types. This happens to fix a bug introduced in the 12.17 series that made hitting control-c not stop recording from oss driver.
--- a/Changelog
+++ b/Changelog
@@ -54,6 +54,9 @@
o Added support for reading non-standard bit size data from AIFF files.
o Ignore unmatched MARK/INSTR chunks in AIFF files now instead of quiting.
o Fixed ALAW encoding bug in .au files as pointed out by Bruce Forsberg.
+ o Unified the raw reading functions. Probably slightly faster for
+ most datatypes but was done to fix recording from the OSS driver.
+ Control-C stopped working somewhere during the 12.17 series.
sox-12.17.1
-----------
--- a/TODO
+++ b/TODO
@@ -1,6 +1,15 @@
People are encouraged to pick some of these and implement it. Send
all patches to cbagwell@sprynet.com.
+ o Make a global version of MIN/MAX instead of sprinkled min/max/MIN/MAX
+
+ o Unify the raw writing functions to work line the raw reading functions.
+ Also, add support to all file handlers to handle 32-bit and float
+ data types since raw functions can handle them.
+
+ o Change "float" from a data type to an encoding method. This will
+ effect command line usage but more accurately describes floats.
+
o All comment code has a memory leak. They must malloc memory to
store comment but its never free()'d.
--- a/src/raw.c
+++ b/src/raw.c
@@ -31,6 +31,10 @@
#define MAXWSPEED 1
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
static void rawdefaults(ft_t ft);
@@ -96,30 +100,6 @@
return(ST_SUCCESS);
}
-/* Read raw file data, and convert it to */
-/* the sox internal signed long format. */
-
-static unsigned char blockgetc(ft)
-ft_t ft;
-{
- char rval;
-
- if (ft->file.pos == ft->file.count)
- {
- if (ft->file.eof)
- return(0);
- ft->file.count = fread(ft->file.buf, 1, ft->file.size, ft->fp);
- ft->file.pos = 0;
- if (ft->file.count == 0)
- {
- ft->file.eof = 1;
- return(0);
- }
- }
- rval = *(ft->file.buf + ft->file.pos++);
- return (rval);
-}
-
/* Util to reverse the n chars starting at p. */
/* FIXME: Move to misc.c */
static void swapn(p, n)
@@ -137,182 +117,277 @@
}
}
-/* Reads a block of 'n' characters and possibly byte swaps */
-static void blockr(p0, n, ft)
-ft_t ft;
-int n;
-void *p0;
+void st_ub_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
{
- int rest;
- char *p;
- p = p0;
-
- while ((rest = ft->file.count - ft->file.pos) < n)
- {
- if (ft->file.eof) {
- memset(p,0,n);
- return;
- }
+ while (len)
+ {
+ unsigned char datum;
- memmove(ft->file.buf, ft->file.buf+ft->file.pos, rest);
+ datum = *((unsigned char *)buf2);
+ buf2++;
+ datum ^= 0x80;
- ft->file.pos = 0;
- ft->file.count = rest;
- ft->file.count += fread(ft->file.buf+rest, 1, ft->file.size-rest, ft->fp);
- ft->file.eof = (ft->file.count < n);
- }
- memcpy(p, ft->file.buf + ft->file.pos, n);
- ft->file.pos += n;
- /* FIXME: For speed, there should be a version of this funciton
- * for WORDS, LONGS, and FLOATS. This is because swapping
- * bytes is an expensive operation and should be done in batch
- * mode.
- */
- if (ft->swap)
- swapn(p,n);
+ *buf1++ = LEFT(datum,24);
+ len--;
+ }
}
-static int blockr_sw(p0, n, ft)
-LONG *p0,n;
-ft_t ft;
+void st_sb_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
{
- LONG x, done;
- short s;
+ while (len)
+ {
+ unsigned char datum;
- for (done=0; done < n;) {
- blockr(&s, sizeof(short), ft);
- x = s;
- if (ft->file.eof) break;
- /* scale signed up to long's range */
- *p0++ = LEFT(x, 16);
- done++;
- }
- return done;
+ datum = *((unsigned char *)buf2);
+ buf2++;
+
+ *buf1++ = LEFT(datum,24);
+ len--;
+ }
}
-LONG st_rawread(ft, buf, nsamp)
-ft_t ft;
-LONG *buf, nsamp;
+void st_ulaw_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
{
- int done = 0;
+ while (len)
+ {
+ unsigned char datum;
- switch(ft->info.size) {
- case ST_SIZE_BYTE:
- switch(ft->info.encoding)
- {
- case ST_ENCODING_SIGN2:
- while(done < nsamp) {
- LONG datum;
- datum = blockgetc(ft);
- if (ft->file.eof)
- return done;
- /* scale signed up to long's range */
- *buf++ = LEFT(datum, 24);
- done++;
- }
- return done;
- case ST_ENCODING_UNSIGNED:
- while(done < nsamp) {
- LONG datum;
- datum = blockgetc(ft);
- if (ft->file.eof)
- return done;
- /* Convert to signed */
- datum ^= 128;
- /* scale signed up to long's range */
- *buf++ = LEFT(datum, 24);
- done++;
- }
- return done;
- case ST_ENCODING_ULAW:
- while(done < nsamp) {
- LONG datum;
- datum = blockgetc(ft);
- if (ft->file.eof)
- return done;
- datum = st_ulaw_to_linear(datum);
- /* scale signed up to long's range */
- *buf++ = LEFT(datum, 16);
- done++;
- }
- return done;
- case ST_ENCODING_ALAW:
- while(done < nsamp) {
- LONG datum;
- datum = blockgetc(ft);
- if (ft->file.eof)
- return done;
- datum = st_Alaw_to_linear(datum);
- /* scale signed up to long's range */
- *buf++ = LEFT(datum, 16);
- done++;
- }
- return done;
- }
+ datum = *((unsigned char *)buf2);
+ buf2++;
+
+ *buf1++ = LEFT(st_ulaw_to_linear(datum),16);
+ len--;
+ }
+}
+
+void st_alaw_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ unsigned char datum;
+
+ datum = *((unsigned char *)buf2);
+ buf2++;
+
+ *buf1++ = LEFT(st_Alaw_to_linear(datum),16);
+ len--;
+ }
+}
+
+void st_uw_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ unsigned short datum;
+
+ datum = *((unsigned short *)buf2);
+ buf2++; buf2++;
+ if (swap)
+ datum = st_swapw(datum);
+ datum ^= 0x8000;
+
+ *buf1++ = LEFT(datum,16);
+ len--;
+ }
+}
+
+void st_sw_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ unsigned short datum;
+
+ datum = *((unsigned short *)buf2);
+ buf2++; buf2++;
+ if (swap)
+ datum = st_swapw(datum);
+
+ *buf1++ = LEFT(datum,16);
+ len--;
+ }
+}
+
+void st_ul_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ ULONG datum;
+
+ datum = *((ULONG *)buf2);
+ buf2++; buf2++; buf2++; buf2++;
+ if (swap)
+ datum = st_swapl(datum);
+
+ datum ^= 0x80000000L;
+
+ *buf1++ = datum;
+ len--;
+ }
+}
+
+void st_sl_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ ULONG datum;
+
+ datum = *((ULONG *)buf2);
+ buf2++; buf2++; buf2++; buf2++;
+ if (swap)
+ datum = st_swapl(datum);
+
+ *buf1++ = datum;
+ len--;
+ }
+}
+
+void st_f32_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ float datum;
+
+ datum = *((float *)buf2);
+ buf2++; buf2++; buf2++; buf2++;
+ if (swap)
+ datum = st_swapf(datum);
+
+ *buf1++ = datum;
+ len--;
+ }
+}
+
+void st_f64_copy_buf(LONG *buf1, char *buf2, ULONG len, char swap)
+{
+ while (len)
+ {
+ double datum;
+
+ datum = *((double *)buf2);
+ buf2++; buf2++; buf2++; buf2++;
+ buf2++; buf2++; buf2++; buf2++;
+ if (swap)
+ datum = st_swapd(datum);
+
+ *buf1++ = datum;
+ len--;
+ }
+}
+
+/* Reads a buffer of different data types into SoX's internal buffer
+ * format.
+ */
+ULONG st_readbuf(LONG *p, int n, int size, int encoding, ft_t ft)
+{
+ ULONG len, done = 0;
+ void (*copy_buf)(LONG *, char *, ULONG, char) = 0;
+
+ switch(size) {
+ case ST_SIZE_BYTE:
+ switch(encoding)
+ {
+ case ST_ENCODING_SIGN2:
+ copy_buf = st_sb_copy_buf;
break;
- case ST_SIZE_WORD:
- switch(ft->info.encoding)
- {
- case ST_ENCODING_SIGN2:
- return blockr_sw(buf, nsamp, ft);
- case ST_ENCODING_UNSIGNED:
- while(done < nsamp) {
- LONG x;
- unsigned short s;
- blockr(&s, sizeof(short), ft);
- x = s;
- if (ft->file.eof)
- return done;
- /* Convert to signed */
- x ^= 0x8000;
- /* scale signed up to long's range */
- *buf++ = LEFT(x, 16);
- done++;
- }
- return done;
- case ST_ENCODING_ULAW:
- st_fail_errno(ft,ST_EFMT,"No U-Law support for shorts");
- return 0;
- case ST_ENCODING_ALAW:
- st_fail_errno(ft,ST_EFMT,"No A-Law support for shorts");
- return 0;
- }
+ case ST_ENCODING_UNSIGNED:
+ copy_buf = st_ub_copy_buf;
break;
- case ST_SIZE_DWORD:
- switch(ft->info.encoding)
- {
- case ST_ENCODING_SIGN2:
- while(done < nsamp) {
- blockr(buf, sizeof(LONG), ft);
- if (ft->file.eof)
- return done;
- /* scale signed up to long's range */
- buf++;
- done++;
- }
- return done;
- }
+ case ST_ENCODING_ULAW:
+ copy_buf = st_ulaw_copy_buf;
break;
- case ST_SIZE_FLOAT:
- while(done < nsamp) {
- float f;
- blockr(&f, sizeof(float), ft);
- if (ft->file.eof)
- return done;
- *buf++ = f * 0x10000; /* hmm... */
- done++;
- }
- return done;
+ case ST_ENCODING_ALAW:
+ copy_buf = st_alaw_copy_buf;
+ break;
default:
- break;
+ st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size.");
+ return(0);
+ }
+ break;
+
+ case ST_SIZE_WORD:
+ switch(encoding)
+ {
+ case ST_ENCODING_SIGN2:
+ copy_buf = st_sw_copy_buf;
+ break;
+ case ST_ENCODING_UNSIGNED:
+ copy_buf = st_uw_copy_buf;
+ break;
+ default:
+ st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size.");
+ return(0);
+ }
+ break;
+
+ case ST_SIZE_DWORD:
+ switch(encoding)
+ {
+ case ST_ENCODING_SIGN2:
+ copy_buf = st_sl_copy_buf;
+ break;
+ case ST_ENCODING_UNSIGNED:
+ copy_buf = st_ul_copy_buf;
+ break;
+ default:
+ st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size.");
+ return(0);
+ }
+ break;
+
+ case ST_SIZE_FLOAT:
+ copy_buf = st_f32_copy_buf;
+ size = 4;
+ break;
+
+ case ST_SIZE_DOUBLE:
+ copy_buf = st_f64_copy_buf;
+ size = 8;
+ break;
+
+ default:
+ st_fail_errno(ft,ST_EFMT,"Do not support this data size for this handler");
+ return (0);
+ }
+
+
+ len = MIN(n,(ft->file.count-ft->file.pos)/size);
+ if (len)
+ {
+ copy_buf(p + done, ft->file.buf + ft->file.pos, len, ft->swap);
+ ft->file.pos += (len*size);
+ done += len;
+ }
+
+ while (done < n)
+ {
+ if (!ft->file.eof && ft->file.pos == ft->file.count)
+ {
+ ft->file.count = fread(ft->file.buf, 1, ft->file.size, ft->fp);
+ ft->file.pos = 0;
+ if (ft->file.count == 0)
+ {
+ ft->file.eof = 1;
+ }
}
-/* 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);
+ len = MIN(n,(ft->file.count-ft->file.pos)/size);
+ if (len)
+ {
+ copy_buf(p + done, ft->file.buf + ft->file.pos, len, ft->swap);
+ ft->file.pos += (len*size);
+ done += len;
+ }
+ if (ft->file.eof)
+ break;
+ }
+ return done;
+}
+
+LONG st_rawread(ft, buf, nsamp)
+ft_t ft;
+LONG *buf, nsamp;
+{
+ return st_readbuf(buf, nsamp, ft->info.size, ft->info.encoding, ft);
}
int st_rawstopread(ft)
--- a/src/util.c
+++ b/src/util.c
@@ -450,9 +450,9 @@
return ST_SUCCESS;
}
-static ft_t ft_queue[2];
+static ft_t ft_queue[2] = {0, 0};
-void sigint(int s)
+static void sigint(int s)
{
if (s == SIGINT) {
if (ft_queue[0])