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