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 char premix_left_buffer[SND_BLOCKSIZE];
47 static char premix_right_buffer[SND_BLOCKSIZE];
48 static int premix_last_buffer[SND_BLOCKSIZE];
50 static unsigned char playing_buffer[SND_BLOCKSIZE];
53 /* forward declaration of internal functions */
54 #if defined(AUDIO_STREAMING_DSP)
55 static void SoundServer_InsertNewSound(struct SoundControl);
56 #elif defined(PLATFORM_UNIX)
57 static unsigned char linear_to_ulaw(int);
58 static int ulaw_to_linear(unsigned char);
61 #if defined(AUDIO_LINUX_IOCTL)
62 static boolean InitAudioDevice_Linux();
63 #elif defined(PLATFORM_NETBSD)
64 static boolean InitAudioDevice_NetBSD();
65 #elif defined(PLATFORM_HPUX)
66 static boolean InitAudioDevice_HPUX();
67 #elif defined(PLATFORM_MSDOS)
68 static void SoundServer_InsertNewSound(struct SoundControl);
69 static void SoundServer_StopSound(int);
70 static void SoundServer_StopAllSounds();
73 #if defined(PLATFORM_UNIX)
74 static int OpenAudioDevice(char *audio_device_name)
78 /* check if desired audio device is accessible */
79 if (access(audio_device_name, W_OK) != 0)
82 /* try to open audio device in non-blocking mode */
83 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
86 /* re-open audio device in blocking mode */
88 audio_fd = open(audio_device_name, O_WRONLY);
93 static boolean TestAudioDevices(void)
95 static char *audio_device_name[] =
103 /* look for available audio devices, starting with preferred ones */
104 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
105 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
110 Error(ERR_WARN, "cannot open audio device -- no sound");
116 audio.device_name = audio_device_name[i];
121 #if !defined(TARGET_SDL)
122 static boolean ForkAudioProcess(void)
124 if (pipe(audio.soundserver_pipe) < 0)
126 Error(ERR_WARN, "cannot create pipe -- no sounds");
130 if ((audio.soundserver_pid = fork()) < 0)
132 Error(ERR_WARN, "cannot create sound server process -- no sounds");
136 if (audio.soundserver_pid == 0) /* we are child process */
143 else /* we are parent */
144 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
150 void UnixOpenAudio(void)
152 if (!TestAudioDevices())
155 audio.sound_available = TRUE;
156 audio.sound_enabled = TRUE;
158 #if defined(AUDIO_STREAMING_DSP)
159 audio.music_available = TRUE;
160 audio.loops_available = TRUE;
164 void UnixCloseAudio(void)
167 close(audio.device_fd);
169 if (audio.soundserver_pid > 0) /* we are parent process */
170 kill(audio.soundserver_pid, SIGTERM);
172 #endif /* PLATFORM_UNIX */
174 void InitPlaylist(void)
178 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
179 playlist[i] = emptySoundControl;
183 void StartSoundserver(void)
185 if (!audio.sound_available)
188 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
189 if (!ForkAudioProcess())
190 audio.sound_available = FALSE;
194 #if defined(PLATFORM_UNIX)
195 void SoundServer(void)
199 struct SoundControl snd_ctrl;
202 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
206 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
207 for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
209 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
211 #if defined(PLATFORM_HPUX)
212 InitAudioDevice_HPUX();
215 FD_ZERO(&sound_fdset);
216 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
218 while(1) /* wait for sound playing commands from client */
220 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
221 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
222 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
224 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
226 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
228 if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
230 char *set_name = checked_malloc(snd_ctrl.data_len);
232 (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
233 TreeInfo *ti = *ti_ptr;
234 unsigned long str_size1, str_size2, str_size3;
238 if (leveldir_current == NULL)
239 leveldir_current = checked_calloc(sizeof(TreeInfo));
242 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
244 if (leveldir_current->fullpath != NULL)
245 free(leveldir_current->fullpath);
246 printf("B.3 ['%s']\n", ti->basepath);
248 if (ti->basepath != NULL)
252 if (ti->fullpath != NULL)
258 if (read(audio.soundserver_pipe[0], set_name,
259 snd_ctrl.data_len) != snd_ctrl.data_len ||
260 read(audio.soundserver_pipe[0], leveldir_current,
261 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
262 read(audio.soundserver_pipe[0], ti,
263 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
264 read(audio.soundserver_pipe[0], &str_size1,
265 sizeof(unsigned long)) != sizeof(unsigned long) ||
266 read(audio.soundserver_pipe[0], &str_size2,
267 sizeof(unsigned long)) != sizeof(unsigned long) ||
268 read(audio.soundserver_pipe[0], &str_size3,
269 sizeof(unsigned long)) != sizeof(unsigned long))
270 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
274 leveldir_current->fullpath = checked_calloc(str_size1);
275 ti->basepath = checked_calloc(str_size2);
276 ti->fullpath = checked_calloc(str_size3);
278 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
279 str_size1) != str_size1 ||
280 read(audio.soundserver_pipe[0], ti->basepath,
281 str_size2) != str_size2 ||
282 read(audio.soundserver_pipe[0], ti->fullpath,
283 str_size3) != str_size3)
284 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
290 close(audio.device_fd);
294 if (snd_ctrl.reload_sounds)
296 artwork.sounds_set_current = set_name;
297 audio.func_reload_sounds();
301 artwork.music_set_current = set_name;
302 audio.func_reload_music();
310 #if defined(AUDIO_STREAMING_DSP)
312 if (snd_ctrl.fade_sound)
318 playlist[audio.music_channel].fade_sound = TRUE;
320 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
321 if (snd_ctrl.stop_all_sounds ||
322 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
323 playlist[i].fade_sound = TRUE;
325 else if (snd_ctrl.stop_all_sounds)
330 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
331 playlist[i] = emptySoundControl;
334 close(audio.device_fd);
336 else if (snd_ctrl.stop_sound)
343 playlist[audio.music_channel] = emptySoundControl;
347 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
349 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
351 playlist[i] = emptySoundControl;
357 close(audio.device_fd);
360 if (playing_sounds || snd_ctrl.active)
362 struct timeval delay = { 0, 0 };
365 static long max_sample_size = 0;
366 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
367 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
368 static boolean stereo = TRUE;
370 if (playing_sounds ||
371 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
373 if (!playing_sounds) /* we just opened the audio device */
375 #if defined(AUDIO_LINUX_IOCTL)
376 stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
377 #elif defined(PLATFORM_NETBSD)
378 stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
380 max_sample_size = fragment_size / (stereo ? 2 : 1);
383 if (snd_ctrl.active) /* new sound has arrived */
384 SoundServer_InsertNewSound(snd_ctrl);
386 while (playing_sounds &&
387 select(audio.soundserver_pipe[0] + 1,
388 &sound_fdset, NULL, NULL, &delay) < 1)
390 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
392 /* first clear the last premixing buffer */
393 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
395 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
399 if (!playlist[i].active)
402 /* get pointer and size of the actual sound sample */
403 sample_ptr = playlist[i].data_ptr + playlist[i].playingpos;
404 sample_size = MIN(max_sample_size,
405 playlist[i].data_len - playlist[i].playingpos);
406 playlist[i].playingpos += sample_size;
408 /* fill the first mixing buffer with original sample */
409 memcpy(premix_first_buffer, sample_ptr, sample_size);
411 /* are we about to restart a looping sound? */
412 if (playlist[i].loop && sample_size < max_sample_size)
414 playlist[i].playingpos = max_sample_size - sample_size;
415 memcpy(premix_first_buffer + sample_size,
416 playlist[i].data_ptr, max_sample_size - sample_size);
417 sample_size = max_sample_size;
420 /* decrease volume if sound is fading out */
421 if (playlist[i].fade_sound &&
422 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
423 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
425 /* adjust volume of actual sound sample */
426 if (playlist[i].volume != PSND_MAX_VOLUME)
427 for(j=0; j<sample_size; j++)
428 premix_first_buffer[j] =
429 (playlist[i].volume * (int)premix_first_buffer[j])
430 >> PSND_MAX_VOLUME_BITS;
432 /* fill the last mixing buffer with stereo or mono sound */
435 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
436 int left_volume = stereo_volume[middle_pos +playlist[i].stereo];
437 int right_volume = stereo_volume[middle_pos -playlist[i].stereo];
439 for(j=0; j<sample_size; j++)
441 premix_left_buffer[j] =
442 (left_volume * (int)premix_first_buffer[j])
443 >> PSND_MAX_LEFT2RIGHT_BITS;
444 premix_right_buffer[j] =
445 (right_volume * (int)premix_first_buffer[j])
446 >> PSND_MAX_LEFT2RIGHT_BITS;
447 premix_last_buffer[2*j+0] += premix_left_buffer[j];
448 premix_last_buffer[2*j+1] += premix_right_buffer[j];
453 for(j=0;j<sample_size;j++)
454 premix_last_buffer[j] += (int)premix_first_buffer[j];
457 /* delete completed sound entries from the playlist */
458 if (playlist[i].playingpos >= playlist[i].data_len)
460 if (playlist[i].loop)
461 playlist[i].playingpos = 0;
464 playlist[i] = emptySoundControl;
468 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
470 playlist[i] = emptySoundControl;
475 /* put last mixing buffer to final playing buffer */
476 for(i=0; i<fragment_size; i++)
478 if (premix_last_buffer[i]<-255)
479 playing_buffer[i] = 0;
480 else if (premix_last_buffer[i]>255)
481 playing_buffer[i] = 255;
483 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
486 /* finally play the sound fragment */
487 write(audio.device_fd, playing_buffer, fragment_size);
490 /* if no sounds playing, free device for other sound programs */
492 close(audio.device_fd);
496 #else /* !AUDIO_STREAMING_DSP */
498 if (snd_ctrl.active && !snd_ctrl.loop)
500 struct timeval delay = { 0, 0 };
502 long sample_size, max_sample_size = SND_BLOCKSIZE;
503 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
504 int wait_percent = 90; /* wait 90% of the real playing time */
507 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
511 while (playing_sounds &&
512 select(audio.soundserver_pipe[0] + 1,
513 &sound_fdset, NULL, NULL, &delay) < 1)
515 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
517 /* get pointer and size of the actual sound sample */
518 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
520 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
521 snd_ctrl.playingpos += sample_size;
523 /* fill the first mixing buffer with original sample */
524 memcpy(premix_first_buffer,sample_ptr,sample_size);
526 /* adjust volume of actual sound sample */
527 if (snd_ctrl.volume != PSND_MAX_VOLUME)
528 for(i=0;i<sample_size;i++)
529 premix_first_buffer[i] =
530 (snd_ctrl.volume * (int)premix_first_buffer[i])
531 >> PSND_MAX_VOLUME_BITS;
533 for(i=0;i<sample_size;i++)
535 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
537 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
540 /* finally play the sound fragment */
541 write(audio.device_fd,playing_buffer,sample_size);
544 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
546 close(audio.device_fd);
549 #endif /* !AUDIO_STREAMING_DSP */
552 #endif /* PLATFORM_UNIX */
554 #if defined(PLATFORM_MSDOS)
555 static void sound_handler(struct SoundControl snd_ctrl)
559 if (snd_ctrl.fade_sound)
564 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
565 if ((snd_ctrl.stop_all_sounds ||
566 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
567 (i == audio.music_channel && snd_ctrl.music)) &&
568 !playlist[i].fade_sound)
570 playlist[i].fade_sound = TRUE;
571 if (voice_check(playlist[i].voice))
572 voice_ramp_volume(playlist[i].voice, 1000, 0);
573 playlist[i].loop = PSND_NO_LOOP;
576 else if (snd_ctrl.stop_all_sounds)
580 SoundServer_StopAllSounds();
582 else if (snd_ctrl.stop_sound)
586 SoundServer_StopSound(snd_ctrl);
589 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
591 if (!playlist[i].active || playlist[i].loop)
594 playlist[i].playingpos = voice_get_position(playlist[i].voice);
595 playlist[i].volume = voice_get_volume(playlist[i].voice);
596 if (playlist[i].playingpos == -1 || !playlist[i].volume)
598 deallocate_voice(playlist[i].voice);
599 playlist[i] = emptySoundControl;
605 SoundServer_InsertNewSound(snd_ctrl);
607 #endif /* PLATFORM_MSDOS */
609 #if !defined(PLATFORM_WIN32)
610 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
615 snd_ctrl.nr = snd_ctrl.nr % num_music;
617 /* if playlist is full, remove oldest sound */
618 if (playing_sounds == MAX_SOUNDS_PLAYING)
620 int longest = 0, longest_nr = 0;
622 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
624 #if !defined(PLATFORM_MSDOS)
625 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
627 int actual = playlist[i].playingpos;
630 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
636 #if defined(PLATFORM_MSDOS)
637 voice_set_volume(playlist[longest_nr].voice, 0);
638 deallocate_voice(playlist[longest_nr].voice);
640 playlist[longest_nr] = emptySoundControl;
644 /* check if sound is already being played (and how often) */
645 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
646 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
649 /* restart loop sounds only if they are just fading out */
650 if (k >= 1 && snd_ctrl.loop)
652 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
654 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
655 playlist[i].fade_sound)
657 playlist[i].fade_sound = FALSE;
658 playlist[i].volume = PSND_MAX_VOLUME;
659 #if defined(PLATFORM_MSDOS)
660 playlist[i].loop = PSND_LOOP;
661 voice_stop_volumeramp(playlist[i].voice);
662 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
670 /* don't play sound more than n times simultaneously (with n == 2 for now) */
673 int longest = 0, longest_nr = 0;
675 /* look for oldest equal sound */
676 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
680 if (!playlist[i].active ||
681 i == audio.music_channel ||
682 playlist[i].nr != snd_ctrl.nr)
685 #if !defined(PLATFORM_MSDOS)
686 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
688 actual = playlist[i].playingpos;
690 if (actual >= longest)
697 #if defined(PLATFORM_MSDOS)
698 voice_set_volume(playlist[longest_nr].voice, 0);
699 deallocate_voice(playlist[longest_nr].voice);
701 playlist[longest_nr] = emptySoundControl;
705 /* add new sound to playlist */
706 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
708 if (!playlist[i].active ||
709 (snd_ctrl.music && i == audio.music_channel))
711 SoundInfo *snd_info =
712 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
714 snd_ctrl.data_ptr = snd_info->data_ptr;
715 snd_ctrl.data_len = snd_info->data_len;
717 playlist[i] = snd_ctrl;
720 #if defined(PLATFORM_MSDOS)
721 playlist[i].voice = allocate_voice(playlist[i].data_ptr);
724 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
726 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
727 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
728 voice_start(playlist[i].voice);
734 #endif /* !PLATFORM_WIN32 */
737 void SoundServer_FadeSound(int nr)
744 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
745 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
746 playlist[i].fade_sound = TRUE;
750 #if !defined(PLATFORM_WIN32)
751 #if defined(PLATFORM_MSDOS)
752 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
754 int nr = snd_ctrl.nr;
760 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
762 if ((i == audio.music_channel && snd_ctrl.music) ||
763 (i != audio.music_channel && playlist[i].nr == nr))
765 #if defined(PLATFORM_MSDOS)
766 voice_set_volume(playlist[i].voice, 0);
767 deallocate_voice(playlist[i].voice);
769 playlist[i] = emptySoundControl;
774 #if !defined(PLATFORM_MSDOS)
776 close(audio.device_fd);
780 static void SoundServer_StopAllSounds()
784 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
786 #if defined(PLATFORM_MSDOS)
787 voice_set_volume(playlist[i].voice, 0);
788 deallocate_voice(playlist[i].voice);
790 playlist[i]=emptySoundControl;
794 #if !defined(PLATFORM_MSDOS)
795 close(audio.device_fd);
798 #endif /* PLATFORM_MSDOS */
799 #endif /* !PLATFORM_WIN32 */
802 /* ------------------------------------------------------------------------- */
803 /* platform dependant audio initialization code */
804 /* ------------------------------------------------------------------------- */
806 #if defined(AUDIO_LINUX_IOCTL)
807 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
809 /* "ioctl()" expects pointer to 'int' value for stereo flag
810 (boolean is defined as 'char', which will not work here) */
812 unsigned long fragment_spec = 0;
814 /* determine logarithm (log2) of the fragment size */
815 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
818 /* use two fragments (play one fragment, prepare the other);
819 one fragment would result in interrupted audio output, more
820 than two fragments would raise audio output latency to much */
821 fragment_spec |= 0x00020000;
823 /* Example for fragment specification:
824 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
825 - (with stereo the effective buffer size will shrink to 256)
826 => fragment_size = 0x00020009 */
828 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
829 Error(ERR_EXIT_SOUND_SERVER,
830 "cannot set fragment size of /dev/dsp -- no sounds");
832 /* try if we can use stereo sound */
833 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
836 static boolean reported = FALSE;
840 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
847 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
848 Error(ERR_EXIT_SOUND_SERVER,
849 "cannot set sample rate of /dev/dsp -- no sounds");
851 /* get the real fragmentation size; this should return 512 */
852 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
853 Error(ERR_EXIT_SOUND_SERVER,
854 "cannot get fragment size of /dev/dsp -- no sounds");
856 return (boolean)stereo;
858 #endif /* AUDIO_LINUX_IOCTL */
860 #if defined(PLATFORM_NETBSD)
861 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
864 boolean stereo = TRUE;
866 AUDIO_INITINFO(&a_info);
867 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
868 a_info.play.precision = 8;
869 a_info.play.channels = 2;
870 a_info.play.sample_rate = sample_rate;
871 a_info.blocksize = fragment_size;
873 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
875 /* try to disable stereo */
876 a_info.play.channels = 1;
879 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
880 Error(ERR_EXIT_SOUND_SERVER,
881 "cannot set sample rate of /dev/audio -- no sounds");
886 #endif /* PLATFORM_NETBSD */
888 #if defined(PLATFORM_HPUX)
889 static boolean InitAudioDevice_HPUX()
891 struct audio_describe ainfo;
894 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
896 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
898 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
899 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
901 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
902 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
904 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
905 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
909 return TRUE; /* to provide common interface for InitAudioDevice_...() */
911 #endif /* PLATFORM_HPUX */
913 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
915 /* these two are stolen from "sox"... :) */
918 ** This routine converts from linear to ulaw.
920 ** Craig Reese: IDA/Supercomputing Research Center
921 ** Joe Campbell: Department of Defense
925 ** 1) CCITT Recommendation G.711 (very difficult to follow)
926 ** 2) "A New Digital Technique for Implementation of Any
927 ** Continuous PCM Companding Law," Villeret, Michel,
928 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
929 ** 1973, pg. 11.12-11.17
930 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
931 ** for Analog-to_Digital Conversion Techniques,"
934 ** Input: Signed 16 bit linear sample
935 ** Output: 8 bit ulaw sample
938 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
939 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
942 static unsigned char linear_to_ulaw(int sample)
944 static int exp_lut[256] =
946 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
947 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
948 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
949 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
950 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
951 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
952 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
953 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
954 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
955 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
956 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
957 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
958 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
959 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
960 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
961 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
964 int sign, exponent, mantissa;
965 unsigned char ulawbyte;
967 /* Get the sample into sign-magnitude. */
968 sign = (sample >> 8) & 0x80; /* set aside the sign */
970 sample = -sample; /* get magnitude */
972 sample = CLIP; /* clip the magnitude */
974 /* Convert from 16 bit linear to ulaw. */
975 sample = sample + BIAS;
976 exponent = exp_lut[( sample >> 7 ) & 0xFF];
977 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
978 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
981 ulawbyte = 0x02; /* optional CCITT trap */
988 ** This routine converts from ulaw to 16 bit linear.
990 ** Craig Reese: IDA/Supercomputing Research Center
994 ** 1) CCITT Recommendation G.711 (very difficult to follow)
995 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
996 ** for Analog-to_Digital Conversion Techniques,"
999 ** Input: 8 bit ulaw sample
1000 ** Output: signed 16 bit linear sample
1003 static int ulaw_to_linear(unsigned char ulawbyte)
1005 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1006 int sign, exponent, mantissa, sample;
1008 ulawbyte = ~ ulawbyte;
1009 sign = ( ulawbyte & 0x80 );
1010 exponent = ( ulawbyte >> 4 ) & 0x07;
1011 mantissa = ulawbyte & 0x0F;
1012 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1018 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1021 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1022 /* ========================================================================= */
1023 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1025 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1026 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1028 static SoundInfo *Load_WAV(char *filename)
1030 SoundInfo *snd_info;
1031 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1032 byte sound_header_buffer[WAV_HEADER_SIZE];
1033 char chunk_name[CHUNK_ID_LEN + 1];
1039 if (!audio.sound_available)
1042 snd_info = checked_calloc(sizeof(SoundInfo));
1044 #if defined(TARGET_SDL)
1046 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1048 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1053 #elif defined(TARGET_ALLEGRO)
1055 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1057 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1062 #else /* PLATFORM_UNIX */
1064 if ((file = fopen(filename, MODE_READ)) == NULL)
1066 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1071 /* read chunk id "RIFF" */
1072 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1073 if (strcmp(chunk_name, "RIFF") != 0)
1075 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1081 /* read "RIFF" type id "WAVE" */
1082 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1083 if (strcmp(chunk_name, "WAVE") != 0)
1085 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1091 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1093 if (strcmp(chunk_name, "fmt ") == 0)
1095 /* read header information */
1096 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1097 sound_header_buffer[i] = fgetc(file);
1099 if (chunk_size > WAV_HEADER_SIZE)
1100 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1102 else if (strcmp(chunk_name, "data") == 0)
1104 snd_info->data_len = chunk_size;
1105 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1107 /* read sound data */
1108 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1111 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1113 free(snd_info->data_ptr);
1118 /* check for odd number of sample bytes (data chunk is word aligned) */
1119 if ((chunk_size % 2) == 1)
1120 ReadUnusedBytesFromFile(file, 1);
1122 else /* unknown chunk -- ignore */
1123 ReadUnusedBytesFromFile(file, chunk_size);
1128 if (snd_info->data_ptr == NULL)
1130 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1135 for (i=0; i<snd_info->data_len; i++)
1136 ((byte *)snd_info->data_ptr)[i] = ((byte *)snd_info->data_ptr)[i] ^ 0x80;
1138 #endif /* PLATFORM_UNIX */
1140 snd_info->type = SND_TYPE_WAV;
1141 snd_info->source_filename = getStringCopy(filename);
1146 SoundInfo *LoadCustomSound(char *basename)
1148 char *filename = getCustomSoundFilename(basename);
1150 if (filename == NULL)
1152 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1156 printf("-> '%s'\n", filename);
1158 return Load_WAV(filename);
1161 void InitSoundList(int num_list_entries)
1163 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1164 num_sounds = num_list_entries;
1167 void LoadSoundToList(char *basename, int list_pos)
1169 if (Sound == NULL || list_pos >= num_sounds)
1172 if (Sound[list_pos])
1173 FreeSound(Sound[list_pos]);
1175 Sound[list_pos] = LoadCustomSound(basename);
1178 static MusicInfo *Load_MOD(char *filename)
1180 #if defined(TARGET_SDL)
1181 MusicInfo *mod_info;
1183 if (!audio.sound_available)
1186 mod_info = checked_calloc(sizeof(MusicInfo));
1188 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1190 Error(ERR_WARN, "cannot read music file '%s'", filename);
1195 mod_info->type = MUS_TYPE_MOD;
1196 mod_info->source_filename = getStringCopy(filename);
1204 void LoadCustomMusic(void)
1206 char *music_directory = getCustomMusicDirectory();
1208 struct dirent *dir_entry;
1210 if (!audio.sound_available)
1213 if ((dir = opendir(music_directory)) == NULL)
1215 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1216 audio.music_available = FALSE;
1220 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1222 char *basename = dir_entry->d_name;
1223 char *filename = getPath2(music_directory, basename);
1224 MusicInfo *mus_info = NULL;
1226 if (FileIsSound(filename))
1227 mus_info = Load_WAV(filename);
1228 else if (FileIsMusic(filename))
1229 mus_info = Load_MOD(filename);
1236 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1237 Music[num_music -1] = mus_info;
1244 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1248 void PlayMusic(int nr)
1250 if (!audio.music_available)
1253 #if defined(TARGET_SDL)
1255 if (Music[nr]->type == MUS_TYPE_MOD)
1257 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1258 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1260 else /* play WAV music loop */
1262 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1263 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1273 void PlaySound(int nr)
1275 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1278 void PlaySoundStereo(int nr, int stereo)
1280 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1283 void PlaySoundLoop(int nr)
1285 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1288 void PlaySoundMusic(int nr)
1290 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1293 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1295 struct SoundControl snd_ctrl = emptySoundControl;
1297 if (!audio.sound_available ||
1298 !audio.sound_enabled ||
1299 audio.sound_deactivated)
1302 if (volume < PSND_MIN_VOLUME)
1303 volume = PSND_MIN_VOLUME;
1304 else if (volume > PSND_MAX_VOLUME)
1305 volume = PSND_MAX_VOLUME;
1307 if (stereo < PSND_MAX_LEFT)
1308 stereo = PSND_MAX_LEFT;
1309 else if (stereo > PSND_MAX_RIGHT)
1310 stereo = PSND_MAX_RIGHT;
1313 snd_ctrl.volume = volume;
1314 snd_ctrl.stereo = stereo;
1315 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1316 snd_ctrl.music = (loop_type == PSND_MUSIC);
1317 snd_ctrl.active = TRUE;
1320 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1321 snd_ctrl.data_len = Sound[nr].data_len;
1324 #if defined(TARGET_SDL)
1325 Mix_Volume(-1, SOUND_MAX_VOLUME);
1326 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1327 #elif defined(PLATFORM_UNIX)
1328 if (audio.soundserver_pid == 0) /* we are child process */
1331 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1333 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1334 audio.sound_available = audio.sound_enabled = FALSE;
1337 #elif defined(PLATFORM_MSDOS)
1338 sound_handler(snd_ctrl);
1342 void FadeMusic(void)
1344 if (!audio.sound_available)
1347 #if defined(TARGET_SDL)
1348 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1349 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1351 StopSoundExt(-1, SSND_FADE_MUSIC);
1355 void FadeSound(int nr)
1357 StopSoundExt(nr, SSND_FADE_SOUND);
1363 StopSoundExt(-1, SSND_FADE_ALL);
1366 void StopMusic(void)
1368 #if defined(TARGET_SDL)
1369 if (!audio.sound_available)
1373 Mix_HaltChannel(audio.music_channel);
1375 StopSoundExt(-1, SSND_STOP_MUSIC);
1379 void StopSound(int nr)
1381 StopSoundExt(nr, SSND_STOP_SOUND);
1386 StopSoundExt(-1, SSND_STOP_ALL);
1389 void StopSoundExt(int nr, int method)
1391 struct SoundControl snd_ctrl = emptySoundControl;
1393 if (!audio.sound_available)
1396 if (method & SSND_FADING)
1397 snd_ctrl.fade_sound = TRUE;
1399 if (method & SSND_ALL)
1400 snd_ctrl.stop_all_sounds = TRUE;
1403 snd_ctrl.stop_sound = TRUE;
1407 if (method & SSND_MUSIC)
1408 snd_ctrl.music = TRUE;
1410 #if defined(TARGET_SDL)
1412 if (method & SSND_FADING)
1416 for (i=0; i<audio.channels; i++)
1417 if (i != audio.music_channel || snd_ctrl.music)
1418 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1420 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1426 for (i=0; i<audio.channels; i++)
1427 if (i != audio.music_channel || snd_ctrl.music)
1433 #elif !defined(PLATFORM_MSDOS)
1435 if (audio.soundserver_pid == 0) /* we are child process */
1438 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1440 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1441 audio.sound_available = audio.sound_enabled = FALSE;
1445 sound_handler(snd_ctrl);
1449 static void InitReloadSoundsOrMusic(char *set_name, int type)
1451 struct SoundControl snd_ctrl = emptySoundControl;
1453 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1454 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1455 unsigned long str_size2 = strlen(ti->basepath) + 1;
1456 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1458 if (!audio.sound_available)
1461 if (leveldir_current == NULL)
1462 Error(ERR_EXIT, "leveldir_current == NULL");
1464 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1465 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1466 snd_ctrl.data_len = strlen(set_name) + 1;
1468 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1469 if (type == SND_RELOAD_SOUNDS)
1470 audio.audio.func_reload_sounds();
1472 audio.audio.func_reload_music();
1473 #elif defined(PLATFORM_UNIX)
1474 if (audio.soundserver_pid == 0) /* we are child process */
1477 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1478 sizeof(snd_ctrl)) < 0 ||
1479 write(audio.soundserver_pipe[1], set_name,
1480 snd_ctrl.data_len) < 0 ||
1481 write(audio.soundserver_pipe[1], leveldir_current,
1482 sizeof(TreeInfo)) < 0 ||
1483 write(audio.soundserver_pipe[1], ti,
1484 sizeof(TreeInfo)) < 0 ||
1485 write(audio.soundserver_pipe[1], &str_size1,
1486 sizeof(unsigned long)) < 0 ||
1487 write(audio.soundserver_pipe[1], &str_size2,
1488 sizeof(unsigned long)) < 0 ||
1489 write(audio.soundserver_pipe[1], &str_size3,
1490 sizeof(unsigned long)) < 0 ||
1491 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1493 write(audio.soundserver_pipe[1], ti->basepath,
1495 write(audio.soundserver_pipe[1], ti->fullpath,
1498 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1499 audio.sound_available = audio.sound_enabled = FALSE;
1508 void InitReloadSounds(char *set_name)
1510 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1513 void InitReloadMusic(char *set_name)
1515 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1518 void FreeSound(SoundInfo *sound)
1523 if (sound->data_ptr)
1525 #if defined(TARGET_SDL)
1526 Mix_FreeChunk(sound->data_ptr);
1527 #elif defined(TARGET_ALLEGRO)
1528 destroy_sample(sound->data_ptr);
1529 #else /* PLATFORM_UNIX */
1530 free(sound->data_ptr);
1537 void FreeMusic(MusicInfo *music)
1542 if (music->data_ptr)
1544 #if defined(TARGET_SDL)
1545 if (music->type == MUS_TYPE_MOD)
1546 Mix_FreeMusic(music->data_ptr);
1548 Mix_FreeChunk(music->data_ptr);
1549 #elif defined(TARGET_ALLEGRO)
1550 destroy_sample(music->data_ptr);
1551 #else /* PLATFORM_UNIX */
1552 free(music->data_ptr);
1559 void FreeAllSounds()
1566 for(i=0; i<num_sounds; i++)
1567 FreeSound(Sound[i]);
1580 for(i=0; i<num_music; i++)
1581 FreeMusic(Music[i]);
1587 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1588 /* ========================================================================= */