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