ref: a0ab06d06dae1301fae8cc24e4d60f092012b8de
parent: 761a3593cbde34f81b18cd1a7bb7b3b38ce02bb9
author: cbagwell <cbagwell>
date: Sun Mar 19 21:07:33 EST 2006
Adding support for multiple channels in dat files.
--- a/Changelog
+++ b/Changelog
@@ -38,6 +38,8 @@
compiler. (1417798) Marty
o Stop calling flow() on effects that returned EOF during drain(). Allows
two back-to-back reverse effects to work.
+ o Added support for multiple channels in .dat files.
+ (1366634) tomchristie
sox-12.17.9
-----------
--- a/src/dat.c
+++ b/src/dat.c
@@ -18,13 +18,23 @@
* September 24, 1998: cbagwell - Set up extra output format info so that
* reports are accurate. Also warn user when forcing to mono.
*
+ * November 25, 2005: tomchristie - Work with multiple channels
+ *
*/
#include "st_i.h"
+#include <string.h>
+/* float output normalized to approx 1.0 */
+#define FLOATTOLONG (2.147483648e9)
+#define LONGTOFLOAT (1 / FLOATTOLONG)
+#define LINEWIDTH 256
+
/* Private data for dat file */
typedef struct dat {
- double timevalue, deltat;
+ double timevalue, deltat;
+ int buffered;
+ char prevline[LINEWIDTH];
} *dat_t;
/* FIXME: Move this to misc.c */
@@ -36,88 +46,102 @@
int st_datstartread(ft_t ft)
{
- char inpstr[82];
- char sc;
- long rate;
+ char inpstr[LINEWIDTH];
+ long rate;
+ int chan;
+ int status;
+ char sc;
- while (ft->info.rate == 0) {
- st_reads(ft, inpstr, 82);
- inpstr[81] = 0;
- sscanf(inpstr," %c",&sc);
- if (sc != ';')
- {
- st_fail_errno(ft,ST_EHDR,"Cannot determine sample rate.");
- return (ST_EOF);
+ /* Read lines until EOF or first non-comment line */
+ while ((status = st_reads(ft, inpstr, LINEWIDTH-1)) != ST_EOF) {
+ inpstr[LINEWIDTH-1] = 0;
+ if ((sscanf(inpstr," %c", &sc) != 0) && (sc != ';')) break;
+ if (sscanf(inpstr," ; Sample Rate %ld", &rate)) {
+ ft->info.rate=rate;
+ } else if (sscanf(inpstr," ; Channels %d", &chan)) {
+ ft->info.channels=chan;
}
- /* Store in system dependent long to get around cross platform
- * problems.
- */
- sscanf(inpstr," ; Sample Rate %ld", &rate);
- ft->info.rate = rate;
- }
+ }
+ /* Hold a copy of the last line we read (first non-comment) */
+ if (status != ST_EOF) {
+ strncpy(((dat_t)ft->priv)->prevline, inpstr, LINEWIDTH);
+ ((dat_t)ft->priv)->buffered = 1;
+ } else {
+ ((dat_t)ft->priv)->buffered = 0;
+ }
- if (ft->info.channels == -1)
+ /* Default channels to 1 if not found */
+ if (ft->info.channels == -1)
ft->info.channels = 1;
- ft->info.size = ST_SIZE_64BIT;
- ft->info.encoding = ST_ENCODING_FLOAT;
+ ft->info.size = ST_SIZE_64BIT;
+ ft->info.encoding = ST_ENCODING_FLOAT;
- return (ST_SUCCESS);
+ return (ST_SUCCESS);
}
int st_datstartwrite(ft_t ft)
{
- dat_t dat = (dat_t) ft->priv;
- double srate;
- char s[80];
- long rate;
+ dat_t dat = (dat_t) ft->priv;
+ char s[LINEWIDTH];
- if (ft->info.channels > 1)
- {
- st_report("Can only create .dat files with one channel.");
- st_report("Forcing output to 1 channel.");
- ft->info.channels = 1;
- }
-
- ft->info.size = ST_SIZE_64BIT;
- ft->info.encoding = ST_ENCODING_FLOAT;
- dat->timevalue = 0.0;
- srate = ft->info.rate;
- dat->deltat = 1.0 / srate;
- rate = ft->info.rate;
- sprintf(s,"; Sample Rate %ld\015\n",rate);
- st_writes(ft, s);
+ ft->info.size = ST_SIZE_64BIT;
+ ft->info.encoding = ST_ENCODING_FLOAT;
+ dat->timevalue = 0.0;
+ dat->deltat = 1.0 / (double)ft->info.rate;
+ /* Write format comments to start of file */
+ sprintf(s,"; Sample Rate %ld\015\n", (long)ft->info.rate);
+ st_writes(ft, s);
+ sprintf(s,"; Channels %d\015\n", (int)ft->info.channels);
+ st_writes(ft, s);
- return (ST_SUCCESS);
+ return (ST_SUCCESS);
}
st_ssize_t st_datread(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
{
- char inpstr[82];
- double sampval;
- int retc;
+ char inpstr[LINEWIDTH];
+ int inpPtr = 0;
+ int inpPtrInc = 0;
+ double sampval = 0.0;
+ int retc = 0;
+ char sc = 0;
int done = 0;
- char sc;
+ int i=0;
+ /* Always read a complete set of channels */
+ nsamp -= (nsamp % ft->info.channels);
+
while (done < nsamp) {
- do {
- st_reads(ft, inpstr, 82);
- if (st_eof(ft)) {
- return (done);
- }
- sscanf(inpstr," %c",&sc);
- }
- while(sc == ';'); /* eliminate comments */
- retc = sscanf(inpstr,"%*s %lg",&sampval);
- if (retc != 1)
- {
- st_fail_errno(ft,ST_EOF,"Unable to read sample.");
- return (0);
+
+ /* Read a line or grab the buffered first line */
+ if (((dat_t)ft->priv)->buffered) {
+ strncpy(inpstr, ((dat_t)ft->priv)->prevline, LINEWIDTH);
+ ((dat_t)ft->priv)->buffered=0;
+ } else {
+ st_reads(ft, inpstr, LINEWIDTH-1);
+ inpstr[LINEWIDTH-1] = 0;
+ if (st_eof(ft)) return (done);
+ }
+
+ /* Skip over comments - ie. 0 or more whitespace, then ';' */
+ if ((sscanf(inpstr," %c", &sc) != 0) && (sc==';')) continue;
+
+ /* Read a complete set of channels */
+ sscanf(inpstr," %*s%n", &inpPtr);
+ for (i=0; i<ft->info.channels; i++) {
+ retc = sscanf(&inpstr[inpPtr]," %lg%n", &sampval, &inpPtrInc);
+ inpPtr += inpPtrInc;
+ if (retc != 1) {
+ st_fail_errno(ft,ST_EOF,"Unable to read sample.");
+ return (ST_EOF);
}
- *buf++ = roundoff(sampval * 2.147483648e9);
- ++done;
+ *buf++ = roundoff(sampval * FLOATTOLONG);
+ done++;
+ }
}
- return (done);
+
+ return (done);
}
st_ssize_t st_datwrite(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
@@ -124,17 +148,28 @@
{
dat_t dat = (dat_t) ft->priv;
int done = 0;
- double sampval;
- char s[80];
+ double sampval=0.0;
+ char s[LINEWIDTH];
+ int i=0;
+ /* Always write a complete set of channels */
+ nsamp -= (nsamp % ft->info.channels);
+
+ /* Write time, then sample values, then CRLF newline */
while(done < nsamp) {
- sampval = *buf++ ;
- sampval = sampval / 2.147483648e9; /* normalize to approx 1.0 */
- sprintf(s," %15.8g %15.8g \015\n",dat->timevalue,sampval);
- st_writes(ft, s);
- dat->timevalue += dat->deltat;
- done++;
- }
+ sprintf(s," %15.8g ",dat->timevalue);
+ st_writes(ft, s);
+ for (i=0; i<ft->info.channels; i++) {
+ sampval = *buf++ ;
+ sampval = sampval * LONGTOFLOAT;
+ sprintf(s," %15.8g", sampval);
+ st_writes(ft, s);
+ done++;
+ }
+ sprintf(s," \015\n");
+ st_writes(ft, s);
+ dat->timevalue += dat->deltat;
+ }
return done;
}