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