[BACK]Return to aproc.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

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: }