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