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