1
0
mirror of https://github.com/ericonr/sndio.git synced 2024-02-18 04:45:21 -06:00

merge (make files continuous stream)

This commit is contained in:
Alexandre Ratchov 2016-05-28 11:21:24 +02:00
parent 105937ab11
commit 8ceee9aeff
3 changed files with 173 additions and 79 deletions

View File

@ -158,14 +158,13 @@ slot_log(struct slot *s)
static void
slot_flush(struct slot *s)
{
int todo, count, n;
int count, n;
unsigned char *data;
todo = s->buf.used;
while (todo > 0) {
for (;;) {
data = abuf_rgetblk(&s->buf, &count);
if (count > todo)
count = todo;
if (count == 0)
break;
n = afile_write(&s->afile, data, count);
if (n == 0) {
slot_log(s);
@ -174,21 +173,19 @@ slot_flush(struct slot *s)
return;
}
abuf_rdiscard(&s->buf, n);
todo -= n;
}
}
static void
slot_fill(struct slot *s)
{
int todo, count, n;
int count, n;
unsigned char *data;
todo = s->buf.len;
while (todo > 0) {
for (;;) {
data = abuf_wgetblk(&s->buf, &count);
if (count > todo)
count = todo;
if (count == 0)
break;
n = afile_read(&s->afile, data, count);
if (n == 0) {
#ifdef DEBUG
@ -201,7 +198,6 @@ slot_fill(struct slot *s)
break;
}
abuf_wcommit(&s->buf, n);
todo -= n;
}
}
@ -275,7 +271,7 @@ slot_init(struct slot *s)
}
#endif
s->bpf = s->afile.par.bps * (s->cmax - s->cmin + 1);
s->round = (dev_round * s->afile.rate + dev_rate / 2) / dev_rate;
s->round = (dev_round * s->afile.rate + dev_rate - 1) / dev_rate;
bufsz = s->round * (dev_bufsz / dev_round);
bufsz -= bufsz % s->round;
@ -315,7 +311,7 @@ slot_init(struct slot *s)
xmalloc(s->round * slot_nch * sizeof(adata_t));
}
if (s->afile.rate != dev_rate) {
resamp_init(&s->resamp, s->round, dev_round,
resamp_init(&s->resamp, s->afile.rate, dev_rate,
slot_nch);
s->resampbuf =
xmalloc(dev_round * slot_nch * sizeof(adata_t));
@ -334,7 +330,7 @@ slot_init(struct slot *s)
s->cmin, s->cmax,
s->cmin, s->cmax);
if (s->afile.rate != dev_rate) {
resamp_init(&s->resamp, dev_round, s->round,
resamp_init(&s->resamp, dev_rate, s->afile.rate,
slot_nch);
s->resampbuf =
xmalloc(dev_round * slot_nch * sizeof(adata_t));
@ -427,37 +423,47 @@ slot_del(struct slot *s)
}
static int
play_filt_resamp(struct slot *s, void *res_in, void *out, int todo)
slot_ocnt(struct slot *s, int icnt)
{
return s->resampbuf ? resamp_ocnt(&s->resamp, icnt) : icnt;
}
static int
slot_icnt(struct slot *s, int ocnt)
{
return s->resampbuf ? resamp_icnt(&s->resamp, ocnt) : ocnt;
}
static void
play_filt_resamp(struct slot *s, void *res_in, void *out, int icnt, int ocnt)
{
int i, offs, vol, nch;
void *in;
if (s->resampbuf) {
todo = resamp_do(&s->resamp,
res_in, s->resampbuf, todo);
resamp_do(&s->resamp, res_in, s->resampbuf, icnt, ocnt);
in = s->resampbuf;
} else
in = res_in;
nch = s->cmap.nch;
vol = s->vol / s->join; /* XXX */
cmap_add(&s->cmap, in, out, vol, todo);
cmap_add(&s->cmap, in, out, vol, ocnt);
offs = 0;
for (i = s->join - 1; i > 0; i--) {
offs += nch;
cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, todo);
cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, ocnt);
}
offs = 0;
for (i = s->expand - 1; i > 0; i--) {
offs += nch;
cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, todo);
cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, ocnt);
}
return todo;
}
static int
play_filt_dec(struct slot *s, void *in, void *out, int todo)
static void
play_filt_dec(struct slot *s, void *in, void *out, int icnt, int ocnt)
{
void *tmp;
@ -465,20 +471,21 @@ play_filt_dec(struct slot *s, void *in, void *out, int todo)
if (tmp) {
switch (s->afile.fmt) {
case AFILE_FMT_PCM:
dec_do(&s->conv, in, tmp, todo);
dec_do(&s->conv, in, tmp, icnt);
break;
case AFILE_FMT_ULAW:
dec_do_ulaw(&s->conv, in, tmp, todo, 0);
dec_do_ulaw(&s->conv, in, tmp, icnt, 0);
break;
case AFILE_FMT_ALAW:
dec_do_ulaw(&s->conv, in, tmp, todo, 1);
dec_do_ulaw(&s->conv, in, tmp, icnt, 1);
break;
case AFILE_FMT_FLOAT:
dec_do_float(&s->conv, in, tmp, todo);
dec_do_float(&s->conv, in, tmp, icnt);
break;
}
}
return play_filt_resamp(s, tmp ? tmp : in, out, todo);
} else
tmp = in;
play_filt_resamp(s, tmp, out, icnt, ocnt);
}
/*
@ -490,25 +497,32 @@ static int
slot_mix_badd(struct slot *s, adata_t *odata)
{
adata_t *idata;
int icount, todo, done;
int len, icnt, ocnt, otodo, odone;
idata = (adata_t *)abuf_rgetblk(&s->buf, &icount);
todo = icount / s->bpf;
if (todo > s->round)
todo = s->round;
#ifdef DEBUG
if (todo == 0) {
log_puts("slot_mix_badd: not enough data\n");
panic();
odone = 0;
otodo = dev_round;
while (otodo > 0) {
idata = (adata_t *)abuf_rgetblk(&s->buf, &len);
icnt = len / s->bpf;
ocnt = slot_ocnt(s, icnt);
if (ocnt > otodo) {
ocnt = otodo;
icnt = slot_icnt(s, ocnt);
}
if (icnt == 0)
break;
play_filt_dec(s, idata, odata, icnt, ocnt);
abuf_rdiscard(&s->buf, icnt * s->bpf);
otodo -= ocnt;
odone += ocnt;
odata += ocnt * dev_pchan;
}
#endif
done = play_filt_dec(s, idata, odata, todo);
abuf_rdiscard(&s->buf, todo * s->bpf);
return done;
return odone;
}
static int
rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo)
static void
rec_filt_resamp(struct slot *s, void *in, void *res_out, int icnt, int ocnt)
{
int i, vol, offs, nch;
void *out = res_out;
@ -517,35 +531,33 @@ rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo)
nch = s->cmap.nch;
vol = ADATA_UNIT / s->join;
cmap_copy(&s->cmap, in, out, vol, todo);
cmap_copy(&s->cmap, in, out, vol, icnt);
offs = 0;
for (i = s->join - 1; i > 0; i--) {
offs += nch;
cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, todo);
cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, icnt);
}
offs = 0;
for (i = s->expand - 1; i > 0; i--) {
offs += nch;
cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, todo);
cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, icnt);
}
if (s->resampbuf) {
todo = resamp_do(&s->resamp,
s->resampbuf, res_out, todo);
}
return todo;
if (s->resampbuf)
resamp_do(&s->resamp, s->resampbuf, res_out, icnt, ocnt);
else
ocnt = icnt;
}
static int
rec_filt_enc(struct slot *s, void *in, void *out, int todo)
static void
rec_filt_enc(struct slot *s, void *in, void *out, int icnt, int ocnt)
{
void *tmp;
tmp = s->convbuf;
todo = rec_filt_resamp(s, in, tmp ? tmp : out, todo);
rec_filt_resamp(s, in, tmp ? tmp : out, icnt, ocnt);
if (tmp)
enc_do(&s->conv, tmp, out, todo);
return todo;
enc_do(&s->conv, tmp, out, ocnt);
}
/*
@ -553,20 +565,27 @@ rec_filt_enc(struct slot *s, void *in, void *out, int todo)
* but not more than a block.
*/
static void
slot_sub_bcopy(struct slot *s, adata_t *idata, int todo)
slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo)
{
adata_t *odata;
int ocount;
int len, icnt, ocnt;
odata = (adata_t *)abuf_wgetblk(&s->buf, &ocount);
#ifdef DEBUG
if (ocount < s->round * s->bpf) {
log_puts("slot_sub_bcopy: not enough space\n");
panic();
while (itodo > 0) {
odata = (adata_t *)abuf_wgetblk(&s->buf, &len);
ocnt = len / s->bpf;
icnt = slot_icnt(s, ocnt);
if (icnt > itodo) {
icnt = itodo;
ocnt = slot_ocnt(s, icnt);
}
if (ocnt == 0)
break;
rec_filt_enc(s, idata, odata, icnt, ocnt);
abuf_wcommit(&s->buf, ocnt * s->bpf);
itodo -= icnt;
idata += icnt * dev_rchan;
}
#endif
ocount = rec_filt_enc(s, idata, odata, todo);
abuf_wcommit(&s->buf, ocount * s->bpf);
}
static int
@ -959,9 +978,11 @@ slot_list_iodo(void)
for (s = slot_list; s != NULL; s = s->next) {
if (s->pstate != SLOT_RUN)
continue;
if ((s->mode & SIO_PLAY) && (s->buf.used == 0))
if ((s->mode & SIO_PLAY) &&
(s->buf.used < s->round * s->bpf))
slot_fill(s);
if ((s->mode & SIO_REC) && (s->buf.used == s->buf.len))
if ((s->mode & SIO_REC) &&
(s->buf.len - s->buf.used < s->round * s->bpf))
slot_flush(s);
}
}

View File

@ -268,10 +268,38 @@ aparams_native(struct aparams *par)
}
/*
* resample the given number of frames
* return the number of output frames resamp_do() would produce with
* the given number of input frames
*/
int
resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo)
resamp_ocnt(struct resamp *p, int icnt)
{
return ((long long)p->oblksz * icnt + p->diff) / p->iblksz;
}
/*
* return the number of input frames resamp_do() needs in order to
* produce the given number of output frames
*/
int
resamp_icnt(struct resamp *p, int ocnt)
{
return ((long long)p->iblksz * ocnt - p->diff +
p->oblksz - 1) / p->oblksz;
}
/*
* Resample the given number of frames. The number of output frames
* must match the coresponding number the input frames. Either
* use:
*
* icnt * orate = ocnt * irate
*
* or use resamp_icnt() or resamp_ocnt() to calculate the proper
* numbers.
*/
void
resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt)
{
unsigned int nch;
adata_t *idata;
@ -298,8 +326,8 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo)
ctxbuf = p->ctx;
ctx_start = p->ctx_start;
nch = p->nch;
ifr = todo;
ofr = oblksz;
ifr = icnt;
ofr = ocnt;
/*
* Start conversion.
@ -307,9 +335,11 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo)
#ifdef DEBUG
if (log_level >= 4) {
log_puts("resamp: copying ");
log_puti(todo);
log_puti(ifr);
log_puts(" -> ");
log_putu(ofr);
log_puts(" frames, diff = ");
log_putu(diff);
log_puti(diff);
log_puts("\n");
}
#endif
@ -359,7 +389,33 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo)
}
p->diff = diff;
p->ctx_start = ctx_start;
return oblksz - ofr;
#ifdef DEBUG
if (ifr != 0) {
log_puts("resamp_do: ");
log_puti(ifr);
log_puts(": too many input frames\n");
panic();
}
if (ofr != 0) {
log_puts("resamp_do: ");
log_puti(ofr);
log_puts(": too many output frames\n");
panic();
}
#endif
}
static unsigned int
uint_gcd(unsigned int a, unsigned int b)
{
unsigned int r;
while (b > 0) {
r = a % b;
a = b;
b = r;
}
return a;
}
/*
@ -369,7 +425,22 @@ void
resamp_init(struct resamp *p, unsigned int iblksz,
unsigned int oblksz, int nch)
{
unsigned int i;
unsigned int i, g;
/*
* reduice iblksz/oblksz fraction
*/
g = uint_gcd(iblksz, oblksz);
iblksz /= g;
oblksz /= g;
/*
* ensure weired rates dont cause integer overflows
*/
while (iblksz > ADATA_UNIT || oblksz > ADATA_UNIT) {
iblksz >>= 1;
oblksz >>= 1;
}
p->iblksz = iblksz;
p->oblksz = oblksz;

View File

@ -147,7 +147,9 @@ int aparams_strtoenc(struct aparams *, char *);
int aparams_enctostr(struct aparams *, char *);
int aparams_native(struct aparams *);
int resamp_do(struct resamp *, adata_t *, adata_t *, int);
int resamp_ocnt(struct resamp *, int);
int resamp_icnt(struct resamp *, int);
void resamp_do(struct resamp *, adata_t *, adata_t *, int, int);
void resamp_init(struct resamp *, unsigned int, unsigned int, int);
void enc_do(struct conv *, unsigned char *, unsigned char *, int);
void enc_sil_do(struct conv *, unsigned char *, int);