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

Annotation of src/usr.bin/aucat/dsp.c, Revision 1.1

1.1     ! ratchov     1: /*     $OpenBSD$       */
        !             2: /*
        !             3:  * Copyright (c) 2008-2012 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: #include <string.h>
        !            18: #include "dsp.h"
        !            19: #include "utils.h"
        !            20:
        !            21: int aparams_ctltovol[128] = {
        !            22:            0,
        !            23:          256,    266,    276,    287,    299,    310,    323,    335,
        !            24:          348,    362,    376,    391,    406,    422,    439,    456,
        !            25:          474,    493,    512,    532,    553,    575,    597,    621,
        !            26:          645,    670,    697,    724,    753,    782,    813,    845,
        !            27:          878,    912,    948,    985,   1024,   1064,   1106,   1149,
        !            28:         1195,   1241,   1290,   1341,   1393,   1448,   1505,   1564,
        !            29:         1625,   1689,   1756,   1825,   1896,   1971,   2048,   2128,
        !            30:         2212,   2299,   2389,   2483,   2580,   2682,   2787,   2896,
        !            31:         3010,   3128,   3251,   3379,   3511,   3649,   3792,   3941,
        !            32:         4096,   4257,   4424,   4598,   4778,   4966,   5161,   5363,
        !            33:         5574,   5793,   6020,   6256,   6502,   6757,   7023,   7298,
        !            34:         7585,   7883,   8192,   8514,   8848,   9195,   9556,   9931,
        !            35:        10321,  10726,  11148,  11585,  12040,  12513,  13004,  13515,
        !            36:        14045,  14596,  15170,  15765,  16384,  17027,  17696,  18390,
        !            37:        19112,  19863,  20643,  21453,  22295,  23170,  24080,  25025,
        !            38:        26008,  27029,  28090,  29193,  30339,  31530,  32768
        !            39: };
        !            40:
        !            41: short dec_ulawmap[256] = {
        !            42:        -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
        !            43:        -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
        !            44:        -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
        !            45:        -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
        !            46:         -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
        !            47:         -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
        !            48:         -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
        !            49:         -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
        !            50:         -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
        !            51:         -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
        !            52:          -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
        !            53:          -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
        !            54:          -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
        !            55:          -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
        !            56:          -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
        !            57:           -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
        !            58:         32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
        !            59:         23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
        !            60:         15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
        !            61:         11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
        !            62:          7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
        !            63:          5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
        !            64:          3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
        !            65:          2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
        !            66:          1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
        !            67:          1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
        !            68:           876,    844,    812,    780,    748,    716,    684,    652,
        !            69:           620,    588,    556,    524,    492,    460,    428,    396,
        !            70:           372,    356,    340,    324,    308,    292,    276,    260,
        !            71:           244,    228,    212,    196,    180,    164,    148,    132,
        !            72:           120,    112,    104,     96,     88,     80,     72,     64,
        !            73:            56,     48,     40,     32,     24,     16,      8,      0
        !            74: };
        !            75:
        !            76: short dec_alawmap[256] = {
        !            77:         -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
        !            78:         -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
        !            79:         -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
        !            80:         -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
        !            81:        -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
        !            82:        -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
        !            83:        -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
        !            84:        -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
        !            85:          -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
        !            86:          -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
        !            87:           -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
        !            88:          -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
        !            89:         -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
        !            90:         -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
        !            91:          -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
        !            92:          -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
        !            93:          5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
        !            94:          7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
        !            95:          2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
        !            96:          3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
        !            97:         22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
        !            98:         30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
        !            99:         11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
        !           100:         15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
        !           101:           344,    328,    376,    360,    280,    264,    312,    296,
        !           102:           472,    456,    504,    488,    408,    392,    440,    424,
        !           103:            88,     72,    120,    104,     24,      8,     56,     40,
        !           104:           216,    200,    248,    232,    152,    136,    184,    168,
        !           105:          1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
        !           106:          1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
        !           107:           688,    656,    752,    720,    560,    528,    624,    592,
        !           108:           944,    912,   1008,    976,    816,    784,    880,    848
        !           109: };
        !           110:
        !           111: /*
        !           112:  * Generate a string corresponding to the encoding in par,
        !           113:  * return the length of the resulting string.
        !           114:  */
        !           115: int
        !           116: aparams_enctostr(struct aparams *par, char *ostr)
        !           117: {
        !           118:        char *p = ostr;
        !           119:
        !           120:        *p++ = par->sig ? 's' : 'u';
        !           121:        if (par->bits > 9)
        !           122:                *p++ = '0' + par->bits / 10;
        !           123:        *p++ = '0' + par->bits % 10;
        !           124:        if (par->bps > 1) {
        !           125:                *p++ = par->le ? 'l' : 'b';
        !           126:                *p++ = 'e';
        !           127:                if (par->bps != APARAMS_BPS(par->bits) ||
        !           128:                    par->bits < par->bps * 8) {
        !           129:                        *p++ = par->bps + '0';
        !           130:                        if (par->bits < par->bps * 8) {
        !           131:                                *p++ = par->msb ? 'm' : 'l';
        !           132:                                *p++ = 's';
        !           133:                                *p++ = 'b';
        !           134:                        }
        !           135:                }
        !           136:        }
        !           137:        *p++ = '\0';
        !           138:        return p - ostr - 1;
        !           139: }
        !           140:
        !           141: /*
        !           142:  * Parse an encoding string, examples: s8, u8, s16, s16le, s24be ...
        !           143:  * set *istr to the char following the encoding. Return the number
        !           144:  * of bytes consumed.
        !           145:  */
        !           146: int
        !           147: aparams_strtoenc(struct aparams *par, char *istr)
        !           148: {
        !           149:        char *p = istr;
        !           150:        int i, sig, bits, le, bps, msb;
        !           151:
        !           152: #define IS_SEP(c)                      \
        !           153:        (((c) < 'a' || (c) > 'z') &&    \
        !           154:         ((c) < 'A' || (c) > 'Z') &&    \
        !           155:         ((c) < '0' || (c) > '9'))
        !           156:
        !           157:        /*
        !           158:         * get signedness
        !           159:         */
        !           160:        if (*p == 's') {
        !           161:                sig = 1;
        !           162:        } else if (*p == 'u') {
        !           163:                sig = 0;
        !           164:        } else
        !           165:                return 0;
        !           166:        p++;
        !           167:
        !           168:        /*
        !           169:         * get number of bits per sample
        !           170:         */
        !           171:        bits = 0;
        !           172:        for (i = 0; i < 2; i++) {
        !           173:                if (*p < '0' || *p > '9')
        !           174:                        break;
        !           175:                bits = (bits * 10) + *p - '0';
        !           176:                p++;
        !           177:        }
        !           178:        if (bits < BITS_MIN || bits > BITS_MAX)
        !           179:                return 0;
        !           180:        bps = APARAMS_BPS(bits);
        !           181:        msb = 1;
        !           182:        le = ADATA_LE;
        !           183:
        !           184:        /*
        !           185:         * get (optional) endianness
        !           186:         */
        !           187:        if (p[0] == 'l' && p[1] == 'e') {
        !           188:                le = 1;
        !           189:                p += 2;
        !           190:        } else if (p[0] == 'b' && p[1] == 'e') {
        !           191:                le = 0;
        !           192:                p += 2;
        !           193:        } else if (IS_SEP(*p)) {
        !           194:                goto done;
        !           195:        } else
        !           196:                return 0;
        !           197:
        !           198:        /*
        !           199:         * get (optional) number of bytes
        !           200:         */
        !           201:        if (*p >= '0' && *p <= '9') {
        !           202:                bps = *p - '0';
        !           203:                if (bps < (bits + 7) / 8 ||
        !           204:                    bps > (BITS_MAX + 7) / 8)
        !           205:                        return 0;
        !           206:                p++;
        !           207:
        !           208:                /*
        !           209:                 * get (optional) alignment
        !           210:                 */
        !           211:                if (p[0] == 'm' && p[1] == 's' && p[2] == 'b') {
        !           212:                        msb = 1;
        !           213:                        p += 3;
        !           214:                } else if (p[0] == 'l' && p[1] == 's' && p[2] == 'b') {
        !           215:                        msb = 0;
        !           216:                        p += 3;
        !           217:                } else if (IS_SEP(*p)) {
        !           218:                        goto done;
        !           219:                } else
        !           220:                        return 0;
        !           221:        } else if (!IS_SEP(*p))
        !           222:                return 0;
        !           223:
        !           224: done:
        !           225:                par->msb = msb;
        !           226:        par->sig = sig;
        !           227:        par->bits = bits;
        !           228:        par->bps = bps;
        !           229:        par->le = le;
        !           230:        return p - istr;
        !           231: }
        !           232:
        !           233: /*
        !           234:  * Initialise parameters structure with the defaults natively supported
        !           235:  * by the machine.
        !           236:  */
        !           237: void
        !           238: aparams_init(struct aparams *par)
        !           239: {
        !           240:        par->bps = sizeof(adata_t);
        !           241:        par->bits = ADATA_BITS;
        !           242:        par->le = ADATA_LE;
        !           243:        par->sig = 1;
        !           244:        par->msb = 0;
        !           245: }
        !           246:
        !           247: /*
        !           248:  * log the given format/channels/encoding
        !           249:  */
        !           250: void
        !           251: aparams_log(struct aparams *par)
        !           252: {
        !           253:        char enc[ENCMAX];
        !           254:
        !           255:        aparams_enctostr(par, enc);
        !           256:        log_puts(enc);
        !           257: }
        !           258:
        !           259: /*
        !           260:  * return true if encoding corresponds to what we store in adata_t
        !           261:  */
        !           262: int
        !           263: aparams_native(struct aparams *par)
        !           264: {
        !           265:        return par->bps == sizeof(adata_t) && par->bits == ADATA_BITS &&
        !           266:            (par->bps == 1 || par->le == ADATA_LE) &&
        !           267:            (par->bits == par->bps * 8 || !par->msb);
        !           268: }
        !           269:
        !           270: /*
        !           271:  * resample the given number of frames
        !           272:  */
        !           273: int
        !           274: resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo)
        !           275: {
        !           276:        unsigned int nch;
        !           277:        adata_t *idata;
        !           278:        unsigned int oblksz;
        !           279:        unsigned int ifr;
        !           280:        int s, ds, diff;
        !           281:        adata_t *odata;
        !           282:        unsigned int iblksz;
        !           283:        unsigned int ofr;
        !           284:        unsigned int c;
        !           285:        adata_t *ctxbuf, *ctx;
        !           286:        unsigned int ctx_start;
        !           287:
        !           288:        /*
        !           289:         * Partially copy structures into local variables, to avoid
        !           290:         * unnecessary indirections; this also allows the compiler to
        !           291:         * order local variables more "cache-friendly".
        !           292:         */
        !           293:        idata = in;
        !           294:        odata = out;
        !           295:        diff = p->diff;
        !           296:        iblksz = p->iblksz;
        !           297:        oblksz = p->oblksz;
        !           298:        ctxbuf = p->ctx;
        !           299:        ctx_start = p->ctx_start;
        !           300:        nch = p->nch;
        !           301:        ifr = todo;
        !           302:        ofr = oblksz;
        !           303:
        !           304:        /*
        !           305:         * Start conversion.
        !           306:         */
        !           307: #ifdef DEBUG
        !           308:        if (log_level >= 4) {
        !           309:                log_puts("resamp: copying ");
        !           310:                log_puti(todo);
        !           311:                log_puts(" frames, diff = ");
        !           312:                log_putu(diff);
        !           313:                log_puts("\n");
        !           314:        }
        !           315: #endif
        !           316:        for (;;) {
        !           317:                if (diff < 0) {
        !           318:                        if (ifr == 0)
        !           319:                                break;
        !           320:                        ctx_start ^= 1;
        !           321:                        ctx = ctxbuf + ctx_start;
        !           322:                        for (c = nch; c > 0; c--) {
        !           323:                                *ctx = *idata++;
        !           324:                                ctx += RESAMP_NCTX;
        !           325:                        }
        !           326:                        diff += oblksz;
        !           327:                        ifr--;
        !           328:                } else if (diff > 0) {
        !           329:                        if (ofr == 0)
        !           330:                                break;
        !           331:                        ctx = ctxbuf;
        !           332:                        for (c = nch; c > 0; c--) {
        !           333:                                s = ctx[ctx_start];
        !           334:                                ds = ctx[ctx_start ^ 1] - s;
        !           335:                                ctx += RESAMP_NCTX;
        !           336:                                *odata++ = s + ADATA_MULDIV(ds, diff, oblksz);
        !           337:                        }
        !           338:                        diff -= iblksz;
        !           339:                        ofr--;
        !           340:                } else {
        !           341:                        if (ifr == 0 || ofr == 0)
        !           342:                                break;
        !           343:                        ctx = ctxbuf + ctx_start;
        !           344:                        for (c = nch; c > 0; c--) {
        !           345:                                *odata++ = *ctx;
        !           346:                                ctx += RESAMP_NCTX;
        !           347:                        }
        !           348:                        ctx_start ^= 1;
        !           349:                        ctx = ctxbuf + ctx_start;
        !           350:                        for (c = nch; c > 0; c--) {
        !           351:                                *ctx = *idata++;
        !           352:                                ctx += RESAMP_NCTX;
        !           353:                        }
        !           354:                        diff -= iblksz;
        !           355:                        diff += oblksz;
        !           356:                        ifr--;
        !           357:                        ofr--;
        !           358:                }
        !           359:        }
        !           360:        p->diff = diff;
        !           361:        p->ctx_start = ctx_start;
        !           362:        return oblksz - ofr;
        !           363: }
        !           364:
        !           365: /*
        !           366:  * initialize resampler with ibufsz/obufsz factor and "nch" channels
        !           367:  */
        !           368: void
        !           369: resamp_init(struct resamp *p, unsigned int iblksz, unsigned int oblksz, int nch)
        !           370: {
        !           371:        unsigned int i;
        !           372:
        !           373:        p->iblksz = iblksz;
        !           374:        p->oblksz = oblksz;
        !           375:        p->diff = 0;
        !           376:        p->idelta = 0;
        !           377:        p->odelta = 0;
        !           378:        p->nch = nch;
        !           379:        p->ctx_start = 0;
        !           380:        for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++)
        !           381:                p->ctx[i] = 0;
        !           382: #ifdef DEBUG
        !           383:        if (log_level >= 3) {
        !           384:                log_puts("resamp: ");
        !           385:                log_putu(iblksz);
        !           386:                log_puts("/");
        !           387:                log_putu(oblksz);
        !           388:                log_puts("\n");
        !           389:        }
        !           390: #endif
        !           391: }
        !           392:
        !           393: /*
        !           394:  * encode "todo" frames from native to foreign encoding
        !           395:  */
        !           396: void
        !           397: enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo)
        !           398: {
        !           399:        unsigned int f;
        !           400:        adata_t *idata;
        !           401:        unsigned int s;
        !           402:        unsigned int oshift;
        !           403:        unsigned int obias;
        !           404:        unsigned int obps;
        !           405:        unsigned int i;
        !           406:        unsigned char *odata;
        !           407:        int obnext;
        !           408:        int osnext;
        !           409:
        !           410: #ifdef DEBUG
        !           411:        if (log_level >= 4) {
        !           412:                log_puts("enc: copying ");
        !           413:                log_putu(todo);
        !           414:                log_puts(" frames\n");
        !           415:        }
        !           416: #endif
        !           417:        /*
        !           418:         * Partially copy structures into local variables, to avoid
        !           419:         * unnecessary indirections; this also allows the compiler to
        !           420:         * order local variables more "cache-friendly".
        !           421:         */
        !           422:        idata = (adata_t *)in;
        !           423:        odata = out;
        !           424:        oshift = p->shift;
        !           425:        obias = p->bias;
        !           426:        obps = p->bps;
        !           427:        obnext = p->bnext;
        !           428:        osnext = p->snext;
        !           429:
        !           430:        /*
        !           431:         * Start conversion.
        !           432:         */
        !           433:        odata += p->bfirst;
        !           434:        for (f = todo * p->nch; f > 0; f--) {
        !           435:                /* convert adata to u32 */
        !           436:                s = (int)*idata++ + ADATA_UNIT;
        !           437:                s <<= 32 - ADATA_BITS;
        !           438:                /* convert u32 to uN */
        !           439:                s >>= oshift;
        !           440:                /* convert uN to sN */
        !           441:                s -= obias;
        !           442:                /* packetize sN */
        !           443:                for (i = obps; i > 0; i--) {
        !           444:                        *odata = (unsigned char)s;
        !           445:                        s >>= 8;
        !           446:                        odata += obnext;
        !           447:                }
        !           448:                odata += osnext;
        !           449:        }
        !           450: }
        !           451:
        !           452: /*
        !           453:  * store "todo" frames of silence in foreign encoding
        !           454:  */
        !           455: void
        !           456: enc_sil_do(struct conv *p, unsigned char *out, int todo)
        !           457: {
        !           458:        unsigned int f;
        !           459:        unsigned int s;
        !           460:        unsigned int oshift;
        !           461:        int obias;
        !           462:        unsigned int obps;
        !           463:        unsigned int i;
        !           464:        unsigned char *odata;
        !           465:        int obnext;
        !           466:        int osnext;
        !           467:
        !           468: #ifdef DEBUG
        !           469:        if (log_level >= 4) {
        !           470:                log_puts("enc: silence ");
        !           471:                log_putu(todo);
        !           472:                log_puts(" frames\n");
        !           473:        }
        !           474: #endif
        !           475:        /*
        !           476:         * Partially copy structures into local variables, to avoid
        !           477:         * unnecessary indirections; this also allows the compiler to
        !           478:         * order local variables more "cache-friendly".
        !           479:         */
        !           480:        odata = out;
        !           481:        oshift = p->shift;
        !           482:        obias = p->bias;
        !           483:        obps = p->bps;
        !           484:        obnext = p->bnext;
        !           485:        osnext = p->snext;
        !           486:
        !           487:        /*
        !           488:         * Start conversion.
        !           489:         */
        !           490:        odata += p->bfirst;
        !           491:        for (f = todo * p->nch; f > 0; f--) {
        !           492:                s = ((1U << 31) >> oshift) - obias;
        !           493:                for (i = obps; i > 0; i--) {
        !           494:                        *odata = (unsigned char)s;
        !           495:                        s >>= 8;
        !           496:                        odata += obnext;
        !           497:                }
        !           498:                odata += osnext;
        !           499:        }
        !           500: }
        !           501:
        !           502: /*
        !           503:  * initialize encoder from native to foreign encoding
        !           504:  */
        !           505: void
        !           506: enc_init(struct conv *p, struct aparams *par, int nch)
        !           507: {
        !           508:        p->nch = nch;
        !           509:        p->bps = par->bps;
        !           510:        if (par->msb) {
        !           511:                p->shift = 32 - par->bps * 8;
        !           512:        } else {
        !           513:                p->shift = 32 - par->bits;
        !           514:        }
        !           515:        if (par->sig) {
        !           516:                p->bias = (1U << 31) >> p->shift;
        !           517:        } else {
        !           518:                p->bias = 0;
        !           519:        }
        !           520:        if (!par->le) {
        !           521:                p->bfirst = par->bps - 1;
        !           522:                p->bnext = -1;
        !           523:                p->snext = 2 * par->bps;
        !           524:        } else {
        !           525:                p->bfirst = 0;
        !           526:                p->bnext = 1;
        !           527:                p->snext = 0;
        !           528:        }
        !           529: #ifdef DEBUG
        !           530:        if (log_level >= 3) {
        !           531:                log_puts("enc: ");
        !           532:                aparams_log(par);
        !           533:                log_puts(", ");
        !           534:                log_puti(p->nch);
        !           535:                log_puts(" channels\n");
        !           536:        }
        !           537: #endif
        !           538: }
        !           539:
        !           540: /*
        !           541:  * decode "todo" frames from from foreign to native encoding
        !           542:  */
        !           543: void
        !           544: dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo)
        !           545: {
        !           546:        unsigned int f;
        !           547:        unsigned int ibps;
        !           548:        unsigned int i;
        !           549:        unsigned int s = 0xdeadbeef;
        !           550:        unsigned char *idata;
        !           551:        int ibnext;
        !           552:        int isnext;
        !           553:        unsigned int ibias;
        !           554:        unsigned int ishift;
        !           555:        adata_t *odata;
        !           556:
        !           557: #ifdef DEBUG
        !           558:        if (log_level >= 4) {
        !           559:                log_puts("dec: copying ");
        !           560:                log_putu(todo);
        !           561:                log_puts(" frames\n");
        !           562:        }
        !           563: #endif
        !           564:        /*
        !           565:         * Partially copy structures into local variables, to avoid
        !           566:         * unnecessary indirections; this also allows the compiler to
        !           567:         * order local variables more "cache-friendly".
        !           568:         */
        !           569:        idata = in;
        !           570:        odata = (adata_t *)out;
        !           571:        ibps = p->bps;
        !           572:        ibnext = p->bnext;
        !           573:        ibias = p->bias;
        !           574:        ishift = p->shift;
        !           575:        isnext = p->snext;
        !           576:
        !           577:        /*
        !           578:         * Start conversion.
        !           579:         */
        !           580:        idata += p->bfirst;
        !           581:        for (f = todo * p->nch; f > 0; f--) {
        !           582:                for (i = ibps; i > 0; i--) {
        !           583:                        s <<= 8;
        !           584:                        s |= *idata;
        !           585:                        idata += ibnext;
        !           586:                }
        !           587:                idata += isnext;
        !           588:                s += ibias;
        !           589:                s <<= ishift;
        !           590:                s >>= 32 - ADATA_BITS;
        !           591:                *odata++ = s - ADATA_UNIT;
        !           592:        }
        !           593: }
        !           594:
        !           595: /*
        !           596:  * convert a 32-bit float to adata_t, clipping to -1:1, boundaries
        !           597:  * excluded
        !           598:  */
        !           599: static inline int
        !           600: f32_to_adata(unsigned int x)
        !           601: {
        !           602:        unsigned int s, e, m, y;
        !           603:
        !           604:        s = (x >> 31);
        !           605:        e = (x >> 23) & 0xff;
        !           606:        m = (x << 8) | 0x80000000;
        !           607:        if (e < 127 - 24)
        !           608:                y = 0;
        !           609:        else if (e > 127 - 1)
        !           610:                y = ADATA_UNIT - 1;
        !           611:        else
        !           612:                y = m >> (127 + (32 - ADATA_BITS) - e);
        !           613:        return (y ^ -s) + s;
        !           614: }
        !           615:
        !           616: /*
        !           617:  * convert samples from little endian ieee 754 floats to adata_t
        !           618:  */
        !           619: void
        !           620: dec_do_float(struct conv *p, unsigned char *in, unsigned char *out, int todo)
        !           621: {
        !           622:        unsigned int f;
        !           623:        unsigned int i;
        !           624:        unsigned int s = 0xdeadbeef;
        !           625:        unsigned char *idata;
        !           626:        int ibnext;
        !           627:        int isnext;
        !           628:        adata_t *odata;
        !           629:
        !           630: #ifdef DEBUG
        !           631:        if (log_level >= 4) {
        !           632:                log_puts("dec_float: copying ");
        !           633:                log_putu(todo);
        !           634:                log_puts(" frames\n");
        !           635:        }
        !           636: #endif
        !           637:        /*
        !           638:         * Partially copy structures into local variables, to avoid
        !           639:         * unnecessary indirections; this also allows the compiler to
        !           640:         * order local variables more "cache-friendly".
        !           641:         */
        !           642:        idata = in;
        !           643:        odata = (adata_t *)out;
        !           644:        ibnext = p->bnext;
        !           645:        isnext = p->snext;
        !           646:
        !           647:        /*
        !           648:         * Start conversion.
        !           649:         */
        !           650:        idata += p->bfirst;
        !           651:        for (f = todo * p->nch; f > 0; f--) {
        !           652:                for (i = 4; i > 0; i--) {
        !           653:                        s <<= 8;
        !           654:                        s |= *idata;
        !           655:                        idata += ibnext;
        !           656:                }
        !           657:                idata += isnext;
        !           658:                *odata++ = f32_to_adata(s);
        !           659:        }
        !           660: }
        !           661:
        !           662: /*
        !           663:  * convert samples from ulaw/alaw to adata_t
        !           664:  */
        !           665: void
        !           666: dec_do_ulaw(struct conv *p, unsigned char *in, unsigned char *out, int todo, int is_alaw)
        !           667: {
        !           668:        unsigned int f;
        !           669:        unsigned char *idata;
        !           670:        adata_t *odata;
        !           671:        short *map;
        !           672:
        !           673: #ifdef DEBUG
        !           674:        if (log_level >= 4) {
        !           675:                log_puts("dec_ulaw: copying ");
        !           676:                log_putu(todo);
        !           677:                log_puts(" frames\n");
        !           678:        }
        !           679: #endif
        !           680:        map = is_alaw ? dec_alawmap : dec_ulawmap;
        !           681:        idata = in;
        !           682:        odata = (adata_t *)out;
        !           683:        for (f = todo * p->nch; f > 0; f--)
        !           684:                *odata++ = map[*idata++] << (ADATA_BITS - 16);
        !           685: }
        !           686:
        !           687: /*
        !           688:  * initialize decoder from foreign to native encoding
        !           689:  */
        !           690: void
        !           691: dec_init(struct conv *p, struct aparams *par, int nch)
        !           692: {
        !           693:        p->bps = par->bps;
        !           694:        p->nch = nch;
        !           695:        if (par->msb) {
        !           696:                p->shift = 32 - par->bps * 8;
        !           697:        } else {
        !           698:                p->shift = 32 - par->bits;
        !           699:        }
        !           700:        if (par->sig) {
        !           701:                p->bias = (1U << 31) >> p->shift;
        !           702:        } else {
        !           703:                p->bias = 0;
        !           704:        }
        !           705:        if (par->le) {
        !           706:                p->bfirst = par->bps - 1;
        !           707:                p->bnext = -1;
        !           708:                p->snext = 2 * par->bps;
        !           709:        } else {
        !           710:                p->bfirst = 0;
        !           711:                p->bnext = 1;
        !           712:                p->snext = 0;
        !           713:        }
        !           714: #ifdef DEBUG
        !           715:        if (log_level >= 3) {
        !           716:                log_puts("dec: ");
        !           717:                aparams_log(par);
        !           718:                log_puts(", ");
        !           719:                log_puti(p->nch);
        !           720:                log_puts(" channels\n");
        !           721:        }
        !           722: #endif
        !           723: }
        !           724:
        !           725: /*
        !           726:  * mix "todo" input frames on the output with the given volume
        !           727:  */
        !           728: void
        !           729: cmap_add(struct cmap *p, void *in, void *out, int vol, int todo)
        !           730: {
        !           731:        adata_t *idata, *odata;
        !           732:        int i, j, nch, istart, inext, onext, ostart, y, v;
        !           733:
        !           734: #ifdef DEBUG
        !           735:        if (log_level >= 4) {
        !           736:                log_puts("cmap: adding ");
        !           737:                log_puti(todo);
        !           738:                log_puts(" frames\n");
        !           739:        }
        !           740: #endif
        !           741:        idata = in;
        !           742:        odata = out;
        !           743:        ostart = p->ostart;
        !           744:        onext = p->onext;
        !           745:        istart = p->istart;
        !           746:        inext = p->inext;
        !           747:        nch = p->nch;
        !           748:        v = vol;
        !           749:
        !           750:        /*
        !           751:         * map/mix input on the output
        !           752:         */
        !           753:        for (i = todo; i > 0; i--) {
        !           754:                odata += ostart;
        !           755:                idata += istart;
        !           756:                for (j = nch; j > 0; j--) {
        !           757:                        y = *odata + ADATA_MUL(*idata, v);
        !           758:                        if (y >= ADATA_UNIT)
        !           759:                                y = ADATA_UNIT - 1;
        !           760:                        else if (y < -ADATA_UNIT)
        !           761:                                y = -ADATA_UNIT;
        !           762:                        *odata = y;
        !           763:                        idata++;
        !           764:                        odata++;
        !           765:                }
        !           766:                odata += onext;
        !           767:                idata += inext;
        !           768:        }
        !           769: }
        !           770:
        !           771: /*
        !           772:  * overwrite output with "todo" input frames with with the given volume
        !           773:  */
        !           774: void
        !           775: cmap_copy(struct cmap *p, void *in, void *out, int vol, int todo)
        !           776: {
        !           777:        adata_t *idata, *odata;
        !           778:        int i, j, nch, istart, inext, onext, ostart, v;
        !           779:
        !           780: #ifdef DEBUG
        !           781:        if (log_level >= 4) {
        !           782:                log_puts("cmap: copying ");
        !           783:                log_puti(todo);
        !           784:                log_puts(" frames\n");
        !           785:        }
        !           786: #endif
        !           787:        idata = in;
        !           788:        odata = out;
        !           789:        ostart = p->ostart;
        !           790:        onext = p->onext;
        !           791:        istart = p->istart;
        !           792:        inext = p->inext;
        !           793:        nch = p->nch;
        !           794:        v = vol;
        !           795:
        !           796:        /*
        !           797:         * copy to the output buffer
        !           798:         */
        !           799:        for (i = todo; i > 0; i--) {
        !           800:                idata += istart;
        !           801:                odata += ostart;
        !           802:                for (j = nch; j > 0; j--) {
        !           803:                        *odata = ADATA_MUL(*idata, v);
        !           804:                        odata++;
        !           805:                        idata++;
        !           806:                }
        !           807:                odata += onext;
        !           808:                idata += inext;
        !           809:        }
        !           810: }
        !           811:
        !           812: /*
        !           813:  * initialize channel mapper, to map a subset of input channel range
        !           814:  * into a subset of the output channel range
        !           815:  */
        !           816: void
        !           817: cmap_init(struct cmap *p,
        !           818:     int imin, int imax, int isubmin, int isubmax,
        !           819:     int omin, int omax, int osubmin, int osubmax)
        !           820: {
        !           821:        int cmin, cmax;
        !           822:
        !           823:        cmin = -NCHAN_MAX;
        !           824:        if (osubmin > cmin)
        !           825:                cmin = osubmin;
        !           826:        if (omin > cmin)
        !           827:                cmin = omin;
        !           828:        if (isubmin > cmin)
        !           829:                cmin = isubmin;
        !           830:        if (imin > cmin)
        !           831:                cmin = imin;
        !           832:
        !           833:        cmax = NCHAN_MAX;
        !           834:        if (osubmax < cmax)
        !           835:                cmax = osubmax;
        !           836:        if (omax < cmax)
        !           837:                cmax = omax;
        !           838:        if (isubmax < cmax)
        !           839:                cmax = isubmax;
        !           840:        if (imax < cmax)
        !           841:                cmax = imax;
        !           842:
        !           843:        p->ostart = cmin - omin;
        !           844:        p->onext = omax - cmax;
        !           845:        p->istart = cmin - imin;
        !           846:        p->inext = imax - cmax;
        !           847:        p->nch = cmax - cmin + 1;
        !           848: #ifdef DEBUG
        !           849:        if (log_level >= 3) {
        !           850:                log_puts("cmap: nch = ");
        !           851:                log_puti(p->nch);
        !           852:                log_puts(", ostart = ");
        !           853:                log_puti(p->ostart);
        !           854:                log_puts(", onext = ");
        !           855:                log_puti(p->onext);
        !           856:                log_puts(", istart = ");
        !           857:                log_puti(p->istart);
        !           858:                log_puts(", inext = ");
        !           859:                log_puti(p->inext);
        !           860:                log_puts("\n");
        !           861:        }
        !           862: #endif
        !           863: }