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;
404 /* expand sample from 8 to 16 bit */
405 for(j=0; j<sample_size; j++)
406 premix_second_buffer[j] = premix_first_buffer[j] << 8;
408 /* decrease volume if sound is fading out */
409 if (playlist[i].fade_sound &&
410 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
411 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
413 /* adjust volume of actual sound sample */
414 if (playlist[i].volume != PSND_MAX_VOLUME)
415 for(j=0; j<sample_size; j++)
416 premix_second_buffer[j] =
417 (playlist[i].volume * (int)premix_second_buffer[j])
418 >> PSND_MAX_VOLUME_BITS;
420 /* fill the last mixing buffer with stereo or mono sound */
423 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
424 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
425 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
427 for(j=0; j<sample_size; j++)
429 premix_left_buffer[j] =
430 (left_volume * premix_second_buffer[j])
431 >> PSND_MAX_LEFT2RIGHT_BITS;
432 premix_right_buffer[j] =
433 (right_volume * premix_second_buffer[j])
434 >> PSND_MAX_LEFT2RIGHT_BITS;
436 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
437 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
442 for(j=0; j<sample_size; j++)
443 premix_last_buffer[j] += premix_second_buffer[j];
446 /* delete completed sound entries from the playlist */
447 if (playlist[i].playingpos >= playlist[i].data_len)
449 if (playlist[i].loop)
450 playlist[i].playingpos = 0;
453 playlist[i] = emptySoundControl;
457 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
459 playlist[i] = emptySoundControl;
464 /* put last mixing buffer to final playing buffer */
465 for(i=0; i<fragment_size; i++)
467 if (premix_last_buffer[i] < -65535)
468 playing_buffer[i] = -32767;
469 else if (premix_last_buffer[i] > 65535)
470 playing_buffer[i] = 32767;
472 playing_buffer[i] = (short)(premix_last_buffer[i] >> 1);
475 /* finally play the sound fragment */
476 write(audio.device_fd, playing_buffer, fragment_size);
479 /* if no sounds playing, free device for other sound programs */
481 close(audio.device_fd);
485 #else /* !AUDIO_STREAMING_DSP */
487 if (snd_ctrl.active && !snd_ctrl.loop)
489 struct timeval delay = { 0, 0 };
491 long sample_size, max_sample_size = SND_BLOCKSIZE;
492 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
493 int wait_percent = 90; /* wait 90% of the real playing time */
496 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
500 while (playing_sounds &&
501 select(audio.soundserver_pipe[0] + 1,
502 &sound_fdset, NULL, NULL, &delay) < 1)
504 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
506 /* get pointer and size of the actual sound sample */
507 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
509 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
510 snd_ctrl.playingpos += sample_size;
512 /* fill the first mixing buffer with original sample */
513 memcpy(premix_first_buffer,sample_ptr,sample_size);
515 /* adjust volume of actual sound sample */
516 if (snd_ctrl.volume != PSND_MAX_VOLUME)
517 for(i=0;i<sample_size;i++)
518 premix_first_buffer[i] =
519 (snd_ctrl.volume * (int)premix_first_buffer[i])
520 >> PSND_MAX_VOLUME_BITS;
522 for(i=0;i<sample_size;i++)
524 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
526 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
529 /* finally play the sound fragment */
530 write(audio.device_fd,playing_buffer,sample_size);
533 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
535 close(audio.device_fd);
538 #endif /* !AUDIO_STREAMING_DSP */
541 #endif /* PLATFORM_UNIX */
543 #if defined(PLATFORM_MSDOS)
544 static void sound_handler(struct SoundControl snd_ctrl)
548 if (snd_ctrl.fade_sound)
553 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
554 if ((snd_ctrl.stop_all_sounds ||
555 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
556 (i == audio.music_channel && snd_ctrl.music)) &&
557 !playlist[i].fade_sound)
559 playlist[i].fade_sound = TRUE;
560 if (voice_check(playlist[i].voice))
561 voice_ramp_volume(playlist[i].voice, 1000, 0);
562 playlist[i].loop = PSND_NO_LOOP;
565 else if (snd_ctrl.stop_all_sounds)
569 SoundServer_StopAllSounds();
571 else if (snd_ctrl.stop_sound)
575 SoundServer_StopSound(snd_ctrl);
578 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
580 if (!playlist[i].active || playlist[i].loop)
583 playlist[i].playingpos = voice_get_position(playlist[i].voice);
584 playlist[i].volume = voice_get_volume(playlist[i].voice);
585 if (playlist[i].playingpos == -1 || !playlist[i].volume)
587 deallocate_voice(playlist[i].voice);
588 playlist[i] = emptySoundControl;
594 SoundServer_InsertNewSound(snd_ctrl);
596 #endif /* PLATFORM_MSDOS */
598 #if !defined(PLATFORM_WIN32)
599 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
604 snd_ctrl.nr = snd_ctrl.nr % num_music;
606 /* if playlist is full, remove oldest sound */
607 if (playing_sounds == MAX_SOUNDS_PLAYING)
609 int longest = 0, longest_nr = 0;
611 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
613 #if !defined(PLATFORM_MSDOS)
614 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
616 int actual = playlist[i].playingpos;
619 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
625 #if defined(PLATFORM_MSDOS)
626 voice_set_volume(playlist[longest_nr].voice, 0);
627 deallocate_voice(playlist[longest_nr].voice);
629 playlist[longest_nr] = emptySoundControl;
633 /* check if sound is already being played (and how often) */
634 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
635 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
638 /* restart loop sounds only if they are just fading out */
639 if (k >= 1 && snd_ctrl.loop)
641 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
643 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
644 playlist[i].fade_sound)
646 playlist[i].fade_sound = FALSE;
647 playlist[i].volume = PSND_MAX_VOLUME;
648 #if defined(PLATFORM_MSDOS)
649 playlist[i].loop = PSND_LOOP;
650 voice_stop_volumeramp(playlist[i].voice);
651 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
659 /* don't play sound more than n times simultaneously (with n == 2 for now) */
662 int longest = 0, longest_nr = 0;
664 /* look for oldest equal sound */
665 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
669 if (!playlist[i].active ||
670 i == audio.music_channel ||
671 playlist[i].nr != snd_ctrl.nr)
674 #if !defined(PLATFORM_MSDOS)
675 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
677 actual = playlist[i].playingpos;
679 if (actual >= longest)
686 #if defined(PLATFORM_MSDOS)
687 voice_set_volume(playlist[longest_nr].voice, 0);
688 deallocate_voice(playlist[longest_nr].voice);
690 playlist[longest_nr] = emptySoundControl;
694 /* add new sound to playlist */
695 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
697 if (!playlist[i].active ||
698 (snd_ctrl.music && i == audio.music_channel))
700 SoundInfo *snd_info =
701 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
703 snd_ctrl.data_ptr = snd_info->data_ptr;
704 snd_ctrl.data_len = snd_info->data_len;
706 playlist[i] = snd_ctrl;
709 #if defined(PLATFORM_MSDOS)
710 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
713 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
715 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
716 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
717 voice_start(playlist[i].voice);
723 #endif /* !PLATFORM_WIN32 */
726 void SoundServer_FadeSound(int nr)
733 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
734 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
735 playlist[i].fade_sound = TRUE;
739 #if !defined(PLATFORM_WIN32)
740 #if defined(PLATFORM_MSDOS)
741 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
743 int nr = snd_ctrl.nr;
749 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
751 if ((i == audio.music_channel && snd_ctrl.music) ||
752 (i != audio.music_channel && playlist[i].nr == nr))
754 #if defined(PLATFORM_MSDOS)
755 voice_set_volume(playlist[i].voice, 0);
756 deallocate_voice(playlist[i].voice);
758 playlist[i] = emptySoundControl;
763 #if !defined(PLATFORM_MSDOS)
765 close(audio.device_fd);
769 static void SoundServer_StopAllSounds()
773 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
775 #if defined(PLATFORM_MSDOS)
776 voice_set_volume(playlist[i].voice, 0);
777 deallocate_voice(playlist[i].voice);
779 playlist[i]=emptySoundControl;
783 #if !defined(PLATFORM_MSDOS)
784 close(audio.device_fd);
787 #endif /* PLATFORM_MSDOS */
788 #endif /* !PLATFORM_WIN32 */
791 /* ------------------------------------------------------------------------- */
792 /* platform dependant audio initialization code */
793 /* ------------------------------------------------------------------------- */
795 #if defined(AUDIO_LINUX_IOCTL)
796 static boolean InitAudioDevice_Linux(int fragment_size, int sample_rate)
798 /* "ioctl()" expects pointer to 'int' value for stereo flag
799 (boolean is defined as 'char', which will not work here) */
800 unsigned int fragment_spec = 0;
801 unsigned int audio_format = 0;
802 int fragment_size_query;
805 /* determine logarithm (log2) of the fragment size */
806 for (fragment_spec=0; (1 << fragment_spec) < fragment_size; fragment_spec++);
808 /* use two fragments (play one fragment, prepare the other);
809 one fragment would result in interrupted audio output, more
810 than two fragments would raise audio output latency to much */
811 fragment_spec |= 0x00020000;
813 /* Example for fragment specification:
814 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
815 - (with stereo the effective buffer size will shrink to 256)
816 => fragment_size = 0x00020009 */
818 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
819 Error(ERR_EXIT_SOUND_SERVER,
820 "cannot set fragment size of /dev/dsp -- no sounds");
822 audio_format = AFMT_S16_LE;
823 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) < 0)
824 Error(ERR_EXIT_SOUND_SERVER,
825 "cannot set audio format of /dev/dsp -- no sounds");
827 /* try if we can use stereo sound */
828 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
831 static boolean reported = FALSE;
835 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
842 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
843 Error(ERR_EXIT_SOUND_SERVER,
844 "cannot set sample rate of /dev/dsp -- no sounds");
846 /* get the real fragmentation size; this should return 512 */
847 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
848 Error(ERR_EXIT_SOUND_SERVER,
849 "cannot get fragment size of /dev/dsp -- no sounds");
850 if (fragment_size_query != fragment_size)
851 Error(ERR_EXIT_SOUND_SERVER,
852 "cannot set fragment size of /dev/dsp -- no sounds");
854 return (boolean)stereo;
856 #endif /* AUDIO_LINUX_IOCTL */
858 #if defined(PLATFORM_NETBSD)
859 static boolean InitAudioDevice_NetBSD(int fragment_size, int sample_rate)
862 boolean stereo = TRUE;
864 AUDIO_INITINFO(&a_info);
865 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
866 a_info.play.precision = 8;
867 a_info.play.channels = 2;
868 a_info.play.sample_rate = sample_rate;
869 a_info.blocksize = fragment_size;
871 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
873 /* try to disable stereo */
874 a_info.play.channels = 1;
877 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
878 Error(ERR_EXIT_SOUND_SERVER,
879 "cannot set sample rate of /dev/audio -- no sounds");
884 #endif /* PLATFORM_NETBSD */
886 #if defined(PLATFORM_HPUX)
887 static boolean InitAudioDevice_HPUX()
889 struct audio_describe ainfo;
892 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
894 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
896 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
897 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
899 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
900 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
902 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
903 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
907 return TRUE; /* to provide common interface for InitAudioDevice_...() */
909 #endif /* PLATFORM_HPUX */
911 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
913 /* these two are stolen from "sox"... :) */
916 ** This routine converts from linear to ulaw.
918 ** Craig Reese: IDA/Supercomputing Research Center
919 ** Joe Campbell: Department of Defense
923 ** 1) CCITT Recommendation G.711 (very difficult to follow)
924 ** 2) "A New Digital Technique for Implementation of Any
925 ** Continuous PCM Companding Law," Villeret, Michel,
926 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
927 ** 1973, pg. 11.12-11.17
928 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
929 ** for Analog-to_Digital Conversion Techniques,"
932 ** Input: Signed 16 bit linear sample
933 ** Output: 8 bit ulaw sample
936 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
937 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
940 static unsigned char linear_to_ulaw(int sample)
942 static int exp_lut[256] =
944 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
945 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
946 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
947 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
948 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
949 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
953 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
962 int sign, exponent, mantissa;
963 unsigned char ulawbyte;
965 /* Get the sample into sign-magnitude. */
966 sign = (sample >> 8) & 0x80; /* set aside the sign */
968 sample = -sample; /* get magnitude */
970 sample = CLIP; /* clip the magnitude */
972 /* Convert from 16 bit linear to ulaw. */
973 sample = sample + BIAS;
974 exponent = exp_lut[( sample >> 7 ) & 0xFF];
975 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
976 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
979 ulawbyte = 0x02; /* optional CCITT trap */
986 ** This routine converts from ulaw to 16 bit linear.
988 ** Craig Reese: IDA/Supercomputing Research Center
992 ** 1) CCITT Recommendation G.711 (very difficult to follow)
993 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
994 ** for Analog-to_Digital Conversion Techniques,"
997 ** Input: 8 bit ulaw sample
998 ** Output: signed 16 bit linear sample
1001 static int ulaw_to_linear(unsigned char ulawbyte)
1003 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1004 int sign, exponent, mantissa, sample;
1006 ulawbyte = ~ ulawbyte;
1007 sign = ( ulawbyte & 0x80 );
1008 exponent = ( ulawbyte >> 4 ) & 0x07;
1009 mantissa = ulawbyte & 0x0F;
1010 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1016 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1019 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1020 /* ========================================================================= */
1021 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1023 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1024 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1026 static SoundInfo *Load_WAV(char *filename)
1028 SoundInfo *snd_info;
1029 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1030 byte sound_header_buffer[WAV_HEADER_SIZE];
1031 char chunk_name[CHUNK_ID_LEN + 1];
1037 if (!audio.sound_available)
1040 snd_info = checked_calloc(sizeof(SoundInfo));
1042 #if defined(TARGET_SDL)
1044 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1046 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1051 #elif defined(TARGET_ALLEGRO)
1053 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1055 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1060 #else /* PLATFORM_UNIX */
1062 if ((file = fopen(filename, MODE_READ)) == NULL)
1064 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1069 /* read chunk id "RIFF" */
1070 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1071 if (strcmp(chunk_name, "RIFF") != 0)
1073 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1079 /* read "RIFF" type id "WAVE" */
1080 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1081 if (strcmp(chunk_name, "WAVE") != 0)
1083 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1089 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1091 if (strcmp(chunk_name, "fmt ") == 0)
1093 /* read header information */
1094 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1095 sound_header_buffer[i] = fgetc(file);
1097 if (chunk_size > WAV_HEADER_SIZE)
1098 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1100 else if (strcmp(chunk_name, "data") == 0)
1102 snd_info->data_len = chunk_size;
1103 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1105 /* read sound data */
1106 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1109 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1111 free(snd_info->data_ptr);
1116 /* check for odd number of sample bytes (data chunk is word aligned) */
1117 if ((chunk_size % 2) == 1)
1118 ReadUnusedBytesFromFile(file, 1);
1120 else /* unknown chunk -- ignore */
1121 ReadUnusedBytesFromFile(file, chunk_size);
1126 if (snd_info->data_ptr == NULL)
1128 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1133 for (i=0; i<snd_info->data_len; i++)
1134 ((byte *)snd_info->data_ptr)[i] ^= 0x80;
1136 #endif /* PLATFORM_UNIX */
1138 snd_info->type = SND_TYPE_WAV;
1139 snd_info->source_filename = getStringCopy(filename);
1144 SoundInfo *LoadCustomSound(char *basename)
1146 char *filename = getCustomSoundFilename(basename);
1148 if (filename == NULL)
1150 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1154 return Load_WAV(filename);
1157 void InitSoundList(int num_list_entries)
1159 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1160 num_sounds = num_list_entries;
1163 void LoadSoundToList(char *basename, int list_pos)
1165 if (Sound == NULL || list_pos >= num_sounds)
1168 if (Sound[list_pos])
1169 FreeSound(Sound[list_pos]);
1171 Sound[list_pos] = LoadCustomSound(basename);
1174 static MusicInfo *Load_MOD(char *filename)
1176 #if defined(TARGET_SDL)
1177 MusicInfo *mod_info;
1179 if (!audio.sound_available)
1182 mod_info = checked_calloc(sizeof(MusicInfo));
1184 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1186 Error(ERR_WARN, "cannot read music file '%s'", filename);
1191 mod_info->type = MUS_TYPE_MOD;
1192 mod_info->source_filename = getStringCopy(filename);
1200 void LoadCustomMusic(void)
1202 char *music_directory = getCustomMusicDirectory();
1204 struct dirent *dir_entry;
1206 if (!audio.sound_available)
1209 if ((dir = opendir(music_directory)) == NULL)
1211 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1212 audio.music_available = FALSE;
1216 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1218 char *basename = dir_entry->d_name;
1219 char *filename = getPath2(music_directory, basename);
1220 MusicInfo *mus_info = NULL;
1222 if (FileIsSound(basename))
1223 mus_info = Load_WAV(filename);
1224 else if (FileIsMusic(basename))
1225 mus_info = Load_MOD(filename);
1232 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1233 Music[num_music -1] = mus_info;
1240 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1244 void PlayMusic(int nr)
1246 if (!audio.music_available)
1249 #if defined(TARGET_SDL)
1251 nr = nr % num_music;
1253 if (Music[nr]->type == MUS_TYPE_MOD)
1255 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1256 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1258 else /* play WAV music loop */
1260 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1261 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1271 void PlaySound(int nr)
1273 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1276 void PlaySoundStereo(int nr, int stereo)
1278 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1281 void PlaySoundLoop(int nr)
1283 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1286 void PlaySoundMusic(int nr)
1288 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1291 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1293 struct SoundControl snd_ctrl = emptySoundControl;
1295 if (!audio.sound_available ||
1296 !audio.sound_enabled ||
1297 audio.sound_deactivated)
1300 if (volume < PSND_MIN_VOLUME)
1301 volume = PSND_MIN_VOLUME;
1302 else if (volume > PSND_MAX_VOLUME)
1303 volume = PSND_MAX_VOLUME;
1305 if (stereo < PSND_MAX_LEFT)
1306 stereo = PSND_MAX_LEFT;
1307 else if (stereo > PSND_MAX_RIGHT)
1308 stereo = PSND_MAX_RIGHT;
1311 snd_ctrl.volume = volume;
1312 snd_ctrl.stereo = stereo;
1313 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1314 snd_ctrl.music = (loop_type == PSND_MUSIC);
1315 snd_ctrl.active = TRUE;
1318 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1319 snd_ctrl.data_len = Sound[nr].data_len;
1322 #if defined(TARGET_SDL)
1323 Mix_Volume(-1, SOUND_MAX_VOLUME);
1324 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1325 #elif defined(PLATFORM_UNIX)
1326 if (audio.soundserver_pid == 0) /* we are child process */
1329 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1331 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1332 audio.sound_available = audio.sound_enabled = FALSE;
1335 #elif defined(PLATFORM_MSDOS)
1336 sound_handler(snd_ctrl);
1340 void FadeMusic(void)
1342 if (!audio.sound_available)
1345 #if defined(TARGET_SDL)
1346 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1347 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1349 StopSoundExt(-1, SSND_FADE_MUSIC);
1353 void FadeSound(int nr)
1355 StopSoundExt(nr, SSND_FADE_SOUND);
1361 StopSoundExt(-1, SSND_FADE_ALL);
1364 void StopMusic(void)
1366 #if defined(TARGET_SDL)
1367 if (!audio.sound_available)
1371 Mix_HaltChannel(audio.music_channel);
1373 StopSoundExt(-1, SSND_STOP_MUSIC);
1377 void StopSound(int nr)
1379 StopSoundExt(nr, SSND_STOP_SOUND);
1384 StopSoundExt(-1, SSND_STOP_ALL);
1387 void StopSoundExt(int nr, int method)
1389 struct SoundControl snd_ctrl = emptySoundControl;
1391 if (!audio.sound_available)
1394 if (method & SSND_FADING)
1395 snd_ctrl.fade_sound = TRUE;
1397 if (method & SSND_ALL)
1398 snd_ctrl.stop_all_sounds = TRUE;
1401 snd_ctrl.stop_sound = TRUE;
1405 if (method & SSND_MUSIC)
1406 snd_ctrl.music = TRUE;
1408 #if defined(TARGET_SDL)
1410 if (method & SSND_FADING)
1414 for (i=0; i<audio.channels; i++)
1415 if (i != audio.music_channel || snd_ctrl.music)
1416 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1418 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1424 for (i=0; i<audio.channels; i++)
1425 if (i != audio.music_channel || snd_ctrl.music)
1431 #elif !defined(PLATFORM_MSDOS)
1433 if (audio.soundserver_pid == 0) /* we are child process */
1436 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1438 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1439 audio.sound_available = audio.sound_enabled = FALSE;
1443 sound_handler(snd_ctrl);
1447 static void InitReloadSoundsOrMusic(char *set_name, int type)
1449 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1450 struct SoundControl snd_ctrl = emptySoundControl;
1452 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1453 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1454 unsigned long str_size2 = strlen(ti->basepath) + 1;
1455 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1458 if (!audio.sound_available)
1461 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1462 if (type == SND_RELOAD_SOUNDS)
1463 audio.func_reload_sounds();
1465 audio.func_reload_music();
1466 #elif defined(PLATFORM_UNIX)
1467 if (audio.soundserver_pid == 0) /* we are child process */
1470 if (leveldir_current == NULL) /* should never happen */
1471 Error(ERR_EXIT, "leveldir_current == NULL");
1473 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1474 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1475 snd_ctrl.data_len = strlen(set_name) + 1;
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;
1505 void InitReloadSounds(char *set_name)
1507 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1510 void InitReloadMusic(char *set_name)
1512 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1515 void FreeSound(SoundInfo *sound)
1520 if (sound->data_ptr)
1522 #if defined(TARGET_SDL)
1523 Mix_FreeChunk(sound->data_ptr);
1524 #elif defined(TARGET_ALLEGRO)
1525 destroy_sample(sound->data_ptr);
1526 #else /* PLATFORM_UNIX */
1527 free(sound->data_ptr);
1534 void FreeMusic(MusicInfo *music)
1539 if (music->data_ptr)
1541 #if defined(TARGET_SDL)
1542 if (music->type == MUS_TYPE_MOD)
1543 Mix_FreeMusic(music->data_ptr);
1545 Mix_FreeChunk(music->data_ptr);
1546 #elif defined(TARGET_ALLEGRO)
1547 destroy_sample(music->data_ptr);
1548 #else /* PLATFORM_UNIX */
1549 free(music->data_ptr);
1556 void FreeAllSounds()
1563 for(i=0; i<num_sounds; i++)
1564 FreeSound(Sound[i]);
1579 for(i=0; i<num_music; i++)
1580 FreeMusic(Music[i]);
1588 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1589 /* ========================================================================= */