1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
27 static SoundInfo **Sound = NULL;
28 static MusicInfo **Music = NULL;
29 static int num_sounds = 0, num_music = 0;
32 /* ========================================================================= */
33 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
35 static int playing_sounds = 0;
36 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
37 static struct SoundControl emptySoundControl =
39 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
42 #if defined(PLATFORM_UNIX)
43 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
44 static char premix_first_buffer[SND_BLOCKSIZE];
45 #if defined(AUDIO_STREAMING_DSP)
46 static short premix_second_buffer[SND_BLOCKSIZE];
47 static short premix_left_buffer[SND_BLOCKSIZE];
48 static short premix_right_buffer[SND_BLOCKSIZE];
49 static long premix_last_buffer[SND_BLOCKSIZE];
51 static short playing_buffer[SND_BLOCKSIZE];
54 /* forward declaration of internal functions */
55 #if defined(AUDIO_STREAMING_DSP)
56 static void SoundServer_InsertNewSound(struct SoundControl);
57 #elif defined(PLATFORM_UNIX)
58 static unsigned char linear_to_ulaw(int);
59 static int ulaw_to_linear(unsigned char);
62 #if defined(AUDIO_LINUX_IOCTL)
63 static boolean InitAudioDevice_Linux();
64 #elif defined(PLATFORM_NETBSD)
65 static boolean InitAudioDevice_NetBSD();
66 #elif defined(PLATFORM_HPUX)
67 static boolean InitAudioDevice_HPUX();
68 #elif defined(PLATFORM_MSDOS)
69 static void SoundServer_InsertNewSound(struct SoundControl);
70 static void SoundServer_StopSound(struct SoundControl);
71 static void SoundServer_StopAllSounds();
74 #if defined(PLATFORM_UNIX)
75 static int OpenAudioDevice(char *audio_device_name)
79 /* check if desired audio device is accessible */
80 if (access(audio_device_name, W_OK) != 0)
83 /* try to open audio device in non-blocking mode */
84 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
87 /* re-open audio device in blocking mode */
89 audio_fd = open(audio_device_name, O_WRONLY);
94 static boolean TestAudioDevices(void)
96 static char *audio_device_name[] =
104 /* look for available audio devices, starting with preferred ones */
105 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
106 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
111 Error(ERR_WARN, "cannot open audio device -- no sound");
117 audio.device_name = audio_device_name[i];
122 #if !defined(TARGET_SDL)
123 static boolean ForkAudioProcess(void)
125 if (pipe(audio.soundserver_pipe) < 0)
127 Error(ERR_WARN, "cannot create pipe -- no sounds");
131 if ((audio.soundserver_pid = fork()) < 0)
133 Error(ERR_WARN, "cannot create sound server process -- no sounds");
137 if (audio.soundserver_pid == 0) /* we are child process */
144 else /* we are parent */
145 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
151 void UnixOpenAudio(void)
153 if (!TestAudioDevices())
156 audio.sound_available = TRUE;
157 audio.sound_enabled = TRUE;
159 #if defined(AUDIO_STREAMING_DSP)
160 audio.music_available = TRUE;
161 audio.loops_available = TRUE;
165 void UnixCloseAudio(void)
168 close(audio.device_fd);
170 if (audio.soundserver_pid > 0) /* we are parent process */
171 kill(audio.soundserver_pid, SIGTERM);
173 #endif /* PLATFORM_UNIX */
175 void InitPlaylist(void)
179 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
180 playlist[i] = emptySoundControl;
184 void StartSoundserver(void)
186 if (!audio.sound_available)
189 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
190 if (!ForkAudioProcess())
191 audio.sound_available = FALSE;
195 #if defined(PLATFORM_UNIX)
196 void SoundServer(void)
200 struct SoundControl snd_ctrl;
203 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
207 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
208 for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
210 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
212 #if defined(PLATFORM_HPUX)
213 InitAudioDevice_HPUX();
216 FD_ZERO(&sound_fdset);
217 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
219 while(1) /* wait for sound playing commands from client */
221 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
222 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
223 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
225 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
227 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
229 if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
231 char *set_name = checked_malloc(snd_ctrl.data_len);
233 (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
234 TreeInfo *ti = *ti_ptr;
235 unsigned long str_size1, str_size2, str_size3;
237 if (leveldir_current == NULL)
238 leveldir_current = checked_calloc(sizeof(TreeInfo));
240 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
241 if (leveldir_current->fullpath != NULL)
242 free(leveldir_current->fullpath);
243 if (ti->basepath != NULL)
245 if (ti->fullpath != NULL)
248 if (read(audio.soundserver_pipe[0], set_name,
249 snd_ctrl.data_len) != snd_ctrl.data_len ||
250 read(audio.soundserver_pipe[0], leveldir_current,
251 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
252 read(audio.soundserver_pipe[0], ti,
253 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
254 read(audio.soundserver_pipe[0], &str_size1,
255 sizeof(unsigned long)) != sizeof(unsigned long) ||
256 read(audio.soundserver_pipe[0], &str_size2,
257 sizeof(unsigned long)) != sizeof(unsigned long) ||
258 read(audio.soundserver_pipe[0], &str_size3,
259 sizeof(unsigned long)) != sizeof(unsigned long))
260 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
262 leveldir_current->fullpath = checked_calloc(str_size1);
263 ti->basepath = checked_calloc(str_size2);
264 ti->fullpath = checked_calloc(str_size3);
266 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
267 str_size1) != str_size1 ||
268 read(audio.soundserver_pipe[0], ti->basepath,
269 str_size2) != str_size2 ||
270 read(audio.soundserver_pipe[0], ti->fullpath,
271 str_size3) != str_size3)
272 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
276 close(audio.device_fd);
278 if (snd_ctrl.reload_sounds)
280 artwork.sounds_set_current = set_name;
281 audio.func_reload_sounds();
285 artwork.music_set_current = set_name;
286 audio.func_reload_music();
294 #if defined(AUDIO_STREAMING_DSP)
296 if (snd_ctrl.fade_sound)
302 playlist[audio.music_channel].fade_sound = TRUE;
304 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
305 if (snd_ctrl.stop_all_sounds ||
306 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
307 playlist[i].fade_sound = TRUE;
309 else if (snd_ctrl.stop_all_sounds)
314 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
315 playlist[i] = emptySoundControl;
318 close(audio.device_fd);
320 else if (snd_ctrl.stop_sound)
327 playlist[audio.music_channel] = emptySoundControl;
331 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
333 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
335 playlist[i] = emptySoundControl;
341 close(audio.device_fd);
344 if (playing_sounds || snd_ctrl.active)
346 struct timeval delay = { 0, 0 };
349 static int max_sample_size = 0;
350 static int fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
351 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
352 static boolean stereo = TRUE;
354 if (playing_sounds ||
355 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
357 if (!playing_sounds) /* we just opened the audio device */
359 #if defined(AUDIO_LINUX_IOCTL)
360 stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
361 #elif defined(PLATFORM_NETBSD)
362 stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
364 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sizeof(short));
367 if (snd_ctrl.active) /* new sound has arrived */
368 SoundServer_InsertNewSound(snd_ctrl);
370 while (playing_sounds &&
371 select(audio.soundserver_pipe[0] + 1,
372 &sound_fdset, NULL, NULL, &delay) < 1)
374 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
376 /* first clear the last premixing buffer */
377 memset(premix_last_buffer, 0, fragment_size * sizeof(short));
379 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
383 if (!playlist[i].active)
386 /* get pointer and size of the actual sound sample */
387 sample_ptr = playlist[i].data_ptr + playlist[i].playingpos;
388 sample_size = MIN(max_sample_size,
389 playlist[i].data_len - playlist[i].playingpos);
390 playlist[i].playingpos += sample_size;
392 /* fill the first mixing buffer with original sample */
393 memcpy(premix_first_buffer, sample_ptr, sample_size);
395 /* are we about to restart a looping sound? */
396 if (playlist[i].loop && sample_size < max_sample_size)
398 playlist[i].playingpos = max_sample_size - sample_size;
399 memcpy(premix_first_buffer + sample_size,
400 playlist[i].data_ptr, max_sample_size - sample_size);
401 sample_size = max_sample_size;
405 /* expand sample from 8 to 16 bit */
406 for(j=0; j<sample_size; j++)
407 premix_second_buffer[j] = premix_first_buffer[j] << 8;
410 /* decrease volume if sound is fading out */
411 if (playlist[i].fade_sound &&
412 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
413 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
415 /* adjust volume of actual sound sample */
416 if (playlist[i].volume != PSND_MAX_VOLUME)
417 for(j=0; j<sample_size; j++)
418 premix_first_buffer[j] =
419 (playlist[i].volume * (int)premix_first_buffer[j])
420 >> PSND_MAX_VOLUME_BITS;
422 /* fill the last mixing buffer with stereo or mono sound */
425 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
426 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
427 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
429 for(j=0; j<sample_size; j++)
431 premix_left_buffer[j] =
432 (left_volume * (int)premix_first_buffer[j])
433 >> PSND_MAX_LEFT2RIGHT_BITS;
434 premix_right_buffer[j] =
435 (right_volume * (int)premix_first_buffer[j])
436 >> PSND_MAX_LEFT2RIGHT_BITS;
438 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
439 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
444 for(j=0; j<sample_size; j++)
445 premix_last_buffer[j] += (int)premix_first_buffer[j];
448 /* delete completed sound entries from the playlist */
449 if (playlist[i].playingpos >= playlist[i].data_len)
451 if (playlist[i].loop)
452 playlist[i].playingpos = 0;
455 playlist[i] = emptySoundControl;
459 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
461 playlist[i] = emptySoundControl;
466 /* put last mixing buffer to final playing buffer */
468 for(i=0; i<fragment_size; i++)
470 if (premix_last_buffer[i] < -255)
471 playing_buffer[i] = 0;
472 else if (premix_last_buffer[i] > 255)
473 playing_buffer[i] = 255;
475 playing_buffer[i] = (premix_last_buffer[i] >> 1) ^ 0x80;
478 for(i=0; i<fragment_size; i++)
480 if (premix_last_buffer[i] < -255)
481 playing_buffer[i] = -127;
482 else if (premix_last_buffer[i] > 255)
483 playing_buffer[i] = 127;
485 playing_buffer[i] = (premix_last_buffer[i] >> 1);
487 playing_buffer[i] <<= 8;
491 /* finally play the sound fragment */
492 write(audio.device_fd, playing_buffer, fragment_size);
495 /* if no sounds playing, free device for other sound programs */
497 close(audio.device_fd);
501 #else /* !AUDIO_STREAMING_DSP */
503 if (snd_ctrl.active && !snd_ctrl.loop)
505 struct timeval delay = { 0, 0 };
507 long sample_size, max_sample_size = SND_BLOCKSIZE;
508 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
509 int wait_percent = 90; /* wait 90% of the real playing time */
512 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
516 while (playing_sounds &&
517 select(audio.soundserver_pipe[0] + 1,
518 &sound_fdset, NULL, NULL, &delay) < 1)
520 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
522 /* get pointer and size of the actual sound sample */
523 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
525 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
526 snd_ctrl.playingpos += sample_size;
528 /* fill the first mixing buffer with original sample */
529 memcpy(premix_first_buffer,sample_ptr,sample_size);
531 /* adjust volume of actual sound sample */
532 if (snd_ctrl.volume != PSND_MAX_VOLUME)
533 for(i=0;i<sample_size;i++)
534 premix_first_buffer[i] =
535 (snd_ctrl.volume * (int)premix_first_buffer[i])
536 >> PSND_MAX_VOLUME_BITS;
538 for(i=0;i<sample_size;i++)
540 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
542 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
545 /* finally play the sound fragment */
546 write(audio.device_fd,playing_buffer,sample_size);
549 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
551 close(audio.device_fd);
554 #endif /* !AUDIO_STREAMING_DSP */
557 #endif /* PLATFORM_UNIX */
559 #if defined(PLATFORM_MSDOS)
560 static void sound_handler(struct SoundControl snd_ctrl)
564 if (snd_ctrl.fade_sound)
569 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
570 if ((snd_ctrl.stop_all_sounds ||
571 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
572 (i == audio.music_channel && snd_ctrl.music)) &&
573 !playlist[i].fade_sound)
575 playlist[i].fade_sound = TRUE;
576 if (voice_check(playlist[i].voice))
577 voice_ramp_volume(playlist[i].voice, 1000, 0);
578 playlist[i].loop = PSND_NO_LOOP;
581 else if (snd_ctrl.stop_all_sounds)
585 SoundServer_StopAllSounds();
587 else if (snd_ctrl.stop_sound)
591 SoundServer_StopSound(snd_ctrl);
594 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
596 if (!playlist[i].active || playlist[i].loop)
599 playlist[i].playingpos = voice_get_position(playlist[i].voice);
600 playlist[i].volume = voice_get_volume(playlist[i].voice);
601 if (playlist[i].playingpos == -1 || !playlist[i].volume)
603 deallocate_voice(playlist[i].voice);
604 playlist[i] = emptySoundControl;
610 SoundServer_InsertNewSound(snd_ctrl);
612 #endif /* PLATFORM_MSDOS */
614 #if !defined(PLATFORM_WIN32)
615 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
620 snd_ctrl.nr = snd_ctrl.nr % num_music;
622 /* if playlist is full, remove oldest sound */
623 if (playing_sounds == MAX_SOUNDS_PLAYING)
625 int longest = 0, longest_nr = 0;
627 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
629 #if !defined(PLATFORM_MSDOS)
630 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
632 int actual = playlist[i].playingpos;
635 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
641 #if defined(PLATFORM_MSDOS)
642 voice_set_volume(playlist[longest_nr].voice, 0);
643 deallocate_voice(playlist[longest_nr].voice);
645 playlist[longest_nr] = emptySoundControl;
649 /* check if sound is already being played (and how often) */
650 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
651 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
654 /* restart loop sounds only if they are just fading out */
655 if (k >= 1 && snd_ctrl.loop)
657 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
659 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
660 playlist[i].fade_sound)
662 playlist[i].fade_sound = FALSE;
663 playlist[i].volume = PSND_MAX_VOLUME;
664 #if defined(PLATFORM_MSDOS)
665 playlist[i].loop = PSND_LOOP;
666 voice_stop_volumeramp(playlist[i].voice);
667 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
675 /* don't play sound more than n times simultaneously (with n == 2 for now) */
678 int longest = 0, longest_nr = 0;
680 /* look for oldest equal sound */
681 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
685 if (!playlist[i].active ||
686 i == audio.music_channel ||
687 playlist[i].nr != snd_ctrl.nr)
690 #if !defined(PLATFORM_MSDOS)
691 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
693 actual = playlist[i].playingpos;
695 if (actual >= longest)
702 #if defined(PLATFORM_MSDOS)
703 voice_set_volume(playlist[longest_nr].voice, 0);
704 deallocate_voice(playlist[longest_nr].voice);
706 playlist[longest_nr] = emptySoundControl;
710 /* add new sound to playlist */
711 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
713 if (!playlist[i].active ||
714 (snd_ctrl.music && i == audio.music_channel))
716 SoundInfo *snd_info =
717 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
719 snd_ctrl.data_ptr = snd_info->data_ptr;
720 snd_ctrl.data_len = snd_info->data_len;
722 playlist[i] = snd_ctrl;
725 #if defined(PLATFORM_MSDOS)
726 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
729 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
731 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
732 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
733 voice_start(playlist[i].voice);
739 #endif /* !PLATFORM_WIN32 */
742 void SoundServer_FadeSound(int nr)
749 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
750 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
751 playlist[i].fade_sound = TRUE;
755 #if !defined(PLATFORM_WIN32)
756 #if defined(PLATFORM_MSDOS)
757 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
759 int nr = snd_ctrl.nr;
765 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
767 if ((i == audio.music_channel && snd_ctrl.music) ||
768 (i != audio.music_channel && playlist[i].nr == nr))
770 #if defined(PLATFORM_MSDOS)
771 voice_set_volume(playlist[i].voice, 0);
772 deallocate_voice(playlist[i].voice);
774 playlist[i] = emptySoundControl;
779 #if !defined(PLATFORM_MSDOS)
781 close(audio.device_fd);
785 static void SoundServer_StopAllSounds()
789 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
791 #if defined(PLATFORM_MSDOS)
792 voice_set_volume(playlist[i].voice, 0);
793 deallocate_voice(playlist[i].voice);
795 playlist[i]=emptySoundControl;
799 #if !defined(PLATFORM_MSDOS)
800 close(audio.device_fd);
803 #endif /* PLATFORM_MSDOS */
804 #endif /* !PLATFORM_WIN32 */
807 /* ------------------------------------------------------------------------- */
808 /* platform dependant audio initialization code */
809 /* ------------------------------------------------------------------------- */
811 #if defined(AUDIO_LINUX_IOCTL)
812 static boolean InitAudioDevice_Linux(int fragment_size, int sample_rate)
814 /* "ioctl()" expects pointer to 'int' value for stereo flag
815 (boolean is defined as 'char', which will not work here) */
816 unsigned int fragment_spec = 0;
817 unsigned int audio_format = 0;
818 int fragment_size_query;
821 /* determine logarithm (log2) of the fragment size */
822 for (fragment_spec=0; (1 << fragment_spec) < fragment_size; fragment_spec++);
824 /* use two fragments (play one fragment, prepare the other);
825 one fragment would result in interrupted audio output, more
826 than two fragments would raise audio output latency to much */
827 fragment_spec |= 0x00020000;
829 /* Example for fragment specification:
830 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
831 - (with stereo the effective buffer size will shrink to 256)
832 => fragment_size = 0x00020009 */
834 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
835 Error(ERR_EXIT_SOUND_SERVER,
836 "cannot set fragment size of /dev/dsp -- no sounds");
838 audio_format = AFMT_S16_LE;
839 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) < 0)
840 Error(ERR_EXIT_SOUND_SERVER,
841 "cannot set audio format of /dev/dsp -- no sounds");
843 /* try if we can use stereo sound */
844 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
847 static boolean reported = FALSE;
851 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
858 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
859 Error(ERR_EXIT_SOUND_SERVER,
860 "cannot set sample rate of /dev/dsp -- no sounds");
862 /* get the real fragmentation size; this should return 512 */
863 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
864 Error(ERR_EXIT_SOUND_SERVER,
865 "cannot get fragment size of /dev/dsp -- no sounds");
866 if (fragment_size_query != fragment_size)
867 Error(ERR_EXIT_SOUND_SERVER,
868 "cannot set fragment size of /dev/dsp -- no sounds");
870 return (boolean)stereo;
872 #endif /* AUDIO_LINUX_IOCTL */
874 #if defined(PLATFORM_NETBSD)
875 static boolean InitAudioDevice_NetBSD(int fragment_size, int sample_rate)
878 boolean stereo = TRUE;
880 AUDIO_INITINFO(&a_info);
881 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
882 a_info.play.precision = 8;
883 a_info.play.channels = 2;
884 a_info.play.sample_rate = sample_rate;
885 a_info.blocksize = fragment_size;
887 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
889 /* try to disable stereo */
890 a_info.play.channels = 1;
893 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
894 Error(ERR_EXIT_SOUND_SERVER,
895 "cannot set sample rate of /dev/audio -- no sounds");
900 #endif /* PLATFORM_NETBSD */
902 #if defined(PLATFORM_HPUX)
903 static boolean InitAudioDevice_HPUX()
905 struct audio_describe ainfo;
908 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
910 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
912 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
913 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
915 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
916 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
918 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
919 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
923 return TRUE; /* to provide common interface for InitAudioDevice_...() */
925 #endif /* PLATFORM_HPUX */
927 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
929 /* these two are stolen from "sox"... :) */
932 ** This routine converts from linear to ulaw.
934 ** Craig Reese: IDA/Supercomputing Research Center
935 ** Joe Campbell: Department of Defense
939 ** 1) CCITT Recommendation G.711 (very difficult to follow)
940 ** 2) "A New Digital Technique for Implementation of Any
941 ** Continuous PCM Companding Law," Villeret, Michel,
942 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
943 ** 1973, pg. 11.12-11.17
944 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
945 ** for Analog-to_Digital Conversion Techniques,"
948 ** Input: Signed 16 bit linear sample
949 ** Output: 8 bit ulaw sample
952 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
953 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
956 static unsigned char linear_to_ulaw(int sample)
958 static int exp_lut[256] =
960 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
961 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
962 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
963 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
964 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
965 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
966 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
967 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
968 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
969 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
970 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
971 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
972 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
973 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
974 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
975 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
978 int sign, exponent, mantissa;
979 unsigned char ulawbyte;
981 /* Get the sample into sign-magnitude. */
982 sign = (sample >> 8) & 0x80; /* set aside the sign */
984 sample = -sample; /* get magnitude */
986 sample = CLIP; /* clip the magnitude */
988 /* Convert from 16 bit linear to ulaw. */
989 sample = sample + BIAS;
990 exponent = exp_lut[( sample >> 7 ) & 0xFF];
991 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
992 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
995 ulawbyte = 0x02; /* optional CCITT trap */
1002 ** This routine converts from ulaw to 16 bit linear.
1004 ** Craig Reese: IDA/Supercomputing Research Center
1005 ** 29 September 1989
1008 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1009 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1010 ** for Analog-to_Digital Conversion Techniques,"
1013 ** Input: 8 bit ulaw sample
1014 ** Output: signed 16 bit linear sample
1017 static int ulaw_to_linear(unsigned char ulawbyte)
1019 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1020 int sign, exponent, mantissa, sample;
1022 ulawbyte = ~ ulawbyte;
1023 sign = ( ulawbyte & 0x80 );
1024 exponent = ( ulawbyte >> 4 ) & 0x07;
1025 mantissa = ulawbyte & 0x0F;
1026 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1032 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1035 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1036 /* ========================================================================= */
1037 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1039 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1040 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1042 static SoundInfo *Load_WAV(char *filename)
1044 SoundInfo *snd_info;
1045 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1046 byte sound_header_buffer[WAV_HEADER_SIZE];
1047 char chunk_name[CHUNK_ID_LEN + 1];
1053 if (!audio.sound_available)
1056 snd_info = checked_calloc(sizeof(SoundInfo));
1058 #if defined(TARGET_SDL)
1060 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1062 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1067 #elif defined(TARGET_ALLEGRO)
1069 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1071 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1076 #else /* PLATFORM_UNIX */
1078 if ((file = fopen(filename, MODE_READ)) == NULL)
1080 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1085 /* read chunk id "RIFF" */
1086 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1087 if (strcmp(chunk_name, "RIFF") != 0)
1089 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1095 /* read "RIFF" type id "WAVE" */
1096 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1097 if (strcmp(chunk_name, "WAVE") != 0)
1099 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1105 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1107 if (strcmp(chunk_name, "fmt ") == 0)
1109 /* read header information */
1110 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1111 sound_header_buffer[i] = fgetc(file);
1113 if (chunk_size > WAV_HEADER_SIZE)
1114 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1116 else if (strcmp(chunk_name, "data") == 0)
1118 snd_info->data_len = chunk_size;
1119 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1121 /* read sound data */
1122 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1125 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1127 free(snd_info->data_ptr);
1132 /* check for odd number of sample bytes (data chunk is word aligned) */
1133 if ((chunk_size % 2) == 1)
1134 ReadUnusedBytesFromFile(file, 1);
1136 else /* unknown chunk -- ignore */
1137 ReadUnusedBytesFromFile(file, chunk_size);
1142 if (snd_info->data_ptr == NULL)
1144 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1149 for (i=0; i<snd_info->data_len; i++)
1150 ((byte *)snd_info->data_ptr)[i] ^= 0x80;
1152 #endif /* PLATFORM_UNIX */
1154 snd_info->type = SND_TYPE_WAV;
1155 snd_info->source_filename = getStringCopy(filename);
1160 SoundInfo *LoadCustomSound(char *basename)
1162 char *filename = getCustomSoundFilename(basename);
1164 if (filename == NULL)
1166 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1170 return Load_WAV(filename);
1173 void InitSoundList(int num_list_entries)
1175 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1176 num_sounds = num_list_entries;
1179 void LoadSoundToList(char *basename, int list_pos)
1181 if (Sound == NULL || list_pos >= num_sounds)
1184 if (Sound[list_pos])
1185 FreeSound(Sound[list_pos]);
1187 Sound[list_pos] = LoadCustomSound(basename);
1190 static MusicInfo *Load_MOD(char *filename)
1192 #if defined(TARGET_SDL)
1193 MusicInfo *mod_info;
1195 if (!audio.sound_available)
1198 mod_info = checked_calloc(sizeof(MusicInfo));
1200 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1202 Error(ERR_WARN, "cannot read music file '%s'", filename);
1207 mod_info->type = MUS_TYPE_MOD;
1208 mod_info->source_filename = getStringCopy(filename);
1216 void LoadCustomMusic(void)
1218 char *music_directory = getCustomMusicDirectory();
1220 struct dirent *dir_entry;
1222 if (!audio.sound_available)
1225 if ((dir = opendir(music_directory)) == NULL)
1227 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1228 audio.music_available = FALSE;
1232 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1234 char *basename = dir_entry->d_name;
1235 char *filename = getPath2(music_directory, basename);
1236 MusicInfo *mus_info = NULL;
1238 if (FileIsSound(basename))
1239 mus_info = Load_WAV(filename);
1240 else if (FileIsMusic(basename))
1241 mus_info = Load_MOD(filename);
1248 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1249 Music[num_music -1] = mus_info;
1256 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1260 void PlayMusic(int nr)
1262 if (!audio.music_available)
1265 #if defined(TARGET_SDL)
1267 nr = nr % num_music;
1269 if (Music[nr]->type == MUS_TYPE_MOD)
1271 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1272 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1274 else /* play WAV music loop */
1276 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1277 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1287 void PlaySound(int nr)
1289 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1292 void PlaySoundStereo(int nr, int stereo)
1294 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1297 void PlaySoundLoop(int nr)
1299 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1302 void PlaySoundMusic(int nr)
1304 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1307 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1309 struct SoundControl snd_ctrl = emptySoundControl;
1311 if (!audio.sound_available ||
1312 !audio.sound_enabled ||
1313 audio.sound_deactivated)
1316 if (volume < PSND_MIN_VOLUME)
1317 volume = PSND_MIN_VOLUME;
1318 else if (volume > PSND_MAX_VOLUME)
1319 volume = PSND_MAX_VOLUME;
1321 if (stereo < PSND_MAX_LEFT)
1322 stereo = PSND_MAX_LEFT;
1323 else if (stereo > PSND_MAX_RIGHT)
1324 stereo = PSND_MAX_RIGHT;
1327 snd_ctrl.volume = volume;
1328 snd_ctrl.stereo = stereo;
1329 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1330 snd_ctrl.music = (loop_type == PSND_MUSIC);
1331 snd_ctrl.active = TRUE;
1334 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1335 snd_ctrl.data_len = Sound[nr].data_len;
1338 #if defined(TARGET_SDL)
1339 Mix_Volume(-1, SOUND_MAX_VOLUME);
1340 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1341 #elif defined(PLATFORM_UNIX)
1342 if (audio.soundserver_pid == 0) /* we are child process */
1345 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1347 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1348 audio.sound_available = audio.sound_enabled = FALSE;
1351 #elif defined(PLATFORM_MSDOS)
1352 sound_handler(snd_ctrl);
1356 void FadeMusic(void)
1358 if (!audio.sound_available)
1361 #if defined(TARGET_SDL)
1362 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1363 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1365 StopSoundExt(-1, SSND_FADE_MUSIC);
1369 void FadeSound(int nr)
1371 StopSoundExt(nr, SSND_FADE_SOUND);
1377 StopSoundExt(-1, SSND_FADE_ALL);
1380 void StopMusic(void)
1382 #if defined(TARGET_SDL)
1383 if (!audio.sound_available)
1387 Mix_HaltChannel(audio.music_channel);
1389 StopSoundExt(-1, SSND_STOP_MUSIC);
1393 void StopSound(int nr)
1395 StopSoundExt(nr, SSND_STOP_SOUND);
1400 StopSoundExt(-1, SSND_STOP_ALL);
1403 void StopSoundExt(int nr, int method)
1405 struct SoundControl snd_ctrl = emptySoundControl;
1407 if (!audio.sound_available)
1410 if (method & SSND_FADING)
1411 snd_ctrl.fade_sound = TRUE;
1413 if (method & SSND_ALL)
1414 snd_ctrl.stop_all_sounds = TRUE;
1417 snd_ctrl.stop_sound = TRUE;
1421 if (method & SSND_MUSIC)
1422 snd_ctrl.music = TRUE;
1424 #if defined(TARGET_SDL)
1426 if (method & SSND_FADING)
1430 for (i=0; i<audio.channels; i++)
1431 if (i != audio.music_channel || snd_ctrl.music)
1432 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1434 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1440 for (i=0; i<audio.channels; i++)
1441 if (i != audio.music_channel || snd_ctrl.music)
1447 #elif !defined(PLATFORM_MSDOS)
1449 if (audio.soundserver_pid == 0) /* we are child process */
1452 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1454 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1455 audio.sound_available = audio.sound_enabled = FALSE;
1459 sound_handler(snd_ctrl);
1463 static void InitReloadSoundsOrMusic(char *set_name, int type)
1465 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1466 struct SoundControl snd_ctrl = emptySoundControl;
1468 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1469 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1470 unsigned long str_size2 = strlen(ti->basepath) + 1;
1471 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1474 if (!audio.sound_available)
1477 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1478 if (type == SND_RELOAD_SOUNDS)
1479 audio.func_reload_sounds();
1481 audio.func_reload_music();
1482 #elif defined(PLATFORM_UNIX)
1483 if (audio.soundserver_pid == 0) /* we are child process */
1486 if (leveldir_current == NULL) /* should never happen */
1487 Error(ERR_EXIT, "leveldir_current == NULL");
1489 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1490 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1491 snd_ctrl.data_len = strlen(set_name) + 1;
1493 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1494 sizeof(snd_ctrl)) < 0 ||
1495 write(audio.soundserver_pipe[1], set_name,
1496 snd_ctrl.data_len) < 0 ||
1497 write(audio.soundserver_pipe[1], leveldir_current,
1498 sizeof(TreeInfo)) < 0 ||
1499 write(audio.soundserver_pipe[1], ti,
1500 sizeof(TreeInfo)) < 0 ||
1501 write(audio.soundserver_pipe[1], &str_size1,
1502 sizeof(unsigned long)) < 0 ||
1503 write(audio.soundserver_pipe[1], &str_size2,
1504 sizeof(unsigned long)) < 0 ||
1505 write(audio.soundserver_pipe[1], &str_size3,
1506 sizeof(unsigned long)) < 0 ||
1507 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1509 write(audio.soundserver_pipe[1], ti->basepath,
1511 write(audio.soundserver_pipe[1], ti->fullpath,
1514 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1515 audio.sound_available = audio.sound_enabled = FALSE;
1521 void InitReloadSounds(char *set_name)
1523 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1526 void InitReloadMusic(char *set_name)
1528 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1531 void FreeSound(SoundInfo *sound)
1536 if (sound->data_ptr)
1538 #if defined(TARGET_SDL)
1539 Mix_FreeChunk(sound->data_ptr);
1540 #elif defined(TARGET_ALLEGRO)
1541 destroy_sample(sound->data_ptr);
1542 #else /* PLATFORM_UNIX */
1543 free(sound->data_ptr);
1550 void FreeMusic(MusicInfo *music)
1555 if (music->data_ptr)
1557 #if defined(TARGET_SDL)
1558 if (music->type == MUS_TYPE_MOD)
1559 Mix_FreeMusic(music->data_ptr);
1561 Mix_FreeChunk(music->data_ptr);
1562 #elif defined(TARGET_ALLEGRO)
1563 destroy_sample(music->data_ptr);
1564 #else /* PLATFORM_UNIX */
1565 free(music->data_ptr);
1572 void FreeAllSounds()
1579 for(i=0; i<num_sounds; i++)
1580 FreeSound(Sound[i]);
1595 for(i=0; i<num_music; i++)
1596 FreeMusic(Music[i]);
1604 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1605 /* ========================================================================= */