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

Annotation of src/usr.bin/aucat/wav.c, Revision 1.11

1.7       ratchov     1: /*
                      2:  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
                      3:  *
                      4:  * Permission to use, copy, modify, and distribute this software for any
                      5:  * purpose with or without fee is hereby granted, provided that the above
                      6:  * copyright notice and this permission notice appear in all copies.
                      7:  *
                      8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                      9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     15:  */
                     16:
1.1       ratchov    17: #include <stdlib.h>
1.10      ratchov    18: #include <stdio.h>
                     19: #include <fcntl.h>
                     20: #include <unistd.h>
1.1       ratchov    21:
1.10      ratchov    22: #include "abuf.h"
                     23: #include "aproc.h"
1.1       ratchov    24: #include "conf.h"
1.10      ratchov    25: #include "dev.h"
1.1       ratchov    26: #include "wav.h"
1.11    ! ratchov    27: #ifdef DEBUG
        !            28: #include "dbg.h"
        !            29: #endif
1.1       ratchov    30:
1.6       ratchov    31: short wav_ulawmap[256] = {
                     32:        -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
                     33:        -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
                     34:        -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
                     35:        -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
                     36:         -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
                     37:         -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
                     38:         -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
                     39:         -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
                     40:         -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
                     41:         -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
                     42:          -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
                     43:          -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
                     44:          -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
                     45:          -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
                     46:          -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
                     47:           -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
                     48:         32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
                     49:         23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
                     50:         15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
                     51:         11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
                     52:          7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
                     53:          5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
                     54:          3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
                     55:          2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
                     56:          1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
                     57:          1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
                     58:           876,    844,    812,    780,    748,    716,    684,    652,
                     59:           620,    588,    556,    524,    492,    460,    428,    396,
                     60:           372,    356,    340,    324,    308,    292,    276,    260,
                     61:           244,    228,    212,    196,    180,    164,    148,    132,
                     62:           120,    112,    104,     96,     88,     80,     72,     64,
                     63:            56,     48,     40,     32,     24,     16,      8,      0
                     64: };
                     65:
                     66: short wav_alawmap[256] = {
                     67:         -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
                     68:         -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
                     69:         -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
                     70:         -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
                     71:        -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
                     72:        -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
                     73:        -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
                     74:        -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
                     75:          -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
                     76:          -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
                     77:           -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
                     78:          -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
                     79:         -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
                     80:         -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
                     81:          -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
                     82:          -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
                     83:          5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
                     84:          7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
                     85:          2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
                     86:          3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
                     87:         22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
                     88:         30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
                     89:         11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
                     90:         15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
                     91:           344,    328,    376,    360,    280,    264,    312,    296,
                     92:           472,    456,    504,    488,    408,    392,    440,    424,
                     93:            88,     72,    120,    104,     24,      8,     56,     40,
                     94:           216,    200,    248,    232,    152,    136,    184,    168,
                     95:          1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
                     96:          1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
                     97:           688,    656,    752,    720,    560,    528,    624,    592,
                     98:           944,    912,   1008,    976,    816,    784,    880,    848
                     99: };
                    100:
1.1       ratchov   101: /*
1.7       ratchov   102:  * Max data of a .wav file. The total file size must be smaller than
1.1       ratchov   103:  * 2^31, and we also have to leave some space for the headers (around 40
1.7       ratchov   104:  * bytes).
1.3       ratchov   105:  */
1.1       ratchov   106: #define WAV_DATAMAX    (0x7fff0000)
                    107:
                    108: struct fileops wav_ops = {
                    109:        "wav",
                    110:        sizeof(struct wav),
                    111:        wav_close,
                    112:        wav_read,
                    113:        wav_write,
                    114:        NULL, /* start */
                    115:        NULL, /* stop */
                    116:        pipe_nfds,
                    117:        pipe_pollfd,
                    118:        pipe_revents
                    119: };
                    120:
1.10      ratchov   121: int rwav_in(struct aproc *, struct abuf *);
                    122: int rwav_out(struct aproc *, struct abuf *);
                    123: void rwav_eof(struct aproc *, struct abuf *);
                    124: void rwav_hup(struct aproc *, struct abuf *);
                    125: void rwav_done(struct aproc *);
                    126:
                    127: int wwav_in(struct aproc *, struct abuf *);
                    128: int wwav_out(struct aproc *, struct abuf *);
                    129: void wwav_eof(struct aproc *, struct abuf *);
                    130: void wwav_hup(struct aproc *, struct abuf *);
                    131: void wwav_done(struct aproc *);
                    132:
                    133: struct aproc_ops rwav_ops = {
                    134:        "rwav",
                    135:        rwav_in,
                    136:        rwav_out,
                    137:        rwav_eof,
                    138:        rwav_hup,
                    139:        NULL, /* newin */
                    140:        NULL, /* newout */
                    141:        NULL, /* ipos */
                    142:        NULL, /* opos */
                    143:        rwav_done
                    144: };
                    145:
                    146: struct aproc_ops wwav_ops = {
                    147:        "wwav",
                    148:        wwav_in,
                    149:        wwav_out,
                    150:        wwav_eof,
                    151:        wwav_hup,
                    152:        NULL, /* newin */
                    153:        NULL, /* newout */
                    154:        NULL, /* ipos */
                    155:        NULL, /* opos */
                    156:        wwav_done
                    157: };
                    158:
                    159: struct aproc *
                    160: rwav_new(struct file *f)
                    161: {
                    162:        struct aproc *p;
                    163:
                    164:        p = aproc_new(&rwav_ops, f->name);
                    165:        p->u.io.file = f;
                    166:        f->rproc = p;
                    167:        return p;
                    168: }
                    169:
                    170: int
                    171: rwav_in(struct aproc *p, struct abuf *ibuf_dummy)
                    172: {
                    173:        struct abuf *obuf = LIST_FIRST(&p->obuflist);
                    174:        struct file *f = p->u.io.file;
                    175:        unsigned char *data;
                    176:        unsigned count;
                    177:
                    178:        if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
                    179:                return 0;
                    180:        data = abuf_wgetblk(obuf, &count, 0);
                    181:        count = file_read(f, data, count);
                    182:        if (count == 0)
                    183:                return 0;
                    184:        abuf_wcommit(obuf, count);
                    185:        if (!abuf_flush(obuf))
                    186:                return 0;
                    187:        return 1;
                    188: }
                    189:
                    190: int
                    191: rwav_out(struct aproc *p, struct abuf *obuf)
                    192: {
                    193:        struct file *f = p->u.io.file;
                    194:        unsigned char *data;
                    195:        unsigned count;
                    196:
                    197:        if (f->state & FILE_RINUSE)
                    198:                return 0;
                    199:        if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
                    200:                return 0;
                    201:        data = abuf_wgetblk(obuf, &count, 0);
                    202:        count = file_read(f, data, count);
                    203:        if (count == 0)
                    204:                return 0;
                    205:        abuf_wcommit(obuf, count);
                    206:        return 1;
                    207: }
                    208:
                    209: void
                    210: rwav_done(struct aproc *p)
                    211: {
                    212:        struct file *f = p->u.io.file;
                    213:        struct abuf *obuf;
                    214:
                    215:        if (f == NULL)
                    216:                return;
                    217:        /*
                    218:         * all buffers must be detached before deleting f->wproc,
                    219:         * because otherwise it could trigger this code again
                    220:         */
                    221:        obuf = LIST_FIRST(&p->obuflist);
                    222:        if (obuf)
                    223:                abuf_eof(obuf);
                    224:        if (f->wproc) {
                    225:                f->rproc = NULL;
                    226:                aproc_del(f->wproc);
                    227:        } else
                    228:                file_del(f);
                    229:        p->u.io.file = NULL;
                    230: }
                    231:
                    232: void
                    233: rwav_eof(struct aproc *p, struct abuf *ibuf_dummy)
                    234: {
                    235:        aproc_del(p);
                    236: }
                    237:
                    238: void
                    239: rwav_hup(struct aproc *p, struct abuf *obuf)
                    240: {
                    241:        aproc_del(p);
                    242: }
                    243:
                    244: struct aproc *
                    245: wwav_new(struct file *f)
                    246: {
                    247:        struct aproc *p;
                    248:
                    249:        p = aproc_new(&wwav_ops, f->name);
                    250:        p->u.io.file = f;
                    251:        f->wproc = p;
                    252:        return p;
                    253: }
                    254:
                    255: void
                    256: wwav_done(struct aproc *p)
                    257: {
                    258:        struct file *f = p->u.io.file;
                    259:        struct abuf *ibuf;
                    260:
                    261:        if (f == NULL)
                    262:                return;
                    263:        /*
                    264:         * all buffers must be detached before deleting f->rproc,
                    265:         * because otherwise it could trigger this code again
                    266:         */
                    267:        ibuf = LIST_FIRST(&p->ibuflist);
                    268:        if (ibuf)
                    269:                abuf_hup(ibuf);
                    270:        if (f->rproc) {
                    271:                f->wproc = NULL;
                    272:                aproc_del(f->rproc);
                    273:        } else
                    274:                file_del(f);
                    275:        p->u.io.file = NULL;
                    276: }
                    277:
                    278: int
                    279: wwav_in(struct aproc *p, struct abuf *ibuf)
                    280: {
                    281:        struct file *f = p->u.io.file;
                    282:        unsigned char *data;
                    283:        unsigned count;
                    284:
                    285:        if (f->state & FILE_WINUSE)
                    286:                return 0;
                    287:        if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
                    288:                return 0;
                    289:        data = abuf_rgetblk(ibuf, &count, 0);
                    290:        count = file_write(f, data, count);
                    291:        if (count == 0)
                    292:                return 0;
                    293:        abuf_rdiscard(ibuf, count);
                    294:        return 1;
                    295: }
                    296:
                    297: int
                    298: wwav_out(struct aproc *p, struct abuf *obuf_dummy)
                    299: {
                    300:        struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
                    301:        struct file *f = p->u.io.file;
                    302:        unsigned char *data;
                    303:        unsigned count;
                    304:
                    305:        if (!abuf_fill(ibuf))
                    306:                return 0;
                    307:        if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
                    308:                return 0;
                    309:        data = abuf_rgetblk(ibuf, &count, 0);
                    310:        if (count == 0) {
                    311:                /* XXX: this can't happen, right ? */
                    312:                return 0;
                    313:        }
                    314:        count = file_write(f, data, count);
                    315:        if (count == 0)
                    316:                return 0;
                    317:        abuf_rdiscard(ibuf, count);
                    318:        return 1;
                    319: }
                    320:
                    321: void
                    322: wwav_eof(struct aproc *p, struct abuf *ibuf)
                    323: {
                    324:        aproc_del(p);
                    325: }
                    326:
                    327: void
                    328: wwav_hup(struct aproc *p, struct abuf *obuf_dummy)
                    329: {
                    330:        aproc_del(p);
                    331: }
                    332:
1.1       ratchov   333: struct wav *
1.10      ratchov   334: wav_new_in(struct fileops *ops, char *name, unsigned hdr,
                    335:     struct aparams *par, unsigned xrun, unsigned volctl)
1.1       ratchov   336: {
1.10      ratchov   337:        int fd;
1.1       ratchov   338:        struct wav *f;
1.10      ratchov   339:        struct aproc *p;
                    340:        struct abuf *buf;
                    341:        unsigned nfr;
                    342:
                    343:        if (name != NULL) {
                    344:                fd = open(name, O_RDONLY | O_NONBLOCK, 0666);
                    345:                if (fd < 0) {
                    346:                        perror(name);
                    347:                        return NULL;
                    348:                }
                    349:        } else {
                    350:                name = "stdin";
                    351:                fd = STDIN_FILENO;
                    352:                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                    353:                        perror(name);
                    354:        }
1.1       ratchov   355:        f = (struct wav *)pipe_new(ops, fd, name);
1.4       ratchov   356:        if (f == NULL)
                    357:                return NULL;
1.1       ratchov   358:        if (hdr == HDR_WAV) {
1.10      ratchov   359:                if (!wav_readhdr(f->pipe.fd, par, &f->rbytes, &f->map)) {
                    360:                        file_del((struct file *)f);
                    361:                        return NULL;
                    362:                }
1.1       ratchov   363:                f->hpar = *par;
1.6       ratchov   364:        } else {
1.1       ratchov   365:                f->rbytes = -1;
1.6       ratchov   366:                f->map = NULL;
                    367:        }
1.1       ratchov   368:        f->hdr = 0;
1.10      ratchov   369:        nfr = dev_bufsz * par->rate / dev_rate;
                    370:        buf = abuf_new(nfr, par);
                    371:        p = rwav_new((struct file *)f);
                    372:        aproc_setout(p, buf);
                    373:        abuf_fill(buf); /* XXX: move this in dev_attach() ? */
                    374:        dev_attach(name, buf, par, xrun, NULL, NULL, 0, ADATA_UNIT);
                    375:        dev_setvol(buf, MIDI_TO_ADATA(volctl));
1.1       ratchov   376:        return f;
                    377: }
                    378:
                    379: struct wav *
1.10      ratchov   380: wav_new_out(struct fileops *ops, char *name, unsigned hdr,
                    381:     struct aparams *par, unsigned xrun)
1.1       ratchov   382: {
1.10      ratchov   383:        int fd;
1.1       ratchov   384:        struct wav *f;
1.10      ratchov   385:        struct aproc *p;
                    386:        struct abuf *buf;
                    387:        unsigned nfr;
                    388:
                    389:        if (name == NULL) {
                    390:                name = "stdout";
                    391:                fd = STDOUT_FILENO;
                    392:                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                    393:                        perror(name);
                    394:        } else {
                    395:                fd = open(name,
                    396:                    O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
                    397:                if (fd < 0) {
                    398:                        perror(name);
                    399:                        return NULL;
                    400:                }
                    401:        }
1.1       ratchov   402:        f = (struct wav *)pipe_new(ops, fd, name);
1.4       ratchov   403:        if (f == NULL)
                    404:                return NULL;
1.1       ratchov   405:        if (hdr == HDR_WAV) {
1.2       ratchov   406:                par->le = 1;
1.3       ratchov   407:                par->sig = (par->bits <= 8) ? 0 : 1;
1.2       ratchov   408:                par->bps = (par->bits + 7) / 8;
1.10      ratchov   409:                if (!wav_writehdr(f->pipe.fd, par)) {
                    410:                        file_del((struct file *)f);
                    411:                        return NULL;
                    412:                }
1.1       ratchov   413:                f->hpar = *par;
                    414:                f->wbytes = WAV_DATAMAX;
                    415:        } else
                    416:                f->wbytes = -1;
                    417:        f->hdr = hdr;
1.10      ratchov   418:        nfr = dev_bufsz * par->rate / dev_rate;
                    419:        p = wwav_new((struct file *)f);
                    420:        buf = abuf_new(nfr, par);
                    421:        aproc_setin(p, buf);
                    422:        dev_attach(name, NULL, NULL, 0, buf, par, xrun, 0);
1.1       ratchov   423:        return f;
                    424: }
                    425:
1.6       ratchov   426: void
                    427: wav_conv(unsigned char *data, unsigned count, short *map)
                    428: {
                    429:        unsigned i;
                    430:        unsigned char *iptr;
                    431:        short *optr;
                    432:
                    433:        iptr = data + count;
                    434:        optr = (short *)data + count;
                    435:        for (i = count; i > 0; i--) {
                    436:                --optr;
                    437:                --iptr;
                    438:                *optr = map[*iptr];
                    439:        }
                    440: }
                    441:
1.1       ratchov   442: unsigned
                    443: wav_read(struct file *file, unsigned char *data, unsigned count)
                    444: {
                    445:        struct wav *f = (struct wav *)file;
                    446:        unsigned n;
                    447:
1.6       ratchov   448:        if (f->map)
                    449:                count /= sizeof(short);
1.1       ratchov   450:        if (f->rbytes >= 0 && count > f->rbytes) {
                    451:                count = f->rbytes; /* file->rbytes fits in count */
                    452:                if (count == 0) {
1.11    ! ratchov   453: #ifdef DEBUG
        !           454:                        if (debug_level >= 3) {
        !           455:                                file_dbg(&f->pipe.file);
        !           456:                                dbg_puts(": read complete\n");
        !           457:                        }
        !           458: #endif
1.1       ratchov   459:                        file_eof(&f->pipe.file);
                    460:                        return 0;
                    461:                }
                    462:        }
                    463:        n = pipe_read(file, data, count);
1.8       jakemsr   464:        if (n == 0)
                    465:                return 0;
1.1       ratchov   466:        if (f->rbytes >= 0)
                    467:                f->rbytes -= n;
1.6       ratchov   468:        if (f->map) {
                    469:                wav_conv(data, n, f->map);
                    470:                n *= sizeof(short);
                    471:        }
1.1       ratchov   472:        return n;
                    473: }
                    474:
                    475: unsigned
                    476: wav_write(struct file *file, unsigned char *data, unsigned count)
                    477: {
                    478:        struct wav *f = (struct wav *)file;
                    479:        unsigned n;
1.3       ratchov   480:
1.1       ratchov   481:        if (f->wbytes >= 0 && count > f->wbytes) {
                    482:                count = f->wbytes; /* wbytes fits in count */
                    483:                if (count == 0) {
1.11    ! ratchov   484: #ifdef DEBUG
        !           485:                        if (debug_level >= 3) {
        !           486:                                file_dbg(&f->pipe.file);
        !           487:                                dbg_puts(": write complete\n");
        !           488:                        }
        !           489: #endif
1.1       ratchov   490:                        file_hup(&f->pipe.file);
                    491:                        return 0;
                    492:                }
                    493:        }
                    494:        n = pipe_write(file, data, count);
                    495:        if (f->wbytes >= 0)
                    496:                f->wbytes -= n;
                    497:        return n;
                    498: }
                    499:
                    500: void
                    501: wav_close(struct file *file)
                    502: {
                    503:        struct wav *f = (struct wav *)file;
                    504:
                    505:        if (f->hdr == HDR_WAV)
                    506:                wav_writehdr(f->pipe.fd, &f->hpar);
                    507:        pipe_close(file);
                    508: }
1.10      ratchov   509: