1 /* 2000-08-10T17:39:15Z
3 * handle sounds in emerald mine
6 #include "../libgame/platform.h"
9 #if defined(TARGET_X11)
11 #if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
14 #include <sys/soundcard.h>
18 #include <soundcard.h>
22 #include <sys/types.h>
24 #include <sys/ioctl.h>
35 static char audioname[] = "/dev/audio";
37 static const int sound_priority[SAMPLE_MAX] =
39 SAMPLE_exit, SAMPLE_die, SAMPLE_time, SAMPLE_boom, SAMPLE_tick,
40 SAMPLE_collect, SAMPLE_roll, SAMPLE_push, SAMPLE_dynamite, SAMPLE_press,
41 SAMPLE_door, SAMPLE_dirt, SAMPLE_blank, SAMPLE_android, SAMPLE_ball,
42 SAMPLE_grow, SAMPLE_squash, SAMPLE_crack, SAMPLE_slurp, SAMPLE_drip,
43 SAMPLE_wonder, SAMPLE_wheel, SAMPLE_stone, SAMPLE_spring, SAMPLE_diamond,
44 SAMPLE_nut, SAMPLE_bug, SAMPLE_tank, SAMPLE_eater, SAMPLE_alien,
48 int sound_thread(void)
50 int audio_fd; /* file descriptor of /dev/audio or -1 if not open */
54 unsigned char *audio_buffer; /* actual buffer pumped to /dev/audio */
57 char sound_play[SAMPLE_MAX]; /* if set, we should be playing these sounds */
58 long sound_pos[SAMPLE_MAX]; /* position in the sound */
59 int mix_play[MIXER_MAX]; /* which sounds we have chosen to mix (calculated each time) */
66 audio_format = AUDIO_ULAW; /* defaults for non-OSS /dev/audio */
73 memset(sound_play, 0, sizeof(sound_play)); /* not playing any sounds */
80 /* pick sounds to play, if any */
81 if (sound_play[SAMPLE_exit] || sound_play[SAMPLE_die])
82 sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */
85 for (i = 0; i < SAMPLE_MAX; i++)
87 if (sound_play[sound_priority[i]])
89 mix_play[mix_count++] = sound_priority[i];
91 if (mix_count == MIXER_MAX)
92 break; /* cant mix too many sounds at once */
96 /* check for incoming messages */
97 if (mix_count || audio_fd != -1)
99 /* dont block if we are playing sounds */
103 FD_SET(sound_pipe[0], &rfds);
105 tv.tv_usec = 0; /* (900000 * fragment_size / sample_rate) */
106 i = select(sound_pipe[0] + 1, &rfds, 0, 0, &tv); /* dont block */
110 fprintf(stderr, "%s: %s: %s\n", progname, "select failed",
116 break; /* no messages */
119 /* get a message and start a sound */
120 i = read(sound_pipe[0], &play, sizeof(play));
124 fprintf(stderr, "%s: %s: %s\n", progname, "read failed",
131 fprintf(stderr, "%s: %s: %s\n", progname, "read sound", "Broken pipe");
135 if (i != sizeof(play))
137 fprintf(stderr, "%s: %s\n", progname, "bad message length");
141 for (i = 0; i < SAMPLE_MAX; i++)
145 sound_play[i] = 1; /* play this sound */
146 sound_pos[i] = 0; /* start it from the start */
151 /* open the audio device if there are sounds to play */
152 if (mix_count && audio_fd == -1)
154 audio_fd = open(audioname, O_WRONLY);
159 #ifdef OPEN_SOUND_SYSTEM
162 if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1)
164 fprintf(stderr, "%s: \"%s\": %s (%d): %s\n", progname, audioname,
165 "unable to set fragment size", 512, strerror(errno));
169 if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i) == -1)
171 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname,
172 "unable to query audio format", strerror(errno));
176 /* prefer 8 bit unsigned and fall back on mu-law */
177 audio_format = (i & AFMT_U8) ? AFMT_U8 : AFMT_MU_LAW;
180 if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &i) == -1)
182 fprintf(stderr, "%s: \"%s\": %s (%d): %s\n", progname, audioname,
183 "unable to set audio format", audio_format, strerror(errno));
187 if (i == AFMT_MU_LAW)
189 audio_format = AUDIO_ULAW;
191 else if (i == AFMT_U8)
193 audio_format = AUDIO_U8;
197 fprintf(stderr, "%s: \"%s\": %s (%d)\n", progname, audioname,
198 "audio format required by device not supported", i);
203 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &i) == -1)
205 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname,
206 "unable to set channels to mono", strerror(errno));
212 fprintf(stderr, "%s: \"%s\": %s (%d)\n", progname, audioname,
213 "channels required by device not supported", i);
218 if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &i) == -1)
220 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname,
221 "unable to set sampling rate", strerror(errno));
226 if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &i) == -1)
228 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname,
229 "unable to get block size", strerror(errno));
236 if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) == -1)
238 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname,
239 "unable to make audio non blocking", strerror(errno));
243 #endif /* OPEN_SOUND_SYSTEM */
245 audio_buffer = malloc(fragment_size * sizeof(*audio_buffer));
246 if (audio_buffer == 0)
248 fprintf(stderr, "%s: %s (%d): %s\n", progname,
249 "unable to malloc audio buffer",
250 fragment_size * sizeof(*audio_buffer), strerror(errno));
254 mix_buffer = malloc(fragment_size * sizeof(*mix_buffer));
257 fprintf(stderr, "%s: %s (%d): %s\n", progname,
258 "unable to malloc mixing buffer",
259 fragment_size * sizeof(*mix_buffer), strerror(errno));
264 /* close the audio device if no sounds are playing */
265 if (mix_count == 0 && audio_fd != -1)
275 /* if we are playing sounds and the audio device is open, mix them */
276 if (mix_count && audio_fd != -1)
278 /* prepare mix buffer */
279 memset(mix_buffer, 0, fragment_size * sizeof(*mix_buffer));
281 for (i = 0; i < mix_count; i++)
283 register short *mix_ptr = mix_buffer;
284 register short *sound_ptr =
285 sound_data[mix_play[i]] + sound_pos[mix_play[i]];
286 register long count =
287 sound_length[mix_play[i]] - sound_pos[mix_play[i]];
289 if (count > fragment_size)
290 count = fragment_size;
293 *mix_ptr++ += *sound_ptr++; /* mix the sounds in */
299 for (i = 0; i < fragment_size; i++)
300 audio_buffer[i] = linear_to_ulaw[mix_buffer[i] + 32768];
304 for (i = 0; i < fragment_size; i++)
305 audio_buffer[i] = (mix_buffer[i] + 32768) >> 8;
309 /* advance sound pointers */
310 for (i = 0; i < SAMPLE_MAX; i++)
314 if (sound_pos[i] + fragment_size < sound_length[i])
316 sound_pos[i] += fragment_size;
325 /* send the data to the audio device */
326 i = write(audio_fd, audio_buffer, fragment_size);
329 fprintf(stderr, "%s: %s: %s\n", progname, "write error",
334 if (i != fragment_size)
336 fprintf(stderr, "%s: %s\n", progname, "bad write length");
350 goto loop; /* back to top */
363 int read_sample(char *name, short **data, long *length)
371 unsigned char buffer[24];
374 file = fopen(name, "rb");
377 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, name, "open error",
383 actual = fread(buffer, 1, 24, file);
386 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, name, "read error",
394 fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "premature eof");
400 temp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
401 if (temp != 0x2e736e64)
403 fprintf(stderr, "%s: \"%s\": %s\n", progname, name,
404 "unrecognized file format");
410 temp = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
413 fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "bad header length");
419 for (i = 24; i < actual; i++)
421 /* skip the rest of the header */
428 temp = buffer[8] << 24 | buffer[9] << 16 | buffer[10] << 8 | buffer[11];
432 temp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15];
435 fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
436 "bad encoding type", temp);
442 temp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19];
445 fprintf(stderr, "%s: \"%s\": %s (%ld != 8000)\n", progname, name,
446 "bad sample rate", temp);
452 temp = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23];
455 fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
456 "unsupported channels", temp);
461 dataptr = malloc(datalength * sizeof(*dataptr));
464 fprintf(stderr, "%s: \"%s\": %s (%ld): %s\n", progname, name,
465 "unable to malloc buffer", datalength * sizeof(*dataptr),
471 for (i = 0; i < datalength; i++)
474 if (ch == EOF) break;
475 dataptr[i] = ulaw_to_linear[ch];
482 *length = datalength;
493 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */