[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.35

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