1 /*
2 * pcmplay.c
3 *
4 * Oliver Fromme <olli@fromme.com>
5 *
6 * Copyright (C) 1997,1998,1999
7 * Oliver Fromme. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the author nor the names of any co-contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY OLIVER FROMME AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL OLIVER FROMME OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)$Id: pcmplay.c,v 1.4 1999/01/01 23:31:55 olli Exp $
34 */
35
36 static const char cvsid[]
37 = "@(#)$Id: pcmplay.c,v 1.4 1999/01/01 23:31:55 olli Exp $";
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <sys/ioctl.h>
44 #include <sys/types.h>
45 #include <sys/uio.h>
46 #include <unistd.h>
47 #include <sys/soundcard.h>
48
49 #include "utils.h"
50 #include "getlopt.h"
51
52 char *audevice = "/dev/dsp";
53 int buffersize = 32;
54 int dsp_samplesize = 16;
55 int dsp_channels = 2;
56 int dsp_speed = 44100;
57 int dsp_unsigned = FALSE;
58 int dsp_network = FALSE;
59 int mix_gain = -1;
60
61 int
usage(char * notused)62 usage (char *notused)
63 {
64 fprintf (stderr, "Usage: %s [options]\n", me);
65 fprintf (stderr, "Options [defaults] (remarks):\n");
66 fprintf (stderr, " -d audio_device [%s]\n", audevice);
67 fprintf (stderr, " -b buffer_size [%d] (in Kbytes)\n", buffersize);
68 fprintf (stderr, " -s bits_per_sample [%d] (must be 8 or 16)\n", dsp_samplesize);
69 fprintf (stderr, " -f frequency [%d]\n", dsp_speed);
70 fprintf (stderr, " -c channels [%d] (must be 1 or 2)\n", dsp_channels);
71 fprintf (stderr, " -g gain [don't change] (0 - 255)\n");
72 fprintf (stderr, " -u (data is unsigned; default is signed)\n");
73 fprintf (stderr, " -n (data in network byte order; default is intel b.o.)\n");
74 exit (1);
75 return 0; /* make compiler happy */
76 }
77
78 topt opts[] = {
79 {'d', "device", GLO_CHAR, 0, &audevice, 0},
80 {'b', "buffer", GLO_NUM, 0, &buffersize, 0},
81 {'s', "bits", GLO_NUM, 0, &dsp_samplesize, 0},
82 {'f', "frequency", GLO_NUM, 0, &dsp_speed, 0},
83 {'c', "channels", GLO_NUM, 0, &dsp_channels, 0},
84 {'g', "gain", GLO_NUM, 0, &mix_gain, 0},
85 {'u', "unsigned", 0, 0, &dsp_unsigned, TRUE},
86 {'n', "network", 0, 0, &dsp_network, TRUE},
87 {'h', "help", 0, usage, 0, 0},
88 {0, NULL, 0, 0, 0, 0}
89 };
90
audio_open()91 int audio_open ()
92 {
93 int fmts;
94 int stereo = (dsp_channels == 2 ? TRUE : FALSE);
95 int fd;
96
97 if (dsp_samplesize == 8)
98 if (dsp_unsigned)
99 fmts = AFMT_U8;
100 else
101 fmts = AFMT_S8;
102 else
103 if (dsp_network)
104 if (dsp_unsigned)
105 fmts = AFMT_U16_BE;
106 else
107 fmts = AFMT_S16_BE;
108 else
109 if (dsp_unsigned)
110 fmts = AFMT_U16_LE;
111 else
112 fmts = AFMT_S16_LE;
113 if ((fd = open(audevice, O_WRONLY)) < 0)
114 return (-1);
115 ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &dsp_samplesize);
116 ioctl (fd, SNDCTL_DSP_STEREO, &stereo);
117 ioctl (fd, SNDCTL_DSP_SPEED, &dsp_speed);
118 ioctl (fd, SNDCTL_DSP_SETFMT, &fmts);
119 if (mix_gain >= 0) {
120 int e, mask;
121 e = ioctl(fd, SOUND_MIXER_READ_DEVMASK, &mask);
122 if (e < 0)
123 fprintf (stderr, "audio/gain: Can't get audio device features list.\n");
124 else if (mask & SOUND_MASK_PCM) {
125 int gain = (mix_gain << 8) | (mix_gain);
126 e = ioctl(fd, SOUND_MIXER_WRITE_PCM, &gain);
127 }
128 else if (!(mask & SOUND_MASK_VOLUME))
129 fprintf (stderr, "audio/gain: setable Volume/PCM-Level not supported by your audio device: %#04x\n", mask);
130 else {
131 int gain = (mix_gain << 8) | (mix_gain);
132 e = ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &gain);
133 }
134 }
135 return (fd);
136 }
137
audio_play(int fd,char * buf,int len)138 int audio_play (int fd, char *buf, int len)
139 {
140 return (write(fd, buf, len));
141 }
142
audio_close(int fd)143 int audio_close (int fd)
144 {
145 return (close (fd));
146 }
147
main(int argc,char * argv[])148 int main (int argc, char *argv[])
149 {
150 int infd = 0;
151 int outfd;
152 int result, bufbytes, numbytes;
153 char *buf;
154
155 utils_init (argv[0]);
156 while ((result = getlopt(argc, argv, opts)))
157 switch (result) {
158 case GLO_UNKNOWN:
159 fprintf (stderr, "%s: Unknown option \"%s\".\n",
160 me, loptarg);
161 exit (1);
162 case GLO_NOARG:
163 fprintf (stderr, "%s: Missing argument for option \"%s\".\n",
164 me, loptarg);
165 exit (1);
166 }
167 if (loptind >= argc)
168 usage (NULL);
169
170 bufbytes = buffersize * 1024;
171 if (!(buf = malloc(bufbytes)))
172 die ("malloc()");
173 if ((outfd = audio_open()) < 0)
174 die (audevice);
175 do {
176 if (!strcmp(argv[loptind], "-"))
177 infd = 0;
178 else if ((infd = open(argv[loptind], O_RDONLY, 0)) < 0)
179 die (argv[loptind]);
180 do {
181 numbytes = read(infd, buf, bufbytes);
182 if (numbytes > 0)
183 audio_play (outfd, buf, numbytes);
184 } while (numbytes > 0);
185 if (infd)
186 close (infd);
187 } while (++loptind < argc);
188 audio_close (outfd);
189 exit (0);
190 }
191
192 /* EOF */
193