Annotation of src/usr.bin/aucat/aproc.c, Revision 1.51
1.51 ! ratchov 1: /* $OpenBSD: aproc.c,v 1.50 2010/04/03 17:59:17 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: /*
18: * aproc structures are simple audio processing units. They are
19: * interconnected by abuf structures and form a kind of circuit. aproc
20: * structure have call-backs that do the actual processing.
21: *
22: * This module implements the following processing units:
23: *
24: * - rpipe: read end of an unix file (pipe, socket, device...)
25: *
26: * - wpipe: write end of an unix file (pipe, socket, device...)
27: *
28: * - mix: mix N inputs -> 1 output
29: *
30: * - sub: from 1 input -> extract/copy N outputs
31: *
32: * - conv: converts/resamples/remaps a single stream
33: *
1.15 ratchov 34: * - resamp: resample streams in native format
35: *
1.1 ratchov 36: */
37: #include <err.h>
38: #include <stdlib.h>
39: #include <string.h>
40:
1.33 ratchov 41: #include "abuf.h"
1.1 ratchov 42: #include "aparams.h"
43: #include "aproc.h"
1.33 ratchov 44: #include "conf.h"
1.1 ratchov 45: #include "file.h"
1.38 ratchov 46: #include "midi.h"
1.42 ratchov 47: #ifdef DEBUG
48: #include "dbg.h"
49: #endif
50:
1.51 ! ratchov 51: /*
! 52: * Same as ABUF_ROK(), but consider that a buffer is
! 53: * readable if there's silence pending to be inserted
! 54: */
! 55: #define MIX_ROK(buf) (ABUF_ROK(buf) || (buf)->r.mix.drop < 0)
! 56:
! 57: /*
! 58: * Same as ABUF_WOK(), but consider that a buffer is
! 59: * writeable if there are samples to drop
! 60: */
! 61: #define SUB_WOK(buf) (ABUF_WOK(buf) || (buf)->w.sub.silence < 0)
! 62:
1.42 ratchov 63: #ifdef DEBUG
64: void
65: aproc_dbg(struct aproc *p)
66: {
67: dbg_puts(p->ops->name);
68: dbg_puts("(");
69: dbg_puts(p->name);
70: dbg_puts(")");
71: }
72:
73: int
74: zomb_in(struct aproc *p, struct abuf *ibuf)
75: {
76: aproc_dbg(p);
77: dbg_puts(": in: terminated\n");
78: dbg_panic();
79: return 0;
80: }
81:
1.1 ratchov 82:
1.42 ratchov 83: int
84: zomb_out(struct aproc *p, struct abuf *obuf)
85: {
86: aproc_dbg(p);
87: dbg_puts(": out: terminated\n");
88: dbg_panic();
89: return 0;
90: }
91:
92: void
93: zomb_eof(struct aproc *p, struct abuf *ibuf)
94: {
95: aproc_dbg(p);
96: dbg_puts(": eof: terminated\n");
97: dbg_panic();
98: }
99:
100: void
101: zomb_hup(struct aproc *p, struct abuf *obuf)
102: {
103: aproc_dbg(p);
104: dbg_puts(": hup: terminated\n");
105: dbg_panic();
106: }
107:
108: void
109: zomb_newin(struct aproc *p, struct abuf *ibuf)
110: {
111: aproc_dbg(p);
112: dbg_puts(": newin: terminated\n");
113: dbg_panic();
114: }
115:
116: void
117: zomb_newout(struct aproc *p, struct abuf *obuf)
118: {
119: aproc_dbg(p);
120: dbg_puts(": newout: terminated\n");
121: dbg_panic();
122: }
123:
124: void
125: zomb_ipos(struct aproc *p, struct abuf *ibuf, int delta)
126: {
127: aproc_dbg(p);
128: dbg_puts(": ipos: terminated\n");
129: dbg_panic();
130: }
131:
132: void
133: zomb_opos(struct aproc *p, struct abuf *obuf, int delta)
134: {
135: aproc_dbg(p);
136: dbg_puts(": opos: terminated\n");
137: dbg_panic();
138: }
139:
140: struct aproc_ops zomb_ops = {
141: "zomb",
142: zomb_in,
143: zomb_out,
144: zomb_eof,
145: zomb_hup,
146: zomb_newin,
147: zomb_newout,
148: zomb_ipos,
149: zomb_opos,
150: NULL
151: };
152: #endif
1.34 ratchov 153:
1.1 ratchov 154: struct aproc *
155: aproc_new(struct aproc_ops *ops, char *name)
156: {
157: struct aproc *p;
158:
159: p = malloc(sizeof(struct aproc));
160: if (p == NULL)
161: err(1, name);
162: LIST_INIT(&p->ibuflist);
163: LIST_INIT(&p->obuflist);
164: p->name = name;
165: p->ops = ops;
1.30 ratchov 166: p->refs = 0;
1.38 ratchov 167: p->flags = 0;
1.1 ratchov 168: return p;
169: }
170:
171: void
172: aproc_del(struct aproc *p)
173: {
1.12 ratchov 174: struct abuf *i;
175:
1.38 ratchov 176: if (!(p->flags & APROC_ZOMB)) {
1.42 ratchov 177: #ifdef DEBUG
178: if (debug_level >= 3) {
179: aproc_dbg(p);
180: dbg_puts(": terminating...\n");
181: }
182: #endif
1.35 ratchov 183: if (p->ops->done) {
1.42 ratchov 184: #ifdef DEBUG
185: if (debug_level >= 3) {
186: aproc_dbg(p);
187: dbg_puts(": done\n");
188: }
189: #endif
1.35 ratchov 190: p->ops->done(p);
191: }
192: while (!LIST_EMPTY(&p->ibuflist)) {
193: i = LIST_FIRST(&p->ibuflist);
194: abuf_hup(i);
195: }
196: while (!LIST_EMPTY(&p->obuflist)) {
197: i = LIST_FIRST(&p->obuflist);
198: abuf_eof(i);
199: }
1.38 ratchov 200: p->flags |= APROC_ZOMB;
1.34 ratchov 201: }
1.35 ratchov 202: if (p->refs > 0) {
1.42 ratchov 203: #ifdef DEBUG
204: if (debug_level >= 3) {
205: aproc_dbg(p);
206: dbg_puts(": free delayed\n");
207: p->ops = &zomb_ops;
208: }
209: #endif
1.35 ratchov 210: return;
1.12 ratchov 211: }
1.42 ratchov 212: #ifdef DEBUG
213: if (debug_level >= 3) {
214: aproc_dbg(p);
215: dbg_puts(": freed\n");
216: }
217: #endif
1.1 ratchov 218: free(p);
219: }
220:
221: void
222: aproc_setin(struct aproc *p, struct abuf *ibuf)
223: {
224: LIST_INSERT_HEAD(&p->ibuflist, ibuf, ient);
225: ibuf->rproc = p;
226: if (p->ops->newin)
227: p->ops->newin(p, ibuf);
228: }
229:
230: void
231: aproc_setout(struct aproc *p, struct abuf *obuf)
232: {
233: LIST_INSERT_HEAD(&p->obuflist, obuf, oent);
234: obuf->wproc = p;
235: if (p->ops->newout)
236: p->ops->newout(p, obuf);
237: }
238:
1.12 ratchov 239: void
240: aproc_ipos(struct aproc *p, struct abuf *ibuf, int delta)
241: {
242: struct abuf *obuf;
243:
244: LIST_FOREACH(obuf, &p->obuflist, oent) {
245: abuf_ipos(obuf, delta);
246: }
247: }
248:
249: void
250: aproc_opos(struct aproc *p, struct abuf *obuf, int delta)
251: {
252: struct abuf *ibuf;
253:
254: LIST_FOREACH(ibuf, &p->ibuflist, ient) {
255: abuf_opos(ibuf, delta);
256: }
257: }
258:
1.1 ratchov 259: int
1.28 ratchov 260: aproc_inuse(struct aproc *p)
261: {
262: struct abuf *i;
263:
264: LIST_FOREACH(i, &p->ibuflist, ient) {
265: if (i->inuse)
266: return 1;
267: }
268: LIST_FOREACH(i, &p->obuflist, oent) {
269: if (i->inuse)
270: return 1;
271: }
272: return 0;
273: }
274:
275: int
1.32 ratchov 276: aproc_depend(struct aproc *p, struct aproc *dep)
277: {
278: struct abuf *i;
279:
280: if (p == dep)
281: return 1;
282: LIST_FOREACH(i, &p->ibuflist, ient) {
283: if (i->wproc && aproc_depend(i->wproc, dep))
284: return 1;
285: }
286: return 0;
287: }
288:
289: int
1.51 ! ratchov 290: rfile_do(struct aproc *p, unsigned todo, unsigned *done)
! 291: {
! 292: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 293: struct file *f = p->u.io.file;
! 294: unsigned char *data;
! 295: unsigned n, count, off;
! 296:
! 297: off = p->u.io.partial;
! 298: data = abuf_wgetblk(obuf, &count, 0);
! 299: if (count > todo)
! 300: count = todo;
! 301: n = file_read(f, data + off, count * obuf->bpf - off);
! 302: if (n == 0)
! 303: return 0;
! 304: n += off;
! 305: p->u.io.partial = n % obuf->bpf;
! 306: count = n / obuf->bpf;
! 307: if (count > 0)
! 308: abuf_wcommit(obuf, count);
! 309: if (done)
! 310: *done = count;
! 311: return 1;
! 312: }
! 313:
! 314: int
1.50 ratchov 315: rfile_in(struct aproc *p, struct abuf *ibuf_dummy)
1.49 ratchov 316: {
317: struct abuf *obuf = LIST_FIRST(&p->obuflist);
318: struct file *f = p->u.io.file;
319:
1.51 ! ratchov 320: if (!ABUF_WOK(obuf) || !(f->state & FILE_ROK))
1.50 ratchov 321: return 0;
1.51 ! ratchov 322: if (!rfile_do(p, obuf->len, NULL))
1.12 ratchov 323: return 0;
324: if (!abuf_flush(obuf))
325: return 0;
326: return 1;
1.1 ratchov 327: }
328:
329: int
1.41 ratchov 330: rfile_out(struct aproc *p, struct abuf *obuf)
1.1 ratchov 331: {
332: struct file *f = p->u.io.file;
333:
1.32 ratchov 334: if (f->state & FILE_RINUSE)
1.12 ratchov 335: return 0;
1.51 ! ratchov 336: if (!ABUF_WOK(obuf) || !(f->state & FILE_ROK))
1.1 ratchov 337: return 0;
1.51 ! ratchov 338: if (!rfile_do(p, obuf->len, NULL))
1.12 ratchov 339: return 0;
340: return 1;
1.1 ratchov 341: }
342:
343: void
1.41 ratchov 344: rfile_done(struct aproc *p)
1.1 ratchov 345: {
346: struct file *f = p->u.io.file;
1.39 ratchov 347: struct abuf *obuf;
1.1 ratchov 348:
1.30 ratchov 349: if (f == NULL)
350: return;
1.39 ratchov 351: /*
1.51 ! ratchov 352: * disconnect from file structure
! 353: */
! 354: f->rproc = NULL;
! 355: p->u.io.file = NULL;
! 356:
! 357: /*
1.39 ratchov 358: * all buffers must be detached before deleting f->wproc,
359: * because otherwise it could trigger this code again
360: */
361: obuf = LIST_FIRST(&p->obuflist);
362: if (obuf)
363: abuf_eof(obuf);
1.37 ratchov 364: if (f->wproc) {
365: aproc_del(f->wproc);
366: } else
1.12 ratchov 367: file_del(f);
1.51 ! ratchov 368:
! 369: #ifdef DEBUG
! 370: if (debug_level >= 2 && p->u.io.partial > 0) {
! 371: aproc_dbg(p);
! 372: dbg_puts(": ");
! 373: dbg_putu(p->u.io.partial);
! 374: dbg_puts(" bytes lost in partial read\n");
! 375: }
! 376: #endif
1.1 ratchov 377: }
378:
379: void
1.41 ratchov 380: rfile_eof(struct aproc *p, struct abuf *ibuf_dummy)
1.1 ratchov 381: {
1.8 ratchov 382: aproc_del(p);
1.1 ratchov 383: }
384:
385: void
1.41 ratchov 386: rfile_hup(struct aproc *p, struct abuf *obuf)
1.1 ratchov 387: {
1.8 ratchov 388: aproc_del(p);
1.1 ratchov 389: }
390:
1.41 ratchov 391: struct aproc_ops rfile_ops = {
1.43 ratchov 392: "rfile",
1.41 ratchov 393: rfile_in,
394: rfile_out,
395: rfile_eof,
396: rfile_hup,
1.12 ratchov 397: NULL, /* newin */
398: NULL, /* newout */
399: aproc_ipos,
400: aproc_opos,
1.41 ratchov 401: rfile_done
1.1 ratchov 402: };
403:
404: struct aproc *
1.41 ratchov 405: rfile_new(struct file *f)
1.1 ratchov 406: {
407: struct aproc *p;
408:
1.41 ratchov 409: p = aproc_new(&rfile_ops, f->name);
1.1 ratchov 410: p->u.io.file = f;
1.51 ! ratchov 411: p->u.io.partial = 0;
1.31 ratchov 412: f->rproc = p;
1.1 ratchov 413: return p;
414: }
415:
416: void
1.41 ratchov 417: wfile_done(struct aproc *p)
1.1 ratchov 418: {
419: struct file *f = p->u.io.file;
1.39 ratchov 420: struct abuf *ibuf;
1.1 ratchov 421:
1.30 ratchov 422: if (f == NULL)
423: return;
1.39 ratchov 424: /*
1.51 ! ratchov 425: * disconnect from file structure
! 426: */
! 427: f->wproc = NULL;
! 428: p->u.io.file = NULL;
! 429:
! 430: /*
1.39 ratchov 431: * all buffers must be detached before deleting f->rproc,
432: * because otherwise it could trigger this code again
433: */
434: ibuf = LIST_FIRST(&p->ibuflist);
435: if (ibuf)
436: abuf_hup(ibuf);
1.37 ratchov 437: if (f->rproc) {
438: aproc_del(f->rproc);
439: } else
1.12 ratchov 440: file_del(f);
1.51 ! ratchov 441: #ifdef DEBUG
! 442: if (debug_level >= 2 && p->u.io.partial > 0) {
! 443: aproc_dbg(p);
! 444: dbg_puts(": ");
! 445: dbg_putu(p->u.io.partial);
! 446: dbg_puts(" bytes lost in partial write\n");
! 447: }
! 448: #endif
1.1 ratchov 449: }
450:
451: int
1.51 ! ratchov 452: wfile_do(struct aproc *p, unsigned todo, unsigned *done)
! 453: {
! 454: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
! 455: struct file *f = p->u.io.file;
! 456: unsigned char *data;
! 457: unsigned n, count, off;
! 458:
! 459: off = p->u.io.partial;
! 460: data = abuf_rgetblk(ibuf, &count, 0);
! 461: if (count > todo)
! 462: count = todo;
! 463: n = file_write(f, data + off, count * ibuf->bpf - off);
! 464: if (n == 0)
! 465: return 0;
! 466: n += off;
! 467: p->u.io.partial = n % ibuf->bpf;
! 468: count = n / ibuf->bpf;
! 469: if (count > 0)
! 470: abuf_rdiscard(ibuf, count);
! 471: if (done)
! 472: *done = count;
! 473: return 1;
! 474: }
! 475: int
1.50 ratchov 476: wfile_in(struct aproc *p, struct abuf *ibuf)
1.49 ratchov 477: {
478: struct file *f = p->u.io.file;
1.1 ratchov 479:
1.32 ratchov 480: if (f->state & FILE_WINUSE)
1.12 ratchov 481: return 0;
1.51 ! ratchov 482: if (!ABUF_ROK(ibuf) || !(f->state & FILE_WOK))
1.1 ratchov 483: return 0;
1.51 ! ratchov 484: if (!wfile_do(p, ibuf->len, NULL))
1.12 ratchov 485: return 0;
486: return 1;
1.1 ratchov 487: }
488:
489: int
1.41 ratchov 490: wfile_out(struct aproc *p, struct abuf *obuf_dummy)
1.1 ratchov 491: {
492: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
493: struct file *f = p->u.io.file;
494:
1.34 ratchov 495: if (!abuf_fill(ibuf))
1.12 ratchov 496: return 0;
1.51 ! ratchov 497: if (!ABUF_ROK(ibuf) || !(f->state & FILE_WOK))
1.12 ratchov 498: return 0;
1.51 ! ratchov 499: if (!wfile_do(p, ibuf->len, NULL))
1.12 ratchov 500: return 0;
1.1 ratchov 501: return 1;
502: }
503:
504: void
1.41 ratchov 505: wfile_eof(struct aproc *p, struct abuf *ibuf)
1.1 ratchov 506: {
1.8 ratchov 507: aproc_del(p);
1.1 ratchov 508: }
509:
510: void
1.41 ratchov 511: wfile_hup(struct aproc *p, struct abuf *obuf_dummy)
1.1 ratchov 512: {
1.8 ratchov 513: aproc_del(p);
1.1 ratchov 514: }
515:
1.41 ratchov 516: struct aproc_ops wfile_ops = {
1.43 ratchov 517: "wfile",
1.41 ratchov 518: wfile_in,
519: wfile_out,
520: wfile_eof,
521: wfile_hup,
1.12 ratchov 522: NULL, /* newin */
523: NULL, /* newout */
524: aproc_ipos,
525: aproc_opos,
1.41 ratchov 526: wfile_done
1.1 ratchov 527: };
528:
529: struct aproc *
1.41 ratchov 530: wfile_new(struct file *f)
1.1 ratchov 531: {
532: struct aproc *p;
533:
1.41 ratchov 534: p = aproc_new(&wfile_ops, f->name);
1.1 ratchov 535: p->u.io.file = f;
1.51 ! ratchov 536: p->u.io.partial = 0;
1.1 ratchov 537: f->wproc = p;
538: return p;
539: }
540:
541: /*
1.51 ! ratchov 542: * Drop as much as possible samples from the reader end,
! 543: * negative values mean ``insert silence''.
! 544: */
! 545: void
! 546: mix_drop(struct abuf *buf, int extra)
! 547: {
! 548: unsigned count;
! 549:
! 550: buf->r.mix.drop += extra;
! 551: while (buf->r.mix.drop > 0) {
! 552: count = buf->r.mix.drop;
! 553: if (count > buf->used)
! 554: count = buf->used;
! 555: if (count == 0) {
! 556: #ifdef DEBUG
! 557: if (debug_level >= 4) {
! 558: abuf_dbg(buf);
! 559: dbg_puts(": drop: no data\n");
! 560: }
! 561: #endif
! 562: return;
! 563: }
! 564: abuf_rdiscard(buf, count);
! 565: buf->r.mix.drop -= count;
! 566: #ifdef DEBUG
! 567: if (debug_level >= 4) {
! 568: abuf_dbg(buf);
! 569: dbg_puts(": dropped ");
! 570: dbg_putu(count);
! 571: dbg_puts(", to drop = ");
! 572: dbg_putu(buf->r.mix.drop);
! 573: dbg_puts("\n");
! 574: }
! 575: #endif
! 576: }
! 577: }
! 578:
! 579: /*
1.28 ratchov 580: * Append the given amount of silence (or less if there's not enough
1.51 ! ratchov 581: * space), and crank w.mix.todo accordingly.
1.1 ratchov 582: */
583: void
1.51 ! ratchov 584: mix_bzero(struct abuf *obuf)
1.1 ratchov 585: {
586: short *odata;
587: unsigned ocount;
588:
1.51 ! ratchov 589: odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->w.mix.todo);
! 590: if (ocount == 0)
! 591: return;
! 592: memset(odata, 0, ocount * obuf->bpf);
! 593: obuf->w.mix.todo += ocount;
1.42 ratchov 594: #ifdef DEBUG
595: if (debug_level >= 4) {
596: abuf_dbg(obuf);
597: dbg_puts(": bzero(");
1.51 ! ratchov 598: dbg_putu(obuf->w.mix.todo);
1.42 ratchov 599: dbg_puts(")\n");
600: }
601: #endif
1.1 ratchov 602: }
603:
604: /*
605: * Mix an input block over an output block.
606: */
1.51 ! ratchov 607: unsigned
1.1 ratchov 608: mix_badd(struct abuf *ibuf, struct abuf *obuf)
609: {
610: short *idata, *odata;
1.13 ratchov 611: unsigned i, j, icnt, onext, ostart;
1.51 ! ratchov 612: unsigned scount, icount, ocount;
1.23 ratchov 613: int vol;
1.1 ratchov 614:
1.42 ratchov 615: #ifdef DEBUG
616: if (debug_level >= 4) {
617: abuf_dbg(ibuf);
1.43 ratchov 618: dbg_puts(": badd: done = ");
619: dbg_putu(ibuf->r.mix.done);
620: dbg_puts("/");
1.42 ratchov 621: dbg_putu(obuf->w.mix.todo);
1.51 ! ratchov 622: dbg_puts(", drop = ");
! 623: dbg_puti(ibuf->r.mix.drop);
1.42 ratchov 624: dbg_puts("\n");
625: }
626: #endif
1.28 ratchov 627: /*
1.51 ! ratchov 628: * Insert silence for xrun correction
! 629: */
! 630: if (ibuf->r.mix.drop < 0) {
! 631: icount = -ibuf->r.mix.drop;
! 632: ocount = obuf->len - obuf->used;
! 633: if (ocount > obuf->w.mix.todo)
! 634: ocount = obuf->w.mix.todo;
! 635: scount = (icount < ocount) ? icount : ocount;
! 636: ibuf->r.mix.done += scount;
! 637: ibuf->r.mix.drop += scount;
! 638: }
! 639:
! 640: /*
1.50 ratchov 641: * Calculate the maximum we can read.
1.49 ratchov 642: */
1.50 ratchov 643: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
644: if (icount == 0)
1.51 ! ratchov 645: return 0;
1.28 ratchov 646:
647: /*
1.33 ratchov 648: * Calculate the maximum we can write.
1.28 ratchov 649: */
1.36 ratchov 650: odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->r.mix.done);
1.1 ratchov 651: if (ocount == 0)
1.51 ! ratchov 652: return 0;
1.1 ratchov 653:
1.36 ratchov 654: vol = (ibuf->r.mix.weight * ibuf->r.mix.vol) >> ADATA_SHIFT;
1.31 ratchov 655: ostart = ibuf->cmin - obuf->cmin;
1.13 ratchov 656: onext = obuf->cmax - ibuf->cmax + ostart;
657: icnt = ibuf->cmax - ibuf->cmin + 1;
658: odata += ostart;
1.1 ratchov 659: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 660: for (i = scount; i > 0; i--) {
661: for (j = icnt; j > 0; j--) {
662: *odata += (*idata * vol) >> ADATA_SHIFT;
663: idata++;
664: odata++;
665: }
666: odata += onext;
667: }
1.51 ! ratchov 668: abuf_rdiscard(ibuf, scount);
! 669: ibuf->r.mix.done += scount;
1.1 ratchov 670:
1.42 ratchov 671: #ifdef DEBUG
672: if (debug_level >= 4) {
673: abuf_dbg(ibuf);
674: dbg_puts(": badd: done = ");
675: dbg_putu(ibuf->r.mix.done);
676: dbg_puts("/");
677: dbg_putu(obuf->w.mix.todo);
678: dbg_puts("\n");
679: }
680: #endif
1.51 ! ratchov 681: return scount;
1.1 ratchov 682: }
683:
1.28 ratchov 684: /*
685: * Handle buffer underrun, return 0 if stream died.
686: */
687: int
1.51 ! ratchov 688: mix_xrun(struct aproc *p, struct abuf *i)
1.28 ratchov 689: {
1.51 ! ratchov 690: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 691: unsigned fdrop, remain;
1.31 ratchov 692:
1.36 ratchov 693: if (i->r.mix.done > 0)
1.28 ratchov 694: return 1;
1.36 ratchov 695: if (i->r.mix.xrun == XRUN_ERROR) {
1.28 ratchov 696: abuf_hup(i);
697: return 0;
698: }
1.51 ! ratchov 699: fdrop = obuf->w.mix.todo;
1.42 ratchov 700: #ifdef DEBUG
701: if (debug_level >= 3) {
702: abuf_dbg(i);
703: dbg_puts(": underrun, dropping ");
704: dbg_putu(fdrop);
705: dbg_puts(" + ");
1.51 ! ratchov 706: dbg_putu(i->r.mix.drop);
1.42 ratchov 707: dbg_puts("\n");
708: }
709: #endif
1.51 ! ratchov 710: i->r.mix.done += fdrop;
1.36 ratchov 711: if (i->r.mix.xrun == XRUN_SYNC)
1.51 ! ratchov 712: mix_drop(i, fdrop);
1.28 ratchov 713: else {
1.51 ! ratchov 714: remain = fdrop % p->u.mix.round;
! 715: if (remain)
! 716: remain = p->u.mix.round - remain;
! 717: mix_drop(i, -(int)remain);
! 718: fdrop += remain;
! 719: #ifdef DEBUG
! 720: if (debug_level >= 3) {
! 721: abuf_dbg(i);
! 722: dbg_puts(": underrun, adding ");
! 723: dbg_putu(remain);
! 724: dbg_puts("\n");
! 725: }
! 726: #endif
1.28 ratchov 727: abuf_opos(i, -(int)fdrop);
728: if (i->duplex) {
1.42 ratchov 729: #ifdef DEBUG
730: if (debug_level >= 3) {
731: abuf_dbg(i->duplex);
732: dbg_puts(": full-duplex resync\n");
733: }
734: #endif
1.51 ! ratchov 735: sub_silence(i->duplex, -(int)fdrop);
1.28 ratchov 736: abuf_ipos(i->duplex, -(int)fdrop);
737: }
738: }
739: return 1;
740: }
741:
1.1 ratchov 742: int
743: mix_in(struct aproc *p, struct abuf *ibuf)
744: {
745: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
1.28 ratchov 746: unsigned odone;
1.51 ! ratchov 747: unsigned maxwrite;
! 748: unsigned scount;
1.1 ratchov 749:
1.42 ratchov 750: #ifdef DEBUG
751: if (debug_level >= 4) {
752: aproc_dbg(p);
753: dbg_puts(": used = ");
754: dbg_putu(ibuf->used);
755: dbg_puts("/");
756: dbg_putu(ibuf->len);
1.43 ratchov 757: dbg_puts(", done = ");
758: dbg_putu(ibuf->r.mix.done);
759: dbg_puts("/");
1.42 ratchov 760: dbg_putu(obuf->w.mix.todo);
761: dbg_puts("\n");
762: }
763: #endif
1.51 ! ratchov 764: if (!MIX_ROK(ibuf))
1.1 ratchov 765: return 0;
1.51 ! ratchov 766: mix_bzero(obuf);
! 767: scount = 0;
! 768: odone = obuf->w.mix.todo;
1.28 ratchov 769: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
770: inext = LIST_NEXT(i, ient);
1.51 ! ratchov 771: if (i->r.mix.drop >= 0 && !abuf_fill(i))
1.28 ratchov 772: continue; /* eof */
1.51 ! ratchov 773: mix_drop(i, 0);
! 774: scount += mix_badd(i, obuf);
1.36 ratchov 775: if (odone > i->r.mix.done)
776: odone = i->r.mix.done;
1.28 ratchov 777: }
1.51 ! ratchov 778: if (LIST_EMPTY(&p->ibuflist) || scount == 0)
1.28 ratchov 779: return 0;
1.51 ! ratchov 780: #ifdef DEBUG
! 781: if (debug_level >= 4) {
! 782: aproc_dbg(p);
! 783: dbg_puts(": maxwrite = ");
! 784: dbg_putu(p->u.mix.maxlat);
! 785: dbg_puts(" - ");
! 786: dbg_putu(p->u.mix.lat);
! 787: dbg_puts(" = ");
! 788: dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
! 789: dbg_puts("\n");
! 790: }
! 791: #endif
! 792: maxwrite = p->u.mix.maxlat - p->u.mix.lat;
! 793: if (maxwrite > 0) {
! 794: if (odone > maxwrite)
! 795: odone = maxwrite;
! 796: p->u.mix.lat += odone;
! 797: p->u.mix.abspos += odone;
! 798: LIST_FOREACH(i, &p->ibuflist, ient) {
! 799: i->r.mix.done -= odone;
! 800: }
! 801: abuf_wcommit(obuf, odone);
! 802: obuf->w.mix.todo -= odone;
! 803: if (APROC_OK(p->u.mix.mon))
! 804: mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone);
! 805: if (!abuf_flush(obuf))
! 806: return 0; /* hup */
1.1 ratchov 807: }
808: return 1;
809: }
810:
811: int
812: mix_out(struct aproc *p, struct abuf *obuf)
813: {
814: struct abuf *i, *inext;
1.28 ratchov 815: unsigned odone;
1.51 ! ratchov 816: unsigned maxwrite;
! 817: unsigned scount;
1.1 ratchov 818:
1.42 ratchov 819: #ifdef DEBUG
820: if (debug_level >= 4) {
821: aproc_dbg(p);
822: dbg_puts(": used = ");
823: dbg_putu(obuf->used);
824: dbg_puts("/");
825: dbg_putu(obuf->len);
826: dbg_puts(", todo = ");
827: dbg_putu(obuf->w.mix.todo);
828: dbg_puts("/");
829: dbg_putu(obuf->len);
830: dbg_puts("\n");
831: }
832: #endif
1.12 ratchov 833: if (!ABUF_WOK(obuf))
1.31 ratchov 834: return 0;
1.51 ! ratchov 835: #ifdef DEBUG
! 836: if (debug_level >= 4) {
! 837: aproc_dbg(p);
! 838: dbg_puts(": maxwrite = ");
! 839: dbg_putu(p->u.mix.maxlat);
! 840: dbg_puts(" - ");
! 841: dbg_putu(p->u.mix.lat);
! 842: dbg_puts(" = ");
! 843: dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
! 844: dbg_puts("\n");
! 845: }
! 846: #endif
! 847: maxwrite = p->u.mix.maxlat - p->u.mix.lat;
! 848: mix_bzero(obuf);
! 849: scount = 0;
1.28 ratchov 850: odone = obuf->len;
1.12 ratchov 851: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 852: inext = LIST_NEXT(i, ient);
1.51 ! ratchov 853: if (i->r.mix.drop >= 0 && !abuf_fill(i))
1.28 ratchov 854: continue; /* eof */
1.51 ! ratchov 855: mix_drop(i, 0);
! 856: if (maxwrite > 0 && !MIX_ROK(i)) {
1.38 ratchov 857: if (p->flags & APROC_DROP) {
1.51 ! ratchov 858: if (!mix_xrun(p, i))
1.5 ratchov 859: continue;
860: }
1.3 ratchov 861: } else
1.51 ! ratchov 862: scount += mix_badd(i, obuf);
1.36 ratchov 863: if (odone > i->r.mix.done)
864: odone = i->r.mix.done;
1.28 ratchov 865: }
866: if (LIST_EMPTY(&p->ibuflist)) {
1.38 ratchov 867: if (p->flags & APROC_QUIT) {
1.28 ratchov 868: aproc_del(p);
869: return 0;
870: }
1.38 ratchov 871: if (!(p->flags & APROC_DROP))
1.28 ratchov 872: return 0;
1.36 ratchov 873: odone = obuf->w.mix.todo;
1.51 ! ratchov 874: p->u.mix.idle += odone;
! 875: }
! 876: if (maxwrite > 0) {
! 877: if (odone > maxwrite)
! 878: odone = maxwrite;
! 879: p->u.mix.lat += odone;
! 880: p->u.mix.abspos += odone;
! 881: LIST_FOREACH(i, &p->ibuflist, ient) {
! 882: i->r.mix.done -= odone;
! 883: }
! 884: abuf_wcommit(obuf, odone);
! 885: obuf->w.mix.todo -= odone;
! 886: if (APROC_OK(p->u.mix.mon))
! 887: mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone);
1.49 ratchov 888: }
1.51 ! ratchov 889: if (scount == 0)
1.50 ratchov 890: return 0;
1.1 ratchov 891: return 1;
892: }
893:
894: void
895: mix_eof(struct aproc *p, struct abuf *ibuf)
896: {
1.51 ! ratchov 897: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
1.28 ratchov 898: unsigned odone;
1.1 ratchov 899:
1.12 ratchov 900: mix_setmaster(p);
901:
1.28 ratchov 902: if (!aproc_inuse(p)) {
1.42 ratchov 903: #ifdef DEBUG
904: if (debug_level >= 3) {
905: aproc_dbg(p);
906: dbg_puts(": running other streams\n");
907: }
908: #endif
1.28 ratchov 909: /*
1.33 ratchov 910: * Find a blocked input.
1.28 ratchov 911: */
912: odone = obuf->len;
1.51 ! ratchov 913: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
! 914: inext = LIST_NEXT(i, ient);
! 915: if (!abuf_fill(i))
! 916: continue;
! 917: if (MIX_ROK(i) && i->r.mix.done < obuf->w.mix.todo) {
1.28 ratchov 918: abuf_run(i);
919: return;
920: }
1.36 ratchov 921: if (odone > i->r.mix.done)
922: odone = i->r.mix.done;
1.28 ratchov 923: }
924: /*
1.33 ratchov 925: * No blocked inputs. Check if output is blocked.
1.28 ratchov 926: */
1.36 ratchov 927: if (LIST_EMPTY(&p->ibuflist) || odone == obuf->w.mix.todo)
1.28 ratchov 928: abuf_run(obuf);
929: }
1.1 ratchov 930: }
931:
932: void
933: mix_hup(struct aproc *p, struct abuf *obuf)
934: {
935: aproc_del(p);
936: }
937:
938: void
939: mix_newin(struct aproc *p, struct abuf *ibuf)
940: {
1.42 ratchov 941: #ifdef DEBUG
942: struct abuf *obuf = LIST_FIRST(&p->obuflist);
943:
944: if (!obuf || ibuf->cmin < obuf->cmin || ibuf->cmax > obuf->cmax) {
945: dbg_puts("newin: channel ranges mismatch\n");
946: dbg_panic();
947: }
948: #endif
1.22 ratchov 949: p->u.mix.idle = 0;
1.36 ratchov 950: ibuf->r.mix.done = 0;
951: ibuf->r.mix.vol = ADATA_UNIT;
952: ibuf->r.mix.weight = ADATA_UNIT;
953: ibuf->r.mix.maxweight = ADATA_UNIT;
954: ibuf->r.mix.xrun = XRUN_IGNORE;
1.51 ! ratchov 955: ibuf->r.mix.drop = 0;
1.1 ratchov 956: }
957:
958: void
959: mix_newout(struct aproc *p, struct abuf *obuf)
960: {
1.42 ratchov 961: #ifdef DEBUG
962: if (debug_level >= 3) {
963: aproc_dbg(p);
964: dbg_puts(": newin, will use ");
1.51 ! ratchov 965: dbg_putu(obuf->len);
! 966: dbg_puts("\n");
1.42 ratchov 967: }
968: #endif
1.36 ratchov 969: obuf->w.mix.todo = 0;
1.1 ratchov 970: }
971:
1.12 ratchov 972: void
973: mix_opos(struct aproc *p, struct abuf *obuf, int delta)
974: {
1.51 ! ratchov 975: p->u.mix.lat -= delta;
1.42 ratchov 976: #ifdef DEBUG
977: if (debug_level >= 4) {
978: aproc_dbg(p);
979: dbg_puts(": opos: lat = ");
980: dbg_puti(p->u.mix.lat);
981: dbg_puts("/");
982: dbg_puti(p->u.mix.maxlat);
1.51 ! ratchov 983: dbg_puts("\n");
1.42 ratchov 984: }
985: #endif
1.51 ! ratchov 986: if (APROC_OK(p->u.mix.ctl))
1.38 ratchov 987: ctl_ontick(p->u.mix.ctl, delta);
1.12 ratchov 988: aproc_opos(p, obuf, delta);
1.51 ! ratchov 989: if (APROC_OK(p->u.mix.mon))
! 990: p->u.mix.mon->ops->ipos(p->u.mix.mon, NULL, delta);
1.12 ratchov 991: }
992:
1.1 ratchov 993: struct aproc_ops mix_ops = {
1.12 ratchov 994: "mix",
995: mix_in,
996: mix_out,
997: mix_eof,
998: mix_hup,
999: mix_newin,
1000: mix_newout,
1001: aproc_ipos,
1002: mix_opos,
1003: NULL
1.1 ratchov 1004: };
1005:
1006: struct aproc *
1.51 ! ratchov 1007: mix_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
1.1 ratchov 1008: {
1009: struct aproc *p;
1010:
1.12 ratchov 1011: p = aproc_new(&mix_ops, name);
1.22 ratchov 1012: p->u.mix.idle = 0;
1.12 ratchov 1013: p->u.mix.lat = 0;
1.51 ! ratchov 1014: p->u.mix.round = round;
1.12 ratchov 1015: p->u.mix.maxlat = maxlat;
1.51 ! ratchov 1016: p->u.mix.abspos = 0;
1.38 ratchov 1017: p->u.mix.ctl = ctl;
1.1 ratchov 1018: return p;
1.10 ratchov 1019: }
1020:
1021: /*
1.33 ratchov 1022: * Normalize input levels.
1.10 ratchov 1023: */
1024: void
1025: mix_setmaster(struct aproc *p)
1026: {
1027: unsigned n;
1.40 ratchov 1028: struct abuf *i, *j;
1.24 ratchov 1029: int weight;
1.10 ratchov 1030:
1.40 ratchov 1031: /*
1032: * count the number of inputs. If a set of inputs
1033: * uses channels that have no intersection, they are
1034: * counted only once because they don't need to
1035: * share their volume
1036: */
1.10 ratchov 1037: n = 0;
1.40 ratchov 1038: LIST_FOREACH(i, &p->ibuflist, ient) {
1039: j = LIST_NEXT(i, ient);
1040: for (;;) {
1041: if (j == NULL) {
1042: n++;
1043: break;
1044: }
1045: if (i->cmin > j->cmax || i->cmax < j->cmin)
1046: break;
1047: j = LIST_NEXT(j, ient);
1048: }
1.24 ratchov 1049: }
1.40 ratchov 1050: LIST_FOREACH(i, &p->ibuflist, ient) {
1.24 ratchov 1051: weight = ADATA_UNIT / n;
1.40 ratchov 1052: if (weight > i->r.mix.maxweight)
1053: weight = i->r.mix.maxweight;
1054: i->r.mix.weight = weight;
1.42 ratchov 1055: #ifdef DEBUG
1056: if (debug_level >= 3) {
1057: abuf_dbg(i);
1058: dbg_puts(": setmaster: ");
1059: dbg_puti(i->r.mix.weight);
1060: dbg_puts("/");
1061: dbg_puti(i->r.mix.maxweight);
1062: dbg_puts("\n");
1063: }
1064: #endif
1.24 ratchov 1065: }
1.1 ratchov 1066: }
1067:
1.22 ratchov 1068: void
1069: mix_clear(struct aproc *p)
1070: {
1071: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1072:
1073: p->u.mix.lat = 0;
1.51 ! ratchov 1074: p->u.mix.abspos = 0;
1.36 ratchov 1075: obuf->w.mix.todo = 0;
1.43 ratchov 1076: }
1077:
1078: void
1079: mix_prime(struct aproc *p)
1080: {
1081: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1082: unsigned todo, count;
1083:
1084: for (;;) {
1085: if (!ABUF_WOK(obuf))
1086: break;
1.51 ! ratchov 1087: todo = p->u.mix.maxlat - p->u.mix.lat;
1.43 ratchov 1088: if (todo == 0)
1089: break;
1.51 ! ratchov 1090: mix_bzero(obuf);
1.43 ratchov 1091: count = obuf->w.mix.todo;
1092: if (count > todo)
1093: count = todo;
1094: obuf->w.mix.todo -= count;
1.51 ! ratchov 1095: p->u.mix.lat += count;
! 1096: p->u.mix.abspos += count;
1.43 ratchov 1097: abuf_wcommit(obuf, count);
1.51 ! ratchov 1098: if (APROC_OK(p->u.mix.mon))
! 1099: mon_snoop(p->u.mix.mon, obuf, 0, count);
1.43 ratchov 1100: abuf_flush(obuf);
1101: }
1102: #ifdef DEBUG
1103: if (debug_level >= 3) {
1104: aproc_dbg(p);
1105: dbg_puts(": prime: lat/maxlat=");
1106: dbg_puti(p->u.mix.lat);
1107: dbg_puts("/");
1108: dbg_puti(p->u.mix.maxlat);
1109: dbg_puts("\n");
1110: }
1111: #endif
1.22 ratchov 1112: }
1113:
1.1 ratchov 1114: /*
1.51 ! ratchov 1115: * Append as much as possible silence on the writer end
! 1116: */
! 1117: void
! 1118: sub_silence(struct abuf *buf, int extra)
! 1119: {
! 1120: unsigned char *data;
! 1121: unsigned count;
! 1122:
! 1123: buf->w.sub.silence += extra;
! 1124: if (buf->w.sub.silence > 0) {
! 1125: data = abuf_wgetblk(buf, &count, 0);
! 1126: if (count >= buf->w.sub.silence)
! 1127: count = buf->w.sub.silence;
! 1128: if (count == 0) {
! 1129: #ifdef DEBUG
! 1130: if (debug_level >= 4) {
! 1131: abuf_dbg(buf);
! 1132: dbg_puts(": no space for silence\n");
! 1133: }
! 1134: #endif
! 1135: return;
! 1136: }
! 1137: memset(data, 0, count * buf->bpf);
! 1138: abuf_wcommit(buf, count);
! 1139: buf->w.sub.silence -= count;
! 1140: #ifdef DEBUG
! 1141: if (debug_level >= 4) {
! 1142: abuf_dbg(buf);
! 1143: dbg_puts(": appended ");
! 1144: dbg_putu(count);
! 1145: dbg_puts(", remaining silence = ");
! 1146: dbg_putu(buf->w.sub.silence);
! 1147: dbg_puts("\n");
! 1148: }
! 1149: #endif
! 1150: }
! 1151: }
! 1152:
! 1153: /*
1.1 ratchov 1154: * Copy data from ibuf to obuf.
1155: */
1156: void
1157: sub_bcopy(struct abuf *ibuf, struct abuf *obuf)
1158: {
1.13 ratchov 1159: short *idata, *odata;
1160: unsigned i, j, ocnt, inext, istart;
1.1 ratchov 1161: unsigned icount, ocount, scount;
1162:
1.51 ! ratchov 1163: /*
! 1164: * Drop samples for xrun correction
! 1165: */
! 1166: if (obuf->w.sub.silence < 0) {
! 1167: scount = -obuf->w.sub.silence;
! 1168: if (scount > ibuf->used)
! 1169: scount = ibuf->used;
! 1170: obuf->w.sub.done += scount;
! 1171: obuf->w.sub.silence += scount;
! 1172: }
! 1173:
1.36 ratchov 1174: idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->w.sub.done);
1.1 ratchov 1175: if (icount == 0)
1176: return;
1.13 ratchov 1177: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1.1 ratchov 1178: if (ocount == 0)
1179: return;
1.13 ratchov 1180: istart = obuf->cmin - ibuf->cmin;
1181: inext = ibuf->cmax - obuf->cmax + istart;
1182: ocnt = obuf->cmax - obuf->cmin + 1;
1.1 ratchov 1183: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 1184: idata += istart;
1185: for (i = scount; i > 0; i--) {
1186: for (j = ocnt; j > 0; j--) {
1187: *odata = *idata;
1188: odata++;
1189: idata++;
1190: }
1191: idata += inext;
1192: }
1.51 ! ratchov 1193: abuf_wcommit(obuf, scount);
! 1194: obuf->w.sub.done += scount;
1.42 ratchov 1195: #ifdef DEBUG
1196: if (debug_level >= 4) {
1197: abuf_dbg(obuf);
1198: dbg_puts(": bcopy ");
1199: dbg_putu(scount);
1.51 ! ratchov 1200: dbg_puts("\n");
1.42 ratchov 1201: }
1202: #endif
1.1 ratchov 1203: }
1204:
1.28 ratchov 1205: /*
1.33 ratchov 1206: * Handle buffer overruns. Return 0 if the stream died.
1.28 ratchov 1207: */
1208: int
1.51 ! ratchov 1209: sub_xrun(struct aproc *p, struct abuf *i)
1.28 ratchov 1210: {
1.51 ! ratchov 1211: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
! 1212: unsigned fdrop, remain;
1.28 ratchov 1213:
1.36 ratchov 1214: if (i->w.sub.done > 0)
1.28 ratchov 1215: return 1;
1.36 ratchov 1216: if (i->w.sub.xrun == XRUN_ERROR) {
1.28 ratchov 1217: abuf_eof(i);
1218: return 0;
1219: }
1.51 ! ratchov 1220: fdrop = ibuf->used;
1.42 ratchov 1221: #ifdef DEBUG
1222: if (debug_level >= 3) {
1223: abuf_dbg(i);
1224: dbg_puts(": overrun, silence ");
1225: dbg_putu(fdrop);
1226: dbg_puts(" + ");
1.51 ! ratchov 1227: dbg_putu(i->w.sub.silence);
1.42 ratchov 1228: dbg_puts("\n");
1229: }
1230: #endif
1.51 ! ratchov 1231: i->w.sub.done += fdrop;
1.36 ratchov 1232: if (i->w.sub.xrun == XRUN_SYNC)
1.51 ! ratchov 1233: sub_silence(i, fdrop);
1.28 ratchov 1234: else {
1.51 ! ratchov 1235: remain = fdrop % p->u.sub.round;
! 1236: if (remain)
! 1237: remain = p->u.sub.round - remain;
! 1238: sub_silence(i, -(int)remain);
! 1239: fdrop += remain;
! 1240: #ifdef DEBUG
! 1241: if (debug_level >= 3) {
! 1242: abuf_dbg(i);
! 1243: dbg_puts(": overrun, adding ");
! 1244: dbg_putu(remain);
! 1245: dbg_puts("\n");
! 1246: }
! 1247: #endif
! 1248:
1.28 ratchov 1249: abuf_ipos(i, -(int)fdrop);
1250: if (i->duplex) {
1.42 ratchov 1251: #ifdef DEBUG
1252: if (debug_level >= 3) {
1253: abuf_dbg(i->duplex);
1254: dbg_puts(": full-duplex resync\n");
1255: }
1256: #endif
1.51 ! ratchov 1257: mix_drop(i->duplex, -(int)fdrop);
1.28 ratchov 1258: abuf_opos(i->duplex, -(int)fdrop);
1259: }
1260: }
1261: return 1;
1262: }
1263:
1.1 ratchov 1264: int
1265: sub_in(struct aproc *p, struct abuf *ibuf)
1266: {
1267: struct abuf *i, *inext;
1.28 ratchov 1268: unsigned idone;
1.31 ratchov 1269:
1.12 ratchov 1270: if (!ABUF_ROK(ibuf))
1271: return 0;
1.28 ratchov 1272: idone = ibuf->len;
1.12 ratchov 1273: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
1.1 ratchov 1274: inext = LIST_NEXT(i, oent);
1.51 ! ratchov 1275: sub_silence(i, 0);
! 1276: if (!SUB_WOK(i)) {
1.38 ratchov 1277: if (p->flags & APROC_DROP) {
1.51 ! ratchov 1278: if (!sub_xrun(p, i))
1.5 ratchov 1279: continue;
1280: }
1.12 ratchov 1281: } else
1.1 ratchov 1282: sub_bcopy(ibuf, i);
1.36 ratchov 1283: if (idone > i->w.sub.done)
1284: idone = i->w.sub.done;
1.12 ratchov 1285: if (!abuf_flush(i))
1286: continue;
1.1 ratchov 1287: }
1.28 ratchov 1288: if (LIST_EMPTY(&p->obuflist)) {
1.38 ratchov 1289: if (p->flags & APROC_QUIT) {
1.28 ratchov 1290: aproc_del(p);
1291: return 0;
1292: }
1.38 ratchov 1293: if (!(p->flags & APROC_DROP))
1.28 ratchov 1294: return 0;
1295: idone = ibuf->used;
1.51 ! ratchov 1296: p->u.sub.idle += idone;
1.28 ratchov 1297: }
1298: if (idone == 0)
1299: return 0;
1.1 ratchov 1300: LIST_FOREACH(i, &p->obuflist, oent) {
1.36 ratchov 1301: i->w.sub.done -= idone;
1.1 ratchov 1302: }
1.28 ratchov 1303: abuf_rdiscard(ibuf, idone);
1.51 ! ratchov 1304: abuf_opos(ibuf, idone);
! 1305: p->u.sub.lat -= idone;
! 1306: p->u.sub.abspos += idone;
1.12 ratchov 1307: return 1;
1.1 ratchov 1308: }
1309:
1310: int
1311: sub_out(struct aproc *p, struct abuf *obuf)
1312: {
1313: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1314: struct abuf *i, *inext;
1.28 ratchov 1315: unsigned idone;
1.1 ratchov 1316:
1.51 ! ratchov 1317: if (!SUB_WOK(obuf))
1.12 ratchov 1318: return 0;
1.28 ratchov 1319: if (!abuf_fill(ibuf))
1320: return 0; /* eof */
1321: idone = ibuf->len;
1.12 ratchov 1322: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
1323: inext = LIST_NEXT(i, oent);
1.51 ! ratchov 1324: sub_silence(i, 0);
1.28 ratchov 1325: sub_bcopy(ibuf, i);
1.36 ratchov 1326: if (idone > i->w.sub.done)
1327: idone = i->w.sub.done;
1.12 ratchov 1328: if (!abuf_flush(i))
1329: continue;
1.1 ratchov 1330: }
1.28 ratchov 1331: if (LIST_EMPTY(&p->obuflist) || idone == 0)
1332: return 0;
1.1 ratchov 1333: LIST_FOREACH(i, &p->obuflist, oent) {
1.36 ratchov 1334: i->w.sub.done -= idone;
1.1 ratchov 1335: }
1.28 ratchov 1336: abuf_rdiscard(ibuf, idone);
1.51 ! ratchov 1337: abuf_opos(ibuf, idone);
! 1338: p->u.sub.lat -= idone;
! 1339: p->u.sub.abspos += idone;
1.1 ratchov 1340: return 1;
1341: }
1342:
1343: void
1344: sub_eof(struct aproc *p, struct abuf *ibuf)
1345: {
1.8 ratchov 1346: aproc_del(p);
1.1 ratchov 1347: }
1348:
1349: void
1350: sub_hup(struct aproc *p, struct abuf *obuf)
1351: {
1.51 ! ratchov 1352: struct abuf *i, *inext, *ibuf = LIST_FIRST(&p->ibuflist);
1.28 ratchov 1353: unsigned idone;
1.1 ratchov 1354:
1.28 ratchov 1355: if (!aproc_inuse(p)) {
1.42 ratchov 1356: #ifdef DEBUG
1357: if (debug_level >= 3) {
1358: aproc_dbg(p);
1359: dbg_puts(": running other streams\n");
1360: }
1361: #endif
1.28 ratchov 1362: /*
1.33 ratchov 1363: * Find a blocked output.
1.28 ratchov 1364: */
1365: idone = ibuf->len;
1.51 ! ratchov 1366: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
! 1367: inext = LIST_NEXT(i, oent);
! 1368: if (!abuf_flush(i))
! 1369: continue;
! 1370: if (SUB_WOK(i) && i->w.sub.done < ibuf->used) {
1.28 ratchov 1371: abuf_run(i);
1372: return;
1373: }
1.36 ratchov 1374: if (idone > i->w.sub.done)
1375: idone = i->w.sub.done;
1.28 ratchov 1376: }
1377: /*
1.33 ratchov 1378: * No blocked outputs. Check if input is blocked.
1.28 ratchov 1379: */
1380: if (LIST_EMPTY(&p->obuflist) || idone == ibuf->used)
1381: abuf_run(ibuf);
1382: }
1.1 ratchov 1383: }
1384:
1385: void
1386: sub_newout(struct aproc *p, struct abuf *obuf)
1387: {
1.42 ratchov 1388: #ifdef DEBUG
1389: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1390:
1391: if (!ibuf || obuf->cmin < ibuf->cmin || obuf->cmax > ibuf->cmax) {
1392: dbg_puts("newout: channel ranges mismatch\n");
1393: dbg_panic();
1394: }
1395: #endif
1.22 ratchov 1396: p->u.sub.idle = 0;
1.36 ratchov 1397: obuf->w.sub.done = 0;
1398: obuf->w.sub.xrun = XRUN_IGNORE;
1.51 ! ratchov 1399: obuf->w.sub.silence = 0;
1.1 ratchov 1400: }
1401:
1.12 ratchov 1402: void
1403: sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
1404: {
1405: p->u.sub.lat += delta;
1.42 ratchov 1406: #ifdef DEBUG
1407: if (debug_level >= 4) {
1408: aproc_dbg(p);
1409: dbg_puts(": ipos: lat = ");
1410: dbg_puti(p->u.sub.lat);
1411: dbg_puts("/");
1412: dbg_puti(p->u.sub.maxlat);
1.51 ! ratchov 1413: dbg_puts("\n");
1.42 ratchov 1414: }
1415: #endif
1.51 ! ratchov 1416: if (APROC_OK(p->u.sub.ctl))
1.38 ratchov 1417: ctl_ontick(p->u.sub.ctl, delta);
1.12 ratchov 1418: aproc_ipos(p, ibuf, delta);
1419: }
1420:
1.1 ratchov 1421: struct aproc_ops sub_ops = {
1.12 ratchov 1422: "sub",
1423: sub_in,
1424: sub_out,
1425: sub_eof,
1426: sub_hup,
1427: NULL,
1428: sub_newout,
1429: sub_ipos,
1430: aproc_opos,
1431: NULL
1.1 ratchov 1432: };
1433:
1434: struct aproc *
1.51 ! ratchov 1435: sub_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
1.1 ratchov 1436: {
1437: struct aproc *p;
1438:
1.12 ratchov 1439: p = aproc_new(&sub_ops, name);
1.22 ratchov 1440: p->u.sub.idle = 0;
1.12 ratchov 1441: p->u.sub.lat = 0;
1.51 ! ratchov 1442: p->u.sub.round = round;
1.12 ratchov 1443: p->u.sub.maxlat = maxlat;
1.51 ! ratchov 1444: p->u.sub.abspos = 0;
1.38 ratchov 1445: p->u.sub.ctl = ctl;
1.1 ratchov 1446: return p;
1.22 ratchov 1447: }
1448:
1449: void
1450: sub_clear(struct aproc *p)
1451: {
1.51 ! ratchov 1452: p->u.sub.lat = 0;
! 1453: p->u.sub.abspos = 0;
1.1 ratchov 1454: }
1455:
1456: /*
1457: * Convert one block.
1458: */
1459: void
1.15 ratchov 1460: resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1461: {
1462: unsigned inch;
1463: short *idata;
1.27 ratchov 1464: unsigned oblksz;
1.15 ratchov 1465: unsigned ifr;
1466: unsigned onch;
1.27 ratchov 1467: int s1, s2, diff;
1.15 ratchov 1468: short *odata;
1.27 ratchov 1469: unsigned iblksz;
1.15 ratchov 1470: unsigned ofr;
1471: unsigned c;
1.31 ratchov 1472: short *ctxbuf, *ctx;
1.27 ratchov 1473: unsigned ctx_start;
1.15 ratchov 1474: unsigned icount, ocount;
1475:
1476: /*
1477: * Calculate max frames readable at once from the input buffer.
1478: */
1479: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1.51 ! ratchov 1480: ifr = icount;
1.15 ratchov 1481:
1482: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1.51 ! ratchov 1483: ofr = ocount;
1.15 ratchov 1484:
1485: /*
1486: * Partially copy structures into local variables, to avoid
1487: * unnecessary indirections; this also allows the compiler to
1488: * order local variables more "cache-friendly".
1489: */
1.27 ratchov 1490: diff = p->u.resamp.diff;
1.15 ratchov 1491: inch = ibuf->cmax - ibuf->cmin + 1;
1.26 ratchov 1492: iblksz = p->u.resamp.iblksz;
1.15 ratchov 1493: onch = obuf->cmax - obuf->cmin + 1;
1.26 ratchov 1494: oblksz = p->u.resamp.oblksz;
1.15 ratchov 1495: ctxbuf = p->u.resamp.ctx;
1.27 ratchov 1496: ctx_start = p->u.resamp.ctx_start;
1.15 ratchov 1497:
1498: /*
1499: * Start conversion.
1500: */
1.42 ratchov 1501: #ifdef DEBUG
1502: if (debug_level >= 4) {
1503: aproc_dbg(p);
1.46 ratchov 1504: dbg_puts(": resamp starting diff = ");
1505: dbg_puti(diff);
1506: dbg_puts(", ifr = ");
1.42 ratchov 1507: dbg_putu(ifr);
1508: dbg_puts(", ofr = ");
1.46 ratchov 1509: dbg_putu(ofr);
1.42 ratchov 1510: dbg_puts(" fr\n");
1511: }
1512: #endif
1.15 ratchov 1513: for (;;) {
1.27 ratchov 1514: if (diff < 0) {
1.51 ! ratchov 1515: if (ifr == 0)
! 1516: break;
1.27 ratchov 1517: ctx_start ^= 1;
1518: ctx = ctxbuf + ctx_start;
1.15 ratchov 1519: for (c = inch; c > 0; c--) {
1.29 ratchov 1520: *ctx = *idata++;
1.27 ratchov 1521: ctx += RESAMP_NCTX;
1.15 ratchov 1522: }
1.27 ratchov 1523: diff += oblksz;
1.51 ! ratchov 1524: ifr--;
! 1525: } else {
! 1526: if (ofr == 0)
1.50 ratchov 1527: break;
1.27 ratchov 1528: ctx = ctxbuf;
1529: for (c = onch; c > 0; c--) {
1.29 ratchov 1530: s1 = ctx[ctx_start];
1531: s2 = ctx[ctx_start ^ 1];
1.27 ratchov 1532: ctx += RESAMP_NCTX;
1533: *odata++ = s1 + (s2 - s1) * diff / (int)oblksz;
1534: }
1535: diff -= iblksz;
1.51 ! ratchov 1536: ofr--;
1.15 ratchov 1537: }
1538: }
1.27 ratchov 1539: p->u.resamp.diff = diff;
1540: p->u.resamp.ctx_start = ctx_start;
1.42 ratchov 1541: #ifdef DEBUG
1542: if (debug_level >= 4) {
1543: aproc_dbg(p);
1.46 ratchov 1544: dbg_puts(": resamp done delta = ");
1545: dbg_puti(diff);
1546: dbg_puts(", ifr = ");
1.42 ratchov 1547: dbg_putu(ifr);
1548: dbg_puts(", ofr = ");
1.46 ratchov 1549: dbg_putu(ofr);
1.42 ratchov 1550: dbg_puts(" fr\n");
1551: }
1552: #endif
1.15 ratchov 1553: /*
1554: * Update FIFO pointers.
1555: */
1.51 ! ratchov 1556: icount -= ifr;
! 1557: ocount -= ofr;
1.15 ratchov 1558: abuf_rdiscard(ibuf, icount);
1559: abuf_wcommit(obuf, ocount);
1560: }
1561:
1562: int
1563: resamp_in(struct aproc *p, struct abuf *ibuf)
1564: {
1565: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1566:
1567: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1568: return 0;
1569: resamp_bcopy(p, ibuf, obuf);
1570: if (!abuf_flush(obuf))
1571: return 0;
1572: return 1;
1573: }
1574:
1575: int
1576: resamp_out(struct aproc *p, struct abuf *obuf)
1577: {
1578: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1579:
1580: if (!abuf_fill(ibuf))
1581: return 0;
1582: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1583: return 0;
1584: resamp_bcopy(p, ibuf, obuf);
1585: return 1;
1586: }
1587:
1588: void
1589: resamp_eof(struct aproc *p, struct abuf *ibuf)
1590: {
1591: aproc_del(p);
1592: }
1593:
1594: void
1595: resamp_hup(struct aproc *p, struct abuf *obuf)
1596: {
1597: aproc_del(p);
1598: }
1599:
1600: void
1601: resamp_ipos(struct aproc *p, struct abuf *ibuf, int delta)
1602: {
1.31 ratchov 1603: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1.15 ratchov 1604: long long ipos;
1.45 ratchov 1605:
1606: ipos = (long long)delta * p->u.resamp.oblksz + p->u.resamp.idelta;
1607: p->u.resamp.idelta = ipos % p->u.resamp.iblksz;
1608: abuf_ipos(obuf, ipos / (int)p->u.resamp.iblksz);
1.15 ratchov 1609: }
1610:
1611: void
1612: resamp_opos(struct aproc *p, struct abuf *obuf, int delta)
1613: {
1614: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1615: long long opos;
1616:
1.45 ratchov 1617: opos = (long long)delta * p->u.resamp.iblksz + p->u.resamp.odelta;
1618: p->u.resamp.odelta = opos % p->u.resamp.oblksz;
1619: abuf_opos(ibuf, opos / p->u.resamp.oblksz);
1.15 ratchov 1620: }
1621:
1622: struct aproc_ops resamp_ops = {
1623: "resamp",
1624: resamp_in,
1625: resamp_out,
1626: resamp_eof,
1627: resamp_hup,
1628: NULL,
1629: NULL,
1630: resamp_ipos,
1631: resamp_opos,
1632: NULL
1633: };
1634:
1635: struct aproc *
1.26 ratchov 1636: resamp_new(char *name, unsigned iblksz, unsigned oblksz)
1.15 ratchov 1637: {
1638: struct aproc *p;
1.16 ratchov 1639: unsigned i;
1.15 ratchov 1640:
1641: p = aproc_new(&resamp_ops, name);
1.26 ratchov 1642: p->u.resamp.iblksz = iblksz;
1643: p->u.resamp.oblksz = oblksz;
1.48 ratchov 1644: p->u.resamp.diff = 0;
1.15 ratchov 1645: p->u.resamp.idelta = 0;
1646: p->u.resamp.odelta = 0;
1.27 ratchov 1647: p->u.resamp.ctx_start = 0;
1648: for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++)
1.16 ratchov 1649: p->u.resamp.ctx[i] = 0;
1.42 ratchov 1650: #ifdef DEBUG
1651: if (debug_level >= 3) {
1652: aproc_dbg(p);
1653: dbg_puts(": new ");
1654: dbg_putu(iblksz);
1655: dbg_puts("/");
1656: dbg_putu(oblksz);
1657: dbg_puts("\n");
1658: }
1659: #endif
1.17 ratchov 1660: return p;
1661: }
1662:
1663: /*
1664: * Convert one block.
1665: */
1666: void
1667: cmap_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1668: {
1669: unsigned inch;
1670: short *idata;
1671: unsigned onch;
1672: short *odata;
1673: short *ctx, *ictx, *octx;
1674: unsigned c, f, scount, icount, ocount;
1675:
1676: /*
1677: * Calculate max frames readable at once from the input buffer.
1678: */
1679: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1680: if (icount == 0)
1681: return;
1682: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1683: if (ocount == 0)
1684: return;
1685: scount = icount < ocount ? icount : ocount;
1686: inch = ibuf->cmax - ibuf->cmin + 1;
1687: onch = obuf->cmax - obuf->cmin + 1;
1688: ictx = p->u.cmap.ctx + ibuf->cmin;
1689: octx = p->u.cmap.ctx + obuf->cmin;
1690:
1691: for (f = scount; f > 0; f--) {
1692: ctx = ictx;
1693: for (c = inch; c > 0; c--) {
1694: *ctx = *idata;
1695: idata++;
1696: ctx++;
1697: }
1698: ctx = octx;
1699: for (c = onch; c > 0; c--) {
1700: *odata = *ctx;
1701: odata++;
1702: ctx++;
1703: }
1704: }
1.42 ratchov 1705: #ifdef DEBUG
1706: if (debug_level >= 4) {
1707: aproc_dbg(p);
1708: dbg_puts(": bcopy ");
1709: dbg_putu(scount);
1710: dbg_puts(" fr\n");
1711: }
1712: #endif
1.51 ! ratchov 1713: abuf_rdiscard(ibuf, scount);
! 1714: abuf_wcommit(obuf, scount);
1.17 ratchov 1715: }
1716:
1717: int
1718: cmap_in(struct aproc *p, struct abuf *ibuf)
1719: {
1720: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1721:
1722: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1723: return 0;
1724: cmap_bcopy(p, ibuf, obuf);
1725: if (!abuf_flush(obuf))
1726: return 0;
1727: return 1;
1728: }
1729:
1730: int
1731: cmap_out(struct aproc *p, struct abuf *obuf)
1732: {
1733: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1734:
1735: if (!abuf_fill(ibuf))
1736: return 0;
1737: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1738: return 0;
1739: cmap_bcopy(p, ibuf, obuf);
1740: return 1;
1741: }
1742:
1743: void
1744: cmap_eof(struct aproc *p, struct abuf *ibuf)
1745: {
1746: aproc_del(p);
1747: }
1748:
1749: void
1750: cmap_hup(struct aproc *p, struct abuf *obuf)
1751: {
1752: aproc_del(p);
1753: }
1754:
1755: struct aproc_ops cmap_ops = {
1756: "cmap",
1757: cmap_in,
1758: cmap_out,
1759: cmap_eof,
1760: cmap_hup,
1761: NULL,
1762: NULL,
1.19 ratchov 1763: aproc_ipos,
1764: aproc_opos,
1.17 ratchov 1765: NULL
1766: };
1767:
1768: struct aproc *
1769: cmap_new(char *name, struct aparams *ipar, struct aparams *opar)
1770: {
1771: struct aproc *p;
1772: unsigned i;
1773:
1774: p = aproc_new(&cmap_ops, name);
1775: for (i = 0; i < NCHAN_MAX; i++)
1776: p->u.cmap.ctx[i] = 0;
1.42 ratchov 1777: #ifdef DEBUG
1778: if (debug_level >= 3) {
1779: aproc_dbg(p);
1780: dbg_puts(": new ");
1781: aparams_dbg(ipar);
1782: dbg_puts(" -> ");
1783: aparams_dbg(opar);
1784: dbg_puts("\n");
1785: }
1786: #endif
1.19 ratchov 1787: return p;
1788: }
1789:
1790: /*
1791: * Convert one block.
1792: */
1793: void
1794: enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1795: {
1796: unsigned nch, scount, icount, ocount;
1797: unsigned f;
1798: short *idata;
1799: int s;
1800: unsigned oshift;
1801: int osigbit;
1802: unsigned obps;
1803: unsigned i;
1804: unsigned char *odata;
1805: int obnext;
1806: int osnext;
1807:
1808: /*
1809: * Calculate max frames readable at once from the input buffer.
1810: */
1811: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1812: if (icount == 0)
1813: return;
1814: odata = abuf_wgetblk(obuf, &ocount, 0);
1815: if (ocount == 0)
1816: return;
1817: scount = (icount < ocount) ? icount : ocount;
1818: nch = ibuf->cmax - ibuf->cmin + 1;
1.42 ratchov 1819: #ifdef DEBUG
1820: if (debug_level >= 4) {
1821: aproc_dbg(p);
1822: dbg_puts(": bcopy ");
1823: dbg_putu(scount);
1.51 ! ratchov 1824: dbg_puts(" fr / ");
1.42 ratchov 1825: dbg_putu(nch);
1826: dbg_puts(" ch\n");
1827: }
1828: #endif
1.19 ratchov 1829: /*
1830: * Partially copy structures into local variables, to avoid
1831: * unnecessary indirections; this also allows the compiler to
1832: * order local variables more "cache-friendly".
1833: */
1834: oshift = p->u.conv.shift;
1835: osigbit = p->u.conv.sigbit;
1836: obps = p->u.conv.bps;
1837: obnext = p->u.conv.bnext;
1838: osnext = p->u.conv.snext;
1839:
1840: /*
1841: * Start conversion.
1842: */
1843: odata += p->u.conv.bfirst;
1844: for (f = scount * nch; f > 0; f--) {
1845: s = *idata++;
1846: s <<= 16;
1847: s >>= oshift;
1848: s ^= osigbit;
1849: for (i = obps; i > 0; i--) {
1850: *odata = (unsigned char)s;
1851: s >>= 8;
1852: odata += obnext;
1853: }
1854: odata += osnext;
1855: }
1856:
1857: /*
1858: * Update FIFO pointers.
1859: */
1.51 ! ratchov 1860: abuf_rdiscard(ibuf, scount);
! 1861: abuf_wcommit(obuf, scount);
1.19 ratchov 1862: }
1863:
1864: int
1865: enc_in(struct aproc *p, struct abuf *ibuf)
1866: {
1867: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1868:
1869: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1870: return 0;
1871: enc_bcopy(p, ibuf, obuf);
1872: if (!abuf_flush(obuf))
1873: return 0;
1874: return 1;
1875: }
1876:
1877: int
1878: enc_out(struct aproc *p, struct abuf *obuf)
1879: {
1880: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1881:
1882: if (!abuf_fill(ibuf))
1883: return 0;
1884: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1885: return 0;
1886: enc_bcopy(p, ibuf, obuf);
1887: return 1;
1888: }
1889:
1890: void
1891: enc_eof(struct aproc *p, struct abuf *ibuf)
1892: {
1893: aproc_del(p);
1894: }
1895:
1896: void
1897: enc_hup(struct aproc *p, struct abuf *obuf)
1898: {
1899: aproc_del(p);
1900: }
1901:
1902: struct aproc_ops enc_ops = {
1903: "enc",
1904: enc_in,
1905: enc_out,
1906: enc_eof,
1907: enc_hup,
1908: NULL,
1909: NULL,
1910: aproc_ipos,
1911: aproc_opos,
1912: NULL
1913: };
1914:
1915: struct aproc *
1916: enc_new(char *name, struct aparams *par)
1917: {
1918: struct aproc *p;
1919:
1920: p = aproc_new(&enc_ops, name);
1921: p->u.conv.bps = par->bps;
1922: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
1923: if (par->msb) {
1924: p->u.conv.shift = 32 - par->bps * 8;
1925: } else {
1926: p->u.conv.shift = 32 - par->bits;
1927: }
1928: if (!par->le) {
1929: p->u.conv.bfirst = par->bps - 1;
1930: p->u.conv.bnext = -1;
1931: p->u.conv.snext = 2 * par->bps;
1932: } else {
1933: p->u.conv.bfirst = 0;
1934: p->u.conv.bnext = 1;
1935: p->u.conv.snext = 0;
1936: }
1.42 ratchov 1937: #ifdef DEBUG
1938: if (debug_level >= 3) {
1939: aproc_dbg(p);
1940: dbg_puts(": new ");
1941: aparams_dbg(par);
1942: dbg_puts("\n");
1943: }
1944: #endif
1.19 ratchov 1945: return p;
1946: }
1947:
1948: /*
1949: * Convert one block.
1950: */
1951: void
1952: dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1953: {
1954: unsigned nch, scount, icount, ocount;
1955: unsigned f;
1956: unsigned ibps;
1957: unsigned i;
1958: int s = 0xdeadbeef;
1959: unsigned char *idata;
1960: int ibnext;
1961: int isnext;
1962: int isigbit;
1963: unsigned ishift;
1964: short *odata;
1965:
1966: /*
1967: * Calculate max frames readable at once from the input buffer.
1968: */
1969: idata = abuf_rgetblk(ibuf, &icount, 0);
1970: if (icount == 0)
1971: return;
1972: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1973: if (ocount == 0)
1974: return;
1975: scount = (icount < ocount) ? icount : ocount;
1976: nch = obuf->cmax - obuf->cmin + 1;
1.42 ratchov 1977: #ifdef DEBUG
1978: if (debug_level >= 4) {
1979: aproc_dbg(p);
1980: dbg_puts(": bcopy ");
1981: dbg_putu(scount);
1.51 ! ratchov 1982: dbg_puts(" fr / ");
1.42 ratchov 1983: dbg_putu(nch);
1984: dbg_puts(" ch\n");
1985: }
1986: #endif
1.19 ratchov 1987: /*
1988: * Partially copy structures into local variables, to avoid
1989: * unnecessary indirections; this also allows the compiler to
1990: * order local variables more "cache-friendly".
1991: */
1992: ibps = p->u.conv.bps;
1993: ibnext = p->u.conv.bnext;
1994: isigbit = p->u.conv.sigbit;
1995: ishift = p->u.conv.shift;
1996: isnext = p->u.conv.snext;
1997:
1998: /*
1999: * Start conversion.
2000: */
2001: idata += p->u.conv.bfirst;
2002: for (f = scount * nch; f > 0; f--) {
2003: for (i = ibps; i > 0; i--) {
2004: s <<= 8;
2005: s |= *idata;
2006: idata += ibnext;
2007: }
2008: idata += isnext;
2009: s ^= isigbit;
2010: s <<= ishift;
2011: s >>= 16;
2012: *odata++ = s;
2013: }
2014:
2015: /*
2016: * Update FIFO pointers.
2017: */
1.51 ! ratchov 2018: abuf_rdiscard(ibuf, scount);
! 2019: abuf_wcommit(obuf, scount);
1.19 ratchov 2020: }
2021:
2022: int
2023: dec_in(struct aproc *p, struct abuf *ibuf)
2024: {
2025: struct abuf *obuf = LIST_FIRST(&p->obuflist);
2026:
2027: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
2028: return 0;
2029: dec_bcopy(p, ibuf, obuf);
2030: if (!abuf_flush(obuf))
2031: return 0;
2032: return 1;
2033: }
2034:
2035: int
2036: dec_out(struct aproc *p, struct abuf *obuf)
2037: {
2038: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
2039:
2040: if (!abuf_fill(ibuf))
2041: return 0;
2042: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
2043: return 0;
2044: dec_bcopy(p, ibuf, obuf);
2045: return 1;
2046: }
2047:
2048: void
2049: dec_eof(struct aproc *p, struct abuf *ibuf)
2050: {
2051: aproc_del(p);
2052: }
2053:
2054: void
2055: dec_hup(struct aproc *p, struct abuf *obuf)
2056: {
2057: aproc_del(p);
2058: }
2059:
2060: struct aproc_ops dec_ops = {
2061: "dec",
2062: dec_in,
2063: dec_out,
2064: dec_eof,
2065: dec_hup,
2066: NULL,
2067: NULL,
2068: aproc_ipos,
2069: aproc_opos,
2070: NULL
2071: };
2072:
2073: struct aproc *
2074: dec_new(char *name, struct aparams *par)
2075: {
2076: struct aproc *p;
2077:
2078: p = aproc_new(&dec_ops, name);
2079: p->u.conv.bps = par->bps;
2080: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
2081: if (par->msb) {
2082: p->u.conv.shift = 32 - par->bps * 8;
2083: } else {
2084: p->u.conv.shift = 32 - par->bits;
2085: }
2086: if (par->le) {
2087: p->u.conv.bfirst = par->bps - 1;
2088: p->u.conv.bnext = -1;
2089: p->u.conv.snext = 2 * par->bps;
2090: } else {
2091: p->u.conv.bfirst = 0;
2092: p->u.conv.bnext = 1;
2093: p->u.conv.snext = 0;
2094: }
1.42 ratchov 2095: #ifdef DEBUG
2096: if (debug_level >= 3) {
2097: aproc_dbg(p);
2098: dbg_puts(": new ");
2099: aparams_dbg(par);
2100: dbg_puts("\n");
1.51 ! ratchov 2101: }
! 2102: #endif
! 2103: return p;
! 2104: }
! 2105:
! 2106: /*
! 2107: * Commit and flush part of the output buffer
! 2108: */
! 2109: void
! 2110: mon_flush(struct aproc *p)
! 2111: {
! 2112: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 2113: unsigned count;
! 2114:
! 2115: #ifdef DEBUG
! 2116: if (debug_level >= 4) {
! 2117: aproc_dbg(p);
! 2118: dbg_puts(": delta = ");
! 2119: dbg_puti(p->u.mon.delta);
! 2120: dbg_puts("/");
! 2121: dbg_putu(p->u.mon.bufsz);
! 2122: dbg_puts(" pending = ");
! 2123: dbg_puti(p->u.mon.pending);
! 2124: dbg_puts("\n");
! 2125: }
! 2126: #endif
! 2127: if (p->u.mon.delta <= 0 || p->u.mon.pending == 0)
! 2128: return;
! 2129: count = p->u.mon.delta;
! 2130: if (count > p->u.mon.pending)
! 2131: count = p->u.mon.pending;
! 2132: abuf_wcommit(obuf, count);
! 2133: p->u.mon.pending -= count;
! 2134: p->u.mon.delta -= count;
! 2135: abuf_flush(obuf);
! 2136: }
! 2137:
! 2138: /*
! 2139: * Copy one block.
! 2140: */
! 2141: void
! 2142: mon_snoop(struct aproc *p, struct abuf *ibuf, unsigned pos, unsigned todo)
! 2143: {
! 2144: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 2145: unsigned scount, icount, ocount;
! 2146: short *idata, *odata;
! 2147:
! 2148: #ifdef DEBUG
! 2149: if (debug_level >= 4) {
! 2150: aproc_dbg(p);
! 2151: dbg_puts(": snoop ");
! 2152: dbg_putu(pos);
! 2153: dbg_puts("..");
! 2154: dbg_putu(todo);
! 2155: dbg_puts("\n");
! 2156: }
! 2157: #endif
! 2158: if (!abuf_flush(obuf))
! 2159: return;
! 2160:
! 2161: while (todo > 0) {
! 2162: /*
! 2163: * Calculate max frames readable at once from the input buffer.
! 2164: */
! 2165: idata = (short *)abuf_rgetblk(ibuf, &icount, pos);
! 2166: odata = (short *)abuf_wgetblk(obuf, &ocount, p->u.mon.pending);
! 2167: scount = (icount < ocount) ? icount : ocount;
! 2168: #ifdef DEBUG
! 2169: if (debug_level >= 4) {
! 2170: aproc_dbg(p);
! 2171: dbg_puts(": snooping ");
! 2172: dbg_putu(scount);
! 2173: dbg_puts(" fr\n");
! 2174: }
! 2175: if (scount == 0) {
! 2176: dbg_puts("monitor xrun, not allowed\n");
! 2177: dbg_panic();
! 2178: }
! 2179: #endif
! 2180: memcpy(odata, idata, scount * obuf->bpf);
! 2181: p->u.mon.pending += scount;
! 2182: todo -= scount;
! 2183: pos += scount;
! 2184: }
! 2185: mon_flush(p);
! 2186: }
! 2187:
! 2188: int
! 2189: mon_in(struct aproc *p, struct abuf *ibuf)
! 2190: {
! 2191: #ifdef DEBUG
! 2192: dbg_puts("monitor can't have inputs to read\n");
! 2193: dbg_panic();
! 2194: #endif
! 2195: return 0;
! 2196: }
! 2197:
! 2198: /*
! 2199: * put the monitor into ``empty'' state
! 2200: */
! 2201: void
! 2202: mon_clear(struct aproc *p)
! 2203: {
! 2204: p->u.mon.pending = 0;
! 2205: p->u.mon.delta = 0;
! 2206: }
! 2207:
! 2208: int
! 2209: mon_out(struct aproc *p, struct abuf *obuf)
! 2210: {
! 2211: /*
! 2212: * can't trigger monitored stream to produce data
! 2213: */
! 2214: return 0;
! 2215: }
! 2216:
! 2217: void
! 2218: mon_eof(struct aproc *p, struct abuf *ibuf)
! 2219: {
! 2220: #ifdef DEBUG
! 2221: dbg_puts("monitor can't have inputs to eof\n");
! 2222: dbg_panic();
! 2223: #endif
! 2224: }
! 2225:
! 2226: void
! 2227: mon_hup(struct aproc *p, struct abuf *obuf)
! 2228: {
! 2229: aproc_del(p);
! 2230: }
! 2231:
! 2232: void
! 2233: mon_ipos(struct aproc *p, struct abuf *ibuf, int delta)
! 2234: {
! 2235: aproc_ipos(p, ibuf, delta);
! 2236: p->u.mon.delta += delta;
! 2237: mon_flush(p);
! 2238: }
! 2239:
! 2240: struct aproc_ops mon_ops = {
! 2241: "mon",
! 2242: mon_in,
! 2243: mon_out,
! 2244: mon_eof,
! 2245: mon_hup,
! 2246: NULL,
! 2247: NULL,
! 2248: mon_ipos,
! 2249: aproc_opos,
! 2250: NULL
! 2251: };
! 2252:
! 2253: struct aproc *
! 2254: mon_new(char *name, unsigned bufsz)
! 2255: {
! 2256: struct aproc *p;
! 2257:
! 2258: p = aproc_new(&mon_ops, name);
! 2259: p->u.mon.pending = 0;
! 2260: p->u.mon.delta = 0;
! 2261: p->u.mon.bufsz = bufsz;
! 2262: #ifdef DEBUG
! 2263: if (debug_level >= 3) {
! 2264: aproc_dbg(p);
! 2265: dbg_puts(": new\n");
1.42 ratchov 2266: }
2267: #endif
1.1 ratchov 2268: return p;
2269: }