Annotation of src/usr.bin/aucat/aproc.c, Revision 1.27
1.27 ! ratchov 1: /* $OpenBSD: aproc.c,v 1.26 2008/12/07 17:10:41 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.13 ratchov 353: unsigned i, j, icnt, onext, ostart;
354: unsigned scount, icount, ocount;
1.23 ratchov 355: int vol;
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.23 ratchov 370: vol = (ibuf->mixweight * ibuf->mixvol) >> ADATA_SHIFT;
1.13 ratchov 371: ostart = ibuf->cmin - obuf->cmin;
372: onext = obuf->cmax - ibuf->cmax + ostart;
373: icnt = ibuf->cmax - ibuf->cmin + 1;
374: odata += ostart;
1.1 ratchov 375: scount = (icount < ocount) ? icount : ocount;
1.13 ratchov 376: for (i = scount; i > 0; i--) {
377: for (j = icnt; j > 0; j--) {
378: *odata += (*idata * vol) >> ADATA_SHIFT;
379: idata++;
380: odata++;
381: }
382: odata += onext;
383: }
384: abuf_rdiscard(ibuf, scount * ibuf->bpf);
1.14 ratchov 385: ibuf->mixodone += scount * obuf->bpf;
1.1 ratchov 386:
1.6 ratchov 387: DPRINTFN(4, "mix_badd: added %u, done = %u, todo = %u\n",
1.14 ratchov 388: scount, ibuf->mixodone, obuf->mixitodo);
1.1 ratchov 389: }
390:
391: int
392: mix_in(struct aproc *p, struct abuf *ibuf)
393: {
394: struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
1.7 ratchov 395: unsigned ocount;
1.1 ratchov 396:
1.7 ratchov 397: DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %u\n",
1.14 ratchov 398: ibuf->used, ibuf->mixodone, obuf->mixitodo);
1.3 ratchov 399:
1.14 ratchov 400: if (!ABUF_ROK(ibuf) || ibuf->mixodone == obuf->mixitodo)
1.1 ratchov 401: return 0;
1.12 ratchov 402:
1.1 ratchov 403: mix_badd(ibuf, obuf);
1.14 ratchov 404: ocount = obuf->mixitodo;
1.1 ratchov 405: LIST_FOREACH(i, &p->ibuflist, ient) {
1.14 ratchov 406: if (ocount > i->mixodone)
407: ocount = i->mixodone;
1.1 ratchov 408: }
409: if (ocount == 0)
410: return 0;
411:
1.6 ratchov 412: abuf_wcommit(obuf, ocount);
1.12 ratchov 413: p->u.mix.lat += ocount / obuf->bpf;
1.14 ratchov 414: obuf->mixitodo -= ocount;
1.12 ratchov 415: if (!abuf_flush(obuf))
416: return 0; /* hup */
1.1 ratchov 417: mix_bzero(p);
1.12 ratchov 418: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 419: inext = LIST_NEXT(i, ient);
1.14 ratchov 420: i->mixodone -= ocount;
421: if (i->mixodone < obuf->mixitodo)
1.1 ratchov 422: mix_badd(i, obuf);
1.12 ratchov 423: if (!abuf_fill(i))
424: continue;
1.1 ratchov 425: }
1.22 ratchov 426: if (LIST_EMPTY(&p->ibuflist))
427: p->u.mix.idle += ocount / obuf->bpf;
1.1 ratchov 428: return 1;
429: }
430:
431: int
432: mix_out(struct aproc *p, struct abuf *obuf)
433: {
434: struct abuf *i, *inext;
1.20 ratchov 435: unsigned ocount, fdrop;
1.1 ratchov 436:
1.6 ratchov 437: DPRINTFN(4, "mix_out: used = %u, todo = %u\n",
1.14 ratchov 438: obuf->used, obuf->mixitodo);
1.1 ratchov 439:
1.12 ratchov 440: if (!ABUF_WOK(obuf))
441: return 0;
442:
1.1 ratchov 443: mix_bzero(p);
1.14 ratchov 444: ocount = obuf->mixitodo;
1.12 ratchov 445: for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
1.1 ratchov 446: inext = LIST_NEXT(i, ient);
1.12 ratchov 447: if (!abuf_fill(i))
448: continue;
1.5 ratchov 449: if (!ABUF_ROK(i)) {
1.14 ratchov 450: if ((p->u.mix.flags & MIX_DROP) && i->mixodone == 0) {
1.5 ratchov 451: if (i->xrun == XRUN_ERROR) {
452: abuf_hup(i);
453: continue;
454: }
1.20 ratchov 455: fdrop = obuf->mixitodo / obuf->bpf;
456: i->mixodone += fdrop * obuf->bpf;
1.5 ratchov 457: if (i->xrun == XRUN_SYNC)
1.20 ratchov 458: i->drop += fdrop * i->bpf;
1.12 ratchov 459: else {
1.20 ratchov 460: abuf_opos(i, -(int)fdrop);
1.12 ratchov 461: if (i->duplex) {
462: DPRINTF("mix_out: duplex %u\n",
1.20 ratchov 463: fdrop);
464: i->duplex->drop += fdrop *
465: i->duplex->bpf;
1.12 ratchov 466: abuf_ipos(i->duplex,
1.20 ratchov 467: -(int)fdrop);
1.12 ratchov 468: }
469: }
1.7 ratchov 470: DPRINTF("mix_out: drop = %u\n", i->drop);
1.5 ratchov 471: }
1.3 ratchov 472: } else
473: mix_badd(i, obuf);
1.14 ratchov 474: if (ocount > i->mixodone)
475: ocount = i->mixodone;
1.1 ratchov 476: }
477: if (ocount == 0)
478: return 0;
1.9 ratchov 479: if (LIST_EMPTY(&p->ibuflist) && (p->u.mix.flags & MIX_AUTOQUIT)) {
1.1 ratchov 480: DPRINTF("mix_out: nothing more to do...\n");
481: aproc_del(p);
482: return 0;
483: }
1.6 ratchov 484: abuf_wcommit(obuf, ocount);
1.12 ratchov 485: p->u.mix.lat += ocount / obuf->bpf;
1.14 ratchov 486: obuf->mixitodo -= ocount;
1.1 ratchov 487: LIST_FOREACH(i, &p->ibuflist, ient) {
1.14 ratchov 488: i->mixodone -= ocount;
1.1 ratchov 489: }
1.22 ratchov 490: if (LIST_EMPTY(&p->ibuflist))
491: p->u.mix.idle += ocount / obuf->bpf;
1.1 ratchov 492: return 1;
493: }
494:
495: void
496: mix_eof(struct aproc *p, struct abuf *ibuf)
497: {
498: struct abuf *obuf = LIST_FIRST(&p->obuflist);
499:
500: DPRINTF("mix_eof: %s: detached\n", p->name);
1.12 ratchov 501: mix_setmaster(p);
502:
1.1 ratchov 503: /*
504: * If there's no more inputs, abuf_run() will trigger the eof
505: * condition and propagate it, so no need to handle it here.
506: */
507: abuf_run(obuf);
508: DPRINTF("mix_eof: done\n");
509: }
510:
511: void
512: mix_hup(struct aproc *p, struct abuf *obuf)
513: {
514: struct abuf *ibuf;
515:
516: while (!LIST_EMPTY(&p->ibuflist)) {
517: ibuf = LIST_FIRST(&p->ibuflist);
518: abuf_hup(ibuf);
519: }
520: DPRINTF("mix_hup: %s: done\n", p->name);
521: aproc_del(p);
522: }
523:
524: void
525: mix_newin(struct aproc *p, struct abuf *ibuf)
526: {
1.13 ratchov 527: struct abuf *obuf = LIST_FIRST(&p->obuflist);
528:
529: if (!obuf || ibuf->cmin < obuf->cmin || ibuf->cmax > obuf->cmax) {
530: fprintf(stderr, "mix_newin: channel ranges mismatch\n");
531: abort();
532: }
1.22 ratchov 533: p->u.mix.idle = 0;
1.14 ratchov 534: ibuf->mixodone = 0;
1.23 ratchov 535: ibuf->mixvol = ADATA_UNIT;
536: ibuf->mixweight = ADATA_UNIT;
1.24 ratchov 537: ibuf->mixmaxweight = ADATA_UNIT;
1.5 ratchov 538: ibuf->xrun = XRUN_IGNORE;
1.1 ratchov 539: }
540:
541: void
542: mix_newout(struct aproc *p, struct abuf *obuf)
543: {
1.21 ratchov 544: DPRINTF("mix_newout: using %u fpb\n", obuf->len / obuf->bpf);
1.14 ratchov 545: obuf->mixitodo = 0;
1.1 ratchov 546: mix_bzero(p);
547: }
548:
1.12 ratchov 549: void
550: mix_opos(struct aproc *p, struct abuf *obuf, int delta)
551: {
552: DPRINTFN(3, "mix_opos: lat = %d/%d\n", p->u.mix.lat, p->u.mix.maxlat);
553: p->u.mix.lat -= delta;
554: aproc_opos(p, obuf, delta);
555: }
556:
1.1 ratchov 557: struct aproc_ops mix_ops = {
1.12 ratchov 558: "mix",
559: mix_in,
560: mix_out,
561: mix_eof,
562: mix_hup,
563: mix_newin,
564: mix_newout,
565: aproc_ipos,
566: mix_opos,
567: NULL
1.1 ratchov 568: };
569:
570: struct aproc *
1.12 ratchov 571: mix_new(char *name, int maxlat)
1.1 ratchov 572: {
573: struct aproc *p;
574:
1.12 ratchov 575: p = aproc_new(&mix_ops, name);
1.5 ratchov 576: p->u.mix.flags = 0;
1.22 ratchov 577: p->u.mix.idle = 0;
1.12 ratchov 578: p->u.mix.lat = 0;
579: p->u.mix.maxlat = maxlat;
1.1 ratchov 580: return p;
1.10 ratchov 581: }
582:
583: void
584: mix_pushzero(struct aproc *p)
585: {
586: struct abuf *obuf = LIST_FIRST(&p->obuflist);
587:
1.14 ratchov 588: abuf_wcommit(obuf, obuf->mixitodo);
589: p->u.mix.lat += obuf->mixitodo / obuf->bpf;
590: obuf->mixitodo = 0;
1.11 ratchov 591: abuf_run(obuf);
1.10 ratchov 592: mix_bzero(p);
593: }
594:
595: /*
596: * Normalize input levels
597: */
598: void
599: mix_setmaster(struct aproc *p)
600: {
601: unsigned n;
602: struct abuf *buf;
1.24 ratchov 603: int weight;
1.10 ratchov 604:
605: n = 0;
1.24 ratchov 606: LIST_FOREACH(buf, &p->ibuflist, ient) {
607: n++;
608: }
609: LIST_FOREACH(buf, &p->ibuflist, ient) {
610: weight = ADATA_UNIT / n;
611: if (weight > buf->mixmaxweight)
612: weight = buf->mixmaxweight;
613: buf->mixweight = weight;
614: DPRINTF("mix_setmaster: %p: %d/%d -> %d\n", buf,
615: buf->mixweight, buf->mixmaxweight, weight);
616: }
1.1 ratchov 617: }
618:
1.22 ratchov 619: void
620: mix_clear(struct aproc *p)
621: {
622: struct abuf *obuf = LIST_FIRST(&p->obuflist);
623:
624: p->u.mix.lat = 0;
625: obuf->mixitodo = 0;
626: mix_bzero(p);
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: }
660: abuf_wcommit(obuf, scount * obuf->bpf);
1.14 ratchov 661: obuf->subidone += scount * ibuf->bpf;
1.13 ratchov 662: DPRINTFN(4, "sub_bcopy: %u frames\n", scount);
1.1 ratchov 663: }
664:
665: int
666: sub_in(struct aproc *p, struct abuf *ibuf)
667: {
668: struct abuf *i, *inext;
1.20 ratchov 669: unsigned done, fdrop;
1.12 ratchov 670:
671: if (!ABUF_ROK(ibuf))
672: return 0;
1.1 ratchov 673: done = ibuf->used;
1.12 ratchov 674: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
1.1 ratchov 675: inext = LIST_NEXT(i, oent);
1.5 ratchov 676: if (!ABUF_WOK(i)) {
1.14 ratchov 677: if ((p->u.sub.flags & SUB_DROP) && i->subidone == 0) {
1.5 ratchov 678: if (i->xrun == XRUN_ERROR) {
679: abuf_eof(i);
680: continue;
681: }
1.20 ratchov 682: fdrop = ibuf->used / ibuf->bpf;
1.5 ratchov 683: if (i->xrun == XRUN_SYNC)
1.20 ratchov 684: i->silence += fdrop * i->bpf;
1.12 ratchov 685: else {
1.20 ratchov 686: abuf_ipos(i, -(int)fdrop);
1.12 ratchov 687: if (i->duplex) {
688: DPRINTF("sub_in: duplex %u\n",
1.20 ratchov 689: fdrop);
690: i->duplex->silence += fdrop *
691: i->duplex->bpf;
1.12 ratchov 692: abuf_opos(i->duplex,
1.20 ratchov 693: -(int)fdrop);
1.12 ratchov 694: }
695: }
1.20 ratchov 696: i->subidone += fdrop * ibuf->bpf;
1.12 ratchov 697: DPRINTF("sub_in: silence = %u\n", i->silence);
1.5 ratchov 698: }
1.12 ratchov 699: } else
1.1 ratchov 700: sub_bcopy(ibuf, i);
1.14 ratchov 701: if (done > i->subidone)
702: done = i->subidone;
1.12 ratchov 703: if (!abuf_flush(i))
704: continue;
1.1 ratchov 705: }
706: LIST_FOREACH(i, &p->obuflist, oent) {
1.14 ratchov 707: i->subidone -= done;
1.1 ratchov 708: }
1.6 ratchov 709: abuf_rdiscard(ibuf, done);
1.12 ratchov 710: p->u.sub.lat -= done / ibuf->bpf;
1.22 ratchov 711: if (LIST_EMPTY(&p->obuflist))
712: p->u.sub.idle += done / ibuf->bpf;
1.12 ratchov 713: return 1;
1.1 ratchov 714: }
715:
716: int
717: sub_out(struct aproc *p, struct abuf *obuf)
718: {
719: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
720: struct abuf *i, *inext;
721: unsigned done;
722:
1.12 ratchov 723: if (!ABUF_WOK(obuf))
724: return 0;
725: if (!abuf_fill(ibuf)) {
726: return 0;
727: }
1.14 ratchov 728: if (obuf->subidone == ibuf->used)
1.1 ratchov 729: return 0;
730:
731: done = ibuf->used;
1.12 ratchov 732: for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
733: inext = LIST_NEXT(i, oent);
734: if (!abuf_flush(i))
735: continue;
736: sub_bcopy(ibuf, i);
1.14 ratchov 737: if (done > i->subidone)
738: done = i->subidone;
1.1 ratchov 739: }
740: LIST_FOREACH(i, &p->obuflist, oent) {
1.14 ratchov 741: i->subidone -= done;
1.1 ratchov 742: }
1.6 ratchov 743: abuf_rdiscard(ibuf, done);
1.12 ratchov 744: p->u.sub.lat -= done / ibuf->bpf;
1.22 ratchov 745: if (LIST_EMPTY(&p->obuflist))
746: p->u.sub.idle += done / ibuf->bpf;
1.1 ratchov 747: return 1;
748: }
749:
750: void
751: sub_eof(struct aproc *p, struct abuf *ibuf)
752: {
753: struct abuf *obuf;
754:
755: while (!LIST_EMPTY(&p->obuflist)) {
756: obuf = LIST_FIRST(&p->obuflist);
757: abuf_eof(obuf);
758: }
1.8 ratchov 759: aproc_del(p);
1.1 ratchov 760: }
761:
762: void
763: sub_hup(struct aproc *p, struct abuf *obuf)
764: {
765: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
766:
767: DPRINTF("sub_hup: %s: detached\n", p->name);
1.12 ratchov 768: abuf_run(ibuf);
1.1 ratchov 769: DPRINTF("sub_hup: done\n");
770: }
771:
772: void
773: sub_newout(struct aproc *p, struct abuf *obuf)
774: {
1.13 ratchov 775: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
776:
777: if (!ibuf || obuf->cmin < ibuf->cmin || obuf->cmax > ibuf->cmax) {
778: fprintf(stderr, "sub_newout: channel ranges mismatch\n");
779: abort();
780: }
1.22 ratchov 781: p->u.sub.idle = 0;
1.14 ratchov 782: obuf->subidone = 0;
1.5 ratchov 783: obuf->xrun = XRUN_IGNORE;
1.1 ratchov 784: }
785:
1.12 ratchov 786: void
787: sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
788: {
789: p->u.sub.lat += delta;
790: DPRINTFN(3, "sub_ipos: lat = %d/%d\n", p->u.sub.lat, p->u.sub.maxlat);
791: aproc_ipos(p, ibuf, delta);
792: }
793:
1.1 ratchov 794: struct aproc_ops sub_ops = {
1.12 ratchov 795: "sub",
796: sub_in,
797: sub_out,
798: sub_eof,
799: sub_hup,
800: NULL,
801: sub_newout,
802: sub_ipos,
803: aproc_opos,
804: NULL
1.1 ratchov 805: };
806:
807: struct aproc *
1.12 ratchov 808: sub_new(char *name, int maxlat)
1.1 ratchov 809: {
810: struct aproc *p;
811:
1.12 ratchov 812: p = aproc_new(&sub_ops, name);
1.5 ratchov 813: p->u.sub.flags = 0;
1.22 ratchov 814: p->u.sub.idle = 0;
1.12 ratchov 815: p->u.sub.lat = 0;
816: p->u.sub.maxlat = maxlat;
1.1 ratchov 817: return p;
1.22 ratchov 818: }
819:
820: void
821: sub_clear(struct aproc *p)
822: {
823: p->u.mix.lat = 0;
1.1 ratchov 824: }
825:
826: /*
827: * Convert one block.
828: */
829: void
1.15 ratchov 830: resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
831: {
832: unsigned inch;
833: short *idata;
1.27 ! ratchov 834: unsigned oblksz;
1.15 ratchov 835: unsigned ifr;
836: unsigned onch;
1.27 ! ratchov 837: int s1, s2, diff;
1.15 ratchov 838: short *odata;
1.27 ! ratchov 839: unsigned iblksz;
1.15 ratchov 840: unsigned ofr;
841: unsigned c;
1.27 ! ratchov 842: short *ctxbuf, *ctx;
! 843: unsigned ctx_start;
1.15 ratchov 844: unsigned icount, ocount;
845:
846: /*
847: * Calculate max frames readable at once from the input buffer.
848: */
849: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
850: ifr = icount / ibuf->bpf;
851: icount = ifr * ibuf->bpf;
852:
853: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
854: ofr = ocount / obuf->bpf;
855: ocount = ofr * obuf->bpf;
856:
857: /*
858: * Partially copy structures into local variables, to avoid
859: * unnecessary indirections; this also allows the compiler to
860: * order local variables more "cache-friendly".
861: */
1.27 ! ratchov 862: diff = p->u.resamp.diff;
1.15 ratchov 863: inch = ibuf->cmax - ibuf->cmin + 1;
1.26 ratchov 864: iblksz = p->u.resamp.iblksz;
1.15 ratchov 865: onch = obuf->cmax - obuf->cmin + 1;
1.26 ratchov 866: oblksz = p->u.resamp.oblksz;
1.15 ratchov 867: ctxbuf = p->u.resamp.ctx;
1.27 ! ratchov 868: ctx_start = p->u.resamp.ctx_start;
1.15 ratchov 869:
870: /*
871: * Start conversion.
872: */
873: DPRINTFN(4, "resamp_bcopy: ifr=%d ofr=%d\n", ifr, ofr);
874: for (;;) {
1.27 ! ratchov 875: if (diff < 0) {
1.15 ratchov 876: if (ifr == 0)
877: break;
1.27 ! ratchov 878: ctx_start ^= 1;
! 879: ctx = ctxbuf + ctx_start;
1.15 ratchov 880: for (c = inch; c > 0; c--) {
881: *ctx = *idata;
882: idata++;
1.27 ! ratchov 883: ctx += RESAMP_NCTX;
1.15 ratchov 884: }
1.27 ! ratchov 885: diff += oblksz;
1.15 ratchov 886: ifr--;
1.27 ! ratchov 887: } else {
! 888: if (ofr == 0)
! 889: break;
! 890: ctx = ctxbuf;
! 891: for (c = onch; c > 0; c--) {
! 892: s1 = ctxbuf[ctx_start];
! 893: s2 = ctxbuf[ctx_start ^ 1];
! 894: ctx += RESAMP_NCTX;
! 895: *odata++ = s1 + (s2 - s1) * diff / (int)oblksz;
! 896: }
! 897: diff -= iblksz;
! 898: ofr--;
1.15 ratchov 899: }
900: }
1.27 ! ratchov 901: p->u.resamp.diff = diff;
! 902: p->u.resamp.ctx_start = ctx_start;
1.15 ratchov 903: DPRINTFN(4, "resamp_bcopy: done, ifr=%d ofr=%d\n", ifr, ofr);
904:
905: /*
906: * Update FIFO pointers.
907: */
908: icount -= ifr * ibuf->bpf;
909: ocount -= ofr * obuf->bpf;
910: abuf_rdiscard(ibuf, icount);
911: abuf_wcommit(obuf, ocount);
912: }
913:
914: int
915: resamp_in(struct aproc *p, struct abuf *ibuf)
916: {
917: struct abuf *obuf = LIST_FIRST(&p->obuflist);
918:
919: DPRINTFN(4, "resamp_in: %s\n", p->name);
920:
921: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
922: return 0;
923: resamp_bcopy(p, ibuf, obuf);
924: if (!abuf_flush(obuf))
925: return 0;
926: return 1;
927: }
928:
929: int
930: resamp_out(struct aproc *p, struct abuf *obuf)
931: {
932: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
933:
934: DPRINTFN(4, "resamp_out: %s\n", p->name);
935:
936: if (!abuf_fill(ibuf))
937: return 0;
938: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
939: return 0;
940: resamp_bcopy(p, ibuf, obuf);
941: return 1;
942: }
943:
944: void
945: resamp_eof(struct aproc *p, struct abuf *ibuf)
946: {
947: DPRINTFN(4, "resamp_eof: %s\n", p->name);
948:
949: aproc_del(p);
950: }
951:
952: void
953: resamp_hup(struct aproc *p, struct abuf *obuf)
954: {
955: DPRINTFN(4, "resamp_hup: %s\n", p->name);
956:
957: aproc_del(p);
958: }
959:
960: void
961: resamp_ipos(struct aproc *p, struct abuf *ibuf, int delta)
962: {
963: struct abuf *obuf = LIST_FIRST(&p->obuflist);
964: long long ipos;
965: int ifac, ofac;
966:
967: DPRINTFN(3, "resamp_ipos: %d\n", delta);
968:
1.26 ratchov 969: ifac = p->u.resamp.iblksz;
970: ofac = p->u.resamp.oblksz;
1.15 ratchov 971: ipos = p->u.resamp.idelta + (long long)delta * ofac;
972: delta = (ipos + ifac - 1) / ifac;
973: p->u.resamp.idelta = ipos - (long long)delta * ifac;
974: abuf_ipos(obuf, delta);
975: }
976:
977: void
978: resamp_opos(struct aproc *p, struct abuf *obuf, int delta)
979: {
980: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
981: long long opos;
982: int ifac, ofac;
983:
984: DPRINTFN(3, "resamp_opos: %d\n", delta);
985:
1.26 ratchov 986: ifac = p->u.resamp.iblksz;
987: ofac = p->u.resamp.oblksz;
1.15 ratchov 988: opos = p->u.resamp.odelta + (long long)delta * ifac;
989: delta = (opos + ofac - 1) / ofac;
990: p->u.resamp.odelta = opos - (long long)delta * ofac;
991: abuf_opos(ibuf, delta);
992: }
993:
994: struct aproc_ops resamp_ops = {
995: "resamp",
996: resamp_in,
997: resamp_out,
998: resamp_eof,
999: resamp_hup,
1000: NULL,
1001: NULL,
1002: resamp_ipos,
1003: resamp_opos,
1004: NULL
1005: };
1006:
1007: struct aproc *
1.26 ratchov 1008: resamp_new(char *name, unsigned iblksz, unsigned oblksz)
1.15 ratchov 1009: {
1010: struct aproc *p;
1.16 ratchov 1011: unsigned i;
1.15 ratchov 1012:
1013: p = aproc_new(&resamp_ops, name);
1.26 ratchov 1014: p->u.resamp.iblksz = iblksz;
1015: p->u.resamp.oblksz = oblksz;
1.27 ! ratchov 1016: p->u.resamp.diff = 0;
1.15 ratchov 1017: p->u.resamp.idelta = 0;
1018: p->u.resamp.odelta = 0;
1.27 ! ratchov 1019: p->u.resamp.ctx_start = 0;
! 1020: for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++)
1.16 ratchov 1021: p->u.resamp.ctx[i] = 0;
1.25 ratchov 1022: #ifdef DEBUG
1.26 ratchov 1023: if (debug_level > 0)
1024: fprintf(stderr, "resamp_new: %u/%u\n", iblksz, oblksz);
1.25 ratchov 1025: #endif
1.17 ratchov 1026: return p;
1027: }
1028:
1029: /*
1030: * Convert one block.
1031: */
1032: void
1033: cmap_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1034: {
1035: unsigned inch;
1036: short *idata;
1037: unsigned onch;
1038: short *odata;
1039: short *ctx, *ictx, *octx;
1040: unsigned c, f, scount, icount, ocount;
1041:
1042: /*
1043: * Calculate max frames readable at once from the input buffer.
1044: */
1045: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1046: icount /= ibuf->bpf;
1047: if (icount == 0)
1048: return;
1049: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1050: ocount /= obuf->bpf;
1051: if (ocount == 0)
1052: return;
1053: scount = icount < ocount ? icount : ocount;
1054: inch = ibuf->cmax - ibuf->cmin + 1;
1055: onch = obuf->cmax - obuf->cmin + 1;
1056: ictx = p->u.cmap.ctx + ibuf->cmin;
1057: octx = p->u.cmap.ctx + obuf->cmin;
1058:
1059: for (f = scount; f > 0; f--) {
1060: ctx = ictx;
1061: for (c = inch; c > 0; c--) {
1062: *ctx = *idata;
1063: idata++;
1064: ctx++;
1065: }
1066: ctx = octx;
1067: for (c = onch; c > 0; c--) {
1068: *odata = *ctx;
1069: odata++;
1070: ctx++;
1071: }
1072: }
1073: DPRINTFN(4, "cmap_bcopy: scount = %u\n", scount);
1074: abuf_rdiscard(ibuf, scount * ibuf->bpf);
1075: abuf_wcommit(obuf, scount * obuf->bpf);
1076: }
1077:
1078: int
1079: cmap_in(struct aproc *p, struct abuf *ibuf)
1080: {
1081: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1082:
1083: DPRINTFN(4, "cmap_in: %s\n", p->name);
1084:
1085: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1086: return 0;
1087: cmap_bcopy(p, ibuf, obuf);
1088: if (!abuf_flush(obuf))
1089: return 0;
1090: return 1;
1091: }
1092:
1093: int
1094: cmap_out(struct aproc *p, struct abuf *obuf)
1095: {
1096: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1097:
1098: DPRINTFN(4, "cmap_out: %s\n", p->name);
1099:
1100: if (!abuf_fill(ibuf))
1101: return 0;
1102: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1103: return 0;
1104: cmap_bcopy(p, ibuf, obuf);
1105: return 1;
1106: }
1107:
1108: void
1109: cmap_eof(struct aproc *p, struct abuf *ibuf)
1110: {
1111: DPRINTFN(4, "cmap_eof: %s\n", p->name);
1112:
1113: aproc_del(p);
1114: }
1115:
1116: void
1117: cmap_hup(struct aproc *p, struct abuf *obuf)
1118: {
1119: DPRINTFN(4, "cmap_hup: %s\n", p->name);
1120:
1121: aproc_del(p);
1122: }
1123:
1124: struct aproc_ops cmap_ops = {
1125: "cmap",
1126: cmap_in,
1127: cmap_out,
1128: cmap_eof,
1129: cmap_hup,
1130: NULL,
1131: NULL,
1.19 ratchov 1132: aproc_ipos,
1133: aproc_opos,
1.17 ratchov 1134: NULL
1135: };
1136:
1137: struct aproc *
1138: cmap_new(char *name, struct aparams *ipar, struct aparams *opar)
1139: {
1140: struct aproc *p;
1141: unsigned i;
1142:
1143: p = aproc_new(&cmap_ops, name);
1144: for (i = 0; i < NCHAN_MAX; i++)
1145: p->u.cmap.ctx[i] = 0;
1.25 ratchov 1146: #ifdef DEBUG
1.17 ratchov 1147: if (debug_level > 0) {
1.25 ratchov 1148: fprintf(stderr, "cmap_new: %s: ", p->name);
1.12 ratchov 1149: aparams_print2(ipar, opar);
1.25 ratchov 1150: fprintf(stderr, "\n");
1.19 ratchov 1151: }
1.25 ratchov 1152: #endif
1.19 ratchov 1153: return p;
1154: }
1155:
1156: /*
1157: * Convert one block.
1158: */
1159: void
1160: enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1161: {
1162: unsigned nch, scount, icount, ocount;
1163: unsigned f;
1164: short *idata;
1165: int s;
1166: unsigned oshift;
1167: int osigbit;
1168: unsigned obps;
1169: unsigned i;
1170: unsigned char *odata;
1171: int obnext;
1172: int osnext;
1173:
1174: /*
1175: * Calculate max frames readable at once from the input buffer.
1176: */
1177: idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
1178: icount /= ibuf->bpf;
1179: if (icount == 0)
1180: return;
1181: odata = abuf_wgetblk(obuf, &ocount, 0);
1182: ocount /= obuf->bpf;
1183: if (ocount == 0)
1184: return;
1185: scount = (icount < ocount) ? icount : ocount;
1186: nch = ibuf->cmax - ibuf->cmin + 1;
1187: DPRINTFN(4, "enc_bcopy: scount = %u, nch = %u\n", scount, nch);
1188:
1189: /*
1190: * Partially copy structures into local variables, to avoid
1191: * unnecessary indirections; this also allows the compiler to
1192: * order local variables more "cache-friendly".
1193: */
1194: oshift = p->u.conv.shift;
1195: osigbit = p->u.conv.sigbit;
1196: obps = p->u.conv.bps;
1197: obnext = p->u.conv.bnext;
1198: osnext = p->u.conv.snext;
1199:
1200: /*
1201: * Start conversion.
1202: */
1203: odata += p->u.conv.bfirst;
1204: for (f = scount * nch; f > 0; f--) {
1205: s = *idata++;
1206: s <<= 16;
1207: s >>= oshift;
1208: s ^= osigbit;
1209: for (i = obps; i > 0; i--) {
1210: *odata = (unsigned char)s;
1211: s >>= 8;
1212: odata += obnext;
1213: }
1214: odata += osnext;
1215: }
1216:
1217: /*
1218: * Update FIFO pointers.
1219: */
1220: abuf_rdiscard(ibuf, scount * ibuf->bpf);
1221: abuf_wcommit(obuf, scount * obuf->bpf);
1222: }
1223:
1224: int
1225: enc_in(struct aproc *p, struct abuf *ibuf)
1226: {
1227: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1228:
1229: DPRINTFN(4, "enc_in: %s\n", p->name);
1230:
1231: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1232: return 0;
1233: enc_bcopy(p, ibuf, obuf);
1234: if (!abuf_flush(obuf))
1235: return 0;
1236: return 1;
1237: }
1238:
1239: int
1240: enc_out(struct aproc *p, struct abuf *obuf)
1241: {
1242: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1243:
1244: DPRINTFN(4, "enc_out: %s\n", p->name);
1245:
1246: if (!abuf_fill(ibuf))
1247: return 0;
1248: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1249: return 0;
1250: enc_bcopy(p, ibuf, obuf);
1251: return 1;
1252: }
1253:
1254: void
1255: enc_eof(struct aproc *p, struct abuf *ibuf)
1256: {
1257: DPRINTFN(4, "enc_eof: %s\n", p->name);
1258:
1259: aproc_del(p);
1260: }
1261:
1262: void
1263: enc_hup(struct aproc *p, struct abuf *obuf)
1264: {
1265: DPRINTFN(4, "enc_hup: %s\n", p->name);
1266:
1267: aproc_del(p);
1268: }
1269:
1270: struct aproc_ops enc_ops = {
1271: "enc",
1272: enc_in,
1273: enc_out,
1274: enc_eof,
1275: enc_hup,
1276: NULL,
1277: NULL,
1278: aproc_ipos,
1279: aproc_opos,
1280: NULL
1281: };
1282:
1283: struct aproc *
1284: enc_new(char *name, struct aparams *par)
1285: {
1286: struct aproc *p;
1287:
1288: p = aproc_new(&enc_ops, name);
1289: p->u.conv.bps = par->bps;
1290: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
1291: if (par->msb) {
1292: p->u.conv.shift = 32 - par->bps * 8;
1293: } else {
1294: p->u.conv.shift = 32 - par->bits;
1295: }
1296: if (!par->le) {
1297: p->u.conv.bfirst = par->bps - 1;
1298: p->u.conv.bnext = -1;
1299: p->u.conv.snext = 2 * par->bps;
1300: } else {
1301: p->u.conv.bfirst = 0;
1302: p->u.conv.bnext = 1;
1303: p->u.conv.snext = 0;
1304: }
1.25 ratchov 1305: #ifdef DEBUG
1.19 ratchov 1306: if (debug_level > 0) {
1307: fprintf(stderr, "enc_new: %s: ", p->name);
1308: aparams_print(par);
1309: fprintf(stderr, "\n");
1310: }
1.25 ratchov 1311: #endif
1.19 ratchov 1312: return p;
1313: }
1314:
1315: /*
1316: * Convert one block.
1317: */
1318: void
1319: dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
1320: {
1321: unsigned nch, scount, icount, ocount;
1322: unsigned f;
1323: unsigned ibps;
1324: unsigned i;
1325: int s = 0xdeadbeef;
1326: unsigned char *idata;
1327: int ibnext;
1328: int isnext;
1329: int isigbit;
1330: unsigned ishift;
1331: short *odata;
1332:
1333: /*
1334: * Calculate max frames readable at once from the input buffer.
1335: */
1336: idata = abuf_rgetblk(ibuf, &icount, 0);
1337: icount /= ibuf->bpf;
1338: if (icount == 0)
1339: return;
1340: odata = (short *)abuf_wgetblk(obuf, &ocount, 0);
1341: ocount /= obuf->bpf;
1342: if (ocount == 0)
1343: return;
1344: scount = (icount < ocount) ? icount : ocount;
1345: nch = obuf->cmax - obuf->cmin + 1;
1346: DPRINTFN(4, "dec_bcopy: scount = %u, nch = %u\n", scount, nch);
1347:
1348: /*
1349: * Partially copy structures into local variables, to avoid
1350: * unnecessary indirections; this also allows the compiler to
1351: * order local variables more "cache-friendly".
1352: */
1353: ibps = p->u.conv.bps;
1354: ibnext = p->u.conv.bnext;
1355: isigbit = p->u.conv.sigbit;
1356: ishift = p->u.conv.shift;
1357: isnext = p->u.conv.snext;
1358:
1359: /*
1360: * Start conversion.
1361: */
1362: idata += p->u.conv.bfirst;
1363: for (f = scount * nch; f > 0; f--) {
1364: for (i = ibps; i > 0; i--) {
1365: s <<= 8;
1366: s |= *idata;
1367: idata += ibnext;
1368: }
1369: idata += isnext;
1370: s ^= isigbit;
1371: s <<= ishift;
1372: s >>= 16;
1373: *odata++ = s;
1374: }
1375:
1376: /*
1377: * Update FIFO pointers.
1378: */
1379: abuf_rdiscard(ibuf, scount * ibuf->bpf);
1380: abuf_wcommit(obuf, scount * obuf->bpf);
1381: }
1382:
1383: int
1384: dec_in(struct aproc *p, struct abuf *ibuf)
1385: {
1386: struct abuf *obuf = LIST_FIRST(&p->obuflist);
1387:
1388: DPRINTFN(4, "dec_in: %s\n", p->name);
1389:
1390: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1391: return 0;
1392: dec_bcopy(p, ibuf, obuf);
1393: if (!abuf_flush(obuf))
1394: return 0;
1395: return 1;
1396: }
1397:
1398: int
1399: dec_out(struct aproc *p, struct abuf *obuf)
1400: {
1401: struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
1402:
1403: DPRINTFN(4, "dec_out: %s\n", p->name);
1404:
1405: if (!abuf_fill(ibuf))
1406: return 0;
1407: if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
1408: return 0;
1409: dec_bcopy(p, ibuf, obuf);
1410: return 1;
1411: }
1412:
1413: void
1414: dec_eof(struct aproc *p, struct abuf *ibuf)
1415: {
1416: DPRINTFN(4, "dec_eof: %s\n", p->name);
1417:
1418: aproc_del(p);
1419: }
1420:
1421: void
1422: dec_hup(struct aproc *p, struct abuf *obuf)
1423: {
1424: DPRINTFN(4, "dec_hup: %s\n", p->name);
1425:
1426: aproc_del(p);
1427: }
1428:
1429: struct aproc_ops dec_ops = {
1430: "dec",
1431: dec_in,
1432: dec_out,
1433: dec_eof,
1434: dec_hup,
1435: NULL,
1436: NULL,
1437: aproc_ipos,
1438: aproc_opos,
1439: NULL
1440: };
1441:
1442: struct aproc *
1443: dec_new(char *name, struct aparams *par)
1444: {
1445: struct aproc *p;
1446:
1447: p = aproc_new(&dec_ops, name);
1448: p->u.conv.bps = par->bps;
1449: p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
1450: if (par->msb) {
1451: p->u.conv.shift = 32 - par->bps * 8;
1452: } else {
1453: p->u.conv.shift = 32 - par->bits;
1454: }
1455: if (par->le) {
1456: p->u.conv.bfirst = par->bps - 1;
1457: p->u.conv.bnext = -1;
1458: p->u.conv.snext = 2 * par->bps;
1459: } else {
1460: p->u.conv.bfirst = 0;
1461: p->u.conv.bnext = 1;
1462: p->u.conv.snext = 0;
1463: }
1.25 ratchov 1464: #ifdef DEBUG
1.19 ratchov 1465: if (debug_level > 0) {
1466: fprintf(stderr, "dec_new: %s: ", p->name);
1467: aparams_print(par);
1468: fprintf(stderr, "\n");
1.12 ratchov 1469: }
1.25 ratchov 1470: #endif
1.1 ratchov 1471: return p;
1472: }