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

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