1 /* 2000-08-10T17:39:15Z
3 * handle sounds in emerald mine
9 #if defined(AUDIO_UNIX_NATIVE)
11 #if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
14 #include <sys/ioctl.h>
15 #include <sys/soundcard.h>
20 #include <soundcard.h>
26 static char audioname[] = "/dev/audio";
28 static const int sound_priority[SAMPLE_MAX] =
67 int sound_thread(void)
69 int audio_fd; /* file descriptor of /dev/audio or -1 if not open */
73 unsigned char *audio_buffer; /* actual buffer pumped to /dev/audio */
76 char sound_play[SAMPLE_MAX]; /* if set, we should be playing these sounds */
77 long sound_pos[SAMPLE_MAX]; /* position in the sound */
78 int mix_play[MIXER_MAX]; /* which sounds we have chosen to mix (calculated each time) */
85 audio_format = AUDIO_ULAW; /* defaults for non-OSS /dev/audio */
92 memset(sound_play, 0, sizeof(sound_play)); /* not playing any sounds */
99 /* pick sounds to play, if any */
100 if (sound_play[SAMPLE_exit_open] ||
101 sound_play[SAMPLE_exit_leave] ||
102 sound_play[SAMPLE_die])
103 sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */
106 for (i = 0; i < SAMPLE_MAX; i++)
108 if (sound_play[sound_priority[i]])
110 mix_play[mix_count++] = sound_priority[i];
112 if (mix_count == MIXER_MAX)
113 break; /* cant mix too many sounds at once */
117 /* check for incoming messages */
118 if (mix_count || audio_fd != -1)
120 /* dont block if we are playing sounds */
124 FD_SET(sound_pipe[0], &rfds);
126 tv.tv_usec = 0; /* (900000 * fragment_size / sample_rate) */
127 i = select(sound_pipe[0] + 1, &rfds, 0, 0, &tv); /* dont block */
131 Error(ERR_WARN, "select() failed in sound thread");
137 break; /* no messages */
140 /* get a message and start a sound */
141 i = read(sound_pipe[0], &play, sizeof(play));
145 Error(ERR_WARN, "read() failed in sound thread");
152 Error(ERR_WARN, "reading sound failed in sound thread");
157 if (i != sizeof(play))
159 Error(ERR_WARN, "bad message length in sound thread");
164 for (i = 0; i < SAMPLE_MAX; i++)
168 sound_play[i] = 1; /* play this sound */
169 sound_pos[i] = 0; /* start it from the start */
174 /* open the audio device if there are sounds to play */
175 if (mix_count && audio_fd == -1)
177 audio_fd = open(audioname, O_WRONLY);
182 #ifdef OPEN_SOUND_SYSTEM
185 if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1)
187 Error(ERR_WARN, "unable to set fragment size in sound thread");
192 if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i) == -1)
194 Error(ERR_WARN, "unable to query audio format in sound thread");
199 /* prefer 8 bit unsigned and fall back on mu-law */
200 audio_format = (i & AFMT_U8) ? AFMT_U8 : AFMT_MU_LAW;
203 if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &i) == -1)
205 Error(ERR_WARN, "unable to set audio format in sound thread");
210 if (i == AFMT_MU_LAW)
212 audio_format = AUDIO_ULAW;
214 else if (i == AFMT_U8)
216 audio_format = AUDIO_U8;
220 Error(ERR_WARN, "audio format required by device not supported");
226 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &i) == -1)
228 Error(ERR_WARN, "unable to set channels to mono in sound thread");
235 Error(ERR_WARN, "channels required by device not supported");
241 if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &i) == -1)
243 Error(ERR_WARN, "unable to set sampling rate in sound thread");
249 if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &i) == -1)
251 Error(ERR_WARN, "unable to get block size in sound thread");
259 if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) == -1)
261 Error(ERR_WARN, "unable to make audio non blocking in sound thread");
266 #endif /* OPEN_SOUND_SYSTEM */
268 audio_buffer = malloc(fragment_size * sizeof(*audio_buffer));
269 if (audio_buffer == 0)
271 Error(ERR_WARN, "unable to malloc audio buffer in sound thread");
276 mix_buffer = malloc(fragment_size * sizeof(*mix_buffer));
279 Error(ERR_WARN, "unable to malloc mixing buffer in sound thread");
285 /* close the audio device if no sounds are playing */
286 if (mix_count == 0 && audio_fd != -1)
296 /* if we are playing sounds and the audio device is open, mix them */
297 if (mix_count && audio_fd != -1)
299 /* prepare mix buffer */
300 memset(mix_buffer, 0, fragment_size * sizeof(*mix_buffer));
302 for (i = 0; i < mix_count; i++)
304 register short *mix_ptr = mix_buffer;
305 register short *sound_ptr =
306 sound_data[mix_play[i]] + sound_pos[mix_play[i]];
307 register long count =
308 sound_length[mix_play[i]] - sound_pos[mix_play[i]];
310 if (count > fragment_size)
311 count = fragment_size;
314 *mix_ptr++ += *sound_ptr++; /* mix the sounds in */
320 for (i = 0; i < fragment_size; i++)
321 audio_buffer[i] = linear_to_ulaw[mix_buffer[i] + 32768];
325 for (i = 0; i < fragment_size; i++)
326 audio_buffer[i] = (mix_buffer[i] + 32768) >> 8;
330 /* advance sound pointers */
331 for (i = 0; i < SAMPLE_MAX; i++)
335 if (sound_pos[i] + fragment_size < sound_length[i])
337 sound_pos[i] += fragment_size;
346 /* send the data to the audio device */
347 i = write(audio_fd, audio_buffer, fragment_size);
350 Error(ERR_WARN, "cannot write to audio device in sound thread");
355 if (i != fragment_size)
357 Error(ERR_WARN, "bad write length to audio device in sound thread");
373 goto loop; /* back to top */
386 int read_sample(char *name, short **data, long *length)
394 unsigned char buffer[24];
397 file = fopen(name, "rb");
400 Error(ERR_WARN, "cannot open file '%s' in sound thread", name);
406 actual = fread(buffer, 1, 24, file);
409 Error(ERR_WARN, "cannot read file '%s' in sound thread", name);
417 Error(ERR_WARN, "premature eof of file '%s' in sound thread", name);
424 temp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
425 if (temp != 0x2e736e64)
427 Error(ERR_WARN, "unrecognized format of file '%s' in sound thread", name);
434 temp = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
437 Error(ERR_WARN, "bad header length of file '%s' in sound thread", name);
444 for (i = 24; i < actual; i++)
446 /* skip the rest of the header */
453 temp = buffer[8] << 24 | buffer[9] << 16 | buffer[10] << 8 | buffer[11];
457 temp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15];
460 fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
461 "bad encoding type", temp);
467 temp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19];
470 fprintf(stderr, "%s: \"%s\": %s (%ld != 8000)\n", progname, name,
471 "bad sample rate", temp);
477 temp = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23];
480 fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
481 "unsupported channels", temp);
486 dataptr = malloc(datalength * sizeof(*dataptr));
489 Error(ERR_WARN, "unable to malloc buffer for file '%s' in sound thread",
496 for (i = 0; i < datalength; i++)
499 if (ch == EOF) break;
500 dataptr[i] = ulaw_to_linear[ch];
507 *length = datalength;
518 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
520 #endif /* AUDIO_UNIX_NATIVE */