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