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