mirror of
https://github.com/ericonr/sndio.git
synced 2024-02-18 04:45:21 -06:00
add support for f32le in .wav files
This commit is contained in:
parent
10149c9d0e
commit
f3ef9df7b4
@ -235,7 +235,20 @@ slot_new(char *path, int mode, struct aparams *par, int hdr,
|
|||||||
log_puts(", ");
|
log_puts(", ");
|
||||||
log_putu(s->wav.rate);
|
log_putu(s->wav.rate);
|
||||||
log_puts("Hz, ");
|
log_puts("Hz, ");
|
||||||
aparams_log(&s->wav.par);
|
switch (s->wav.enc) {
|
||||||
|
case ENC_PCM:
|
||||||
|
aparams_log(&s->wav.par);
|
||||||
|
break;
|
||||||
|
case ENC_ULAW:
|
||||||
|
log_puts("ulaw");
|
||||||
|
break;
|
||||||
|
case ENC_ALAW:
|
||||||
|
log_puts("alaw");
|
||||||
|
break;
|
||||||
|
case ENC_F32LE:
|
||||||
|
log_puts("f32le");
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (s->mode == SIO_PLAY && s->wav.endpos >= 0) {
|
if (s->mode == SIO_PLAY && s->wav.endpos >= 0) {
|
||||||
log_puts(", ");
|
log_puts(", ");
|
||||||
log_puti(s->wav.endpos - s->wav.startpos);
|
log_puti(s->wav.endpos - s->wav.startpos);
|
||||||
@ -294,8 +307,17 @@ slot_init(struct slot *s)
|
|||||||
s->cmin, s->cmax,
|
s->cmin, s->cmax,
|
||||||
0, dev_pchan - 1,
|
0, dev_pchan - 1,
|
||||||
0, dev_pchan - 1);
|
0, dev_pchan - 1);
|
||||||
if (!aparams_native(&s->wav.par)) {
|
if (s->wav.enc != ENC_PCM || !aparams_native(&s->wav.par)) {
|
||||||
dec_init(&s->conv, &s->wav.par, slot_nch);
|
switch (s->wav.enc) {
|
||||||
|
case ENC_PCM:
|
||||||
|
dec_init(&s->conv, &s->wav.par, slot_nch);
|
||||||
|
break;
|
||||||
|
case ENC_ALAW:
|
||||||
|
case ENC_ULAW:
|
||||||
|
case ENC_F32LE:
|
||||||
|
/* nothing */
|
||||||
|
break;
|
||||||
|
};
|
||||||
s->convbuf =
|
s->convbuf =
|
||||||
xmalloc(s->round * slot_nch * sizeof(adata_t));
|
xmalloc(s->round * slot_nch * sizeof(adata_t));
|
||||||
}
|
}
|
||||||
@ -447,8 +469,22 @@ play_filt_dec(struct slot *s, void *in, void *out, int todo)
|
|||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
||||||
tmp = s->convbuf;
|
tmp = s->convbuf;
|
||||||
if (tmp)
|
if (tmp) {
|
||||||
dec_do(&s->conv, in, tmp, todo);
|
switch (s->wav.enc) {
|
||||||
|
case ENC_PCM:
|
||||||
|
dec_do(&s->conv, in, tmp, todo);
|
||||||
|
break;
|
||||||
|
case ENC_ULAW:
|
||||||
|
wav_dec_ulaw(in, tmp, todo * s->wav.nch);
|
||||||
|
break;
|
||||||
|
case ENC_ALAW:
|
||||||
|
wav_dec_alaw(in, tmp, todo * s->wav.nch);
|
||||||
|
break;
|
||||||
|
case ENC_F32LE:
|
||||||
|
wav_dec_f32le(in, tmp, todo * s->wav.nch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return play_filt_resamp(s, tmp ? tmp : in, out, todo);
|
return play_filt_resamp(s, tmp ? tmp : in, out, todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
140
aucat/wav.c
140
aucat/wav.c
@ -30,11 +30,11 @@
|
|||||||
/*
|
/*
|
||||||
* Encoding IDs used in .wav headers.
|
* Encoding IDs used in .wav headers.
|
||||||
*/
|
*/
|
||||||
#define WAV_ENC_PCM 1
|
#define WAV_FMT_PCM 1
|
||||||
#define WAV_ENC_FLOAT 3
|
#define WAV_FMT_FLOAT 3
|
||||||
#define WAV_ENC_ALAW 6
|
#define WAV_FMT_ALAW 6
|
||||||
#define WAV_ENC_ULAW 7
|
#define WAV_FMT_ULAW 7
|
||||||
#define WAV_ENC_EXT 0xfffe
|
#define WAV_FMT_EXT 0xfffe
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char ld[4];
|
unsigned char ld[4];
|
||||||
@ -191,24 +191,64 @@ le32_set(le32_t *p, unsigned int v)
|
|||||||
p->ld[3] = v >> 24;
|
p->ld[3] = v >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
|
* convert a 32-bit float to adata_t, clipping to -1:1, boundaries
|
||||||
|
* excluded
|
||||||
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
f32_to_s24(unsigned int x)
|
f32_to_adata(unsigned int x)
|
||||||
{
|
{
|
||||||
unsigned int s, e, m, y;
|
unsigned int s, e, m, y;
|
||||||
|
|
||||||
s = (x >> 31);
|
s = (x >> 31);
|
||||||
e = (x >> 23) & 0xff;
|
e = (x >> 23) & 0xff;
|
||||||
m = (x & 0x007fffff) | 0x00800000;
|
m = (x << 8) | 0x80000000;
|
||||||
if (e < 127 - 24)
|
if (e < 127 - 24)
|
||||||
y = 0;
|
y = 0;
|
||||||
else if (e > 127 - 1)
|
else if (e > 127 - 1)
|
||||||
y = 0x00800000;
|
y = ADATA_UNIT - 1;
|
||||||
else
|
else
|
||||||
y = m >> (127 - e);
|
y = m >> (127 + (32 - ADATA_BITS) - e);
|
||||||
return (y ^ -s) + s;
|
return (y ^ -s) + s;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
/*
|
||||||
|
* convert samples from little endian ieee 754 floats to adata_t
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wav_dec_f32le(unsigned char *in, adata_t *out, int count)
|
||||||
|
{
|
||||||
|
while (count > 0) {
|
||||||
|
*out = f32_to_adata(le32_get((le32_t *)in));
|
||||||
|
in += 4;
|
||||||
|
out++;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* convert samples from ulaw to adata_t
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wav_dec_ulaw(unsigned char *in, adata_t *out, int count)
|
||||||
|
{
|
||||||
|
while (count > 0) {
|
||||||
|
*out++ = (adata_t)(wav_ulawmap[*in++]) << (ADATA_BITS - 16);
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* convert samples from alaw to adata_t
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wav_dec_alaw(unsigned char *in, adata_t *out, int count)
|
||||||
|
{
|
||||||
|
while (count > 0) {
|
||||||
|
*out++ = (adata_t)(wav_alawmap[*in++]) << (ADATA_BITS - 16);
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wav_readfmt(struct wav *w, unsigned int csize)
|
wav_readfmt(struct wav *w, unsigned int csize)
|
||||||
@ -229,7 +269,7 @@ wav_readfmt(struct wav *w, unsigned int csize)
|
|||||||
}
|
}
|
||||||
enc = le16_get(&fmt.fmt);
|
enc = le16_get(&fmt.fmt);
|
||||||
bits = le16_get(&fmt.bits);
|
bits = le16_get(&fmt.bits);
|
||||||
if (enc == WAV_ENC_EXT) {
|
if (enc == WAV_FMT_EXT) {
|
||||||
if (csize != WAV_FMT_EXT_SIZE) {
|
if (csize != WAV_FMT_EXT_SIZE) {
|
||||||
log_puts("missing extended format chunk in .wav file\n");
|
log_puts("missing extended format chunk in .wav file\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -243,21 +283,6 @@ wav_readfmt(struct wav *w, unsigned int csize)
|
|||||||
enc = le16_get(&fmt.extfmt);
|
enc = le16_get(&fmt.extfmt);
|
||||||
} else
|
} else
|
||||||
bps = (bits + 7) / 8;
|
bps = (bits + 7) / 8;
|
||||||
switch (enc) {
|
|
||||||
case WAV_ENC_PCM:
|
|
||||||
w->map = NULL;
|
|
||||||
break;
|
|
||||||
case WAV_ENC_ALAW:
|
|
||||||
w->map = wav_alawmap;
|
|
||||||
break;
|
|
||||||
case WAV_ENC_ULAW:
|
|
||||||
w->map = wav_ulawmap;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log_putu(enc);
|
|
||||||
log_puts(": unsupported encoding in .wav file\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
nch = le16_get(&fmt.nch);
|
nch = le16_get(&fmt.nch);
|
||||||
if (nch == 0) {
|
if (nch == 0) {
|
||||||
log_puts("zero number of channels in .wav file\n");
|
log_puts("zero number of channels in .wav file\n");
|
||||||
@ -278,22 +303,44 @@ wav_readfmt(struct wav *w, unsigned int csize)
|
|||||||
log_puts("bits larger than bytes-per-sample\n");
|
log_puts("bits larger than bytes-per-sample\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (enc == WAV_ENC_PCM) {
|
switch (enc) {
|
||||||
|
case WAV_FMT_PCM:
|
||||||
|
w->enc = ENC_PCM;
|
||||||
w->par.bps = bps;
|
w->par.bps = bps;
|
||||||
w->par.bits = bits;
|
w->par.bits = bits;
|
||||||
w->par.le = 1;
|
w->par.le = 1;
|
||||||
w->par.sig = (bits <= 8) ? 0 : 1; /* ask microsoft why... */
|
w->par.sig = (bits <= 8) ? 0 : 1; /* ask microsoft why... */
|
||||||
w->par.msb = 1;
|
w->par.msb = 1;
|
||||||
} else {
|
break;
|
||||||
|
case WAV_FMT_ALAW:
|
||||||
|
case WAV_FMT_ULAW:
|
||||||
|
w->enc = (enc == WAV_FMT_ULAW) ? ENC_ULAW : ENC_ALAW;
|
||||||
if (bits != 8) {
|
if (bits != 8) {
|
||||||
log_puts("mulaw/alaw encoding not 8-bit\n");
|
log_puts("mulaw/alaw encoding not 8-bit\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
w->par.bits = ADATA_BITS;
|
w->par.bits = 8;
|
||||||
w->par.bps = sizeof(adata_t);
|
w->par.bps = 1;
|
||||||
w->par.le = ADATA_LE;
|
w->par.le = ADATA_LE;
|
||||||
|
w->par.sig = 0;
|
||||||
|
w->par.msb = 0;
|
||||||
|
break;
|
||||||
|
case WAV_FMT_FLOAT:
|
||||||
|
w->enc = ENC_F32LE;
|
||||||
|
if (bits != 32) {
|
||||||
|
log_puts("only 32-bit float supported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
w->par.bits = 32;
|
||||||
|
w->par.bps = 4;
|
||||||
|
w->par.le = 1;
|
||||||
w->par.sig = 1;
|
w->par.sig = 1;
|
||||||
w->par.msb = 0;
|
w->par.msb = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_putu(enc);
|
||||||
|
log_puts(": unsupported encoding in .wav file\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
w->nch = nch;
|
w->nch = nch;
|
||||||
w->rate = rate;
|
w->rate = rate;
|
||||||
@ -398,33 +445,12 @@ wav_writehdr(struct wav *w)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* convert ``count'' samples using the given char->short map
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
wav_conv_map(unsigned char *data, unsigned int count, short *map)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned char *iptr;
|
|
||||||
adata_t *optr;
|
|
||||||
|
|
||||||
iptr = data + count;
|
|
||||||
optr = (adata_t *)data + count;
|
|
||||||
for (i = count; i > 0; i--) {
|
|
||||||
--optr;
|
|
||||||
--iptr;
|
|
||||||
*optr = (adata_t)(map[*iptr]) << (ADATA_BITS - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
wav_read(struct wav *w, void *data, size_t count)
|
wav_read(struct wav *w, void *data, size_t count)
|
||||||
{
|
{
|
||||||
off_t maxread;
|
off_t maxread;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
if (w->map)
|
|
||||||
count /= sizeof(adata_t);
|
|
||||||
if (w->endpos >= 0) {
|
if (w->endpos >= 0) {
|
||||||
maxread = w->endpos - w->curpos;
|
maxread = w->endpos - w->curpos;
|
||||||
if (maxread == 0) {
|
if (maxread == 0) {
|
||||||
@ -446,10 +472,6 @@ wav_read(struct wav *w, void *data, size_t count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
w->curpos += n;
|
w->curpos += n;
|
||||||
if (w->map) {
|
|
||||||
wav_conv_map(data, n, w->map);
|
|
||||||
n *= sizeof(adata_t);
|
|
||||||
}
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,8 +510,6 @@ wav_write(struct wav *w, void *data, size_t count)
|
|||||||
int
|
int
|
||||||
wav_seek(struct wav *w, off_t pos)
|
wav_seek(struct wav *w, off_t pos)
|
||||||
{
|
{
|
||||||
if (w->map)
|
|
||||||
pos /= sizeof(adata_t);
|
|
||||||
pos += w->startpos;
|
pos += w->startpos;
|
||||||
if (w->endpos >= 0 && pos > w->endpos) {
|
if (w->endpos >= 0 && pos > w->endpos) {
|
||||||
log_puts(w->path);
|
log_puts(w->path);
|
||||||
@ -561,7 +581,7 @@ wav_open(struct wav *w, char *path, int hdr, int flags,
|
|||||||
} else {
|
} else {
|
||||||
w->startpos = 0;
|
w->startpos = 0;
|
||||||
w->endpos = -1; /* read until EOF */
|
w->endpos = -1; /* read until EOF */
|
||||||
w->map = NULL;
|
w->enc = ENC_PCM;
|
||||||
}
|
}
|
||||||
w->curpos = w->startpos;
|
w->curpos = w->startpos;
|
||||||
} else if (flags == WAV_FWRITE) {
|
} else if (flags == WAV_FWRITE) {
|
||||||
|
10
aucat/wav.h
10
aucat/wav.h
@ -22,6 +22,11 @@
|
|||||||
|
|
||||||
struct wav {
|
struct wav {
|
||||||
struct aparams par; /* file params */
|
struct aparams par; /* file params */
|
||||||
|
#define ENC_PCM 0 /* simple integers (fixed point) */
|
||||||
|
#define ENC_ULAW 1 /* 8-bit mu-law */
|
||||||
|
#define ENC_ALAW 2 /* 8-bit a-law */
|
||||||
|
#define ENC_F32LE 3 /* IEEE 754 32-bit floats */
|
||||||
|
int enc; /* one of above */
|
||||||
int rate; /* file sample rate */
|
int rate; /* file sample rate */
|
||||||
int nch; /* file channel count */
|
int nch; /* file channel count */
|
||||||
#define HDR_AUTO 0
|
#define HDR_AUTO 0
|
||||||
@ -36,7 +41,6 @@ struct wav {
|
|||||||
off_t startpos; /* where payload starts */
|
off_t startpos; /* where payload starts */
|
||||||
off_t endpos; /* where payload ends */
|
off_t endpos; /* where payload ends */
|
||||||
off_t maxpos; /* max allowed pos (.wav limitation) */
|
off_t maxpos; /* max allowed pos (.wav limitation) */
|
||||||
short *map; /* mulaw/alaw conversions */
|
|
||||||
char *path; /* file name (debug only) */
|
char *path; /* file name (debug only) */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,4 +50,8 @@ size_t wav_write(struct wav *, void *, size_t);
|
|||||||
int wav_seek(struct wav *, off_t);
|
int wav_seek(struct wav *, off_t);
|
||||||
void wav_close(struct wav *);
|
void wav_close(struct wav *);
|
||||||
|
|
||||||
|
void wav_dec_f32le(unsigned char *, adata_t *, int);
|
||||||
|
void wav_dec_ulaw(unsigned char *, adata_t *, int);
|
||||||
|
void wav_dec_alaw(unsigned char *, adata_t *, int);
|
||||||
|
|
||||||
#endif /* !defined(WAV_H) */
|
#endif /* !defined(WAV_H) */
|
||||||
|
Loading…
Reference in New Issue
Block a user