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