Annotation of src/usr.bin/aucat/aproc.c, Revision 1.19
1.19 ! ratchov 1: /* $OpenBSD: aproc.c,v 1.18 2008/11/04 18:24:06 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: /*
18: * aproc structures are simple audio processing units. They are
19: * interconnected by abuf structures and form a kind of circuit. aproc
20: * structure have call-backs that do the actual processing.
21: *
22: * This module implements the following processing units:
23: *
24: * - rpipe: read end of an unix file (pipe, socket, device...)
25: *
26: * - wpipe: write end of an unix file (pipe, socket, device...)
27: *
28: * - mix: mix N inputs -> 1 output
29: *
30: * - sub: from 1 input -> extract/copy N outputs
31: *
32: * - conv: converts/resamples/remaps a single stream
33: *
1.15 ratchov 34: * - resamp: resample streams in native format
35: *
1.1 ratchov 36: * TODO
37: *
38: * (easy) split the "conv" into 2 converters: one for input (that
39: * convers anything to 16bit signed) and one for the output (that
40: * converts 16bit signed to anything)
41: *
42: * (hard) add a lowpass filter for the resampler. Quality is
43: * not acceptable as is.
1.12 ratchov 44: *
1.1 ratchov 45: */
46: #include <err.h>
47: #include <limits.h>
48: #include <stdio.h>
49: #include <stdlib.h>
50: #include <string.h>
51:
52: #include "conf.h"
53: #include "aparams.h"
54: #include "abuf.h"
55: #include "aproc.h"
56: #include "file.h"
57:
58: struct aproc *
59: aproc_new(struct aproc_ops *ops, char *name)
60: {
61: struct aproc *p;
62:
63: p = malloc(sizeof(struct aproc));
64: if (p == NULL)
65: err(1, name);
66: LIST_INIT(&p->ibuflist);
67: LIST_INIT(&p->obuflist);
68: p->name = name;
69: p->ops = ops;
70: return p;
71: }
72:
73: void
74: aproc_del(struct aproc *p)
75: {
1.12 ratchov 76: struct abuf *i;
77:
78: DPRINTF("aproc_del: %s(%s): terminating...\n", p->ops->name, p->name);
79:
1.8 ratchov 80: if (p->ops->done)
81: p->ops->done(p);
1.12 ratchov 82:
83: while (!LIST_EMPTY(&p->ibuflist)) {
84: i = LIST_FIRST(&p->ibuflist);
85: abuf_hup(i);
86: }
87: while (!LIST_EMPTY(&p->obuflist)) {
88: i = LIST_FIRST(&p->obuflist);
89: abuf_eof(i);
90: }
91: DPRINTF("aproc_del: %s(%s): freed\n", p->ops->name, p->name);
1.1 ratchov 92: free(p);
93: }
94:
95: void
96: aproc_setin(struct aproc *p, struct abuf *ibuf)
97: {
98: LIST_INSERT_HEAD(&p->ibuflist, ibuf, ient);
99: ibuf->rproc = p;
100: if (p->ops->newin)
101: p->ops->newin(p, ibuf);
102: }
103:
104: void
105: aproc_setout(struct aproc *p, struct abuf *obuf)
106: {
107: LIST_INSERT_HEAD(&p->obuflist, obuf, oent);
108: obuf->wproc = p;
109: if (p->ops->newout)
110: p->ops->newout(p, obuf);
111: }
112:
1.12 ratchov 113: void
114: aproc_ipos(struct aproc *p, struct abuf *ibuf, int delta)
115: {
116: struct abuf *obuf;
117:
118: DPRINTFN(3, "aproc_ipos: %s: delta = %d\n", p->name, delta);
119:
120: LIST_FOREACH(obuf, &p->obuflist, oent) {
121: abuf_ipos(obuf, delta);
122: }
123: }
124:
125: void
126: aproc_opos(struct aproc *p, struct abuf *obuf, int delta)
127: {
128: struct abuf *ibuf;
129:
130: DPRINTFN(3, "aproc_opos: %s: delta = %d\n", p->name, delta);
131:
132: LIST_FOREACH(ibuf, &p->ibuflist, ient) {
133: abuf_opos(ibuf, delta);
134: }
135: }
136:
1.1 ratchov 137: int
138: rpipe_in(struct aproc *p, struct abuf *ibuf_dummy)
139: {
140: struct abuf *obuf = LIST_FIRST(&p->obuflist);
141: struct file *f = p->u.io.file;
142: unsigned char *data;
143: unsigned count;
144:
1.6 ratchov 145: DPRINTFN(3, "rpipe_in: %s\n", p->name);
146:
1.12 ratchov 147: if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
1.1 ratchov 148: return 0;
149: data = abuf_wgetblk(obuf, &count, 0);
1.6 ratchov 150: count = file_read(f, data, count);
1.12 ratchov 151: if (count == 0)
152: return 0;
1.6 ratchov 153: abuf_wcommit(obuf, count);
1.12 ratchov 154: if (!abuf_flush(obuf))
155: return 0;
156: return 1;
1.1 ratchov 157: }
158:
159: int
160: rpipe_out(struct aproc *p, struct abuf *obuf)
161: {
162: struct file *f = p->u.io.file;
163: unsigned char *data;
164: unsigned count;
165:
1.12 ratchov 166: if (f->refs > 0)
167: return 0;
1.6 ratchov 168: DPRINTFN(3, "rpipe_out: %s\n", p->name);
1.12 ratchov 169:
170: if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
1.1 ratchov 171: return 0;
172: data = abuf_wgetblk(obuf, &count, 0);
1.6 ratchov 173: count = file_read(f, data, count);
1.12 ratchov 174: if (count == 0)
175: return 0;
1.6 ratchov 176: abuf_wcommit(obuf, count);
1.12 ratchov 177: return 1;
1.1 ratchov 178: }
179:
180: void
1.8 ratchov 181: rpipe_done(struct aproc *p)
1.1 ratchov 182: {
183: struct file *f = p->u.io.file;
184:
185: f->rproc = NULL;
1.12 ratchov 186: if (f->wproc == NULL)
187: file_del(f);
1.1 ratchov 188: }
189:
190: void
191: rpipe_eof(struct aproc *p, struct abuf *ibuf_dummy)
192: {
193: DPRINTFN(3, "rpipe_eof: %s\n", p->name);
1.8 ratchov 194: aproc_del(p);
1.1 ratchov 195: }
196:
197: void
198: rpipe_hup(struct aproc *p, struct abuf *obuf)
199: {
200: DPRINTFN(3, "rpipe_hup: %s\n", p->name);
1.8 ratchov 201: aproc_del(p);
1.1 ratchov 202: }
203:
204: struct aproc_ops rpipe_ops = {
1.12 ratchov 205: "rpipe",
206: rpipe_in,
207: rpipe_out,
208: rpipe_eof,
209: rpipe_hup,
210: NULL, /* newin */
211: NULL, /* newout */
212: aproc_ipos,
213: aproc_opos,
214: rpipe_done
1.1 ratchov 215: };
216:
217: struct aproc *
218: rpipe_new(struct file *f)
219: {
220: struct aproc *p;
221:
222: p = aproc_new(&rpipe_ops, f->name);
223: p->u.io.file = f;
1.12 ratchov 224: f->rproc = p;
1.1 ratchov 225: return p;
226: }
227:
228: void
1.8 ratchov 229: wpipe_done(struct aproc *p)
1.1 ratchov 230: {
231: struct file *f = p->u.io.file;
232:
233: f->wproc = NULL;
1.12 ratchov 234: if (f->rproc == NULL)
235: file_del(f);
1.1 ratchov 236: }
237:
238: int
239: wpipe_in(struct aproc *p, struct abuf *ibuf)
240: {
241: struct file *f = p->u.io.file;
242: unsigned char *data;
243: unsigned count;
244:
1.12 ratchov 245: if (f->refs > 0)
246: return 0;
1.6 ratchov 247: DPRINTFN(3, "wpipe_in: %s\n", p->name);
248:
1.12 ratchov 249: if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
1.1 ratchov 250: return 0;
251: data = abuf_rgetblk(ibuf, &count, 0);
252: count = file_write(f, data, count);
1.12 ratchov 253: if (count == 0)
254: return 0;
1.6 ratchov 255: abuf_rdiscard(ibuf, count);
1.12 ratchov 256: return 1;
1.1 ratchov 257: }
258:
259: int
260: wpipe_out(struct aproc *p, struct abuf *obuf_dummy)
261: {
262: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
263: struct file *f = p->u.io.file;
264: unsigned char *data;
265: unsigned count;
266:
1.6 ratchov 267: DPRINTFN(3, "wpipe_out: %s\n", p->name);
268:
1.12 ratchov 269: if (!abuf_fill(ibuf)) {
270: DPRINTFN(3, "wpipe_out: fill failed\n");
271: return 0;
272: }
273: if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
1.1 ratchov 274: return 0;
275: data = abuf_rgetblk(ibuf, &count, 0);
1.12 ratchov 276: if (count == 0) {
277: DPRINTF("wpipe_out: %s: underrun\n", p->name);
278: return 0;
279: }
1.1 ratchov 280: count = file_write(f, data, count);
1.12 ratchov 281: if (count == 0)
282: return 0;
1.6 ratchov 283: abuf_rdiscard(ibuf, count);
1.1 ratchov 284: return 1;
285: }
286:
287: void
288: wpipe_eof(struct aproc *p, struct abuf *ibuf)
289: {
290: DPRINTFN(3, "wpipe_eof: %s\n", p->name);
1.8 ratchov 291: aproc_del(p);
1.1 ratchov 292: }
293:
294: void
295: wpipe_hup(struct aproc *p, struct abuf *obuf_dummy)
296: {
297: DPRINTFN(3, "wpipe_hup: %s\n", p->name);
1.8 ratchov 298: aproc_del(p);
1.1 ratchov 299: }
300:
301: struct aproc_ops wpipe_ops = {
1.12 ratchov 302: "wpipe",
303: wpipe_in,
304: wpipe_out,
305: wpipe_eof,
306: wpipe_hup,
307: NULL, /* newin */
308: NULL, /* newout */
309: aproc_ipos,
310: aproc_opos,
311: wpipe_done
1.1 ratchov 312: };
313:
314: struct aproc *
315: wpipe_new(struct file *f)
316: {
317: struct aproc *p;
318:
319: p = aproc_new(&wpipe_ops, f->name);
320: p->u.io.file = f;
321: f->wproc = p;
322: return p;
323: }
324:
325: /*
326: * Fill an output block with silence.
327: */
328: void
329: mix_bzero(struct aproc *p)
330: {
331: struct abuf *obuf = LIST_FIRST(&p->obuflist);
332: short *odata;
333: unsigned ocount;
334:
1.6 ratchov 335: DPRINTFN(4, "mix_bzero: used = %u, todo = %u\n",
1.14 ratchov 336: obuf->used, obuf->mixitodo);
337: odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->mixitodo);
1.12 ratchov 338: ocount -= ocount % obuf->bpf;
1.1 ratchov 339: if (ocount == 0)
340: return;
341: memset(odata, 0, ocount);
1.14 ratchov 342: obuf->mixitodo += ocount;
343: DPRINTFN(4, "mix_bzero: ocount %u, todo %u\n", ocount, obuf->mixitodo);
1.1 ratchov 344: }
345:
346: /*
347: * Mix an input block over an output block.
348: */
349: void
350: mix_badd(struct abuf *ibuf, struct abuf *obuf)
351: {
352: short *idata, *odata;
1.14 ratchov 353: int vol = ibuf->mixivol;
1.13 ratchov 354: unsigned i, j, icnt, onext, ostart;
355: unsigned scount, icount, ocount;
1.1 ratchov 356:
1.6 ratchov 357: DPRINTFN(4, "mix_badd: todo = %u, done = %u\n",
1.14 ratchov 358: obuf->mixitodo, ibuf->mixodone);
1.1 ratchov 359:
360: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1.13 ratchov 361: icount /= ibuf->bpf;
1.1 ratchov 362: if (icount == 0)
363: return;
364:
1.14 ratchov 365: odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixodone);
1.13 ratchov 366: ocount /= obuf->bpf;
1.1 ratchov 367: if (ocount == 0)
368: return;
369:
1.13 ratchov 370: ostart = ibuf->cmin - obuf->cmin;
371: onext = obuf->cmax - ibuf->cmax + ostart;
372: icnt = ibuf->cmax - ibuf->cmin + 1;
373: odata += ostart;
1.1 ratchov 374: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 375: for (i = scount; i > 0; i--) {
376: for (j = icnt; j > 0; j--) {
377: *odata += (*idata * vol) >> ADATA_SHIFT;
378: idata++;
379: odata++;
380: }
381: odata += onext;
382: }
383: abuf_rdiscard(ibuf, scount * ibuf->bpf);
1.14 ratchov 384: ibuf->mixodone += scount * obuf->bpf;
1.1 ratchov 385:
1.6 ratchov 386: DPRINTFN(4, "mix_badd: added %u, done = %u, todo = %u\n",
1.14 ratchov 387: scount, ibuf->mixodone, obuf->mixitodo);
1.1 ratchov 388: }
389:
390: int
391: mix_in(struct aproc *p, struct abuf *ibuf)
392: {
393: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
1.7 ratchov 394: unsigned ocount;
1.1 ratchov 395:
1.7 ratchov 396: DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %u\n",
1.14 ratchov 397: ibuf->used, ibuf->mixodone, obuf->mixitodo);
1.3 ratchov 398:
1.14 ratchov 399: if (!ABUF_ROK(ibuf) || ibuf->mixodone == obuf->mixitodo)
1.1 ratchov 400: return 0;
1.12 ratchov 401:
1.1 ratchov 402: mix_badd(ibuf, obuf);
1.14 ratchov 403: ocount = obuf->mixitodo;
1.1 ratchov 404: LIST_FOREACH(i, &p->ibuflist, ient) {
1.14 ratchov 405: if (ocount > i->mixodone)
406: ocount = i->mixodone;
1.1 ratchov 407: }
408: if (ocount == 0)
409: return 0;
410:
1.6 ratchov 411: abuf_wcommit(obuf, ocount);
1.12 ratchov 412: p->u.mix.lat += ocount / obuf->bpf;
1.14 ratchov 413: obuf->mixitodo -= ocount;
1.12 ratchov 414: if (!abuf_flush(obuf))
415: return 0; /* hup */
1.1 ratchov 416: mix_bzero(p);
1.12 ratchov 417: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 418: inext = LIST_NEXT(i, ient);
1.14 ratchov 419: i->mixodone -= ocount;
420: if (i->mixodone < obuf->mixitodo)
1.1 ratchov 421: mix_badd(i, obuf);
1.12 ratchov 422: if (!abuf_fill(i))
423: continue;
1.1 ratchov 424: }
425: return 1;
426: }
427:
428: int
429: mix_out(struct aproc *p, struct abuf *obuf)
430: {
431: struct abuf *i, *inext;
1.3 ratchov 432: unsigned ocount, drop;
1.1 ratchov 433:
1.6 ratchov 434: DPRINTFN(4, "mix_out: used = %u, todo = %u\n",
1.14 ratchov 435: obuf->used, obuf->mixitodo);
1.1 ratchov 436:
1.12 ratchov 437: if (!ABUF_WOK(obuf))
438: return 0;
439:
1.1 ratchov 440: mix_bzero(p);
1.14 ratchov 441: ocount = obuf->mixitodo;
1.12 ratchov 442: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 443: inext = LIST_NEXT(i, ient);
1.12 ratchov 444: if (!abuf_fill(i))
445: continue;
1.5 ratchov 446: if (!ABUF_ROK(i)) {
1.14 ratchov 447: if ((p->u.mix.flags & MIX_DROP) && i->mixodone == 0) {
1.5 ratchov 448: if (i->xrun == XRUN_ERROR) {
449: abuf_hup(i);
450: continue;
451: }
1.14 ratchov 452: drop = obuf->mixitodo;
453: i->mixodone += drop;
1.5 ratchov 454: if (i->xrun == XRUN_SYNC)
1.7 ratchov 455: i->drop += drop;
1.12 ratchov 456: else {
457: abuf_opos(i, -(int)(drop / i->bpf));
458: if (i->duplex) {
459: DPRINTF("mix_out: duplex %u\n",
460: drop);
461: i->duplex->drop += drop *
462: i->duplex->bpf / i->bpf;
463: abuf_ipos(i->duplex,
464: -(int)(drop / i->bpf));
465: }
466: }
1.7 ratchov 467: DPRINTF("mix_out: drop = %u\n", i->drop);
1.5 ratchov 468: }
1.3 ratchov 469: } else
470: mix_badd(i, obuf);
1.14 ratchov 471: if (ocount > i->mixodone)
472: ocount = i->mixodone;
1.1 ratchov 473: }
474: if (ocount == 0)
475: return 0;
1.9 ratchov 476: if (LIST_EMPTY(&p->ibuflist) && (p->u.mix.flags & MIX_AUTOQUIT)) {
1.1 ratchov 477: DPRINTF("mix_out: nothing more to do...\n");
478: aproc_del(p);
479: return 0;
480: }
1.6 ratchov 481: abuf_wcommit(obuf, ocount);
1.12 ratchov 482: p->u.mix.lat += ocount / obuf->bpf;
1.14 ratchov 483: obuf->mixitodo -= ocount;
1.1 ratchov 484: LIST_FOREACH(i, &p->ibuflist, ient) {
1.14 ratchov 485: i->mixodone -= ocount;
1.1 ratchov 486: }
487: return 1;
488: }
489:
490: void
491: mix_eof(struct aproc *p, struct abuf *ibuf)
492: {
493: struct abuf *obuf = LIST_FIRST(&p->obuflist);
494:
495: DPRINTF("mix_eof: %s: detached\n", p->name);
1.12 ratchov 496: mix_setmaster(p);
497:
1.1 ratchov 498: /*
499: * If there's no more inputs, abuf_run() will trigger the eof
500: * condition and propagate it, so no need to handle it here.
501: */
502: abuf_run(obuf);
503: DPRINTF("mix_eof: done\n");
504: }
505:
506: void
507: mix_hup(struct aproc *p, struct abuf *obuf)
508: {
509: struct abuf *ibuf;
510:
511: while (!LIST_EMPTY(&p->ibuflist)) {
512: ibuf = LIST_FIRST(&p->ibuflist);
513: abuf_hup(ibuf);
514: }
515: DPRINTF("mix_hup: %s: done\n", p->name);
516: aproc_del(p);
517: }
518:
519: void
520: mix_newin(struct aproc *p, struct abuf *ibuf)
521: {
1.13 ratchov 522: struct abuf *obuf = LIST_FIRST(&p->obuflist);
523:
524: if (!obuf || ibuf->cmin < obuf->cmin || ibuf->cmax > obuf->cmax) {
525: fprintf(stderr, "mix_newin: channel ranges mismatch\n");
526: abort();
527: }
1.14 ratchov 528: ibuf->mixodone = 0;
529: ibuf->mixivol = ADATA_UNIT;
1.5 ratchov 530: ibuf->xrun = XRUN_IGNORE;
1.12 ratchov 531: mix_setmaster(p);
1.1 ratchov 532: }
533:
534: void
535: mix_newout(struct aproc *p, struct abuf *obuf)
536: {
1.14 ratchov 537: obuf->mixitodo = 0;
1.1 ratchov 538: mix_bzero(p);
539: }
540:
1.12 ratchov 541: void
542: mix_opos(struct aproc *p, struct abuf *obuf, int delta)
543: {
544: DPRINTFN(3, "mix_opos: lat = %d/%d\n", p->u.mix.lat, p->u.mix.maxlat);
545: p->u.mix.lat -= delta;
546: aproc_opos(p, obuf, delta);
547: }
548:
1.1 ratchov 549: struct aproc_ops mix_ops = {
1.12 ratchov 550: "mix",
551: mix_in,
552: mix_out,
553: mix_eof,
554: mix_hup,
555: mix_newin,
556: mix_newout,
557: aproc_ipos,
558: mix_opos,
559: NULL
1.1 ratchov 560: };
561:
562: struct aproc *
1.12 ratchov 563: mix_new(char *name, int maxlat)
1.1 ratchov 564: {
565: struct aproc *p;
566:
1.12 ratchov 567: p = aproc_new(&mix_ops, name);
1.5 ratchov 568: p->u.mix.flags = 0;
1.12 ratchov 569: p->u.mix.lat = 0;
570: p->u.mix.maxlat = maxlat;
1.1 ratchov 571: return p;
1.10 ratchov 572: }
573:
574: void
575: mix_pushzero(struct aproc *p)
576: {
577: struct abuf *obuf = LIST_FIRST(&p->obuflist);
578:
1.14 ratchov 579: abuf_wcommit(obuf, obuf->mixitodo);
580: p->u.mix.lat += obuf->mixitodo / obuf->bpf;
581: obuf->mixitodo = 0;
1.11 ratchov 582: abuf_run(obuf);
1.10 ratchov 583: mix_bzero(p);
584: }
585:
586: /*
587: * Normalize input levels
588: */
589: void
590: mix_setmaster(struct aproc *p)
591: {
592: unsigned n;
593: struct abuf *buf;
594:
595: n = 0;
596: LIST_FOREACH(buf, &p->ibuflist, ient)
597: n++;
598: LIST_FOREACH(buf, &p->ibuflist, ient)
1.14 ratchov 599: buf->mixivol = ADATA_UNIT / n;
1.1 ratchov 600: }
601:
602: /*
603: * Copy data from ibuf to obuf.
604: */
605: void
606: sub_bcopy(struct abuf *ibuf, struct abuf *obuf)
607: {
1.13 ratchov 608: short *idata, *odata;
609: unsigned i, j, ocnt, inext, istart;
1.1 ratchov 610: unsigned icount, ocount, scount;
611:
1.14 ratchov 612: idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->subidone);
1.13 ratchov 613: icount /= ibuf->bpf;
1.1 ratchov 614: if (icount == 0)
615: return;
1.13 ratchov 616: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
617: ocount /= obuf->bpf;
1.1 ratchov 618: if (ocount == 0)
619: return;
1.13 ratchov 620: istart = obuf->cmin - ibuf->cmin;
621: inext = ibuf->cmax - obuf->cmax + istart;
622: ocnt = obuf->cmax - obuf->cmin + 1;
1.1 ratchov 623: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 624: idata += istart;
625: for (i = scount; i > 0; i--) {
626: for (j = ocnt; j > 0; j--) {
627: *odata = *idata;
628: odata++;
629: idata++;
630: }
631: idata += inext;
632: }
633: abuf_wcommit(obuf, scount * obuf->bpf);
1.14 ratchov 634: obuf->subidone += scount * ibuf->bpf;
1.13 ratchov 635: DPRINTFN(4, "sub_bcopy: %u frames\n", scount);
1.1 ratchov 636: }
637:
638: int
639: sub_in(struct aproc *p, struct abuf *ibuf)
640: {
641: struct abuf *i, *inext;
1.3 ratchov 642: unsigned done, drop;
1.12 ratchov 643:
644: if (!ABUF_ROK(ibuf))
645: return 0;
1.1 ratchov 646: done = ibuf->used;
1.12 ratchov 647: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
1.1 ratchov 648: inext = LIST_NEXT(i, oent);
1.5 ratchov 649: if (!ABUF_WOK(i)) {
1.14 ratchov 650: if ((p->u.sub.flags & SUB_DROP) && i->subidone == 0) {
1.5 ratchov 651: if (i->xrun == XRUN_ERROR) {
652: abuf_eof(i);
653: continue;
654: }
655: drop = ibuf->used;
656: if (i->xrun == XRUN_SYNC)
1.7 ratchov 657: i->silence += drop;
1.12 ratchov 658: else {
659: abuf_ipos(i, -(int)(drop / i->bpf));
660: if (i->duplex) {
661: DPRINTF("sub_in: duplex %u\n",
662: drop);
663: i->duplex->silence += drop *
664: i->duplex->bpf / i->bpf;
665: abuf_opos(i->duplex,
666: -(int)(drop / i->bpf));
667: }
668: }
1.14 ratchov 669: i->subidone += drop;
1.12 ratchov 670: DPRINTF("sub_in: silence = %u\n", i->silence);
1.5 ratchov 671: }
1.12 ratchov 672: } else
1.1 ratchov 673: sub_bcopy(ibuf, i);
1.14 ratchov 674: if (done > i->subidone)
675: done = i->subidone;
1.12 ratchov 676: if (!abuf_flush(i))
677: continue;
1.1 ratchov 678: }
679: LIST_FOREACH(i, &p->obuflist, oent) {
1.14 ratchov 680: i->subidone -= done;
1.1 ratchov 681: }
1.6 ratchov 682: abuf_rdiscard(ibuf, done);
1.12 ratchov 683: p->u.sub.lat -= done / ibuf->bpf;
684: return 1;
1.1 ratchov 685: }
686:
687: int
688: sub_out(struct aproc *p, struct abuf *obuf)
689: {
690: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
691: struct abuf *i, *inext;
692: unsigned done;
693:
1.12 ratchov 694: if (!ABUF_WOK(obuf))
695: return 0;
696: if (!abuf_fill(ibuf)) {
697: return 0;
698: }
1.14 ratchov 699: if (obuf->subidone == ibuf->used)
1.1 ratchov 700: return 0;
701:
702: done = ibuf->used;
1.12 ratchov 703: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
704: inext = LIST_NEXT(i, oent);
705: if (!abuf_flush(i))
706: continue;
707: sub_bcopy(ibuf, i);
1.14 ratchov 708: if (done > i->subidone)
709: done = i->subidone;
1.1 ratchov 710: }
711: LIST_FOREACH(i, &p->obuflist, oent) {
1.14 ratchov 712: i->subidone -= done;
1.1 ratchov 713: }
1.6 ratchov 714: abuf_rdiscard(ibuf, done);
1.12 ratchov 715: p->u.sub.lat -= done / ibuf->bpf;
1.1 ratchov 716: return 1;
717: }
718:
719: void
720: sub_eof(struct aproc *p, struct abuf *ibuf)
721: {
722: struct abuf *obuf;
723:
724: while (!LIST_EMPTY(&p->obuflist)) {
725: obuf = LIST_FIRST(&p->obuflist);
726: abuf_eof(obuf);
727: }
1.8 ratchov 728: aproc_del(p);
1.1 ratchov 729: }
730:
731: void
732: sub_hup(struct aproc *p, struct abuf *obuf)
733: {
734: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
735:
736: DPRINTF("sub_hup: %s: detached\n", p->name);
1.12 ratchov 737: abuf_run(ibuf);
1.1 ratchov 738: DPRINTF("sub_hup: done\n");
739: }
740:
741: void
742: sub_newout(struct aproc *p, struct abuf *obuf)
743: {
1.13 ratchov 744: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
745:
746: if (!ibuf || obuf->cmin < ibuf->cmin || obuf->cmax > ibuf->cmax) {
747: fprintf(stderr, "sub_newout: channel ranges mismatch\n");
748: abort();
749: }
1.14 ratchov 750: obuf->subidone = 0;
1.5 ratchov 751: obuf->xrun = XRUN_IGNORE;
1.1 ratchov 752: }
753:
1.12 ratchov 754: void
755: sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
756: {
757: p->u.sub.lat += delta;
758: DPRINTFN(3, "sub_ipos: lat = %d/%d\n", p->u.sub.lat, p->u.sub.maxlat);
759: aproc_ipos(p, ibuf, delta);
760: }
761:
1.1 ratchov 762: struct aproc_ops sub_ops = {
1.12 ratchov 763: "sub",
764: sub_in,
765: sub_out,
766: sub_eof,
767: sub_hup,
768: NULL,
769: sub_newout,
770: sub_ipos,
771: aproc_opos,
772: NULL
1.1 ratchov 773: };
774:
775: struct aproc *
1.12 ratchov 776: sub_new(char *name, int maxlat)
1.1 ratchov 777: {
778: struct aproc *p;
779:
1.12 ratchov 780: p = aproc_new(&sub_ops, name);
1.5 ratchov 781: p->u.sub.flags = 0;
1.12 ratchov 782: p->u.sub.lat = 0;
783: p->u.sub.maxlat = maxlat;
1.1 ratchov 784: return p;
785: }
786:
787: /*
788: * Convert one block.
789: */
790: void
1.15 ratchov 791: resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
792: {
793: unsigned inch;
794: short *idata;
795: unsigned ipos, orate;
796: unsigned ifr;
797: unsigned onch;
798: short *odata;
799: unsigned opos, irate;
800: unsigned ofr;
801: unsigned c;
802: short *ctxbuf, *ctx;
803: unsigned icount, ocount;
804:
805: /*
806: * Calculate max frames readable at once from the input buffer.
807: */
808: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
809: ifr = icount / ibuf->bpf;
810: icount = ifr * ibuf->bpf;
811:
812: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
813: ofr = ocount / obuf->bpf;
814: ocount = ofr * obuf->bpf;
815:
816: /*
817: * Partially copy structures into local variables, to avoid
818: * unnecessary indirections; this also allows the compiler to
819: * order local variables more "cache-friendly".
820: */
821: inch = ibuf->cmax - ibuf->cmin + 1;
822: ipos = p->u.resamp.ipos;
823: irate = p->u.resamp.irate;
824: onch = obuf->cmax - obuf->cmin + 1;
825: opos = p->u.resamp.opos;
826: orate = p->u.resamp.orate;
827: ctxbuf = p->u.resamp.ctx;
828:
829: /*
830: * Start conversion.
831: */
832: DPRINTFN(4, "resamp_bcopy: ifr=%d ofr=%d\n", ifr, ofr);
833: for (;;) {
834: if ((int)(ipos - opos) > 0) {
835: if (ofr == 0)
836: break;
837: ctx = ctxbuf;
838: for (c = onch; c > 0; c--) {
839: *odata = *ctx;
840: odata++;
841: ctx++;
842: }
843: opos += irate;
844: ofr--;
845: } else {
846: if (ifr == 0)
847: break;
848: ctx = ctxbuf;
849: for (c = inch; c > 0; c--) {
850: *ctx = *idata;
851: idata++;
852: ctx++;
853: }
854: ipos += orate;
855: ifr--;
856: }
857: }
858: p->u.resamp.ipos = ipos;
859: p->u.resamp.opos = opos;
860: DPRINTFN(4, "resamp_bcopy: done, ifr=%d ofr=%d\n", ifr, ofr);
861:
862: /*
863: * Update FIFO pointers.
864: */
865: icount -= ifr * ibuf->bpf;
866: ocount -= ofr * obuf->bpf;
867: abuf_rdiscard(ibuf, icount);
868: abuf_wcommit(obuf, ocount);
869: }
870:
871: int
872: resamp_in(struct aproc *p, struct abuf *ibuf)
873: {
874: struct abuf *obuf = LIST_FIRST(&p->obuflist);
875:
876: DPRINTFN(4, "resamp_in: %s\n", p->name);
877:
878: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
879: return 0;
880: resamp_bcopy(p, ibuf, obuf);
881: if (!abuf_flush(obuf))
882: return 0;
883: return 1;
884: }
885:
886: int
887: resamp_out(struct aproc *p, struct abuf *obuf)
888: {
889: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
890:
891: DPRINTFN(4, "resamp_out: %s\n", p->name);
892:
893: if (!abuf_fill(ibuf))
894: return 0;
895: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
896: return 0;
897: resamp_bcopy(p, ibuf, obuf);
898: return 1;
899: }
900:
901: void
902: resamp_eof(struct aproc *p, struct abuf *ibuf)
903: {
904: DPRINTFN(4, "resamp_eof: %s\n", p->name);
905:
906: aproc_del(p);
907: }
908:
909: void
910: resamp_hup(struct aproc *p, struct abuf *obuf)
911: {
912: DPRINTFN(4, "resamp_hup: %s\n", p->name);
913:
914: aproc_del(p);
915: }
916:
917: void
918: resamp_ipos(struct aproc *p, struct abuf *ibuf, int delta)
919: {
920: struct abuf *obuf = LIST_FIRST(&p->obuflist);
921: long long ipos;
922: int ifac, ofac;
923:
924: DPRINTFN(3, "resamp_ipos: %d\n", delta);
925:
926: ifac = p->u.resamp.irate;
927: ofac = p->u.resamp.orate;
928: ipos = p->u.resamp.idelta + (long long)delta * ofac;
929: delta = (ipos + ifac - 1) / ifac;
930: p->u.resamp.idelta = ipos - (long long)delta * ifac;
931: abuf_ipos(obuf, delta);
932: }
933:
934: void
935: resamp_opos(struct aproc *p, struct abuf *obuf, int delta)
936: {
937: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
938: long long opos;
939: int ifac, ofac;
940:
941: DPRINTFN(3, "resamp_opos: %d\n", delta);
942:
943: ifac = p->u.resamp.irate;
944: ofac = p->u.resamp.orate;
945: opos = p->u.resamp.odelta + (long long)delta * ifac;
946: delta = (opos + ofac - 1) / ofac;
947: p->u.resamp.odelta = opos - (long long)delta * ofac;
948: abuf_opos(ibuf, delta);
949: }
950:
951: struct aproc_ops resamp_ops = {
952: "resamp",
953: resamp_in,
954: resamp_out,
955: resamp_eof,
956: resamp_hup,
957: NULL,
958: NULL,
959: resamp_ipos,
960: resamp_opos,
961: NULL
962: };
963:
964: struct aproc *
965: resamp_new(char *name, struct aparams *ipar, struct aparams *opar)
966: {
967: struct aproc *p;
1.16 ratchov 968: unsigned i;
1.15 ratchov 969:
970: p = aproc_new(&resamp_ops, name);
971: p->u.resamp.irate = ipar->rate;
972: p->u.resamp.orate = opar->rate;
973: p->u.resamp.ipos = 0;
974: p->u.resamp.opos = 0;
975: p->u.resamp.idelta = 0;
976: p->u.resamp.odelta = 0;
1.16 ratchov 977: for (i = 0; i < NCHAN_MAX; i++)
978: p->u.resamp.ctx[i] = 0;
1.15 ratchov 979: if (debug_level > 0) {
980: DPRINTF("resamp_new: %s: ", p->name);
1.17 ratchov 981: aparams_print2(ipar, opar);
982: DPRINTF("\n");
983: }
984: return p;
985: }
986:
987: /*
988: * Convert one block.
989: */
990: void
991: cmap_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
992: {
993: unsigned inch;
994: short *idata;
995: unsigned onch;
996: short *odata;
997: short *ctx, *ictx, *octx;
998: unsigned c, f, scount, icount, ocount;
999:
1000: /*
1001: * Calculate max frames readable at once from the input buffer.
1002: */
1003: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1004: icount /= ibuf->bpf;
1005: if (icount == 0)
1006: return;
1007: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1008: ocount /= obuf->bpf;
1009: if (ocount == 0)
1010: return;
1011: scount = icount < ocount ? icount : ocount;
1012: inch = ibuf->cmax - ibuf->cmin + 1;
1013: onch = obuf->cmax - obuf->cmin + 1;
1014: ictx = p->u.cmap.ctx + ibuf->cmin;
1015: octx = p->u.cmap.ctx + obuf->cmin;
1016:
1017: for (f = scount; f > 0; f--) {
1018: ctx = ictx;
1019: for (c = inch; c > 0; c--) {
1020: *ctx = *idata;
1021: idata++;
1022: ctx++;
1023: }
1024: ctx = octx;
1025: for (c = onch; c > 0; c--) {
1026: *odata = *ctx;
1027: odata++;
1028: ctx++;
1029: }
1030: }
1031: DPRINTFN(4, "cmap_bcopy: scount = %u\n", scount);
1032: abuf_rdiscard(ibuf, scount * ibuf->bpf);
1033: abuf_wcommit(obuf, scount * obuf->bpf);
1034: }
1035:
1036: int
1037: cmap_in(struct aproc *p, struct abuf *ibuf)
1038: {
1039: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1040:
1041: DPRINTFN(4, "cmap_in: %s\n", p->name);
1042:
1043: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1044: return 0;
1045: cmap_bcopy(p, ibuf, obuf);
1046: if (!abuf_flush(obuf))
1047: return 0;
1048: return 1;
1049: }
1050:
1051: int
1052: cmap_out(struct aproc *p, struct abuf *obuf)
1053: {
1054: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1055:
1056: DPRINTFN(4, "cmap_out: %s\n", p->name);
1057:
1058: if (!abuf_fill(ibuf))
1059: return 0;
1060: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1061: return 0;
1062: cmap_bcopy(p, ibuf, obuf);
1063: return 1;
1064: }
1065:
1066: void
1067: cmap_eof(struct aproc *p, struct abuf *ibuf)
1068: {
1069: DPRINTFN(4, "cmap_eof: %s\n", p->name);
1070:
1071: aproc_del(p);
1072: }
1073:
1074: void
1075: cmap_hup(struct aproc *p, struct abuf *obuf)
1076: {
1077: DPRINTFN(4, "cmap_hup: %s\n", p->name);
1078:
1079: aproc_del(p);
1080: }
1081:
1082: struct aproc_ops cmap_ops = {
1083: "cmap",
1084: cmap_in,
1085: cmap_out,
1086: cmap_eof,
1087: cmap_hup,
1088: NULL,
1089: NULL,
1.19 ! ratchov 1090: aproc_ipos,
! 1091: aproc_opos,
1.17 ratchov 1092: NULL
1093: };
1094:
1095: struct aproc *
1096: cmap_new(char *name, struct aparams *ipar, struct aparams *opar)
1097: {
1098: struct aproc *p;
1099: unsigned i;
1100:
1101: p = aproc_new(&cmap_ops, name);
1102: for (i = 0; i < NCHAN_MAX; i++)
1103: p->u.cmap.ctx[i] = 0;
1104: if (debug_level > 0) {
1105: DPRINTF("cmap_new: %s: ", p->name);
1.12 ratchov 1106: aparams_print2(ipar, opar);
1107: DPRINTF("\n");
1.19 ! ratchov 1108: }
! 1109: return p;
! 1110: }
! 1111:
! 1112: /*
! 1113: * Convert one block.
! 1114: */
! 1115: void
! 1116: enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
! 1117: {
! 1118: unsigned nch, scount, icount, ocount;
! 1119: unsigned f;
! 1120: short *idata;
! 1121: int s;
! 1122: unsigned oshift;
! 1123: int osigbit;
! 1124: unsigned obps;
! 1125: unsigned i;
! 1126: unsigned char *odata;
! 1127: int obnext;
! 1128: int osnext;
! 1129:
! 1130: /*
! 1131: * Calculate max frames readable at once from the input buffer.
! 1132: */
! 1133: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
! 1134: icount /= ibuf->bpf;
! 1135: if (icount == 0)
! 1136: return;
! 1137: odata = abuf_wgetblk(obuf, &ocount, 0);
! 1138: ocount /= obuf->bpf;
! 1139: if (ocount == 0)
! 1140: return;
! 1141: scount = (icount < ocount) ? icount : ocount;
! 1142: nch = ibuf->cmax - ibuf->cmin + 1;
! 1143: DPRINTFN(4, "enc_bcopy: scount = %u, nch = %u\n", scount, nch);
! 1144:
! 1145: /*
! 1146: * Partially copy structures into local variables, to avoid
! 1147: * unnecessary indirections; this also allows the compiler to
! 1148: * order local variables more "cache-friendly".
! 1149: */
! 1150: oshift = p->u.conv.shift;
! 1151: osigbit = p->u.conv.sigbit;
! 1152: obps = p->u.conv.bps;
! 1153: obnext = p->u.conv.bnext;
! 1154: osnext = p->u.conv.snext;
! 1155:
! 1156: /*
! 1157: * Start conversion.
! 1158: */
! 1159: odata += p->u.conv.bfirst;
! 1160: for (f = scount * nch; f > 0; f--) {
! 1161: s = *idata++;
! 1162: s <<= 16;
! 1163: s >>= oshift;
! 1164: s ^= osigbit;
! 1165: for (i = obps; i > 0; i--) {
! 1166: *odata = (unsigned char)s;
! 1167: s >>= 8;
! 1168: odata += obnext;
! 1169: }
! 1170: odata += osnext;
! 1171: }
! 1172:
! 1173: /*
! 1174: * Update FIFO pointers.
! 1175: */
! 1176: abuf_rdiscard(ibuf, scount * ibuf->bpf);
! 1177: abuf_wcommit(obuf, scount * obuf->bpf);
! 1178: }
! 1179:
! 1180: int
! 1181: enc_in(struct aproc *p, struct abuf *ibuf)
! 1182: {
! 1183: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 1184:
! 1185: DPRINTFN(4, "enc_in: %s\n", p->name);
! 1186:
! 1187: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
! 1188: return 0;
! 1189: enc_bcopy(p, ibuf, obuf);
! 1190: if (!abuf_flush(obuf))
! 1191: return 0;
! 1192: return 1;
! 1193: }
! 1194:
! 1195: int
! 1196: enc_out(struct aproc *p, struct abuf *obuf)
! 1197: {
! 1198: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
! 1199:
! 1200: DPRINTFN(4, "enc_out: %s\n", p->name);
! 1201:
! 1202: if (!abuf_fill(ibuf))
! 1203: return 0;
! 1204: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
! 1205: return 0;
! 1206: enc_bcopy(p, ibuf, obuf);
! 1207: return 1;
! 1208: }
! 1209:
! 1210: void
! 1211: enc_eof(struct aproc *p, struct abuf *ibuf)
! 1212: {
! 1213: DPRINTFN(4, "enc_eof: %s\n", p->name);
! 1214:
! 1215: aproc_del(p);
! 1216: }
! 1217:
! 1218: void
! 1219: enc_hup(struct aproc *p, struct abuf *obuf)
! 1220: {
! 1221: DPRINTFN(4, "enc_hup: %s\n", p->name);
! 1222:
! 1223: aproc_del(p);
! 1224: }
! 1225:
! 1226: struct aproc_ops enc_ops = {
! 1227: "enc",
! 1228: enc_in,
! 1229: enc_out,
! 1230: enc_eof,
! 1231: enc_hup,
! 1232: NULL,
! 1233: NULL,
! 1234: aproc_ipos,
! 1235: aproc_opos,
! 1236: NULL
! 1237: };
! 1238:
! 1239: struct aproc *
! 1240: enc_new(char *name, struct aparams *par)
! 1241: {
! 1242: struct aproc *p;
! 1243:
! 1244: p = aproc_new(&enc_ops, name);
! 1245: p->u.conv.bps = par->bps;
! 1246: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
! 1247: if (par->msb) {
! 1248: p->u.conv.shift = 32 - par->bps * 8;
! 1249: } else {
! 1250: p->u.conv.shift = 32 - par->bits;
! 1251: }
! 1252: if (!par->le) {
! 1253: p->u.conv.bfirst = par->bps - 1;
! 1254: p->u.conv.bnext = -1;
! 1255: p->u.conv.snext = 2 * par->bps;
! 1256: } else {
! 1257: p->u.conv.bfirst = 0;
! 1258: p->u.conv.bnext = 1;
! 1259: p->u.conv.snext = 0;
! 1260: }
! 1261: if (debug_level > 0) {
! 1262: fprintf(stderr, "enc_new: %s: ", p->name);
! 1263: aparams_print(par);
! 1264: fprintf(stderr, "\n");
! 1265: }
! 1266: return p;
! 1267: }
! 1268:
! 1269: /*
! 1270: * Convert one block.
! 1271: */
! 1272: void
! 1273: dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
! 1274: {
! 1275: unsigned nch, scount, icount, ocount;
! 1276: unsigned f;
! 1277: unsigned ibps;
! 1278: unsigned i;
! 1279: int s = 0xdeadbeef;
! 1280: unsigned char *idata;
! 1281: int ibnext;
! 1282: int isnext;
! 1283: int isigbit;
! 1284: unsigned ishift;
! 1285: short *odata;
! 1286:
! 1287: /*
! 1288: * Calculate max frames readable at once from the input buffer.
! 1289: */
! 1290: idata = abuf_rgetblk(ibuf, &icount, 0);
! 1291: icount /= ibuf->bpf;
! 1292: if (icount == 0)
! 1293: return;
! 1294: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
! 1295: ocount /= obuf->bpf;
! 1296: if (ocount == 0)
! 1297: return;
! 1298: scount = (icount < ocount) ? icount : ocount;
! 1299: nch = obuf->cmax - obuf->cmin + 1;
! 1300: DPRINTFN(4, "dec_bcopy: scount = %u, nch = %u\n", scount, nch);
! 1301:
! 1302: /*
! 1303: * Partially copy structures into local variables, to avoid
! 1304: * unnecessary indirections; this also allows the compiler to
! 1305: * order local variables more "cache-friendly".
! 1306: */
! 1307: ibps = p->u.conv.bps;
! 1308: ibnext = p->u.conv.bnext;
! 1309: isigbit = p->u.conv.sigbit;
! 1310: ishift = p->u.conv.shift;
! 1311: isnext = p->u.conv.snext;
! 1312:
! 1313: /*
! 1314: * Start conversion.
! 1315: */
! 1316: idata += p->u.conv.bfirst;
! 1317: for (f = scount * nch; f > 0; f--) {
! 1318: for (i = ibps; i > 0; i--) {
! 1319: s <<= 8;
! 1320: s |= *idata;
! 1321: idata += ibnext;
! 1322: }
! 1323: idata += isnext;
! 1324: s ^= isigbit;
! 1325: s <<= ishift;
! 1326: s >>= 16;
! 1327: *odata++ = s;
! 1328: }
! 1329:
! 1330: /*
! 1331: * Update FIFO pointers.
! 1332: */
! 1333: abuf_rdiscard(ibuf, scount * ibuf->bpf);
! 1334: abuf_wcommit(obuf, scount * obuf->bpf);
! 1335: }
! 1336:
! 1337: int
! 1338: dec_in(struct aproc *p, struct abuf *ibuf)
! 1339: {
! 1340: struct abuf *obuf = LIST_FIRST(&p->obuflist);
! 1341:
! 1342: DPRINTFN(4, "dec_in: %s\n", p->name);
! 1343:
! 1344: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
! 1345: return 0;
! 1346: dec_bcopy(p, ibuf, obuf);
! 1347: if (!abuf_flush(obuf))
! 1348: return 0;
! 1349: return 1;
! 1350: }
! 1351:
! 1352: int
! 1353: dec_out(struct aproc *p, struct abuf *obuf)
! 1354: {
! 1355: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
! 1356:
! 1357: DPRINTFN(4, "dec_out: %s\n", p->name);
! 1358:
! 1359: if (!abuf_fill(ibuf))
! 1360: return 0;
! 1361: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
! 1362: return 0;
! 1363: dec_bcopy(p, ibuf, obuf);
! 1364: return 1;
! 1365: }
! 1366:
! 1367: void
! 1368: dec_eof(struct aproc *p, struct abuf *ibuf)
! 1369: {
! 1370: DPRINTFN(4, "dec_eof: %s\n", p->name);
! 1371:
! 1372: aproc_del(p);
! 1373: }
! 1374:
! 1375: void
! 1376: dec_hup(struct aproc *p, struct abuf *obuf)
! 1377: {
! 1378: DPRINTFN(4, "dec_hup: %s\n", p->name);
! 1379:
! 1380: aproc_del(p);
! 1381: }
! 1382:
! 1383: struct aproc_ops dec_ops = {
! 1384: "dec",
! 1385: dec_in,
! 1386: dec_out,
! 1387: dec_eof,
! 1388: dec_hup,
! 1389: NULL,
! 1390: NULL,
! 1391: aproc_ipos,
! 1392: aproc_opos,
! 1393: NULL
! 1394: };
! 1395:
! 1396: struct aproc *
! 1397: dec_new(char *name, struct aparams *par)
! 1398: {
! 1399: struct aproc *p;
! 1400:
! 1401: p = aproc_new(&dec_ops, name);
! 1402: p->u.conv.bps = par->bps;
! 1403: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
! 1404: if (par->msb) {
! 1405: p->u.conv.shift = 32 - par->bps * 8;
! 1406: } else {
! 1407: p->u.conv.shift = 32 - par->bits;
! 1408: }
! 1409: if (par->le) {
! 1410: p->u.conv.bfirst = par->bps - 1;
! 1411: p->u.conv.bnext = -1;
! 1412: p->u.conv.snext = 2 * par->bps;
! 1413: } else {
! 1414: p->u.conv.bfirst = 0;
! 1415: p->u.conv.bnext = 1;
! 1416: p->u.conv.snext = 0;
! 1417: }
! 1418: if (debug_level > 0) {
! 1419: fprintf(stderr, "dec_new: %s: ", p->name);
! 1420: aparams_print(par);
! 1421: fprintf(stderr, "\n");
1.12 ratchov 1422: }
1.1 ratchov 1423: return p;
1424: }