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