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