1 /*
2 * XBoing - An X11 blockout style computer game
3 *
4 * (c) Copyright 1993, 1994, 1995, Justin C. Kibell, All Rights Reserved
5 *
6 * The X Consortium, and any party obtaining a copy of these files from
7 * the X Consortium, directly or indirectly, is granted, free of charge, a
8 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9 * nonexclusive right and license to deal in this software and
10 * documentation files (the "Software"), including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons who receive
13 * copies from any such party to do so. This license includes without
14 * limitation a license to do the foregoing actions under any patents of
15 * the party supplying this software to the X Consortium.
16 *
17 * In no event shall the author be liable to any party for direct, indirect,
18 * special, incidental, or consequential damages arising out of the use of
19 * this software and its documentation, even if the author has been advised
20 * of the possibility of such damage.
21 *
22 * The author specifically disclaims any warranties, including, but not limited
23 * to, the implied warranties of merchantability and fitness for a particular
24 * purpose. The software provided hereunder is on an "AS IS" basis, and the
25 * author has no obligation to provide maintenance, support, updates,
26 * enhancements, or modifications.
27 */
28
29 /*
30 * =========================================================================
31 *
32 * $Id: BSDaudio.c,v 1.1.1.1 1994/12/16 01:36:57 jck Exp $
33 * $Source: /usr5/legends/jck/xb/master/xboing/audio/BSDaudio.c,v $
34 * $Revision: 1.1.1.1 $
35 * $Date: 1994/12/16 01:36:57 $
36 *
37 * $Log: BSDaudio.c,v $
38 * Revision 1.1.1.1 1994/12/16 01:36:57 jck
39 * The XBoing distribution requires configuration management. This is why the
40 * cvs utility is being used. This is the initial import of all source etc..
41 *
42 *
43 * =========================================================================
44 */
45
46 /* SoundBlaster support for NetBSD */
47
48 /*
49 ** Modified by Justin Kibell to suit xboing 30/09/93.
50 **
51 ** Copyright (C) 1993 by Jordan Hubbard
52 **
53 ** Ulaw code Copyright (C) 1989 by Jef Poskanzer.
54 **
55 ** Permission to use, copy, modify, and distribute this software and its
56 ** documentation for any purpose and without fee is hereby granted, provided
57 ** that the above copyright notice appear in all copies and that both that
58 ** copyright notice and this permission notice appear in supporting
59 ** documentation. This software is provided "as is" without express or
60 ** implied warranty.
61 **
62 *
63 */
64
65 /*
66 * Include file dependencies:
67 */
68
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <fcntl.h>
72 #include <sys/sblast.h>
73
74 /*
75 * Internal macro definitions:
76 */
77
78 #define BSIZE 4096
79
80 /*
81 ** This macro converts from ulaw to 16 bit linear, faster.
82 **
83 ** Jef Poskanzer
84 ** 23 October 1989
85 **
86 ** Input: 8 bit ulaw sample
87 ** Output: signed 16 bit linear sample
88 */
89
90 #define ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
91
92 /* Define the magic number for audio files - just to check */
93 #define SUN_AUDIO_MAGIC ((u_long)0x2e736e64)
94
95 /*
96 * Internal type declarations:
97 */
98
99 /* What sun's .au format looks like */
100 struct _sun_audio
101 {
102 u_long magic;
103 u_long hdr_size;
104 u_long data_size;
105 u_long data_encoding;
106 u_long sample_rate;
107 u_long nchannels;
108 };
109 typedef struct _sun_audio Sun_audio_hdr;
110
111 /*
112 * Internal variable declarations:
113 */
114
115 static int ulaw_table[256] =
116 {
117 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
118 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
119 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
120 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
121 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
122 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
123 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
124 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
125 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
126 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
127 -876, -844, -812, -780, -748, -716, -684, -652,
128 -620, -588, -556, -524, -492, -460, -428, -396,
129 -372, -356, -340, -324, -308, -292, -276, -260,
130 -244, -228, -212, -196, -180, -164, -148, -132,
131 -120, -112, -104, -96, -88, -80, -72, -64,
132 -56, -48, -40, -32, -24, -16, -8, 0,
133 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
134 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
135 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
136 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
137 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
138 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
139 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
140 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
141 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
142 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
143 876, 844, 812, 780, 748, 716, 684, 652,
144 620, 588, 556, 524, 492, 460, 428, 396,
145 372, 356, 340, 324, 308, 292, 276, 260,
146 244, 228, 212, 196, 180, 164, 148, 132,
147 120, 112, 104, 96, 88, 80, 72, 64,
148 56, 48, 40, 32, 24, 16, 8, 0
149 };
150
151
152 /* The audio device */
153 int Audio_fd;
154 char errorString[255];
155
156
157 /* Slurp in a .au file */
158 #if NeedFunctionPrototypes
read_audio_header(int fd,Sun_audio_hdr * buf)159 static int read_audio_header(int fd, Sun_audio_hdr *buf)
160 #else
161 static int read_audio_header(fd, buf)
162 int fd;
163 Sun_audio_hdr *buf;
164 #endif
165 {
166 read(fd, buf, sizeof(Sun_audio_hdr));
167
168 buf->magic = ntohl(buf->magic);
169 buf->hdr_size = ntohl(buf->hdr_size);
170 buf->data_size = ntohl(buf->data_size);
171 buf->data_encoding = ntohl(buf->data_encoding);
172 buf->sample_rate = ntohl(buf->sample_rate);
173 buf->nchannels = ntohl(buf->nchannels);
174
175 lseek(fd, buf->hdr_size, SEEK_SET);
176
177 return buf->magic == SUN_AUDIO_MAGIC;
178 }
179
180 #if NeedFunctionPrototypes
set_volume(int volume)181 static int set_volume(int volume)
182 #else
183 static int set_volume(volume)
184 int volume;
185 #endif
186 {
187 static struct sb_mixer_levels save; /* Saved mixer level settings */
188 struct sb_mixer_levels l; /* New mixer level settings */
189 static int mixer = 0;
190
191 if (!mixer)
192 {
193 mixer = open ("/dev/sb_mixer", O_RDWR, 0);
194
195 if (mixer < 0)
196 perror ("open mixer");
197 else if (ioctl (mixer, MIXER_IOCTL_READ_LEVELS, &save) < 0)
198 perror ("mixer ioctl");
199 }
200 else if (mixer > 0)
201 {
202 /* Just change master volume */
203 l.master.l = l.master.r = volume;
204
205 /* If bad volume, put it back */
206 if (ioctl (mixer, MIXER_IOCTL_SET_LEVELS, &l) == -1)
207 ioctl (mixer, MIXER_IOCTL_SET_LEVELS, &save);
208 }
209
210 return 0;
211 }
212
213 /* Send an ioctl to the DSP with error checking. */
214 #define IOCTL(cmd, arg) \
215 if (ioctl(Audio_fd, DSP_IOCTL_##cmd, arg) == -1) \
216 perror ("ioctl") \
217
218 #if NeedFunctionPrototypes
SetUpAudioSystem(Display * display)219 int SetUpAudioSystem(Display *display)
220 #else
221 int SetUpAudioSystem(display)
222 Display *display;
223 #endif
224 {
225 Audio_fd = open("/dev/sb_dsp", O_RDWR);
226 if (Audio_fd < 1)
227 {
228 /* Unable to open audio device so barf */
229 ErrorMessage("/dev/sb_dsp audio device is busy.");
230 return False;
231 }
232
233 /* Audio device is open */
234 return True;
235 }
236
237 #if NeedFunctionPrototypes
SetMaximumVolume(int Volume)238 void SetMaximumVolume(int Volume)
239 #else
240 void SetMaximumVolume(Volume)
241 int Volume;
242 #endif
243 {
244 /* Set the maximum volume for the audio system */
245 set_volume(volume);
246 }
247
248 #if NeedFunctionPrototypes
GetMaximumVolume(void)249 int GetMaximumVolume(void)
250 #else
251 int GetMaximumVolume()
252 #endif
253 {
254 /* Return the maximum volume as a % of 100 */
255 return 100;
256 }
257
258
259 #if NeedFunctionPrototypes
FreeAudioSystem(void)260 void FreeAudioSystem(void)
261 #else
262 void FreeAudioSystem()
263 #endif
264 {
265 /* Close the audio device thanks */
266 (void) close(Audio_fd);
267 }
268
269 #if NeedFunctionPrototypes
playSoundFile(char * filename,int volume)270 void playSoundFile(char *filename, int volume)
271 #else
272 void playSoundFile(filename, volume)
273 char *filename;
274 int volume;
275 #endif
276 {
277 Sun_audio_hdr ahdr;
278 int fd;
279 unsigned char buf[BSIZE];
280 int i, len;
281 int zero = 0;
282 int one = 1;
283 char soundfile[FILENAME_MAX];
284 char *str;
285
286 /* Set to the required volume */
287 set_volume(volume);
288
289 /* Construct the sounds file path and use env var if exists */
290 if ((str = getenv("XBOING_SOUND_DIR")) != NULL)
291 sprintf(soundfile, "%s/%s.au", str, filename);
292 else
293 sprintf(soundfile, "%s/%s.au", SOUNDS_DIR, filename);
294
295 /* Open the sound file for reading */
296 if ((fd = open(soundfile, O_RDONLY, 0)) < 0)
297 {
298 /* Issue an error about not opening sound file */
299 sprintf(errorString, "Unable to open sound file %s.", soundfile);
300 WarningMessage(errorString);
301 return;
302 }
303
304 if (read_audio_header(fd, &ahdr) == 0)
305 {
306 /* Cannot understand the sound file so close file and return */
307 sprintf(errorString, "Unable to play sound file %s.", soundfile);
308 WarningMessage(errorString);
309 (void) close(fd); /* Close the sound file */
310 return;
311 }
312
313 /* Set up the DSP, now that we know a little about sample */
314 if (ioctl(Audio_fd, DSP_IOCTL_STEREO,
315 (ahdr.nchannels == 1) ? &zero : &one) == -1)
316 {
317 /* Cannot set up the DSP */
318 WarningMessage("Unable to setup DSP stero setting.");
319 (void) close(fd); /* Close the sound file */
320 return;
321 }
322
323 if (ioctl (Audio_fd, DSP_IOCTL_SPEED, &ahdr.sample_rate) == -1)
324 {
325 /* Cannot set up the DSP */
326 WarningMessage("Unable to setup DSP speed setting.");
327 (void) close(fd); /* Close the sound file */
328 return;
329 }
330
331 while ((len = read(fd, buf, BSIZE)) > 0)
332 {
333 /* Is it mulaw? Else assume linear (usually mulaw so far) */
334 if (ahdr.data_encoding == 1)
335 {
336 /* Convert data to linear format - ie: uncompress */
337 for(i = 0; i < len; i++)
338 buf[i] = (char) 128 + (ulaw_to_linear(buf[i]) / 256);
339 }
340
341 /* Write the data to the DSP for the sound hopefully */
342 if (len != write(Audio_fd, buf, len))
343 {
344 WarningMessage("Unable to write to DSP.");
345 (void) close(fd); /* Close the sound file */
346 return;
347 }
348 }
349
350 /* Close the sound file */
351 (void) close(fd);
352 }
353
354 #if NeedFunctionPrototypes
audioDeviceEvents(void)355 void audioDeviceEvents(void)
356 #else
357 void audioDeviceEvents()
358 #endif
359 {
360 /* None to do */
361 }
362
363