Annotation of src/usr.bin/aucat/aproc.c, Revision 1.55
1.55 ! ratchov 1: /* $OpenBSD: aproc.c,v 1.54 2010/04/24 06:18:23 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);
1.54 ratchov 162: LIST_INIT(&p->ins);
163: LIST_INIT(&p->outs);
1.1 ratchov 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: }
1.54 ratchov 192: while (!LIST_EMPTY(&p->ins)) {
193: i = LIST_FIRST(&p->ins);
1.35 ratchov 194: abuf_hup(i);
195: }
1.54 ratchov 196: while (!LIST_EMPTY(&p->outs)) {
197: i = LIST_FIRST(&p->outs);
1.35 ratchov 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: {
1.54 ratchov 224: LIST_INSERT_HEAD(&p->ins, ibuf, ient);
1.1 ratchov 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: {
1.54 ratchov 233: LIST_INSERT_HEAD(&p->outs, obuf, oent);
1.1 ratchov 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:
1.54 ratchov 244: LIST_FOREACH(obuf, &p->outs, oent) {
1.12 ratchov 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:
1.54 ratchov 254: LIST_FOREACH(ibuf, &p->ins, ient) {
1.12 ratchov 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:
1.54 ratchov 264: LIST_FOREACH(i, &p->ins, ient) {
1.28 ratchov 265: if (i->inuse)
266: return 1;
267: }
1.54 ratchov 268: LIST_FOREACH(i, &p->outs, oent) {
1.28 ratchov 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;
1.54 ratchov 282: LIST_FOREACH(i, &p->ins, ient) {
1.32 ratchov 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: {
1.54 ratchov 292: struct abuf *obuf = LIST_FIRST(&p->outs);
1.51 ratchov 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: {
1.54 ratchov 317: struct abuf *obuf = LIST_FIRST(&p->outs);
1.49 ratchov 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: */
1.54 ratchov 361: obuf = LIST_FIRST(&p->outs);
1.39 ratchov 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: */
1.54 ratchov 434: ibuf = LIST_FIRST(&p->ins);
1.39 ratchov 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: {
1.54 ratchov 454: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.51 ratchov 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: {
1.54 ratchov 492: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.1 ratchov 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.52 ratchov 611: unsigned cmin, cmax;
612: unsigned i, j, cc, istart, inext, onext, ostart;
1.51 ratchov 613: unsigned scount, icount, ocount;
1.23 ratchov 614: int vol;
1.1 ratchov 615:
1.42 ratchov 616: #ifdef DEBUG
617: if (debug_level >= 4) {
618: abuf_dbg(ibuf);
1.43 ratchov 619: dbg_puts(": badd: done = ");
620: dbg_putu(ibuf->r.mix.done);
621: dbg_puts("/");
1.42 ratchov 622: dbg_putu(obuf->w.mix.todo);
1.51 ratchov 623: dbg_puts(", drop = ");
624: dbg_puti(ibuf->r.mix.drop);
1.42 ratchov 625: dbg_puts("\n");
626: }
627: #endif
1.28 ratchov 628: /*
1.51 ratchov 629: * Insert silence for xrun correction
630: */
631: if (ibuf->r.mix.drop < 0) {
632: icount = -ibuf->r.mix.drop;
633: ocount = obuf->len - obuf->used;
634: if (ocount > obuf->w.mix.todo)
635: ocount = obuf->w.mix.todo;
636: scount = (icount < ocount) ? icount : ocount;
637: ibuf->r.mix.done += scount;
638: ibuf->r.mix.drop += scount;
639: }
640:
641: /*
1.50 ratchov 642: * Calculate the maximum we can read.
1.49 ratchov 643: */
1.50 ratchov 644: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
645: if (icount == 0)
1.51 ratchov 646: return 0;
1.28 ratchov 647:
648: /*
1.33 ratchov 649: * Calculate the maximum we can write.
1.28 ratchov 650: */
1.36 ratchov 651: odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->r.mix.done);
1.1 ratchov 652: if (ocount == 0)
1.51 ratchov 653: return 0;
1.1 ratchov 654:
1.36 ratchov 655: vol = (ibuf->r.mix.weight * ibuf->r.mix.vol) >> ADATA_SHIFT;
1.52 ratchov 656: cmin = obuf->cmin > ibuf->cmin ? obuf->cmin : ibuf->cmin;
657: cmax = obuf->cmax < ibuf->cmax ? obuf->cmax : ibuf->cmax;
658: ostart = cmin - obuf->cmin;
659: istart = cmin - ibuf->cmin;
660: onext = obuf->cmax - cmax + ostart;
661: inext = ibuf->cmax - cmax + istart;
662: cc = cmax - cmin + 1;
1.13 ratchov 663: odata += ostart;
1.52 ratchov 664: idata += istart;
1.1 ratchov 665: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 666: for (i = scount; i > 0; i--) {
1.52 ratchov 667: for (j = cc; j > 0; j--) {
1.13 ratchov 668: *odata += (*idata * vol) >> ADATA_SHIFT;
669: idata++;
670: odata++;
671: }
672: odata += onext;
1.52 ratchov 673: idata += inext;
1.13 ratchov 674: }
1.51 ratchov 675: abuf_rdiscard(ibuf, scount);
676: ibuf->r.mix.done += scount;
1.1 ratchov 677:
1.42 ratchov 678: #ifdef DEBUG
679: if (debug_level >= 4) {
680: abuf_dbg(ibuf);
681: dbg_puts(": badd: done = ");
682: dbg_putu(ibuf->r.mix.done);
683: dbg_puts("/");
684: dbg_putu(obuf->w.mix.todo);
685: dbg_puts("\n");
686: }
687: #endif
1.51 ratchov 688: return scount;
1.1 ratchov 689: }
690:
1.28 ratchov 691: /*
692: * Handle buffer underrun, return 0 if stream died.
693: */
694: int
1.51 ratchov 695: mix_xrun(struct aproc *p, struct abuf *i)
1.28 ratchov 696: {
1.54 ratchov 697: struct abuf *obuf = LIST_FIRST(&p->outs);
1.51 ratchov 698: unsigned fdrop, remain;
1.31 ratchov 699:
1.36 ratchov 700: if (i->r.mix.done > 0)
1.28 ratchov 701: return 1;
1.36 ratchov 702: if (i->r.mix.xrun == XRUN_ERROR) {
1.28 ratchov 703: abuf_hup(i);
704: return 0;
705: }
1.51 ratchov 706: fdrop = obuf->w.mix.todo;
1.42 ratchov 707: #ifdef DEBUG
708: if (debug_level >= 3) {
709: abuf_dbg(i);
710: dbg_puts(": underrun, dropping ");
711: dbg_putu(fdrop);
712: dbg_puts(" + ");
1.51 ratchov 713: dbg_putu(i->r.mix.drop);
1.42 ratchov 714: dbg_puts("\n");
715: }
716: #endif
1.51 ratchov 717: i->r.mix.done += fdrop;
1.36 ratchov 718: if (i->r.mix.xrun == XRUN_SYNC)
1.51 ratchov 719: mix_drop(i, fdrop);
1.28 ratchov 720: else {
1.51 ratchov 721: remain = fdrop % p->u.mix.round;
722: if (remain)
723: remain = p->u.mix.round - remain;
724: mix_drop(i, -(int)remain);
725: fdrop += remain;
726: #ifdef DEBUG
727: if (debug_level >= 3) {
728: abuf_dbg(i);
729: dbg_puts(": underrun, adding ");
730: dbg_putu(remain);
731: dbg_puts("\n");
732: }
733: #endif
1.28 ratchov 734: abuf_opos(i, -(int)fdrop);
735: if (i->duplex) {
1.42 ratchov 736: #ifdef DEBUG
737: if (debug_level >= 3) {
738: abuf_dbg(i->duplex);
739: dbg_puts(": full-duplex resync\n");
740: }
741: #endif
1.51 ratchov 742: sub_silence(i->duplex, -(int)fdrop);
1.28 ratchov 743: abuf_ipos(i->duplex, -(int)fdrop);
744: }
745: }
746: return 1;
747: }
748:
1.1 ratchov 749: int
750: mix_in(struct aproc *p, struct abuf *ibuf)
751: {
1.54 ratchov 752: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->outs);
1.28 ratchov 753: unsigned odone;
1.51 ratchov 754: unsigned maxwrite;
755: unsigned scount;
1.1 ratchov 756:
1.42 ratchov 757: #ifdef DEBUG
758: if (debug_level >= 4) {
759: aproc_dbg(p);
760: dbg_puts(": used = ");
761: dbg_putu(ibuf->used);
762: dbg_puts("/");
763: dbg_putu(ibuf->len);
1.43 ratchov 764: dbg_puts(", done = ");
765: dbg_putu(ibuf->r.mix.done);
766: dbg_puts("/");
1.42 ratchov 767: dbg_putu(obuf->w.mix.todo);
768: dbg_puts("\n");
769: }
770: #endif
1.51 ratchov 771: if (!MIX_ROK(ibuf))
1.1 ratchov 772: return 0;
1.51 ratchov 773: mix_bzero(obuf);
774: scount = 0;
775: odone = obuf->w.mix.todo;
1.54 ratchov 776: for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
1.28 ratchov 777: inext = LIST_NEXT(i, ient);
1.51 ratchov 778: if (i->r.mix.drop >= 0 && !abuf_fill(i))
1.28 ratchov 779: continue; /* eof */
1.51 ratchov 780: mix_drop(i, 0);
781: scount += mix_badd(i, obuf);
1.36 ratchov 782: if (odone > i->r.mix.done)
783: odone = i->r.mix.done;
1.28 ratchov 784: }
1.54 ratchov 785: if (LIST_EMPTY(&p->ins) || scount == 0)
1.28 ratchov 786: return 0;
1.51 ratchov 787: #ifdef DEBUG
788: if (debug_level >= 4) {
789: aproc_dbg(p);
790: dbg_puts(": maxwrite = ");
791: dbg_putu(p->u.mix.maxlat);
792: dbg_puts(" - ");
793: dbg_putu(p->u.mix.lat);
794: dbg_puts(" = ");
795: dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
796: dbg_puts("\n");
797: }
798: #endif
799: maxwrite = p->u.mix.maxlat - p->u.mix.lat;
800: if (maxwrite > 0) {
801: if (odone > maxwrite)
802: odone = maxwrite;
803: p->u.mix.lat += odone;
804: p->u.mix.abspos += odone;
1.54 ratchov 805: LIST_FOREACH(i, &p->ins, ient) {
1.51 ratchov 806: i->r.mix.done -= odone;
807: }
808: abuf_wcommit(obuf, odone);
809: obuf->w.mix.todo -= odone;
810: if (APROC_OK(p->u.mix.mon))
811: mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone);
812: if (!abuf_flush(obuf))
813: return 0; /* hup */
1.1 ratchov 814: }
815: return 1;
816: }
817:
818: int
819: mix_out(struct aproc *p, struct abuf *obuf)
820: {
821: struct abuf *i, *inext;
1.28 ratchov 822: unsigned odone;
1.51 ratchov 823: unsigned maxwrite;
824: unsigned scount;
1.1 ratchov 825:
1.42 ratchov 826: #ifdef DEBUG
827: if (debug_level >= 4) {
828: aproc_dbg(p);
829: dbg_puts(": used = ");
830: dbg_putu(obuf->used);
831: dbg_puts("/");
832: dbg_putu(obuf->len);
833: dbg_puts(", todo = ");
834: dbg_putu(obuf->w.mix.todo);
835: dbg_puts("/");
836: dbg_putu(obuf->len);
837: dbg_puts("\n");
838: }
839: #endif
1.12 ratchov 840: if (!ABUF_WOK(obuf))
1.31 ratchov 841: return 0;
1.51 ratchov 842: #ifdef DEBUG
843: if (debug_level >= 4) {
844: aproc_dbg(p);
845: dbg_puts(": maxwrite = ");
846: dbg_putu(p->u.mix.maxlat);
847: dbg_puts(" - ");
848: dbg_putu(p->u.mix.lat);
849: dbg_puts(" = ");
850: dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
851: dbg_puts("\n");
852: }
853: #endif
854: maxwrite = p->u.mix.maxlat - p->u.mix.lat;
855: mix_bzero(obuf);
856: scount = 0;
1.55 ! ratchov 857: /* XXX: can obuf->len be larger than obuf->w.mix.todo ? */
1.28 ratchov 858: odone = obuf->len;
1.54 ratchov 859: for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
1.1 ratchov 860: inext = LIST_NEXT(i, ient);
1.51 ratchov 861: if (i->r.mix.drop >= 0 && !abuf_fill(i))
1.28 ratchov 862: continue; /* eof */
1.51 ratchov 863: mix_drop(i, 0);
864: if (maxwrite > 0 && !MIX_ROK(i)) {
1.38 ratchov 865: if (p->flags & APROC_DROP) {
1.51 ratchov 866: if (!mix_xrun(p, i))
1.5 ratchov 867: continue;
868: }
1.3 ratchov 869: } else
1.51 ratchov 870: scount += mix_badd(i, obuf);
1.36 ratchov 871: if (odone > i->r.mix.done)
872: odone = i->r.mix.done;
1.28 ratchov 873: }
1.54 ratchov 874: if (LIST_EMPTY(&p->ins)) {
1.38 ratchov 875: if (p->flags & APROC_QUIT) {
1.28 ratchov 876: aproc_del(p);
877: return 0;
878: }
1.38 ratchov 879: if (!(p->flags & APROC_DROP))
1.28 ratchov 880: return 0;
1.36 ratchov 881: odone = obuf->w.mix.todo;
1.51 ratchov 882: }
883: if (maxwrite > 0) {
884: if (odone > maxwrite)
885: odone = maxwrite;
886: p->u.mix.lat += odone;
887: p->u.mix.abspos += odone;
1.54 ratchov 888: LIST_FOREACH(i, &p->ins, ient) {
1.51 ratchov 889: i->r.mix.done -= odone;
890: }
891: abuf_wcommit(obuf, odone);
892: obuf->w.mix.todo -= odone;
893: if (APROC_OK(p->u.mix.mon))
894: mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone);
1.49 ratchov 895: }
1.55 ! ratchov 896: if (LIST_EMPTY(&p->ins))
! 897: p->u.mix.idle += odone;
1.51 ratchov 898: if (scount == 0)
1.50 ratchov 899: return 0;
1.1 ratchov 900: return 1;
901: }
902:
903: void
904: mix_eof(struct aproc *p, struct abuf *ibuf)
905: {
1.54 ratchov 906: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->outs);
1.28 ratchov 907: unsigned odone;
1.1 ratchov 908:
1.12 ratchov 909: mix_setmaster(p);
910:
1.28 ratchov 911: if (!aproc_inuse(p)) {
1.42 ratchov 912: #ifdef DEBUG
913: if (debug_level >= 3) {
914: aproc_dbg(p);
915: dbg_puts(": running other streams\n");
916: }
917: #endif
1.28 ratchov 918: /*
1.33 ratchov 919: * Find a blocked input.
1.28 ratchov 920: */
921: odone = obuf->len;
1.54 ratchov 922: for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
1.51 ratchov 923: inext = LIST_NEXT(i, ient);
924: if (!abuf_fill(i))
925: continue;
926: if (MIX_ROK(i) && i->r.mix.done < obuf->w.mix.todo) {
1.28 ratchov 927: abuf_run(i);
928: return;
929: }
1.36 ratchov 930: if (odone > i->r.mix.done)
931: odone = i->r.mix.done;
1.28 ratchov 932: }
933: /*
1.33 ratchov 934: * No blocked inputs. Check if output is blocked.
1.28 ratchov 935: */
1.54 ratchov 936: if (LIST_EMPTY(&p->ins) || odone == obuf->w.mix.todo)
1.28 ratchov 937: abuf_run(obuf);
938: }
1.1 ratchov 939: }
940:
941: void
942: mix_hup(struct aproc *p, struct abuf *obuf)
943: {
944: aproc_del(p);
945: }
946:
947: void
948: mix_newin(struct aproc *p, struct abuf *ibuf)
949: {
1.22 ratchov 950: p->u.mix.idle = 0;
1.36 ratchov 951: ibuf->r.mix.done = 0;
952: ibuf->r.mix.vol = ADATA_UNIT;
953: ibuf->r.mix.weight = ADATA_UNIT;
954: ibuf->r.mix.maxweight = ADATA_UNIT;
955: ibuf->r.mix.xrun = XRUN_IGNORE;
1.51 ratchov 956: ibuf->r.mix.drop = 0;
1.1 ratchov 957: }
958:
959: void
960: mix_newout(struct aproc *p, struct abuf *obuf)
961: {
1.42 ratchov 962: #ifdef DEBUG
963: if (debug_level >= 3) {
964: aproc_dbg(p);
965: dbg_puts(": newin, will use ");
1.51 ratchov 966: dbg_putu(obuf->len);
967: dbg_puts("\n");
1.42 ratchov 968: }
969: #endif
1.36 ratchov 970: obuf->w.mix.todo = 0;
1.1 ratchov 971: }
972:
1.12 ratchov 973: void
974: mix_opos(struct aproc *p, struct abuf *obuf, int delta)
975: {
1.51 ratchov 976: p->u.mix.lat -= delta;
1.42 ratchov 977: #ifdef DEBUG
978: if (debug_level >= 4) {
979: aproc_dbg(p);
980: dbg_puts(": opos: lat = ");
981: dbg_puti(p->u.mix.lat);
982: dbg_puts("/");
983: dbg_puti(p->u.mix.maxlat);
1.51 ratchov 984: dbg_puts("\n");
1.42 ratchov 985: }
986: #endif
1.51 ratchov 987: if (APROC_OK(p->u.mix.ctl))
1.38 ratchov 988: ctl_ontick(p->u.mix.ctl, delta);
1.12 ratchov 989: aproc_opos(p, obuf, delta);
1.51 ratchov 990: if (APROC_OK(p->u.mix.mon))
991: p->u.mix.mon->ops->ipos(p->u.mix.mon, NULL, delta);
1.12 ratchov 992: }
993:
1.1 ratchov 994: struct aproc_ops mix_ops = {
1.12 ratchov 995: "mix",
996: mix_in,
997: mix_out,
998: mix_eof,
999: mix_hup,
1000: mix_newin,
1001: mix_newout,
1002: aproc_ipos,
1003: mix_opos,
1004: NULL
1.1 ratchov 1005: };
1006:
1007: struct aproc *
1.51 ratchov 1008: mix_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
1.1 ratchov 1009: {
1010: struct aproc *p;
1011:
1.12 ratchov 1012: p = aproc_new(&mix_ops, name);
1.22 ratchov 1013: p->u.mix.idle = 0;
1.12 ratchov 1014: p->u.mix.lat = 0;
1.51 ratchov 1015: p->u.mix.round = round;
1.12 ratchov 1016: p->u.mix.maxlat = maxlat;
1.51 ratchov 1017: p->u.mix.abspos = 0;
1.38 ratchov 1018: p->u.mix.ctl = ctl;
1.1 ratchov 1019: return p;
1.10 ratchov 1020: }
1021:
1022: /*
1.33 ratchov 1023: * Normalize input levels.
1.10 ratchov 1024: */
1025: void
1026: mix_setmaster(struct aproc *p)
1027: {
1028: unsigned n;
1.40 ratchov 1029: struct abuf *i, *j;
1.24 ratchov 1030: int weight;
1.10 ratchov 1031:
1.40 ratchov 1032: /*
1033: * count the number of inputs. If a set of inputs
1034: * uses channels that have no intersection, they are
1035: * counted only once because they don't need to
1036: * share their volume
1037: */
1.10 ratchov 1038: n = 0;
1.54 ratchov 1039: LIST_FOREACH(i, &p->ins, ient) {
1.40 ratchov 1040: j = LIST_NEXT(i, ient);
1041: for (;;) {
1042: if (j == NULL) {
1043: n++;
1044: break;
1045: }
1046: if (i->cmin > j->cmax || i->cmax < j->cmin)
1047: break;
1048: j = LIST_NEXT(j, ient);
1049: }
1.24 ratchov 1050: }
1.54 ratchov 1051: LIST_FOREACH(i, &p->ins, ient) {
1.24 ratchov 1052: weight = ADATA_UNIT / n;
1.40 ratchov 1053: if (weight > i->r.mix.maxweight)
1054: weight = i->r.mix.maxweight;
1055: i->r.mix.weight = weight;
1.42 ratchov 1056: #ifdef DEBUG
1057: if (debug_level >= 3) {
1058: abuf_dbg(i);
1059: dbg_puts(": setmaster: ");
1060: dbg_puti(i->r.mix.weight);
1061: dbg_puts("/");
1062: dbg_puti(i->r.mix.maxweight);
1063: dbg_puts("\n");
1064: }
1065: #endif
1.24 ratchov 1066: }
1.1 ratchov 1067: }
1068:
1.22 ratchov 1069: void
1070: mix_clear(struct aproc *p)
1071: {
1.54 ratchov 1072: struct abuf *obuf = LIST_FIRST(&p->outs);
1.22 ratchov 1073:
1074: p->u.mix.lat = 0;
1.51 ratchov 1075: p->u.mix.abspos = 0;
1.36 ratchov 1076: obuf->w.mix.todo = 0;
1.43 ratchov 1077: }
1078:
1079: void
1080: mix_prime(struct aproc *p)
1081: {
1.54 ratchov 1082: struct abuf *obuf = LIST_FIRST(&p->outs);
1.43 ratchov 1083: unsigned todo, count;
1084:
1085: for (;;) {
1086: if (!ABUF_WOK(obuf))
1087: break;
1.51 ratchov 1088: todo = p->u.mix.maxlat - p->u.mix.lat;
1.43 ratchov 1089: if (todo == 0)
1090: break;
1.51 ratchov 1091: mix_bzero(obuf);
1.43 ratchov 1092: count = obuf->w.mix.todo;
1093: if (count > todo)
1094: count = todo;
1095: obuf->w.mix.todo -= count;
1.51 ratchov 1096: p->u.mix.lat += count;
1097: p->u.mix.abspos += count;
1.43 ratchov 1098: abuf_wcommit(obuf, count);
1.51 ratchov 1099: if (APROC_OK(p->u.mix.mon))
1100: mon_snoop(p->u.mix.mon, obuf, 0, count);
1.43 ratchov 1101: abuf_flush(obuf);
1102: }
1103: #ifdef DEBUG
1104: if (debug_level >= 3) {
1105: aproc_dbg(p);
1106: dbg_puts(": prime: lat/maxlat=");
1107: dbg_puti(p->u.mix.lat);
1108: dbg_puts("/");
1109: dbg_puti(p->u.mix.maxlat);
1110: dbg_puts("\n");
1111: }
1112: #endif
1.22 ratchov 1113: }
1114:
1.1 ratchov 1115: /*
1.51 ratchov 1116: * Append as much as possible silence on the writer end
1117: */
1118: void
1119: sub_silence(struct abuf *buf, int extra)
1120: {
1121: unsigned char *data;
1122: unsigned count;
1123:
1124: buf->w.sub.silence += extra;
1125: if (buf->w.sub.silence > 0) {
1126: data = abuf_wgetblk(buf, &count, 0);
1127: if (count >= buf->w.sub.silence)
1128: count = buf->w.sub.silence;
1129: if (count == 0) {
1130: #ifdef DEBUG
1131: if (debug_level >= 4) {
1132: abuf_dbg(buf);
1133: dbg_puts(": no space for silence\n");
1134: }
1135: #endif
1136: return;
1137: }
1138: memset(data, 0, count * buf->bpf);
1139: abuf_wcommit(buf, count);
1140: buf->w.sub.silence -= count;
1141: #ifdef DEBUG
1142: if (debug_level >= 4) {
1143: abuf_dbg(buf);
1144: dbg_puts(": appended ");
1145: dbg_putu(count);
1146: dbg_puts(", remaining silence = ");
1147: dbg_putu(buf->w.sub.silence);
1148: dbg_puts("\n");
1149: }
1150: #endif
1151: }
1152: }
1153:
1154: /*
1.1 ratchov 1155: * Copy data from ibuf to obuf.
1156: */
1157: void
1158: sub_bcopy(struct abuf *ibuf, struct abuf *obuf)
1159: {
1.13 ratchov 1160: short *idata, *odata;
1.52 ratchov 1161: unsigned cmin, cmax;
1162: unsigned i, j, cc, istart, inext, onext, ostart;
1.1 ratchov 1163: unsigned icount, ocount, scount;
1164:
1.51 ratchov 1165: /*
1166: * Drop samples for xrun correction
1167: */
1168: if (obuf->w.sub.silence < 0) {
1169: scount = -obuf->w.sub.silence;
1170: if (scount > ibuf->used)
1171: scount = ibuf->used;
1172: obuf->w.sub.done += scount;
1173: obuf->w.sub.silence += scount;
1174: }
1175:
1.36 ratchov 1176: idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->w.sub.done);
1.1 ratchov 1177: if (icount == 0)
1178: return;
1.13 ratchov 1179: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1.1 ratchov 1180: if (ocount == 0)
1181: return;
1.52 ratchov 1182: cmin = obuf->cmin > ibuf->cmin ? obuf->cmin : ibuf->cmin;
1183: cmax = obuf->cmax < ibuf->cmax ? obuf->cmax : ibuf->cmax;
1184: ostart = cmin - obuf->cmin;
1185: istart = cmin - ibuf->cmin;
1186: onext = obuf->cmax - cmax;
1187: inext = ibuf->cmax - cmax + istart;
1188: cc = cmax - cmin + 1;
1189: idata += istart;
1.1 ratchov 1190: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 1191: for (i = scount; i > 0; i--) {
1.52 ratchov 1192: for (j = ostart; j > 0; j--)
1193: *odata++ = 0x1111;
1194: for (j = cc; j > 0; j--) {
1.13 ratchov 1195: *odata = *idata;
1196: odata++;
1197: idata++;
1198: }
1.52 ratchov 1199: for (j = onext; j > 0; j--)
1200: *odata++ = 0x2222;
1.13 ratchov 1201: idata += inext;
1202: }
1.51 ratchov 1203: abuf_wcommit(obuf, scount);
1204: obuf->w.sub.done += scount;
1.42 ratchov 1205: #ifdef DEBUG
1206: if (debug_level >= 4) {
1207: abuf_dbg(obuf);
1208: dbg_puts(": bcopy ");
1209: dbg_putu(scount);
1.51 ratchov 1210: dbg_puts("\n");
1.42 ratchov 1211: }
1212: #endif
1.1 ratchov 1213: }
1214:
1.28 ratchov 1215: /*
1.33 ratchov 1216: * Handle buffer overruns. Return 0 if the stream died.
1.28 ratchov 1217: */
1218: int
1.51 ratchov 1219: sub_xrun(struct aproc *p, struct abuf *i)
1.28 ratchov 1220: {
1.54 ratchov 1221: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.51 ratchov 1222: unsigned fdrop, remain;
1.28 ratchov 1223:
1.36 ratchov 1224: if (i->w.sub.done > 0)
1.28 ratchov 1225: return 1;
1.36 ratchov 1226: if (i->w.sub.xrun == XRUN_ERROR) {
1.28 ratchov 1227: abuf_eof(i);
1228: return 0;
1229: }
1.51 ratchov 1230: fdrop = ibuf->used;
1.42 ratchov 1231: #ifdef DEBUG
1232: if (debug_level >= 3) {
1233: abuf_dbg(i);
1234: dbg_puts(": overrun, silence ");
1235: dbg_putu(fdrop);
1236: dbg_puts(" + ");
1.51 ratchov 1237: dbg_putu(i->w.sub.silence);
1.42 ratchov 1238: dbg_puts("\n");
1239: }
1240: #endif
1.51 ratchov 1241: i->w.sub.done += fdrop;
1.36 ratchov 1242: if (i->w.sub.xrun == XRUN_SYNC)
1.51 ratchov 1243: sub_silence(i, fdrop);
1.28 ratchov 1244: else {
1.51 ratchov 1245: remain = fdrop % p->u.sub.round;
1246: if (remain)
1247: remain = p->u.sub.round - remain;
1248: sub_silence(i, -(int)remain);
1249: fdrop += remain;
1250: #ifdef DEBUG
1251: if (debug_level >= 3) {
1252: abuf_dbg(i);
1253: dbg_puts(": overrun, adding ");
1254: dbg_putu(remain);
1255: dbg_puts("\n");
1256: }
1257: #endif
1258:
1.28 ratchov 1259: abuf_ipos(i, -(int)fdrop);
1260: if (i->duplex) {
1.42 ratchov 1261: #ifdef DEBUG
1262: if (debug_level >= 3) {
1263: abuf_dbg(i->duplex);
1264: dbg_puts(": full-duplex resync\n");
1265: }
1266: #endif
1.51 ratchov 1267: mix_drop(i->duplex, -(int)fdrop);
1.28 ratchov 1268: abuf_opos(i->duplex, -(int)fdrop);
1269: }
1270: }
1271: return 1;
1272: }
1273:
1.1 ratchov 1274: int
1275: sub_in(struct aproc *p, struct abuf *ibuf)
1276: {
1277: struct abuf *i, *inext;
1.28 ratchov 1278: unsigned idone;
1.31 ratchov 1279:
1.12 ratchov 1280: if (!ABUF_ROK(ibuf))
1281: return 0;
1.28 ratchov 1282: idone = ibuf->len;
1.54 ratchov 1283: for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.1 ratchov 1284: inext = LIST_NEXT(i, oent);
1.51 ratchov 1285: sub_silence(i, 0);
1286: if (!SUB_WOK(i)) {
1.38 ratchov 1287: if (p->flags & APROC_DROP) {
1.51 ratchov 1288: if (!sub_xrun(p, i))
1.5 ratchov 1289: continue;
1290: }
1.12 ratchov 1291: } else
1.1 ratchov 1292: sub_bcopy(ibuf, i);
1.36 ratchov 1293: if (idone > i->w.sub.done)
1294: idone = i->w.sub.done;
1.12 ratchov 1295: if (!abuf_flush(i))
1296: continue;
1.1 ratchov 1297: }
1.54 ratchov 1298: if (LIST_EMPTY(&p->outs)) {
1.38 ratchov 1299: if (p->flags & APROC_QUIT) {
1.28 ratchov 1300: aproc_del(p);
1301: return 0;
1302: }
1.38 ratchov 1303: if (!(p->flags & APROC_DROP))
1.28 ratchov 1304: return 0;
1305: idone = ibuf->used;
1.51 ratchov 1306: p->u.sub.idle += idone;
1.28 ratchov 1307: }
1308: if (idone == 0)
1309: return 0;
1.54 ratchov 1310: LIST_FOREACH(i, &p->outs, oent) {
1.36 ratchov 1311: i->w.sub.done -= idone;
1.1 ratchov 1312: }
1.28 ratchov 1313: abuf_rdiscard(ibuf, idone);
1.51 ratchov 1314: abuf_opos(ibuf, idone);
1315: p->u.sub.lat -= idone;
1316: p->u.sub.abspos += idone;
1.12 ratchov 1317: return 1;
1.1 ratchov 1318: }
1319:
1320: int
1321: sub_out(struct aproc *p, struct abuf *obuf)
1322: {
1.54 ratchov 1323: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.1 ratchov 1324: struct abuf *i, *inext;
1.28 ratchov 1325: unsigned idone;
1.1 ratchov 1326:
1.51 ratchov 1327: if (!SUB_WOK(obuf))
1.12 ratchov 1328: return 0;
1.28 ratchov 1329: if (!abuf_fill(ibuf))
1330: return 0; /* eof */
1331: idone = ibuf->len;
1.54 ratchov 1332: for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.12 ratchov 1333: inext = LIST_NEXT(i, oent);
1.51 ratchov 1334: sub_silence(i, 0);
1.28 ratchov 1335: sub_bcopy(ibuf, i);
1.36 ratchov 1336: if (idone > i->w.sub.done)
1337: idone = i->w.sub.done;
1.12 ratchov 1338: if (!abuf_flush(i))
1339: continue;
1.1 ratchov 1340: }
1.54 ratchov 1341: if (LIST_EMPTY(&p->outs) || idone == 0)
1.28 ratchov 1342: return 0;
1.54 ratchov 1343: LIST_FOREACH(i, &p->outs, oent) {
1.36 ratchov 1344: i->w.sub.done -= idone;
1.1 ratchov 1345: }
1.28 ratchov 1346: abuf_rdiscard(ibuf, idone);
1.51 ratchov 1347: abuf_opos(ibuf, idone);
1348: p->u.sub.lat -= idone;
1349: p->u.sub.abspos += idone;
1.1 ratchov 1350: return 1;
1351: }
1352:
1353: void
1354: sub_eof(struct aproc *p, struct abuf *ibuf)
1355: {
1.8 ratchov 1356: aproc_del(p);
1.1 ratchov 1357: }
1358:
1359: void
1360: sub_hup(struct aproc *p, struct abuf *obuf)
1361: {
1.54 ratchov 1362: struct abuf *i, *inext, *ibuf = LIST_FIRST(&p->ins);
1.28 ratchov 1363: unsigned idone;
1.1 ratchov 1364:
1.28 ratchov 1365: if (!aproc_inuse(p)) {
1.42 ratchov 1366: #ifdef DEBUG
1367: if (debug_level >= 3) {
1368: aproc_dbg(p);
1369: dbg_puts(": running other streams\n");
1370: }
1371: #endif
1.28 ratchov 1372: /*
1.33 ratchov 1373: * Find a blocked output.
1.28 ratchov 1374: */
1375: idone = ibuf->len;
1.54 ratchov 1376: for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.51 ratchov 1377: inext = LIST_NEXT(i, oent);
1378: if (!abuf_flush(i))
1379: continue;
1380: if (SUB_WOK(i) && i->w.sub.done < ibuf->used) {
1.28 ratchov 1381: abuf_run(i);
1382: return;
1383: }
1.36 ratchov 1384: if (idone > i->w.sub.done)
1385: idone = i->w.sub.done;
1.28 ratchov 1386: }
1387: /*
1.33 ratchov 1388: * No blocked outputs. Check if input is blocked.
1.28 ratchov 1389: */
1.54 ratchov 1390: if (LIST_EMPTY(&p->outs) || idone == ibuf->used)
1.28 ratchov 1391: abuf_run(ibuf);
1392: }
1.1 ratchov 1393: }
1394:
1395: void
1396: sub_newout(struct aproc *p, struct abuf *obuf)
1397: {
1.22 ratchov 1398: p->u.sub.idle = 0;
1.36 ratchov 1399: obuf->w.sub.done = 0;
1400: obuf->w.sub.xrun = XRUN_IGNORE;
1.51 ratchov 1401: obuf->w.sub.silence = 0;
1.1 ratchov 1402: }
1403:
1.12 ratchov 1404: void
1405: sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
1406: {
1407: p->u.sub.lat += delta;
1.42 ratchov 1408: #ifdef DEBUG
1409: if (debug_level >= 4) {
1410: aproc_dbg(p);
1411: dbg_puts(": ipos: lat = ");
1412: dbg_puti(p->u.sub.lat);
1413: dbg_puts("/");
1414: dbg_puti(p->u.sub.maxlat);
1.51 ratchov 1415: dbg_puts("\n");
1.42 ratchov 1416: }
1417: #endif
1.51 ratchov 1418: if (APROC_OK(p->u.sub.ctl))
1.38 ratchov 1419: ctl_ontick(p->u.sub.ctl, delta);
1.12 ratchov 1420: aproc_ipos(p, ibuf, delta);
1421: }
1422:
1.1 ratchov 1423: struct aproc_ops sub_ops = {
1.12 ratchov 1424: "sub",
1425: sub_in,
1426: sub_out,
1427: sub_eof,
1428: sub_hup,
1429: NULL,
1430: sub_newout,
1431: sub_ipos,
1432: aproc_opos,
1433: NULL
1.1 ratchov 1434: };
1435:
1436: struct aproc *
1.51 ratchov 1437: sub_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
1.1 ratchov 1438: {
1439: struct aproc *p;
1440:
1.12 ratchov 1441: p = aproc_new(&sub_ops, name);
1.22 ratchov 1442: p->u.sub.idle = 0;
1.12 ratchov 1443: p->u.sub.lat = 0;
1.51 ratchov 1444: p->u.sub.round = round;
1.12 ratchov 1445: p->u.sub.maxlat = maxlat;
1.51 ratchov 1446: p->u.sub.abspos = 0;
1.38 ratchov 1447: p->u.sub.ctl = ctl;
1.1 ratchov 1448: return p;
1.22 ratchov 1449: }
1450:
1451: void
1452: sub_clear(struct aproc *p)
1453: {
1.51 ratchov 1454: p->u.sub.lat = 0;
1455: p->u.sub.abspos = 0;
1.1 ratchov 1456: }
1457:
1458: /*
1459: * Convert one block.
1460: */
1461: void
1.15 ratchov 1462: resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1463: {
1464: unsigned inch;
1465: short *idata;
1.27 ratchov 1466: unsigned oblksz;
1.15 ratchov 1467: unsigned ifr;
1468: unsigned onch;
1.27 ratchov 1469: int s1, s2, diff;
1.15 ratchov 1470: short *odata;
1.27 ratchov 1471: unsigned iblksz;
1.15 ratchov 1472: unsigned ofr;
1473: unsigned c;
1.31 ratchov 1474: short *ctxbuf, *ctx;
1.27 ratchov 1475: unsigned ctx_start;
1.15 ratchov 1476: unsigned icount, ocount;
1477:
1478: /*
1479: * Calculate max frames readable at once from the input buffer.
1480: */
1481: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1.51 ratchov 1482: ifr = icount;
1.15 ratchov 1483:
1484: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1.51 ratchov 1485: ofr = ocount;
1.15 ratchov 1486:
1487: /*
1488: * Partially copy structures into local variables, to avoid
1489: * unnecessary indirections; this also allows the compiler to
1490: * order local variables more "cache-friendly".
1491: */
1.27 ratchov 1492: diff = p->u.resamp.diff;
1.15 ratchov 1493: inch = ibuf->cmax - ibuf->cmin + 1;
1.26 ratchov 1494: iblksz = p->u.resamp.iblksz;
1.15 ratchov 1495: onch = obuf->cmax - obuf->cmin + 1;
1.26 ratchov 1496: oblksz = p->u.resamp.oblksz;
1.15 ratchov 1497: ctxbuf = p->u.resamp.ctx;
1.27 ratchov 1498: ctx_start = p->u.resamp.ctx_start;
1.15 ratchov 1499:
1500: /*
1501: * Start conversion.
1502: */
1.42 ratchov 1503: #ifdef DEBUG
1504: if (debug_level >= 4) {
1505: aproc_dbg(p);
1.46 ratchov 1506: dbg_puts(": resamp starting diff = ");
1507: dbg_puti(diff);
1508: dbg_puts(", ifr = ");
1.42 ratchov 1509: dbg_putu(ifr);
1510: dbg_puts(", ofr = ");
1.46 ratchov 1511: dbg_putu(ofr);
1.42 ratchov 1512: dbg_puts(" fr\n");
1513: }
1514: #endif
1.15 ratchov 1515: for (;;) {
1.27 ratchov 1516: if (diff < 0) {
1.51 ratchov 1517: if (ifr == 0)
1518: break;
1.27 ratchov 1519: ctx_start ^= 1;
1520: ctx = ctxbuf + ctx_start;
1.15 ratchov 1521: for (c = inch; c > 0; c--) {
1.29 ratchov 1522: *ctx = *idata++;
1.27 ratchov 1523: ctx += RESAMP_NCTX;
1.15 ratchov 1524: }
1.27 ratchov 1525: diff += oblksz;
1.51 ratchov 1526: ifr--;
1527: } else {
1528: if (ofr == 0)
1.50 ratchov 1529: break;
1.27 ratchov 1530: ctx = ctxbuf;
1531: for (c = onch; c > 0; c--) {
1.29 ratchov 1532: s1 = ctx[ctx_start];
1533: s2 = ctx[ctx_start ^ 1];
1.27 ratchov 1534: ctx += RESAMP_NCTX;
1535: *odata++ = s1 + (s2 - s1) * diff / (int)oblksz;
1536: }
1537: diff -= iblksz;
1.51 ratchov 1538: ofr--;
1.15 ratchov 1539: }
1540: }
1.27 ratchov 1541: p->u.resamp.diff = diff;
1542: p->u.resamp.ctx_start = ctx_start;
1.42 ratchov 1543: #ifdef DEBUG
1544: if (debug_level >= 4) {
1545: aproc_dbg(p);
1.46 ratchov 1546: dbg_puts(": resamp done delta = ");
1547: dbg_puti(diff);
1548: dbg_puts(", ifr = ");
1.42 ratchov 1549: dbg_putu(ifr);
1550: dbg_puts(", ofr = ");
1.46 ratchov 1551: dbg_putu(ofr);
1.42 ratchov 1552: dbg_puts(" fr\n");
1553: }
1554: #endif
1.15 ratchov 1555: /*
1556: * Update FIFO pointers.
1557: */
1.51 ratchov 1558: icount -= ifr;
1559: ocount -= ofr;
1.15 ratchov 1560: abuf_rdiscard(ibuf, icount);
1561: abuf_wcommit(obuf, ocount);
1562: }
1563:
1564: int
1565: resamp_in(struct aproc *p, struct abuf *ibuf)
1566: {
1.54 ratchov 1567: struct abuf *obuf = LIST_FIRST(&p->outs);
1.15 ratchov 1568:
1569: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1570: return 0;
1571: resamp_bcopy(p, ibuf, obuf);
1572: if (!abuf_flush(obuf))
1573: return 0;
1574: return 1;
1575: }
1576:
1577: int
1578: resamp_out(struct aproc *p, struct abuf *obuf)
1579: {
1.54 ratchov 1580: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 1581:
1582: if (!abuf_fill(ibuf))
1583: return 0;
1584: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1585: return 0;
1586: resamp_bcopy(p, ibuf, obuf);
1587: return 1;
1588: }
1589:
1590: void
1591: resamp_eof(struct aproc *p, struct abuf *ibuf)
1592: {
1593: aproc_del(p);
1594: }
1595:
1596: void
1597: resamp_hup(struct aproc *p, struct abuf *obuf)
1598: {
1599: aproc_del(p);
1600: }
1601:
1602: void
1603: resamp_ipos(struct aproc *p, struct abuf *ibuf, int delta)
1604: {
1.54 ratchov 1605: struct abuf *obuf = LIST_FIRST(&p->outs);
1.15 ratchov 1606: long long ipos;
1.45 ratchov 1607:
1608: ipos = (long long)delta * p->u.resamp.oblksz + p->u.resamp.idelta;
1609: p->u.resamp.idelta = ipos % p->u.resamp.iblksz;
1610: abuf_ipos(obuf, ipos / (int)p->u.resamp.iblksz);
1.15 ratchov 1611: }
1612:
1613: void
1614: resamp_opos(struct aproc *p, struct abuf *obuf, int delta)
1615: {
1.54 ratchov 1616: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 1617: long long opos;
1618:
1.45 ratchov 1619: opos = (long long)delta * p->u.resamp.iblksz + p->u.resamp.odelta;
1620: p->u.resamp.odelta = opos % p->u.resamp.oblksz;
1621: abuf_opos(ibuf, opos / p->u.resamp.oblksz);
1.15 ratchov 1622: }
1623:
1624: struct aproc_ops resamp_ops = {
1625: "resamp",
1626: resamp_in,
1627: resamp_out,
1628: resamp_eof,
1629: resamp_hup,
1630: NULL,
1631: NULL,
1632: resamp_ipos,
1633: resamp_opos,
1634: NULL
1635: };
1636:
1637: struct aproc *
1.26 ratchov 1638: resamp_new(char *name, unsigned iblksz, unsigned oblksz)
1.15 ratchov 1639: {
1640: struct aproc *p;
1.16 ratchov 1641: unsigned i;
1.15 ratchov 1642:
1643: p = aproc_new(&resamp_ops, name);
1.26 ratchov 1644: p->u.resamp.iblksz = iblksz;
1645: p->u.resamp.oblksz = oblksz;
1.48 ratchov 1646: p->u.resamp.diff = 0;
1.15 ratchov 1647: p->u.resamp.idelta = 0;
1648: p->u.resamp.odelta = 0;
1.27 ratchov 1649: p->u.resamp.ctx_start = 0;
1650: for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++)
1.16 ratchov 1651: p->u.resamp.ctx[i] = 0;
1.42 ratchov 1652: #ifdef DEBUG
1653: if (debug_level >= 3) {
1654: aproc_dbg(p);
1655: dbg_puts(": new ");
1656: dbg_putu(iblksz);
1657: dbg_puts("/");
1658: dbg_putu(oblksz);
1659: dbg_puts("\n");
1660: }
1661: #endif
1.19 ratchov 1662: return p;
1663: }
1664:
1665: /*
1666: * Convert one block.
1667: */
1668: void
1669: enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1670: {
1671: unsigned nch, scount, icount, ocount;
1672: unsigned f;
1673: short *idata;
1674: int s;
1675: unsigned oshift;
1676: int osigbit;
1677: unsigned obps;
1678: unsigned i;
1679: unsigned char *odata;
1680: int obnext;
1681: int osnext;
1682:
1683: /*
1684: * Calculate max frames readable at once from the input buffer.
1685: */
1686: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1687: if (icount == 0)
1688: return;
1689: odata = abuf_wgetblk(obuf, &ocount, 0);
1690: if (ocount == 0)
1691: return;
1692: scount = (icount < ocount) ? icount : ocount;
1693: nch = ibuf->cmax - ibuf->cmin + 1;
1.42 ratchov 1694: #ifdef DEBUG
1695: if (debug_level >= 4) {
1696: aproc_dbg(p);
1697: dbg_puts(": bcopy ");
1698: dbg_putu(scount);
1.51 ratchov 1699: dbg_puts(" fr / ");
1.42 ratchov 1700: dbg_putu(nch);
1701: dbg_puts(" ch\n");
1702: }
1703: #endif
1.19 ratchov 1704: /*
1705: * Partially copy structures into local variables, to avoid
1706: * unnecessary indirections; this also allows the compiler to
1707: * order local variables more "cache-friendly".
1708: */
1709: oshift = p->u.conv.shift;
1710: osigbit = p->u.conv.sigbit;
1711: obps = p->u.conv.bps;
1712: obnext = p->u.conv.bnext;
1713: osnext = p->u.conv.snext;
1714:
1715: /*
1716: * Start conversion.
1717: */
1718: odata += p->u.conv.bfirst;
1719: for (f = scount * nch; f > 0; f--) {
1720: s = *idata++;
1721: s <<= 16;
1722: s >>= oshift;
1723: s ^= osigbit;
1724: for (i = obps; i > 0; i--) {
1725: *odata = (unsigned char)s;
1726: s >>= 8;
1727: odata += obnext;
1728: }
1729: odata += osnext;
1730: }
1731:
1732: /*
1733: * Update FIFO pointers.
1734: */
1.51 ratchov 1735: abuf_rdiscard(ibuf, scount);
1736: abuf_wcommit(obuf, scount);
1.19 ratchov 1737: }
1738:
1739: int
1740: enc_in(struct aproc *p, struct abuf *ibuf)
1741: {
1.54 ratchov 1742: struct abuf *obuf = LIST_FIRST(&p->outs);
1.19 ratchov 1743:
1744: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1745: return 0;
1746: enc_bcopy(p, ibuf, obuf);
1747: if (!abuf_flush(obuf))
1748: return 0;
1749: return 1;
1750: }
1751:
1752: int
1753: enc_out(struct aproc *p, struct abuf *obuf)
1754: {
1.54 ratchov 1755: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.19 ratchov 1756:
1757: if (!abuf_fill(ibuf))
1758: return 0;
1759: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1760: return 0;
1761: enc_bcopy(p, ibuf, obuf);
1762: return 1;
1763: }
1764:
1765: void
1766: enc_eof(struct aproc *p, struct abuf *ibuf)
1767: {
1768: aproc_del(p);
1769: }
1770:
1771: void
1772: enc_hup(struct aproc *p, struct abuf *obuf)
1773: {
1774: aproc_del(p);
1775: }
1776:
1777: struct aproc_ops enc_ops = {
1778: "enc",
1779: enc_in,
1780: enc_out,
1781: enc_eof,
1782: enc_hup,
1783: NULL,
1784: NULL,
1785: aproc_ipos,
1786: aproc_opos,
1787: NULL
1788: };
1789:
1790: struct aproc *
1791: enc_new(char *name, struct aparams *par)
1792: {
1793: struct aproc *p;
1794:
1795: p = aproc_new(&enc_ops, name);
1796: p->u.conv.bps = par->bps;
1797: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
1798: if (par->msb) {
1799: p->u.conv.shift = 32 - par->bps * 8;
1800: } else {
1801: p->u.conv.shift = 32 - par->bits;
1802: }
1803: if (!par->le) {
1804: p->u.conv.bfirst = par->bps - 1;
1805: p->u.conv.bnext = -1;
1806: p->u.conv.snext = 2 * par->bps;
1807: } else {
1808: p->u.conv.bfirst = 0;
1809: p->u.conv.bnext = 1;
1810: p->u.conv.snext = 0;
1811: }
1.42 ratchov 1812: #ifdef DEBUG
1813: if (debug_level >= 3) {
1814: aproc_dbg(p);
1815: dbg_puts(": new ");
1816: aparams_dbg(par);
1817: dbg_puts("\n");
1818: }
1819: #endif
1.19 ratchov 1820: return p;
1821: }
1822:
1823: /*
1824: * Convert one block.
1825: */
1826: void
1827: dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1828: {
1829: unsigned nch, scount, icount, ocount;
1830: unsigned f;
1831: unsigned ibps;
1832: unsigned i;
1833: int s = 0xdeadbeef;
1834: unsigned char *idata;
1835: int ibnext;
1836: int isnext;
1837: int isigbit;
1838: unsigned ishift;
1839: short *odata;
1840:
1841: /*
1842: * Calculate max frames readable at once from the input buffer.
1843: */
1844: idata = abuf_rgetblk(ibuf, &icount, 0);
1845: if (icount == 0)
1846: return;
1847: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1848: if (ocount == 0)
1849: return;
1850: scount = (icount < ocount) ? icount : ocount;
1851: nch = obuf->cmax - obuf->cmin + 1;
1.42 ratchov 1852: #ifdef DEBUG
1853: if (debug_level >= 4) {
1854: aproc_dbg(p);
1855: dbg_puts(": bcopy ");
1856: dbg_putu(scount);
1.51 ratchov 1857: dbg_puts(" fr / ");
1.42 ratchov 1858: dbg_putu(nch);
1859: dbg_puts(" ch\n");
1860: }
1861: #endif
1.19 ratchov 1862: /*
1863: * Partially copy structures into local variables, to avoid
1864: * unnecessary indirections; this also allows the compiler to
1865: * order local variables more "cache-friendly".
1866: */
1867: ibps = p->u.conv.bps;
1868: ibnext = p->u.conv.bnext;
1869: isigbit = p->u.conv.sigbit;
1870: ishift = p->u.conv.shift;
1871: isnext = p->u.conv.snext;
1872:
1873: /*
1874: * Start conversion.
1875: */
1876: idata += p->u.conv.bfirst;
1877: for (f = scount * nch; f > 0; f--) {
1878: for (i = ibps; i > 0; i--) {
1879: s <<= 8;
1880: s |= *idata;
1881: idata += ibnext;
1882: }
1883: idata += isnext;
1884: s ^= isigbit;
1885: s <<= ishift;
1886: s >>= 16;
1887: *odata++ = s;
1888: }
1889:
1890: /*
1891: * Update FIFO pointers.
1892: */
1.51 ratchov 1893: abuf_rdiscard(ibuf, scount);
1894: abuf_wcommit(obuf, scount);
1.19 ratchov 1895: }
1896:
1897: int
1898: dec_in(struct aproc *p, struct abuf *ibuf)
1899: {
1.54 ratchov 1900: struct abuf *obuf = LIST_FIRST(&p->outs);
1.19 ratchov 1901:
1902: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1903: return 0;
1904: dec_bcopy(p, ibuf, obuf);
1905: if (!abuf_flush(obuf))
1906: return 0;
1907: return 1;
1908: }
1909:
1910: int
1911: dec_out(struct aproc *p, struct abuf *obuf)
1912: {
1.54 ratchov 1913: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.19 ratchov 1914:
1915: if (!abuf_fill(ibuf))
1916: return 0;
1917: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1918: return 0;
1919: dec_bcopy(p, ibuf, obuf);
1920: return 1;
1921: }
1922:
1923: void
1924: dec_eof(struct aproc *p, struct abuf *ibuf)
1925: {
1926: aproc_del(p);
1927: }
1928:
1929: void
1930: dec_hup(struct aproc *p, struct abuf *obuf)
1931: {
1932: aproc_del(p);
1933: }
1934:
1935: struct aproc_ops dec_ops = {
1936: "dec",
1937: dec_in,
1938: dec_out,
1939: dec_eof,
1940: dec_hup,
1941: NULL,
1942: NULL,
1943: aproc_ipos,
1944: aproc_opos,
1945: NULL
1946: };
1947:
1948: struct aproc *
1949: dec_new(char *name, struct aparams *par)
1950: {
1951: struct aproc *p;
1952:
1953: p = aproc_new(&dec_ops, name);
1954: p->u.conv.bps = par->bps;
1955: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
1956: if (par->msb) {
1957: p->u.conv.shift = 32 - par->bps * 8;
1958: } else {
1959: p->u.conv.shift = 32 - par->bits;
1960: }
1961: if (par->le) {
1962: p->u.conv.bfirst = par->bps - 1;
1963: p->u.conv.bnext = -1;
1964: p->u.conv.snext = 2 * par->bps;
1965: } else {
1966: p->u.conv.bfirst = 0;
1967: p->u.conv.bnext = 1;
1968: p->u.conv.snext = 0;
1969: }
1.42 ratchov 1970: #ifdef DEBUG
1971: if (debug_level >= 3) {
1972: aproc_dbg(p);
1973: dbg_puts(": new ");
1974: aparams_dbg(par);
1.53 ratchov 1975: dbg_puts("\n");
1976: }
1977: #endif
1978: return p;
1979: }
1980:
1981: /*
1982: * Convert one block.
1983: */
1984: void
1985: join_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1986: {
1987: unsigned h, hops;
1988: unsigned inch, inext;
1989: short *idata;
1990: unsigned onch, onext;
1991: short *odata;
1992: int scale;
1993: unsigned c, f, scount, icount, ocount;
1994:
1995: /*
1996: * Calculate max frames readable at once from the input buffer.
1997: */
1998: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1999: if (icount == 0)
2000: return;
2001: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
2002: if (ocount == 0)
2003: return;
2004: scount = icount < ocount ? icount : ocount;
2005: inch = ibuf->cmax - ibuf->cmin + 1;
2006: onch = obuf->cmax - obuf->cmin + 1;
2007: if (2 * inch <= onch) {
2008: hops = onch / inch;
2009: inext = inch * hops;
2010: onext = onch - inext;
2011: for (f = scount; f > 0; f--) {
2012: h = hops;
2013: for (;;) {
2014: for (c = inch; c > 0; c--)
2015: *odata++ = *idata++;
2016: if (--h == 0)
2017: break;
2018: idata -= inch;
2019: }
2020: for (c = onext; c > 0; c--)
2021: *odata++ = 0;
2022: }
2023: } else if (inch >= 2 * onch) {
2024: hops = inch / onch;
2025: inext = inch - onch * hops;
2026: scale = ADATA_UNIT / hops;
2027: inch -= onch + inext;
2028: hops--;
2029: for (f = scount; f > 0; f--) {
2030: for (c = onch; c > 0; c--)
2031: *odata++ = (*idata++ * scale)
2032: >> ADATA_SHIFT;
2033: for (h = hops; h > 0; h--) {
2034: odata -= onch;
2035: for (c = onch; c > 0; c--)
2036: *odata++ += (*idata++ * scale)
2037: >> ADATA_SHIFT;
2038: }
2039: idata += inext;
2040: }
2041: } else {
2042: #ifdef DEBUG
2043: aproc_dbg(p);
2044: dbg_puts(": nothing to do\n");
2045: dbg_panic();
2046: #endif
2047: }
2048: #ifdef DEBUG
2049: if (debug_level >= 4) {
2050: aproc_dbg(p);
2051: dbg_puts(": bcopy ");
2052: dbg_putu(scount);
2053: dbg_puts(" fr\n");
2054: }
2055: #endif
2056: abuf_rdiscard(ibuf, scount);
2057: abuf_wcommit(obuf, scount);
2058: }
2059:
2060: int
2061: join_in(struct aproc *p, struct abuf *ibuf)
2062: {
1.54 ratchov 2063: struct abuf *obuf = LIST_FIRST(&p->outs);
1.53 ratchov 2064:
2065: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
2066: return 0;
2067: join_bcopy(p, ibuf, obuf);
2068: if (!abuf_flush(obuf))
2069: return 0;
2070: return 1;
2071: }
2072:
2073: int
2074: join_out(struct aproc *p, struct abuf *obuf)
2075: {
1.54 ratchov 2076: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.53 ratchov 2077:
2078: if (!abuf_fill(ibuf))
2079: return 0;
2080: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
2081: return 0;
2082: join_bcopy(p, ibuf, obuf);
2083: return 1;
2084: }
2085:
2086: void
2087: join_eof(struct aproc *p, struct abuf *ibuf)
2088: {
2089: aproc_del(p);
2090: }
2091:
2092: void
2093: join_hup(struct aproc *p, struct abuf *obuf)
2094: {
2095: aproc_del(p);
2096: }
2097:
2098: struct aproc_ops join_ops = {
2099: "join",
2100: join_in,
2101: join_out,
2102: join_eof,
2103: join_hup,
2104: NULL,
2105: NULL,
2106: aproc_ipos,
2107: aproc_opos,
2108: NULL
2109: };
2110:
2111: struct aproc *
2112: join_new(char *name)
2113: {
2114: struct aproc *p;
2115:
2116: p = aproc_new(&join_ops, name);
2117: #ifdef DEBUG
2118: if (debug_level >= 3) {
2119: aproc_dbg(p);
1.42 ratchov 2120: dbg_puts("\n");
1.51 ratchov 2121: }
2122: #endif
2123: return p;
2124: }
2125:
2126: /*
2127: * Commit and flush part of the output buffer
2128: */
2129: void
2130: mon_flush(struct aproc *p)
2131: {
1.54 ratchov 2132: struct abuf *obuf = LIST_FIRST(&p->outs);
1.51 ratchov 2133: unsigned count;
2134:
2135: #ifdef DEBUG
2136: if (debug_level >= 4) {
2137: aproc_dbg(p);
2138: dbg_puts(": delta = ");
2139: dbg_puti(p->u.mon.delta);
2140: dbg_puts("/");
2141: dbg_putu(p->u.mon.bufsz);
2142: dbg_puts(" pending = ");
2143: dbg_puti(p->u.mon.pending);
2144: dbg_puts("\n");
2145: }
2146: #endif
2147: if (p->u.mon.delta <= 0 || p->u.mon.pending == 0)
2148: return;
2149: count = p->u.mon.delta;
2150: if (count > p->u.mon.pending)
2151: count = p->u.mon.pending;
2152: abuf_wcommit(obuf, count);
2153: p->u.mon.pending -= count;
2154: p->u.mon.delta -= count;
2155: abuf_flush(obuf);
2156: }
2157:
2158: /*
2159: * Copy one block.
2160: */
2161: void
2162: mon_snoop(struct aproc *p, struct abuf *ibuf, unsigned pos, unsigned todo)
2163: {
1.54 ratchov 2164: struct abuf *obuf = LIST_FIRST(&p->outs);
1.51 ratchov 2165: unsigned scount, icount, ocount;
2166: short *idata, *odata;
2167:
2168: #ifdef DEBUG
2169: if (debug_level >= 4) {
2170: aproc_dbg(p);
2171: dbg_puts(": snoop ");
2172: dbg_putu(pos);
2173: dbg_puts("..");
2174: dbg_putu(todo);
2175: dbg_puts("\n");
2176: }
2177: #endif
2178: if (!abuf_flush(obuf))
2179: return;
2180:
2181: while (todo > 0) {
2182: /*
2183: * Calculate max frames readable at once from the input buffer.
2184: */
2185: idata = (short *)abuf_rgetblk(ibuf, &icount, pos);
2186: odata = (short *)abuf_wgetblk(obuf, &ocount, p->u.mon.pending);
2187: scount = (icount < ocount) ? icount : ocount;
2188: #ifdef DEBUG
2189: if (debug_level >= 4) {
2190: aproc_dbg(p);
2191: dbg_puts(": snooping ");
2192: dbg_putu(scount);
2193: dbg_puts(" fr\n");
2194: }
2195: if (scount == 0) {
2196: dbg_puts("monitor xrun, not allowed\n");
2197: dbg_panic();
2198: }
2199: #endif
2200: memcpy(odata, idata, scount * obuf->bpf);
2201: p->u.mon.pending += scount;
2202: todo -= scount;
2203: pos += scount;
2204: }
2205: mon_flush(p);
2206: }
2207:
2208: int
2209: mon_in(struct aproc *p, struct abuf *ibuf)
2210: {
2211: #ifdef DEBUG
2212: dbg_puts("monitor can't have inputs to read\n");
2213: dbg_panic();
2214: #endif
2215: return 0;
2216: }
2217:
2218: /*
2219: * put the monitor into ``empty'' state
2220: */
2221: void
2222: mon_clear(struct aproc *p)
2223: {
2224: p->u.mon.pending = 0;
2225: p->u.mon.delta = 0;
2226: }
2227:
2228: int
2229: mon_out(struct aproc *p, struct abuf *obuf)
2230: {
2231: /*
2232: * can't trigger monitored stream to produce data
2233: */
2234: return 0;
2235: }
2236:
2237: void
2238: mon_eof(struct aproc *p, struct abuf *ibuf)
2239: {
2240: #ifdef DEBUG
2241: dbg_puts("monitor can't have inputs to eof\n");
2242: dbg_panic();
2243: #endif
2244: }
2245:
2246: void
2247: mon_hup(struct aproc *p, struct abuf *obuf)
2248: {
2249: aproc_del(p);
2250: }
2251:
2252: void
2253: mon_ipos(struct aproc *p, struct abuf *ibuf, int delta)
2254: {
2255: aproc_ipos(p, ibuf, delta);
2256: p->u.mon.delta += delta;
2257: mon_flush(p);
2258: }
2259:
2260: struct aproc_ops mon_ops = {
2261: "mon",
2262: mon_in,
2263: mon_out,
2264: mon_eof,
2265: mon_hup,
2266: NULL,
2267: NULL,
2268: mon_ipos,
2269: aproc_opos,
2270: NULL
2271: };
2272:
2273: struct aproc *
2274: mon_new(char *name, unsigned bufsz)
2275: {
2276: struct aproc *p;
2277:
2278: p = aproc_new(&mon_ops, name);
2279: p->u.mon.pending = 0;
2280: p->u.mon.delta = 0;
2281: p->u.mon.bufsz = bufsz;
2282: #ifdef DEBUG
2283: if (debug_level >= 3) {
2284: aproc_dbg(p);
2285: dbg_puts(": new\n");
1.42 ratchov 2286: }
2287: #endif
1.1 ratchov 2288: return p;
2289: }