Annotation of src/usr.bin/aucat/aproc.c, Revision 1.12
1.11 ratchov 1: /* $OpenBSD: aproc.c,v 1.10 2008/08/14 09:58: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: *
34: * TODO
35: *
36: * (easy) split the "conv" into 2 converters: one for input (that
37: * convers anything to 16bit signed) and one for the output (that
38: * converts 16bit signed to anything)
39: *
40: * (hard) add a lowpass filter for the resampler. Quality is
41: * not acceptable as is.
1.12 ! ratchov 42: *
1.1 ratchov 43: */
44: #include <err.h>
45: #include <limits.h>
46: #include <stdio.h>
47: #include <stdlib.h>
48: #include <string.h>
49:
50: #include "conf.h"
51: #include "aparams.h"
52: #include "abuf.h"
53: #include "aproc.h"
54: #include "file.h"
55:
56: struct aproc *
57: aproc_new(struct aproc_ops *ops, char *name)
58: {
59: struct aproc *p;
60:
61: p = malloc(sizeof(struct aproc));
62: if (p == NULL)
63: err(1, name);
64: LIST_INIT(&p->ibuflist);
65: LIST_INIT(&p->obuflist);
66: p->name = name;
67: p->ops = ops;
68: return p;
69: }
70:
71: void
72: aproc_del(struct aproc *p)
73: {
1.12 ! ratchov 74: struct abuf *i;
! 75:
! 76: DPRINTF("aproc_del: %s(%s): terminating...\n", p->ops->name, p->name);
! 77:
1.8 ratchov 78: if (p->ops->done)
79: p->ops->done(p);
1.12 ! ratchov 80:
! 81: while (!LIST_EMPTY(&p->ibuflist)) {
! 82: i = LIST_FIRST(&p->ibuflist);
! 83: abuf_hup(i);
! 84: }
! 85: while (!LIST_EMPTY(&p->obuflist)) {
! 86: i = LIST_FIRST(&p->obuflist);
! 87: abuf_eof(i);
! 88: }
! 89: DPRINTF("aproc_del: %s(%s): freed\n", p->ops->name, p->name);
1.1 ratchov 90: free(p);
91: }
92:
93: void
94: aproc_setin(struct aproc *p, struct abuf *ibuf)
95: {
96: LIST_INSERT_HEAD(&p->ibuflist, ibuf, ient);
97: ibuf->rproc = p;
98: if (p->ops->newin)
99: p->ops->newin(p, ibuf);
100: }
101:
102: void
103: aproc_setout(struct aproc *p, struct abuf *obuf)
104: {
105: LIST_INSERT_HEAD(&p->obuflist, obuf, oent);
106: obuf->wproc = p;
107: if (p->ops->newout)
108: p->ops->newout(p, obuf);
109: }
110:
1.12 ! ratchov 111: void
! 112: aproc_ipos(struct aproc *p, struct abuf *ibuf, int delta)
! 113: {
! 114: struct abuf *obuf;
! 115:
! 116: DPRINTFN(3, "aproc_ipos: %s: delta = %d\n", p->name, delta);
! 117:
! 118: LIST_FOREACH(obuf, &p->obuflist, oent) {
! 119: abuf_ipos(obuf, delta);
! 120: }
! 121: }
! 122:
! 123: void
! 124: aproc_opos(struct aproc *p, struct abuf *obuf, int delta)
! 125: {
! 126: struct abuf *ibuf;
! 127:
! 128: DPRINTFN(3, "aproc_opos: %s: delta = %d\n", p->name, delta);
! 129:
! 130: LIST_FOREACH(ibuf, &p->ibuflist, ient) {
! 131: abuf_opos(ibuf, delta);
! 132: }
! 133: }
! 134:
1.1 ratchov 135: int
136: rpipe_in(struct aproc *p, struct abuf *ibuf_dummy)
137: {
138: struct abuf *obuf = LIST_FIRST(&p->obuflist);
139: struct file *f = p->u.io.file;
140: unsigned char *data;
141: unsigned count;
142:
1.6 ratchov 143: DPRINTFN(3, "rpipe_in: %s\n", p->name);
144:
1.12 ! ratchov 145: if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
1.1 ratchov 146: return 0;
147: data = abuf_wgetblk(obuf, &count, 0);
1.6 ratchov 148: count = file_read(f, data, count);
1.12 ! ratchov 149: if (count == 0)
! 150: return 0;
1.6 ratchov 151: abuf_wcommit(obuf, count);
1.12 ! ratchov 152: if (!abuf_flush(obuf))
! 153: return 0;
! 154: return 1;
1.1 ratchov 155: }
156:
157: int
158: rpipe_out(struct aproc *p, struct abuf *obuf)
159: {
160: struct file *f = p->u.io.file;
161: unsigned char *data;
162: unsigned count;
163:
1.12 ! ratchov 164: if (f->refs > 0)
! 165: return 0;
1.6 ratchov 166: DPRINTFN(3, "rpipe_out: %s\n", p->name);
1.12 ! ratchov 167:
! 168: if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
1.1 ratchov 169: return 0;
170: data = abuf_wgetblk(obuf, &count, 0);
1.6 ratchov 171: count = file_read(f, data, count);
1.12 ! ratchov 172: if (count == 0)
! 173: return 0;
1.6 ratchov 174: abuf_wcommit(obuf, count);
1.12 ! ratchov 175: return 1;
1.1 ratchov 176: }
177:
178: void
1.8 ratchov 179: rpipe_done(struct aproc *p)
1.1 ratchov 180: {
181: struct file *f = p->u.io.file;
182:
183: f->rproc = NULL;
1.12 ! ratchov 184: if (f->wproc == NULL)
! 185: file_del(f);
1.1 ratchov 186: }
187:
188: void
189: rpipe_eof(struct aproc *p, struct abuf *ibuf_dummy)
190: {
191: DPRINTFN(3, "rpipe_eof: %s\n", p->name);
1.8 ratchov 192: aproc_del(p);
1.1 ratchov 193: }
194:
195: void
196: rpipe_hup(struct aproc *p, struct abuf *obuf)
197: {
198: DPRINTFN(3, "rpipe_hup: %s\n", p->name);
1.8 ratchov 199: aproc_del(p);
1.1 ratchov 200: }
201:
202: struct aproc_ops rpipe_ops = {
1.12 ! ratchov 203: "rpipe",
! 204: rpipe_in,
! 205: rpipe_out,
! 206: rpipe_eof,
! 207: rpipe_hup,
! 208: NULL, /* newin */
! 209: NULL, /* newout */
! 210: aproc_ipos,
! 211: aproc_opos,
! 212: rpipe_done
1.1 ratchov 213: };
214:
215: struct aproc *
216: rpipe_new(struct file *f)
217: {
218: struct aproc *p;
219:
220: p = aproc_new(&rpipe_ops, f->name);
221: p->u.io.file = f;
1.12 ! ratchov 222: f->rproc = p;
1.1 ratchov 223: return p;
224: }
225:
226: void
1.8 ratchov 227: wpipe_done(struct aproc *p)
1.1 ratchov 228: {
229: struct file *f = p->u.io.file;
230:
231: f->wproc = NULL;
1.12 ! ratchov 232: if (f->rproc == NULL)
! 233: file_del(f);
1.1 ratchov 234: }
235:
236: int
237: wpipe_in(struct aproc *p, struct abuf *ibuf)
238: {
239: struct file *f = p->u.io.file;
240: unsigned char *data;
241: unsigned count;
242:
1.12 ! ratchov 243: if (f->refs > 0)
! 244: return 0;
1.6 ratchov 245: DPRINTFN(3, "wpipe_in: %s\n", p->name);
246:
1.12 ! ratchov 247: if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
1.1 ratchov 248: return 0;
249: data = abuf_rgetblk(ibuf, &count, 0);
250: count = file_write(f, data, count);
1.12 ! ratchov 251: if (count == 0)
! 252: return 0;
1.6 ratchov 253: abuf_rdiscard(ibuf, count);
1.12 ! ratchov 254: return 1;
1.1 ratchov 255: }
256:
257: int
258: wpipe_out(struct aproc *p, struct abuf *obuf_dummy)
259: {
260: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
261: struct file *f = p->u.io.file;
262: unsigned char *data;
263: unsigned count;
264:
1.6 ratchov 265: DPRINTFN(3, "wpipe_out: %s\n", p->name);
266:
1.12 ! ratchov 267: if (!abuf_fill(ibuf)) {
! 268: DPRINTFN(3, "wpipe_out: fill failed\n");
! 269: return 0;
! 270: }
! 271: if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
1.1 ratchov 272: return 0;
273: data = abuf_rgetblk(ibuf, &count, 0);
1.12 ! ratchov 274: if (count == 0) {
! 275: DPRINTF("wpipe_out: %s: underrun\n", p->name);
! 276: return 0;
! 277: }
1.1 ratchov 278: count = file_write(f, data, count);
1.12 ! ratchov 279: if (count == 0)
! 280: return 0;
1.6 ratchov 281: abuf_rdiscard(ibuf, count);
1.1 ratchov 282: return 1;
283: }
284:
285: void
286: wpipe_eof(struct aproc *p, struct abuf *ibuf)
287: {
288: DPRINTFN(3, "wpipe_eof: %s\n", p->name);
1.8 ratchov 289: aproc_del(p);
1.1 ratchov 290: }
291:
292: void
293: wpipe_hup(struct aproc *p, struct abuf *obuf_dummy)
294: {
295: DPRINTFN(3, "wpipe_hup: %s\n", p->name);
1.8 ratchov 296: aproc_del(p);
1.1 ratchov 297: }
298:
299: struct aproc_ops wpipe_ops = {
1.12 ! ratchov 300: "wpipe",
! 301: wpipe_in,
! 302: wpipe_out,
! 303: wpipe_eof,
! 304: wpipe_hup,
! 305: NULL, /* newin */
! 306: NULL, /* newout */
! 307: aproc_ipos,
! 308: aproc_opos,
! 309: wpipe_done
1.1 ratchov 310: };
311:
312: struct aproc *
313: wpipe_new(struct file *f)
314: {
315: struct aproc *p;
316:
317: p = aproc_new(&wpipe_ops, f->name);
318: p->u.io.file = f;
319: f->wproc = p;
320: return p;
321: }
322:
323: /*
324: * Fill an output block with silence.
325: */
326: void
327: mix_bzero(struct aproc *p)
328: {
329: struct abuf *obuf = LIST_FIRST(&p->obuflist);
330: short *odata;
331: unsigned ocount;
332:
1.6 ratchov 333: DPRINTFN(4, "mix_bzero: used = %u, todo = %u\n",
1.1 ratchov 334: obuf->used, obuf->mixtodo);
335: odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->mixtodo);
1.12 ! ratchov 336: ocount -= ocount % obuf->bpf;
1.1 ratchov 337: if (ocount == 0)
338: return;
339: memset(odata, 0, ocount);
340: obuf->mixtodo += ocount;
341: DPRINTFN(4, "mix_bzero: ocount %u, todo %u\n", ocount, obuf->mixtodo);
342: }
343:
344: /*
345: * Mix an input block over an output block.
346: */
347: void
348: mix_badd(struct abuf *ibuf, struct abuf *obuf)
349: {
350: short *idata, *odata;
351: unsigned i, scount, icount, ocount;
352: int vol = ibuf->mixvol;
353:
1.6 ratchov 354: DPRINTFN(4, "mix_badd: todo = %u, done = %u\n",
1.1 ratchov 355: obuf->mixtodo, ibuf->mixdone);
356:
357: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1.12 ! ratchov 358: icount -= icount % ibuf->bpf;
1.1 ratchov 359: if (icount == 0)
360: return;
361:
362: odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixdone);
1.12 ! ratchov 363: ocount -= ocount % obuf->bpf;
1.1 ratchov 364: if (ocount == 0)
365: return;
366:
367: scount = (icount < ocount) ? icount : ocount;
368: for (i = scount / sizeof(short); i > 0; i--) {
369: *odata += (*idata * vol) >> ADATA_SHIFT;
370: idata++;
371: odata++;
1.6 ratchov 372: }
373: abuf_rdiscard(ibuf, scount);
1.1 ratchov 374: ibuf->mixdone += scount;
375:
1.6 ratchov 376: DPRINTFN(4, "mix_badd: added %u, done = %u, todo = %u\n",
1.1 ratchov 377: scount, ibuf->mixdone, obuf->mixtodo);
378: }
379:
380: int
381: mix_in(struct aproc *p, struct abuf *ibuf)
382: {
383: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
1.7 ratchov 384: unsigned ocount;
1.1 ratchov 385:
1.7 ratchov 386: DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %u\n",
1.1 ratchov 387: ibuf->used, ibuf->mixdone, obuf->mixtodo);
1.3 ratchov 388:
1.12 ! ratchov 389: if (!ABUF_ROK(ibuf) || ibuf->mixdone == obuf->mixtodo)
1.1 ratchov 390: return 0;
1.12 ! ratchov 391:
1.1 ratchov 392: mix_badd(ibuf, obuf);
393: ocount = obuf->mixtodo;
394: LIST_FOREACH(i, &p->ibuflist, ient) {
395: if (ocount > i->mixdone)
396: ocount = i->mixdone;
397: }
398: if (ocount == 0)
399: return 0;
400:
1.6 ratchov 401: abuf_wcommit(obuf, ocount);
1.12 ! ratchov 402: p->u.mix.lat += ocount / obuf->bpf;
1.1 ratchov 403: obuf->mixtodo -= ocount;
1.12 ! ratchov 404: if (!abuf_flush(obuf))
! 405: return 0; /* hup */
1.1 ratchov 406: mix_bzero(p);
1.12 ! ratchov 407: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 408: inext = LIST_NEXT(i, ient);
409: i->mixdone -= ocount;
1.12 ! ratchov 410: if (i->mixdone < obuf->mixtodo)
1.1 ratchov 411: mix_badd(i, obuf);
1.12 ! ratchov 412: if (!abuf_fill(i))
! 413: continue;
1.1 ratchov 414: }
415: return 1;
416: }
417:
418: int
419: mix_out(struct aproc *p, struct abuf *obuf)
420: {
421: struct abuf *i, *inext;
1.3 ratchov 422: unsigned ocount, drop;
1.1 ratchov 423:
1.6 ratchov 424: DPRINTFN(4, "mix_out: used = %u, todo = %u\n",
1.1 ratchov 425: obuf->used, obuf->mixtodo);
426:
1.12 ! ratchov 427: if (!ABUF_WOK(obuf))
! 428: return 0;
! 429:
1.1 ratchov 430: mix_bzero(p);
431: ocount = obuf->mixtodo;
1.12 ! ratchov 432: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 433: inext = LIST_NEXT(i, ient);
1.12 ! ratchov 434: if (!abuf_fill(i))
! 435: continue;
1.5 ratchov 436: if (!ABUF_ROK(i)) {
437: if ((p->u.mix.flags & MIX_DROP) && i->mixdone == 0) {
438: if (i->xrun == XRUN_ERROR) {
439: abuf_hup(i);
440: continue;
441: }
442: drop = obuf->mixtodo;
443: i->mixdone += drop;
444: if (i->xrun == XRUN_SYNC)
1.7 ratchov 445: i->drop += drop;
1.12 ! ratchov 446: else {
! 447: abuf_opos(i, -(int)(drop / i->bpf));
! 448: if (i->duplex) {
! 449: DPRINTF("mix_out: duplex %u\n",
! 450: drop);
! 451: i->duplex->drop += drop *
! 452: i->duplex->bpf / i->bpf;
! 453: abuf_ipos(i->duplex,
! 454: -(int)(drop / i->bpf));
! 455: }
! 456: }
1.7 ratchov 457: DPRINTF("mix_out: drop = %u\n", i->drop);
1.5 ratchov 458: }
1.3 ratchov 459: } else
460: mix_badd(i, obuf);
1.1 ratchov 461: if (ocount > i->mixdone)
462: ocount = i->mixdone;
463: }
464: if (ocount == 0)
465: return 0;
1.9 ratchov 466: if (LIST_EMPTY(&p->ibuflist) && (p->u.mix.flags & MIX_AUTOQUIT)) {
1.1 ratchov 467: DPRINTF("mix_out: nothing more to do...\n");
468: aproc_del(p);
469: return 0;
470: }
1.6 ratchov 471: abuf_wcommit(obuf, ocount);
1.12 ! ratchov 472: p->u.mix.lat += ocount / obuf->bpf;
1.1 ratchov 473: obuf->mixtodo -= ocount;
474: LIST_FOREACH(i, &p->ibuflist, ient) {
475: i->mixdone -= ocount;
476: }
477: return 1;
478: }
479:
480: void
481: mix_eof(struct aproc *p, struct abuf *ibuf)
482: {
483: struct abuf *obuf = LIST_FIRST(&p->obuflist);
484:
485: DPRINTF("mix_eof: %s: detached\n", p->name);
1.12 ! ratchov 486: mix_setmaster(p);
! 487:
1.1 ratchov 488: /*
489: * If there's no more inputs, abuf_run() will trigger the eof
490: * condition and propagate it, so no need to handle it here.
491: */
492: abuf_run(obuf);
493: DPRINTF("mix_eof: done\n");
494: }
495:
496: void
497: mix_hup(struct aproc *p, struct abuf *obuf)
498: {
499: struct abuf *ibuf;
500:
501: while (!LIST_EMPTY(&p->ibuflist)) {
502: ibuf = LIST_FIRST(&p->ibuflist);
503: abuf_hup(ibuf);
504: }
505: DPRINTF("mix_hup: %s: done\n", p->name);
506: aproc_del(p);
507: }
508:
509: void
510: mix_newin(struct aproc *p, struct abuf *ibuf)
511: {
512: ibuf->mixdone = 0;
513: ibuf->mixvol = ADATA_UNIT;
1.5 ratchov 514: ibuf->xrun = XRUN_IGNORE;
1.12 ! ratchov 515: mix_setmaster(p);
1.1 ratchov 516: }
517:
518: void
519: mix_newout(struct aproc *p, struct abuf *obuf)
520: {
521: obuf->mixtodo = 0;
522: mix_bzero(p);
523: }
524:
1.12 ! ratchov 525: void
! 526: mix_opos(struct aproc *p, struct abuf *obuf, int delta)
! 527: {
! 528: DPRINTFN(3, "mix_opos: lat = %d/%d\n", p->u.mix.lat, p->u.mix.maxlat);
! 529: p->u.mix.lat -= delta;
! 530: aproc_opos(p, obuf, delta);
! 531: }
! 532:
1.1 ratchov 533: struct aproc_ops mix_ops = {
1.12 ! ratchov 534: "mix",
! 535: mix_in,
! 536: mix_out,
! 537: mix_eof,
! 538: mix_hup,
! 539: mix_newin,
! 540: mix_newout,
! 541: aproc_ipos,
! 542: mix_opos,
! 543: NULL
1.1 ratchov 544: };
545:
546: struct aproc *
1.12 ! ratchov 547: mix_new(char *name, int maxlat)
1.1 ratchov 548: {
549: struct aproc *p;
550:
1.12 ! ratchov 551: p = aproc_new(&mix_ops, name);
1.5 ratchov 552: p->u.mix.flags = 0;
1.12 ! ratchov 553: p->u.mix.lat = 0;
! 554: p->u.mix.maxlat = maxlat;
1.1 ratchov 555: return p;
1.10 ratchov 556: }
557:
558: void
559: mix_pushzero(struct aproc *p)
560: {
561: struct abuf *obuf = LIST_FIRST(&p->obuflist);
562:
563: abuf_wcommit(obuf, obuf->mixtodo);
1.12 ! ratchov 564: p->u.mix.lat += obuf->mixtodo / obuf->bpf;
1.10 ratchov 565: obuf->mixtodo = 0;
1.11 ratchov 566: abuf_run(obuf);
1.10 ratchov 567: mix_bzero(p);
568: }
569:
570: /*
571: * Normalize input levels
572: */
573: void
574: mix_setmaster(struct aproc *p)
575: {
576: unsigned n;
577: struct abuf *buf;
578:
579: n = 0;
580: LIST_FOREACH(buf, &p->ibuflist, ient)
581: n++;
582: LIST_FOREACH(buf, &p->ibuflist, ient)
583: buf->mixvol = ADATA_UNIT / n;
1.1 ratchov 584: }
585:
586: /*
587: * Copy data from ibuf to obuf.
588: */
589: void
590: sub_bcopy(struct abuf *ibuf, struct abuf *obuf)
591: {
592: unsigned char *idata, *odata;
593: unsigned icount, ocount, scount;
594:
595: idata = abuf_rgetblk(ibuf, &icount, obuf->subdone);
1.12 ! ratchov 596: icount -= icount % ibuf->bpf;
1.1 ratchov 597: if (icount == 0)
598: return;
599: odata = abuf_wgetblk(obuf, &ocount, 0);
1.12 ! ratchov 600: ocount -= icount % obuf->bpf;
1.1 ratchov 601: if (ocount == 0)
602: return;
603: scount = (icount < ocount) ? icount : ocount;
604: memcpy(odata, idata, scount);
1.12 ! ratchov 605: abuf_wcommit(obuf, scount);
1.1 ratchov 606: obuf->subdone += scount;
607: DPRINTFN(4, "sub_bcopy: %u bytes\n", scount);
608: }
609:
610: int
611: sub_in(struct aproc *p, struct abuf *ibuf)
612: {
613: struct abuf *i, *inext;
1.3 ratchov 614: unsigned done, drop;
1.12 ! ratchov 615:
! 616: if (!ABUF_ROK(ibuf))
! 617: return 0;
1.1 ratchov 618: done = ibuf->used;
1.12 ! ratchov 619: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
1.1 ratchov 620: inext = LIST_NEXT(i, oent);
1.5 ratchov 621: if (!ABUF_WOK(i)) {
622: if ((p->u.sub.flags & SUB_DROP) && i->subdone == 0) {
623: if (i->xrun == XRUN_ERROR) {
624: abuf_eof(i);
625: continue;
626: }
627: drop = ibuf->used;
628: if (i->xrun == XRUN_SYNC)
1.7 ratchov 629: i->silence += drop;
1.12 ! ratchov 630: else {
! 631: abuf_ipos(i, -(int)(drop / i->bpf));
! 632: if (i->duplex) {
! 633: DPRINTF("sub_in: duplex %u\n",
! 634: drop);
! 635: i->duplex->silence += drop *
! 636: i->duplex->bpf / i->bpf;
! 637: abuf_opos(i->duplex,
! 638: -(int)(drop / i->bpf));
! 639: }
! 640: }
1.5 ratchov 641: i->subdone += drop;
1.12 ! ratchov 642: DPRINTF("sub_in: silence = %u\n", i->silence);
1.5 ratchov 643: }
1.12 ! ratchov 644: } else
1.1 ratchov 645: sub_bcopy(ibuf, i);
646: if (done > i->subdone)
647: done = i->subdone;
1.12 ! ratchov 648: if (!abuf_flush(i))
! 649: continue;
1.1 ratchov 650: }
651: LIST_FOREACH(i, &p->obuflist, oent) {
652: i->subdone -= done;
653: }
1.6 ratchov 654: abuf_rdiscard(ibuf, done);
1.12 ! ratchov 655: p->u.sub.lat -= done / ibuf->bpf;
! 656: return 1;
1.1 ratchov 657: }
658:
659: int
660: sub_out(struct aproc *p, struct abuf *obuf)
661: {
662: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
663: struct abuf *i, *inext;
664: unsigned done;
665:
1.12 ! ratchov 666: if (!ABUF_WOK(obuf))
! 667: return 0;
! 668: if (!abuf_fill(ibuf)) {
! 669: return 0;
! 670: }
! 671: if (obuf->subdone == ibuf->used)
1.1 ratchov 672: return 0;
673:
674: done = ibuf->used;
1.12 ! ratchov 675: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
! 676: inext = LIST_NEXT(i, oent);
! 677: if (!abuf_flush(i))
! 678: continue;
! 679: sub_bcopy(ibuf, i);
1.1 ratchov 680: if (done > i->subdone)
681: done = i->subdone;
682: }
683: LIST_FOREACH(i, &p->obuflist, oent) {
684: i->subdone -= done;
685: }
1.6 ratchov 686: abuf_rdiscard(ibuf, done);
1.12 ! ratchov 687: p->u.sub.lat -= done / ibuf->bpf;
1.1 ratchov 688: return 1;
689: }
690:
691: void
692: sub_eof(struct aproc *p, struct abuf *ibuf)
693: {
694: struct abuf *obuf;
695:
696: while (!LIST_EMPTY(&p->obuflist)) {
697: obuf = LIST_FIRST(&p->obuflist);
698: abuf_eof(obuf);
699: }
1.8 ratchov 700: aproc_del(p);
1.1 ratchov 701: }
702:
703: void
704: sub_hup(struct aproc *p, struct abuf *obuf)
705: {
706: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
707:
708: DPRINTF("sub_hup: %s: detached\n", p->name);
1.12 ! ratchov 709: abuf_run(ibuf);
1.1 ratchov 710: DPRINTF("sub_hup: done\n");
711: }
712:
713: void
714: sub_newout(struct aproc *p, struct abuf *obuf)
715: {
716: obuf->subdone = 0;
1.5 ratchov 717: obuf->xrun = XRUN_IGNORE;
1.1 ratchov 718: }
719:
1.12 ! ratchov 720: void
! 721: sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
! 722: {
! 723: p->u.sub.lat += delta;
! 724: DPRINTFN(3, "sub_ipos: lat = %d/%d\n", p->u.sub.lat, p->u.sub.maxlat);
! 725: aproc_ipos(p, ibuf, delta);
! 726: }
! 727:
1.1 ratchov 728: struct aproc_ops sub_ops = {
1.12 ! ratchov 729: "sub",
! 730: sub_in,
! 731: sub_out,
! 732: sub_eof,
! 733: sub_hup,
! 734: NULL,
! 735: sub_newout,
! 736: sub_ipos,
! 737: aproc_opos,
! 738: NULL
1.1 ratchov 739: };
740:
741: struct aproc *
1.12 ! ratchov 742: sub_new(char *name, int maxlat)
1.1 ratchov 743: {
744: struct aproc *p;
745:
1.12 ! ratchov 746: p = aproc_new(&sub_ops, name);
1.5 ratchov 747: p->u.sub.flags = 0;
1.12 ! ratchov 748: p->u.sub.lat = 0;
! 749: p->u.sub.maxlat = maxlat;
1.1 ratchov 750: return p;
751: }
752:
753: /*
754: * Convert one block.
755: */
756: void
757: conv_bcopy(struct aconv *ist, struct aconv *ost,
758: struct abuf *ibuf, struct abuf *obuf)
759: {
760: int *ictx;
761: unsigned inch, ibps;
762: unsigned char *idata;
763: int ibnext, isigbit;
764: unsigned ishift;
765: int isnext;
766: unsigned ipos, orate;
767: unsigned ifr;
768: int *octx;
769: unsigned onch, oshift;
770: int osigbit;
771: unsigned obps;
772: unsigned char *odata;
773: int obnext, osnext;
774: unsigned opos, irate;
775: unsigned ofr;
776: unsigned c, i;
777: int s, *ctx;
778: unsigned icount, ocount;
779:
780: /*
781: * It's ok to have s uninitialized, but we dont want the compiler to
782: * complain about it.
783: */
784: s = (int)0xdeadbeef;
785:
786: /*
787: * Calculate max frames readable at once from the input buffer.
788: */
789: idata = abuf_rgetblk(ibuf, &icount, 0);
790: ifr = icount / ibuf->bpf;
1.12 ! ratchov 791: icount = ifr * ibuf->bpf;
1.1 ratchov 792:
793: odata = abuf_wgetblk(obuf, &ocount, 0);
794: ofr = ocount / obuf->bpf;
1.12 ! ratchov 795: ocount = ofr * obuf->bpf;
1.1 ratchov 796:
797: /*
798: * Partially copy structures into local variables, to avoid
799: * unnecessary indirections; this also allows the compiler to
800: * order local variables more "cache-friendly".
801: */
802: ictx = ist->ctx + ist->cmin;
803: octx = ist->ctx + ost->cmin;
804: inch = ist->nch;
805: ibps = ist->bps;
806: ibnext = ist->bnext;
807: isigbit = ist->sigbit;
808: ishift = ist->shift;
809: isnext = ist->snext;
810: ipos = ist->pos;
811: irate = ist->rate;
812: onch = ost->nch;
813: oshift = ost->shift;
814: osigbit = ost->sigbit;
815: obps = ost->bps;
816: obnext = ost->bnext;
817: osnext = ost->snext;
818: opos = ost->pos;
819: orate = ost->rate;
820:
821: /*
822: * Start conversion.
823: */
824: idata += ist->bfirst;
825: odata += ost->bfirst;
826: DPRINTFN(4, "conv_bcopy: ifr=%d ofr=%d\n", ifr, ofr);
827: for (;;) {
828: if ((int)(ipos - opos) > 0) {
829: if (ofr == 0)
830: break;
831: ctx = octx;
832: for (c = onch; c > 0; c--) {
833: s = *ctx++ << 16;
834: s >>= oshift;
835: s ^= osigbit;
836: for (i = obps; i > 0; i--) {
837: *odata = (unsigned char)s;
838: s >>= 8;
839: odata += obnext;
840: }
841: odata += osnext;
842: }
843: opos += irate;
844: ofr--;
845: } else {
846: if (ifr == 0)
847: break;
848: ctx = ictx;
849: for (c = inch; c > 0; c--) {
850: for (i = ibps; i > 0; i--) {
851: s <<= 8;
852: s |= *idata;
853: idata += ibnext;
854: }
855: s ^= isigbit;
856: s <<= ishift;
857: *ctx++ = (short)(s >> 16);
858: idata += isnext;
859: }
860: ipos += orate;
861: ifr--;
862: }
863: }
864: ist->pos = ipos;
865: ost->pos = opos;
866: DPRINTFN(4, "conv_bcopy: done, ifr=%d ofr=%d\n", ifr, ofr);
867:
868: /*
869: * Update FIFO pointers.
870: */
871: icount -= ifr * ist->bpf;
872: ocount -= ofr * ost->bpf;
1.6 ratchov 873: abuf_rdiscard(ibuf, icount);
874: abuf_wcommit(obuf, ocount);
1.1 ratchov 875: }
876:
877: int
878: conv_in(struct aproc *p, struct abuf *ibuf)
879: {
880: struct abuf *obuf = LIST_FIRST(&p->obuflist);
881:
1.12 ! ratchov 882: DPRINTFN(4, "conv_in: %s\n", p->name);
! 883:
! 884: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1.1 ratchov 885: return 0;
886: conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf);
1.12 ! ratchov 887: if (!abuf_flush(obuf))
! 888: return 0;
! 889: return 1;
1.1 ratchov 890: }
891:
892: int
893: conv_out(struct aproc *p, struct abuf *obuf)
894: {
895: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
896:
1.12 ! ratchov 897: DPRINTFN(4, "conv_out: %s\n", p->name);
! 898:
! 899: if (!abuf_fill(ibuf))
! 900: return 0;
! 901: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1.1 ratchov 902: return 0;
903: conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf);
904: return 1;
905: }
906:
907: void
908: conv_eof(struct aproc *p, struct abuf *ibuf)
909: {
1.12 ! ratchov 910: DPRINTFN(4, "conv_eof: %s\n", p->name);
! 911:
1.8 ratchov 912: aproc_del(p);
1.1 ratchov 913: }
914:
915: void
916: conv_hup(struct aproc *p, struct abuf *obuf)
917: {
1.12 ! ratchov 918: DPRINTFN(4, "conv_hup: %s\n", p->name);
! 919:
1.8 ratchov 920: aproc_del(p);
1.1 ratchov 921: }
922:
923: void
924: aconv_init(struct aconv *st, struct aparams *par, int input)
925: {
926: unsigned i;
927:
928: st->bps = par->bps;
929: st->sigbit = par->sig ? 0 : 1 << (par->bits - 1);
930: if (par->msb) {
931: st->shift = 32 - par->bps * 8;
932: } else {
933: st->shift = 32 - par->bits;
934: }
935: if ((par->le && input) || (!par->le && !input)) {
936: st->bfirst = st->bps - 1;
937: st->bnext = -1;
938: st->snext = 2 * st->bps;
939: } else {
940: st->bfirst = 0;
941: st->bnext = 1;
942: st->snext = 0;
943: }
944: st->cmin = par->cmin;
945: st->nch = par->cmax - par->cmin + 1;
946: st->bpf = st->nch * st->bps;
947: st->rate = par->rate;
948: st->pos = 0;
949:
1.12 ! ratchov 950: for (i = 0; i < NCHAN_MAX; i++)
1.1 ratchov 951: st->ctx[i] = 0;
952: }
953:
1.12 ! ratchov 954: void
! 955: conv_ipos(struct aproc *p, struct abuf *ibuf, int delta)
! 956: {
! 957: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 958: long long ipos;
! 959: int ifac, ofac;
! 960:
! 961: DPRINTFN(3, "conv_ipos: %d\n", delta);
! 962:
! 963: ifac = p->u.conv.ist.rate;
! 964: ofac = p->u.conv.ost.rate;
! 965: ipos = p->u.conv.idelta + (long long)delta * ofac;
! 966: delta = (ipos + ifac - 1) / ifac;
! 967: p->u.conv.idelta = ipos - (long long)delta * ifac;
! 968: abuf_ipos(obuf, delta);
! 969: }
! 970:
! 971: void
! 972: conv_opos(struct aproc *p, struct abuf *obuf, int delta)
! 973: {
! 974: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
! 975: long long opos;
! 976: int ifac, ofac;
! 977:
! 978: DPRINTFN(3, "conv_opos: %d\n", delta);
! 979:
! 980: ifac = p->u.conv.ist.rate;
! 981: ofac = p->u.conv.ost.rate;
! 982: opos = p->u.conv.odelta + (long long)delta * ifac;
! 983: delta = (opos + ofac - 1) / ofac;
! 984: p->u.conv.odelta = opos - (long long)delta * ofac;
! 985: abuf_opos(ibuf, delta);
! 986: }
! 987:
1.1 ratchov 988: struct aproc_ops conv_ops = {
1.12 ! ratchov 989: "conv",
! 990: conv_in,
! 991: conv_out,
! 992: conv_eof,
! 993: conv_hup,
! 994: NULL,
! 995: NULL,
! 996: conv_ipos,
! 997: conv_opos,
! 998: NULL
1.1 ratchov 999: };
1000:
1001: struct aproc *
1002: conv_new(char *name, struct aparams *ipar, struct aparams *opar)
1003: {
1004: struct aproc *p;
1005:
1006: p = aproc_new(&conv_ops, name);
1007: aconv_init(&p->u.conv.ist, ipar, 1);
1008: aconv_init(&p->u.conv.ost, opar, 0);
1.12 ! ratchov 1009: p->u.conv.idelta = 0;
! 1010: p->u.conv.odelta = 0;
! 1011: if (debug_level > 0) {
! 1012: DPRINTF("conv_new: %s: ", p->name);
! 1013: aparams_print2(ipar, opar);
! 1014: DPRINTF("\n");
! 1015: }
1.1 ratchov 1016: return p;
1017: }