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