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

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

1.11    ! jakemsr     1: /*     $OpenBSD: legacy.c,v 1.10 2010/04/03 17:59:17 ratchov Exp $     */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 1997 Kenneth Stailey.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by Kenneth Stailey.
                     16:  * 4. The name of the author may not be used to endorse or promote products
                     17:  *    derived from this software without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     22:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     24:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     28:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30:
1.5       jakemsr    31: #include <sndio.h>
1.2       ratchov    32:
1.7       ratchov    33: #include <err.h>
                     34: #include <fcntl.h>
1.4       ratchov    35: #include <stdlib.h>
1.2       ratchov    36: #include <string.h>
1.1       ratchov    37: #include <unistd.h>
                     38:
1.3       ratchov    39: #include "wav.h"
1.1       ratchov    40:
1.7       ratchov    41: /*
                     42:  * Headerless data files.  Played at /dev/audio's defaults.
1.1       ratchov    43:  */
                     44: #define FMT_RAW        0
                     45:
1.7       ratchov    46: /*
                     47:  * Sun/NeXT .au files.  Header is skipped and /dev/audio is configured
1.1       ratchov    48:  * for monaural 8-bit ulaw @ 8kHz, the de facto format for .au files,
                     49:  * as well as the historical default configuration for /dev/audio.
                     50:  */
                     51: #define FMT_AU 1
                     52:
1.7       ratchov    53: /*
                     54:  * RIFF WAV files.  Header is parsed for format details which are
1.1       ratchov    55:  * applied to /dev/audio.
                     56:  */
                     57: #define FMT_WAV        2
                     58:
1.3       ratchov    59:
1.1       ratchov    60: int
                     61: legacy_play(char *dev, char *aufile)
                     62: {
1.5       jakemsr    63:        struct sio_hdl *hdl;
                     64:        struct sio_par spar, par;
                     65:        struct aparams apar;
1.1       ratchov    66:        ssize_t rd;
1.10      ratchov    67:        off_t datasz;
1.1       ratchov    68:        char buf[5120];
1.5       jakemsr    69:        size_t readsz;
                     70:        int fd, fmt = FMT_RAW;
                     71:        u_int32_t pos = 0, snd_fmt = 1, rate = 8000, chan = 1;
1.1       ratchov    72:        char magic[4];
1.6       ratchov    73:        short *map;
1.1       ratchov    74:
                     75:        if ((fd = open(aufile, O_RDONLY)) < 0) {
                     76:                warn("cannot open %s", aufile);
                     77:                return(1);
                     78:        }
                     79:
                     80:        if (read(fd, magic, sizeof(magic)) != sizeof(magic)) {
1.7       ratchov    81:                /*
                     82:                 * read() error, or the file is smaller than sizeof(magic).
1.1       ratchov    83:                 * treat as a raw file, like previous versions of aucat.
                     84:                 */
                     85:        } else if (!strncmp(magic, ".snd", 4)) {
                     86:                fmt = FMT_AU;
                     87:                if (read(fd, &pos, sizeof(pos)) == sizeof(pos))
                     88:                        pos = ntohl(pos);
1.5       jakemsr    89:                /* data size */
                     90:                if (lseek(fd, 4, SEEK_CUR) == -1)
                     91:                        warn("lseek hdr");
                     92:                if (read(fd, &snd_fmt, sizeof(snd_fmt)) == sizeof(snd_fmt))
                     93:                        snd_fmt = ntohl(snd_fmt);
                     94:                if (read(fd, &rate, sizeof(rate)) == sizeof(rate))
                     95:                        rate = ntohl(rate);
                     96:                if (read(fd, &chan, sizeof(chan)) == sizeof(chan))
                     97:                        chan = ntohl(chan);
1.1       ratchov    98:        } else if (!strncmp(magic, "RIFF", 4) &&
1.10      ratchov    99:                    wav_readhdr(fd, &apar, &datasz, &map)) {
1.1       ratchov   100:                        fmt = FMT_WAV;
                    101:        }
                    102:
1.7       ratchov   103:        /*
                    104:         * Seek to start of audio data.  wav_readhdr already took care
1.1       ratchov   105:         * of this for FMT_WAV.
                    106:         */
                    107:        if (fmt == FMT_RAW || fmt == FMT_AU)
                    108:                if (lseek(fd, (off_t)pos, SEEK_SET) == -1)
                    109:                        warn("lseek");
1.5       jakemsr   110:
1.8       ratchov   111:        if ((hdl = sio_open(dev, SIO_PLAY, 0)) == NULL) {
1.5       jakemsr   112:                warnx("can't get sndio handle");
1.1       ratchov   113:                return(1);
                    114:        }
                    115:
1.5       jakemsr   116:        sio_initpar(&par);
1.1       ratchov   117:        switch(fmt) {
                    118:        case FMT_WAV:
1.5       jakemsr   119:                par.rate = apar.rate;
                    120:                par.pchan = apar.cmax - apar.cmin + 1;
                    121:                par.sig = apar.sig;
                    122:                par.bits = apar.bits;
                    123:                par.le = apar.le;
1.1       ratchov   124:                break;
                    125:        case FMT_AU:
1.5       jakemsr   126:                par.rate = rate;
                    127:                par.pchan = chan;
                    128:                par.sig = 1;
                    129:                par.bits = 16;
1.11    ! jakemsr   130:                par.le = SIO_LE_NATIVE;
1.6       ratchov   131:                map = wav_ulawmap;
1.5       jakemsr   132:                if (snd_fmt == 27)
1.6       ratchov   133:                        map = wav_alawmap;
1.1       ratchov   134:                break;
                    135:        case FMT_RAW:
                    136:        default:
                    137:                break;
                    138:        }
1.5       jakemsr   139:        spar = par;
1.1       ratchov   140:
1.5       jakemsr   141:        if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
                    142:                warnx("can't set audio parameters");
1.7       ratchov   143:                /*
                    144:                 * Only WAV could fail in previous aucat versions (unless
1.1       ratchov   145:                 * the parameters returned by AUDIO_GETINFO would fail,
1.7       ratchov   146:                 * which is unlikely).
1.1       ratchov   147:                 */
                    148:                if (fmt == FMT_WAV)
                    149:                        return(1);
                    150:        }
                    151:
1.7       ratchov   152:         /*
                    153:         * Parameters may be silently modified.  See audio(9)'s
                    154:         * description of set_params.  For compatability with previous
1.1       ratchov   155:         * aucat versions, continue running if something doesn't match.
                    156:         */
1.5       jakemsr   157:        if (par.bits != spar.bits ||
                    158:            par.sig != par.sig ||
                    159:            par.le != spar.le ||
                    160:            par.pchan != spar.pchan ||
1.7       ratchov   161:            /*
                    162:             * Devices may return a very close rate, such as 44099 when
                    163:             * 44100 was requested.  The difference is inaudible.  Allow
1.1       ratchov   164:             * 2% deviation as an example of how to cope.
                    165:             */
1.5       jakemsr   166:            (par.rate > spar.rate * 1.02 || par.rate < spar.rate * 0.98)) {
                    167:                warnx("format not supported");
                    168:        }
                    169:        if (!sio_start(hdl)) {
                    170:                warnx("could not start sndio");
                    171:                exit(1);
1.1       ratchov   172:        }
                    173:
1.5       jakemsr   174:        readsz = sizeof(buf);
1.6       ratchov   175:        if (map)
1.5       jakemsr   176:                readsz /= 2;
                    177:        while ((rd = read(fd, buf, readsz)) > 0) {
1.6       ratchov   178:                if (map) {
                    179:                        wav_conv(buf, rd, map);
1.5       jakemsr   180:                        rd *= 2;
                    181:                }
                    182:                if (sio_write(hdl, buf, rd) != rd)
                    183:                        warnx("sio_write: short write");
                    184:        }
1.1       ratchov   185:        if (rd == -1)
                    186:                warn("read");
                    187:
1.5       jakemsr   188:        sio_close(hdl);
1.7       ratchov   189:        close(fd);
1.1       ratchov   190:
                    191:        return(0);
                    192: }