diff --git a/sndiod/abuf.c b/sndiod/abuf.c index 7068312..bd8cc54 100644 --- a/sndiod/abuf.c +++ b/sndiod/abuf.c @@ -43,11 +43,10 @@ abuf_log(struct abuf *buf) #endif void -abuf_init(struct abuf *buf, unsigned int len, unsigned int bpf) +abuf_init(struct abuf *buf, unsigned int len) { - buf->data = xmalloc((size_t)len * bpf); + buf->data = xmalloc(len); buf->len = len; - buf->bpf = bpf; buf->used = 0; buf->start = 0; } @@ -80,7 +79,7 @@ abuf_rgetblk(struct abuf *buf, int *rsize) if (count > buf->used) count = buf->used; *rsize = count; - return buf->data + buf->start * buf->bpf; + return buf->data + buf->start; } /* @@ -136,5 +135,5 @@ abuf_wgetblk(struct abuf *buf, int *rsize) if (count > avail) count = avail; *rsize = count; - return buf->data + end * buf->bpf; + return buf->data + end; } diff --git a/sndiod/abuf.h b/sndiod/abuf.h index b89acff..84b67ee 100644 --- a/sndiod/abuf.h +++ b/sndiod/abuf.h @@ -18,14 +18,13 @@ #define ABUF_H struct abuf { - int bpf; /* bytes per frames */ int start; /* offset (frames) where stored data starts */ int used; /* frames stored in the buffer */ int len; /* total size of the buffer (frames) */ unsigned char *data; }; -void abuf_init(struct abuf *, unsigned int, unsigned int); +void abuf_init(struct abuf *, unsigned int); void abuf_done(struct abuf *); void abuf_log(struct abuf *); unsigned char *abuf_rgetblk(struct abuf *, int *); diff --git a/sndiod/dev.c b/sndiod/dev.c index 51c6b7c..76cb046 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -481,14 +481,14 @@ dev_midi_exit(void *arg) void slot_mix_drop(struct slot *s) { - while (s->mix.drop > 0 && s->mix.buf.used >= s->round) { + while (s->mix.drop > 0 && s->mix.buf.used >= s->round * s->mix.bpf) { #ifdef DEBUG if (log_level >= 4) { slot_log(s); log_puts(": dropped a play block\n"); } #endif - abuf_rdiscard(&s->mix.buf, s->round); + abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf); s->mix.drop--; } } @@ -501,7 +501,7 @@ slot_sub_sil(struct slot *s) while (s->sub.silence > 0) { data = abuf_wgetblk(&s->sub.buf, &count); - if (count < s->round) + if (count < s->round * s->sub.bpf) break; #ifdef DEBUG if (log_level >= 4) { @@ -512,8 +512,8 @@ slot_sub_sil(struct slot *s) if (s->sub.encbuf) enc_sil_do(&s->sub.enc, data, s->round); else - memset(data, 0, s->round * s->sub.buf.bpf); - abuf_wcommit(&s->sub.buf, s->round); + memset(data, 0, s->round * s->sub.bpf); + abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf); s->sub.silence--; } } @@ -594,20 +594,18 @@ dev_mix_badd(struct dev *d, struct slot *s) odata = DEV_PBUF(d); idata = (adata_t *)abuf_rgetblk(&s->mix.buf, &icount); #ifdef DEBUG - if (icount < s->round && s->pstate != SLOT_STOP) { + if (icount < s->round * s->mix.bpf) { slot_log(s); log_puts(": not enough data to mix ("); log_putu(icount); log_puts(" of "); - log_putu(d->round); + log_putu(d->round * s->mix.bpf); log_puts(")\n"); panic(); } #endif - if (icount > s->round) - icount = s->round; - play_filt_dec(s, idata, odata, icount); - abuf_rdiscard(&s->mix.buf, icount); + play_filt_dec(s, idata, odata, s->round); + abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf); } void @@ -649,7 +647,12 @@ dev_mix_cycle(struct dev *d) ps = &s->next; continue; } - if (s->pstate == SLOT_STOP && s->mix.buf.used == 0) { + if (s->mix.buf.used < s->round * s->mix.bpf && + s->pstate == SLOT_STOP) { + /* + * partial blocks are zero-filled by socket + * layer + */ s->pstate = SLOT_INIT; abuf_done(&s->mix.buf); if (s->mix.decbuf) @@ -660,7 +663,8 @@ dev_mix_cycle(struct dev *d) *ps = s->next; continue; } - if (s->mix.buf.used < s->round && !(s->pstate == SLOT_STOP)) { + if (s->mix.buf.used < s->round * s->mix.bpf && + !(s->pstate == SLOT_STOP)) { if (s->xrun == XRUN_IGNORE) { if (s->mode & MODE_RECMASK) s->sub.silence--; @@ -803,13 +807,13 @@ dev_sub_bcopy(struct dev *d, struct slot *s) idata = (s->mode & MODE_MON) ? DEV_PBUF(d) : d->rbuf; odata = (adata_t *)abuf_wgetblk(&s->sub.buf, &ocount); #ifdef DEBUG - if (ocount < s->round) { + if (ocount < s->round * s->sub.bpf) { log_puts("dev_sub_bcopy: not enough space\n"); panic(); } #endif ocount = rec_filt_enc(s, idata, odata, d->round); - abuf_wcommit(&s->sub.buf, ocount); + abuf_wcommit(&s->sub.buf, ocount * s->sub.bpf); } void @@ -837,7 +841,7 @@ dev_sub_cycle(struct dev *d) ps = &s->next; continue; } - if (s->sub.buf.len - s->sub.buf.used < s->round) { + if (s->sub.buf.len - s->sub.buf.used < s->round * s->sub.bpf) { if (s->xrun == XRUN_IGNORE) { if (s->mode & MODE_PLAY) s->mix.drop--; @@ -1812,8 +1816,9 @@ slot_start(struct slot *s) log_puts("\n"); } #endif - abuf_init(&s->mix.buf, bufsz, - s->par.bps * (s->mix.slot_cmax - s->mix.slot_cmin + 1)); + s->mix.bpf = s->par.bps * + (s->mix.slot_cmax - s->mix.slot_cmin + 1); + abuf_init(&s->mix.buf, bufsz * s->mix.bpf); } if (s->mode & MODE_RECMASK) { #ifdef DEBUG @@ -1826,8 +1831,9 @@ slot_start(struct slot *s) log_puts("\n"); } #endif - abuf_init(&s->sub.buf, bufsz, - s->par.bps * (s->sub.slot_cmax - s->sub.slot_cmin + 1)); + s->sub.bpf = s->par.bps * + (s->sub.slot_cmax - s->sub.slot_cmin + 1); + abuf_init(&s->sub.buf, bufsz * s->sub.bpf); } s->mix.weight = MIDI_TO_ADATA(MIDI_MAXCTL); #ifdef DEBUG diff --git a/sndiod/dev.h b/sndiod/dev.h index a5d9471..a2bbb0e 100644 --- a/sndiod/dev.h +++ b/sndiod/dev.h @@ -53,6 +53,7 @@ struct slot { unsigned int vol; /* volume within the vol */ int drop; /* to drop on next read */ struct abuf buf; /* socket side buffer */ + int bpf; /* byte per frame */ int slot_cmin, slot_cmax; /* slot source chans */ int dev_cmin, dev_cmax; /* device destination chans */ struct cmap cmap; /* channel mapper state */ @@ -65,6 +66,7 @@ struct slot { struct { int silence; /* to add on next write */ struct abuf buf; /* socket side buffer */ + int bpf; /* byte per frame */ int slot_cmin, slot_cmax; /* slot destination chans */ int dev_cmin, dev_cmax; /* device source chans */ struct cmap cmap; /* channel mapper state */ diff --git a/sndiod/midi.c b/sndiod/midi.c index 1218084..922ded0 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -130,10 +130,10 @@ midi_new(struct midiops *ops, void *arg, int mode) * to client input */ if (ep->mode & MODE_MIDIOUT) { - abuf_init(&ep->ibuf, MIDI_BUFSZ, 1); + abuf_init(&ep->ibuf, MIDI_BUFSZ); } if (ep->mode & MODE_MIDIIN) { - abuf_init(&ep->obuf, MIDI_BUFSZ, 1); + abuf_init(&ep->obuf, MIDI_BUFSZ); } return ep; } diff --git a/sndiod/sock.c b/sndiod/sock.c index 076e580..ee64d67 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -184,7 +184,7 @@ sock_slot_flush(void *arg) struct sock *f = arg; struct slot *s = f->slot; - f->wmax += s->round * s->sub.buf.bpf; + f->wmax += s->round * s->sub.bpf; #ifdef DEBUG if (log_level >= 4) { sock_log(f); @@ -527,7 +527,7 @@ sock_rdata(struct sock *f) * XXX: this can happen in MIDIOUT mode, since we dont * have flow control */ - if (count * buf->bpf < f->rtodo) { + if (count < f->rtodo) { sock_log(f); log_puts(": data read buffer overrun\n"); panic(); @@ -545,7 +545,7 @@ sock_rdata(struct sock *f) * XXX: commit data earlier, don't sacrify a full block in case * of xrun */ - abuf_wcommit(buf, f->rsize / buf->bpf); + abuf_wcommit(buf, f->rsize); f->rtodo = 0; #ifdef DEBUG if (log_level >= 4) { @@ -611,7 +611,7 @@ sock_wdata(struct sock *f) return 0; } if (f->pstate != SOCK_STOP) { - abuf_rdiscard(buf, f->wsize / buf->bpf); + abuf_rdiscard(buf, f->wsize); if (f->slot) slot_read(f->slot); } @@ -960,6 +960,7 @@ sock_execmsg(struct sock *f) struct slot *s = f->slot; struct amsg *m = &f->rmsg; unsigned int size, ctl; + unsigned char *data; switch (ntohl(m->cmd)) { case AMSG_DATA: @@ -991,7 +992,7 @@ sock_execmsg(struct sock *f) return 0; } size = ntohl(m->u.data.size); - if (s != NULL && size % s->mix.buf.bpf != 0) { + if (s != NULL && size % s->mix.bpf != 0) { #ifdef DEBUG if (log_level >= 1) { sock_log(f); @@ -1020,7 +1021,7 @@ sock_execmsg(struct sock *f) if (s != NULL) { f->ralign -= size; if (f->ralign == 0) - f->ralign = s->round * s->mix.buf.bpf; + f->ralign = s->round * s->mix.bpf; } if (f->rtodo > f->rmax) { #ifdef DEBUG @@ -1071,11 +1072,11 @@ sock_execmsg(struct sock *f) if (s->mode & MODE_PLAY) { f->fillpending = -(int)s->dev->bufsz * (int)s->round / (int)s->dev->round; - f->ralign = s->round * s->mix.buf.bpf; - f->rmax = SLOT_BUFSZ(s) * s->mix.buf.bpf; + f->ralign = s->round * s->mix.bpf; + f->rmax = SLOT_BUFSZ(s) * s->mix.bpf; } if (s->mode & MODE_RECMASK) { - f->walign = s->round * s->sub.buf.bpf; + f->walign = s->round * s->sub.bpf; f->wmax = 0; } f->pstate = SOCK_START; @@ -1129,7 +1130,20 @@ sock_execmsg(struct sock *f) f->pstate = SOCK_STOP; f->rstate = SOCK_RMSG; f->rtodo = sizeof(struct amsg); - slot_stop(s); + if (s->mode & MODE_PLAY) { + data = abuf_wgetblk(&s->mix.buf, &size); +#ifdef DEBUG + if (size < f->ralign) { + sock_log(f); + log_puts(": unaligned stop\n"); + panic(); + } +#endif + memset(data, 0, f->ralign); + abuf_wcommit(&s->mix.buf, f->ralign); + f->ralign = 0; + } + slot_stop(s); break; case AMSG_SETPAR: #ifdef DEBUG @@ -1357,7 +1371,7 @@ sock_buildmsg(struct sock *f) f->wmsg.u.ts.delta = htonl(f->fillpending); size = f->fillpending; if (f->slot) - size *= f->slot->mix.buf.bpf; + size *= f->slot->mix.bpf; f->rmax += size; f->wtodo = sizeof(struct amsg); f->wstate = SOCK_WMSG; @@ -1404,7 +1418,8 @@ sock_buildmsg(struct sock *f) * If data available, build a DATA message. */ if (f->slot != NULL && f->slot->sub.buf.used > 0 && f->wmax > 0) { - size = f->slot->sub.buf.used * f->slot->sub.buf.bpf; + /* XXX: round to bpf */ + size = f->slot->sub.buf.used; if (size > AMSG_DATAMAX) size = AMSG_DATAMAX; if (size > f->walign) @@ -1421,7 +1436,7 @@ sock_buildmsg(struct sock *f) f->walign -= size; f->wmax -= size; if (f->walign == 0) - f->walign = f->slot->round * f->slot->sub.buf.bpf; + f->walign = f->slot->round * f->slot->sub.bpf; #ifdef DEBUG if (log_level >= 4) { sock_log(f);