Annotation of src/usr.bin/aucat/legacy.c, Revision 1.6
1.6 ! ratchov 1: /* $OpenBSD: legacy.c,v 1.5 2009/04/11 10:24:21 jakemsr 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.4 ratchov 33: #include <stdlib.h>
1.1 ratchov 34: #include <fcntl.h>
1.2 ratchov 35: #include <string.h>
1.1 ratchov 36: #include <unistd.h>
37: #include <err.h>
38:
1.3 ratchov 39: #include "wav.h"
1.1 ratchov 40:
41: /* headerless data files. played at /dev/audio's defaults.
42: */
43: #define FMT_RAW 0
44:
45: /* Sun/NeXT .au files. header is skipped and /dev/audio is configured
46: * for monaural 8-bit ulaw @ 8kHz, the de facto format for .au files,
47: * as well as the historical default configuration for /dev/audio.
48: */
49: #define FMT_AU 1
50:
51: /* RIFF WAV files. header is parsed for format details which are
52: * applied to /dev/audio.
53: */
54: #define FMT_WAV 2
55:
1.3 ratchov 56:
1.1 ratchov 57: int
58: legacy_play(char *dev, char *aufile)
59: {
1.5 jakemsr 60: struct sio_hdl *hdl;
61: struct sio_par spar, par;
62: struct aparams apar;
1.1 ratchov 63: ssize_t rd;
64: off_t datasz;
65: char buf[5120];
1.5 jakemsr 66: size_t readsz;
67: int fd, fmt = FMT_RAW;
68: u_int32_t pos = 0, snd_fmt = 1, rate = 8000, chan = 1;
1.1 ratchov 69: char magic[4];
1.6 ! ratchov 70: short *map;
1.1 ratchov 71:
72: if ((fd = open(aufile, O_RDONLY)) < 0) {
73: warn("cannot open %s", aufile);
74: return(1);
75: }
76:
77: if (read(fd, magic, sizeof(magic)) != sizeof(magic)) {
78: /* read() error, or the file is smaller than sizeof(magic).
79: * treat as a raw file, like previous versions of aucat.
80: */
81: } else if (!strncmp(magic, ".snd", 4)) {
82: fmt = FMT_AU;
83: if (read(fd, &pos, sizeof(pos)) == sizeof(pos))
84: pos = ntohl(pos);
1.5 jakemsr 85: /* data size */
86: if (lseek(fd, 4, SEEK_CUR) == -1)
87: warn("lseek hdr");
88: if (read(fd, &snd_fmt, sizeof(snd_fmt)) == sizeof(snd_fmt))
89: snd_fmt = ntohl(snd_fmt);
90: if (read(fd, &rate, sizeof(rate)) == sizeof(rate))
91: rate = ntohl(rate);
92: if (read(fd, &chan, sizeof(chan)) == sizeof(chan))
93: chan = ntohl(chan);
1.1 ratchov 94: } else if (!strncmp(magic, "RIFF", 4) &&
1.6 ! ratchov 95: wav_readhdr(fd, &apar, &datasz, &map)) {
1.1 ratchov 96: fmt = FMT_WAV;
97: }
98:
99: /* seek to start of audio data. wav_readhdr already took care
100: * of this for FMT_WAV.
101: */
102: if (fmt == FMT_RAW || fmt == FMT_AU)
103: if (lseek(fd, (off_t)pos, SEEK_SET) == -1)
104: warn("lseek");
1.5 jakemsr 105:
106: if ((hdl = sio_open(dev, SIO_PLAY, 0)) < 0) {
107: warnx("can't get sndio handle");
1.1 ratchov 108: return(1);
109: }
110:
1.5 jakemsr 111: sio_initpar(&par);
1.1 ratchov 112: switch(fmt) {
113: case FMT_WAV:
1.5 jakemsr 114: par.rate = apar.rate;
115: par.pchan = apar.cmax - apar.cmin + 1;
116: par.sig = apar.sig;
117: par.bits = apar.bits;
118: par.le = apar.le;
1.1 ratchov 119: break;
120: case FMT_AU:
1.5 jakemsr 121: par.rate = rate;
122: par.pchan = chan;
123: par.sig = 1;
124: par.bits = 16;
125: par.le = 1;
1.6 ! ratchov 126: map = wav_ulawmap;
1.5 jakemsr 127: if (snd_fmt == 27)
1.6 ! ratchov 128: map = wav_alawmap;
1.1 ratchov 129: break;
130: case FMT_RAW:
131: default:
132: break;
133: }
1.5 jakemsr 134: spar = par;
1.1 ratchov 135:
1.5 jakemsr 136: if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
137: warnx("can't set audio parameters");
1.1 ratchov 138: /* only WAV could fail in previous aucat versions (unless
139: * the parameters returned by AUDIO_GETINFO would fail,
140: * which is unlikely)
141: */
142: if (fmt == FMT_WAV)
143: return(1);
144: }
145:
146: /* parameters may be silently modified. see audio(9)'s
147: * description of set_params. for compatability with previous
148: * aucat versions, continue running if something doesn't match.
149: */
1.5 jakemsr 150: if (par.bits != spar.bits ||
151: par.sig != par.sig ||
152: par.le != spar.le ||
153: par.pchan != spar.pchan ||
1.1 ratchov 154: /* devices may return a very close rate, such as 44099 when
155: * 44100 was requested. the difference is inaudible. allow
156: * 2% deviation as an example of how to cope.
157: */
1.5 jakemsr 158: (par.rate > spar.rate * 1.02 || par.rate < spar.rate * 0.98)) {
159: warnx("format not supported");
160: }
161: if (!sio_start(hdl)) {
162: warnx("could not start sndio");
163: exit(1);
1.1 ratchov 164: }
165:
1.5 jakemsr 166: readsz = sizeof(buf);
1.6 ! ratchov 167: if (map)
1.5 jakemsr 168: readsz /= 2;
169: while ((rd = read(fd, buf, readsz)) > 0) {
1.6 ! ratchov 170: if (map) {
! 171: wav_conv(buf, rd, map);
1.5 jakemsr 172: rd *= 2;
173: }
174: if (sio_write(hdl, buf, rd) != rd)
175: warnx("sio_write: short write");
176: }
1.1 ratchov 177: if (rd == -1)
178: warn("read");
179:
1.5 jakemsr 180: sio_close(hdl);
1.1 ratchov 181: (void) close(fd);
182:
183: return(0);
184: }