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 short premix_first_buffer[SND_BLOCKSIZE];
45 #if defined(AUDIO_STREAMING_DSP)
46 static short premix_left_buffer[SND_BLOCKSIZE];
47 static short premix_right_buffer[SND_BLOCKSIZE];
48 static long premix_last_buffer[SND_BLOCKSIZE];
50 static byte playing_buffer[SND_BLOCKSIZE];
53 /* forward declaration of internal functions */
54 #if defined(AUDIO_STREAMING_DSP)
55 static void SoundServer_InsertNewSound(struct SoundControl);
56 static boolean InitAudioDevice_DSP(int, int);
57 #elif defined(PLATFORM_HPUX)
58 static boolean InitAudioDevice_HPUX();
59 #elif defined(PLATFORM_UNIX)
60 static unsigned char linear_to_ulaw(int);
61 static int ulaw_to_linear(unsigned char);
62 #elif defined(PLATFORM_MSDOS)
63 static void SoundServer_InsertNewSound(struct SoundControl);
64 static void SoundServer_StopSound(struct SoundControl);
65 static void SoundServer_StopAllSounds();
68 #if defined(PLATFORM_UNIX)
69 static int OpenAudioDevice(char *audio_device_name)
73 /* check if desired audio device is accessible */
74 if (access(audio_device_name, W_OK) != 0)
77 /* try to open audio device in non-blocking mode */
78 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
81 /* re-open audio device in blocking mode */
83 audio_fd = open(audio_device_name, O_WRONLY);
88 static boolean TestAudioDevices(void)
90 static char *audio_device_name[] =
98 /* look for available audio devices, starting with preferred ones */
99 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
100 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
105 Error(ERR_WARN, "cannot open audio device -- no sound");
111 audio.device_name = audio_device_name[i];
116 #if !defined(TARGET_SDL)
117 static boolean ForkAudioProcess(void)
119 if (pipe(audio.soundserver_pipe) < 0)
121 Error(ERR_WARN, "cannot create pipe -- no sounds");
125 if ((audio.soundserver_pid = fork()) < 0)
127 Error(ERR_WARN, "cannot create sound server process -- no sounds");
131 if (audio.soundserver_pid == 0) /* we are child process */
138 else /* we are parent */
139 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
145 void UnixOpenAudio(void)
147 if (!TestAudioDevices())
150 audio.sound_available = TRUE;
151 audio.sound_enabled = TRUE;
153 #if defined(AUDIO_STREAMING_DSP)
154 audio.music_available = TRUE;
155 audio.loops_available = TRUE;
159 void UnixCloseAudio(void)
162 close(audio.device_fd);
164 if (audio.soundserver_pid > 0) /* we are parent process */
165 kill(audio.soundserver_pid, SIGTERM);
167 #endif /* PLATFORM_UNIX */
169 void InitPlaylist(void)
173 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
174 playlist[i] = emptySoundControl;
178 void StartSoundserver(void)
180 if (!audio.sound_available)
183 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
184 if (!ForkAudioProcess())
185 audio.sound_available = FALSE;
189 #if defined(PLATFORM_UNIX)
190 void SoundServer(void)
194 struct SoundControl snd_ctrl;
197 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
201 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
202 for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
204 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
206 #if defined(PLATFORM_HPUX)
207 InitAudioDevice_HPUX();
210 FD_ZERO(&sound_fdset);
211 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
213 while(1) /* wait for sound playing commands from client */
215 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
216 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
217 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
219 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
221 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
223 if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
225 char *set_name = checked_malloc(snd_ctrl.data_len);
227 (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
228 TreeInfo *ti = *ti_ptr;
229 unsigned long str_size1, str_size2, str_size3;
231 if (leveldir_current == NULL)
232 leveldir_current = checked_calloc(sizeof(TreeInfo));
234 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
235 if (leveldir_current->fullpath != NULL)
236 free(leveldir_current->fullpath);
237 if (ti->basepath != NULL)
239 if (ti->fullpath != NULL)
242 if (read(audio.soundserver_pipe[0], set_name,
243 snd_ctrl.data_len) != snd_ctrl.data_len ||
244 read(audio.soundserver_pipe[0], leveldir_current,
245 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
246 read(audio.soundserver_pipe[0], ti,
247 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
248 read(audio.soundserver_pipe[0], &str_size1,
249 sizeof(unsigned long)) != sizeof(unsigned long) ||
250 read(audio.soundserver_pipe[0], &str_size2,
251 sizeof(unsigned long)) != sizeof(unsigned long) ||
252 read(audio.soundserver_pipe[0], &str_size3,
253 sizeof(unsigned long)) != sizeof(unsigned long))
254 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
256 leveldir_current->fullpath = checked_calloc(str_size1);
257 ti->basepath = checked_calloc(str_size2);
258 ti->fullpath = checked_calloc(str_size3);
260 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
261 str_size1) != str_size1 ||
262 read(audio.soundserver_pipe[0], ti->basepath,
263 str_size2) != str_size2 ||
264 read(audio.soundserver_pipe[0], ti->fullpath,
265 str_size3) != str_size3)
266 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
270 close(audio.device_fd);
272 if (snd_ctrl.reload_sounds)
274 artwork.sounds_set_current = set_name;
275 audio.func_reload_sounds();
279 artwork.music_set_current = set_name;
280 audio.func_reload_music();
288 #if defined(AUDIO_STREAMING_DSP)
290 if (snd_ctrl.fade_sound)
296 playlist[audio.music_channel].fade_sound = TRUE;
298 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
299 if (snd_ctrl.stop_all_sounds ||
300 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
301 playlist[i].fade_sound = TRUE;
303 else if (snd_ctrl.stop_all_sounds)
308 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
309 playlist[i] = emptySoundControl;
312 close(audio.device_fd);
314 else if (snd_ctrl.stop_sound)
321 playlist[audio.music_channel] = emptySoundControl;
325 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
327 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
329 playlist[i] = emptySoundControl;
335 close(audio.device_fd);
338 if (playing_sounds || snd_ctrl.active)
340 if (playing_sounds ||
341 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
343 struct timeval delay = { 0, 0 };
344 static int fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
345 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
346 static boolean stereo = TRUE;
348 if (!playing_sounds) /* we just opened the audio device */
349 stereo = InitAudioDevice_DSP(fragment_size, sample_rate);
351 if (snd_ctrl.active) /* new sound has arrived */
352 SoundServer_InsertNewSound(snd_ctrl);
354 while (playing_sounds &&
355 select(audio.soundserver_pipe[0] + 1,
356 &sound_fdset, NULL, NULL, &delay) < 1)
362 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
364 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sizeof(short));
366 /* first clear the last premixing buffer */
367 memset(premix_last_buffer, 0,
368 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
370 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
374 if (!playlist[i].active)
377 /* get pointer and size of the actual sound sample */
378 sample_ptr = (short *)playlist[i].data_ptr +playlist[i].playingpos;
379 sample_size = MIN(max_sample_size,
380 playlist[i].data_len - playlist[i].playingpos);
381 playlist[i].playingpos += sample_size;
383 /* fill the first mixing buffer with original sample */
384 memcpy(premix_first_buffer, sample_ptr,
385 sample_size * sizeof(short));
387 /* are we about to restart a looping sound? */
388 if (playlist[i].loop && sample_size < max_sample_size)
390 playlist[i].playingpos = max_sample_size - sample_size;
391 memcpy(premix_first_buffer + sample_size * sizeof(short),
392 playlist[i].data_ptr,
393 (max_sample_size - sample_size) * sizeof(short));
394 sample_size = max_sample_size;
397 /* decrease volume if sound is fading out */
398 if (playlist[i].fade_sound &&
399 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
400 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
402 /* adjust volume of actual sound sample */
403 if (playlist[i].volume != PSND_MAX_VOLUME)
404 for(j=0; j<sample_size; j++)
405 premix_first_buffer[j] =
406 (playlist[i].volume * (long)premix_first_buffer[j])
407 >> PSND_MAX_VOLUME_BITS;
409 /* fill the last mixing buffer with stereo or mono sound */
412 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
413 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
414 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
416 for(j=0; j<sample_size; j++)
418 premix_left_buffer[j] =
419 (left_volume * premix_first_buffer[j])
420 >> PSND_MAX_LEFT2RIGHT_BITS;
421 premix_right_buffer[j] =
422 (right_volume * premix_first_buffer[j])
423 >> PSND_MAX_LEFT2RIGHT_BITS;
425 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
426 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
431 for(j=0; j<sample_size; j++)
432 premix_last_buffer[j] += premix_first_buffer[j];
435 /* delete completed sound entries from the playlist */
436 if (playlist[i].playingpos >= playlist[i].data_len)
438 if (playlist[i].loop)
439 playlist[i].playingpos = 0;
442 playlist[i] = emptySoundControl;
446 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
448 playlist[i] = emptySoundControl;
453 /* put last mixing buffer to final playing buffer */
454 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
456 /* cut off at 17 bit value */
457 if (premix_last_buffer[i] < -65535)
458 premix_last_buffer[i] = -65535;
459 else if (premix_last_buffer[i] > 65535)
460 premix_last_buffer[i] = 65535;
462 /* shift to 16 bit value */
463 premix_last_buffer[i] >>= 1;
465 /* fill playing buffer for "signed 16 bit little endian" audio
466 format (independently of endianess of "short" integer type) */
467 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
468 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
471 /* finally play the sound fragment */
472 write(audio.device_fd, playing_buffer, fragment_size);
475 /* if no sounds playing, free device for other sound programs */
477 close(audio.device_fd);
481 #else /* !AUDIO_STREAMING_DSP */
483 if (snd_ctrl.active && !snd_ctrl.loop)
485 struct timeval delay = { 0, 0 };
487 long sample_size, max_sample_size = SND_BLOCKSIZE;
488 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
489 int wait_percent = 90; /* wait 90% of the real playing time */
492 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
496 while (playing_sounds &&
497 select(audio.soundserver_pipe[0] + 1,
498 &sound_fdset, NULL, NULL, &delay) < 1)
500 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
502 /* get pointer and size of the actual sound sample */
503 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
505 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
506 snd_ctrl.playingpos += sample_size;
508 /* fill the first mixing buffer with original sample */
509 memcpy(premix_first_buffer,sample_ptr,sample_size);
511 /* adjust volume of actual sound sample */
512 if (snd_ctrl.volume != PSND_MAX_VOLUME)
513 for(i=0;i<sample_size;i++)
514 premix_first_buffer[i] =
515 (snd_ctrl.volume * (int)premix_first_buffer[i])
516 >> PSND_MAX_VOLUME_BITS;
518 for(i=0;i<sample_size;i++)
520 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
522 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
525 /* finally play the sound fragment */
526 write(audio.device_fd,playing_buffer,sample_size);
529 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
531 close(audio.device_fd);
534 #endif /* !AUDIO_STREAMING_DSP */
537 #endif /* PLATFORM_UNIX */
539 #if defined(PLATFORM_MSDOS)
540 static void sound_handler(struct SoundControl snd_ctrl)
544 if (snd_ctrl.fade_sound)
549 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
550 if ((snd_ctrl.stop_all_sounds ||
551 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
552 (i == audio.music_channel && snd_ctrl.music)) &&
553 !playlist[i].fade_sound)
555 playlist[i].fade_sound = TRUE;
556 if (voice_check(playlist[i].voice))
557 voice_ramp_volume(playlist[i].voice, 1000, 0);
558 playlist[i].loop = PSND_NO_LOOP;
561 else if (snd_ctrl.stop_all_sounds)
565 SoundServer_StopAllSounds();
567 else if (snd_ctrl.stop_sound)
571 SoundServer_StopSound(snd_ctrl);
574 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
576 if (!playlist[i].active || playlist[i].loop)
579 playlist[i].playingpos = voice_get_position(playlist[i].voice);
580 playlist[i].volume = voice_get_volume(playlist[i].voice);
581 if (playlist[i].playingpos == -1 || !playlist[i].volume)
583 deallocate_voice(playlist[i].voice);
584 playlist[i] = emptySoundControl;
590 SoundServer_InsertNewSound(snd_ctrl);
592 #endif /* PLATFORM_MSDOS */
594 #if !defined(PLATFORM_WIN32)
595 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
600 snd_ctrl.nr = snd_ctrl.nr % num_music;
602 /* if playlist is full, remove oldest sound */
603 if (playing_sounds == MAX_SOUNDS_PLAYING)
605 int longest = 0, longest_nr = 0;
607 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
609 #if !defined(PLATFORM_MSDOS)
610 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
612 int actual = playlist[i].playingpos;
615 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
621 #if defined(PLATFORM_MSDOS)
622 voice_set_volume(playlist[longest_nr].voice, 0);
623 deallocate_voice(playlist[longest_nr].voice);
625 playlist[longest_nr] = emptySoundControl;
629 /* check if sound is already being played (and how often) */
630 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
631 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
634 /* restart loop sounds only if they are just fading out */
635 if (k >= 1 && snd_ctrl.loop)
637 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
639 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
640 playlist[i].fade_sound)
642 playlist[i].fade_sound = FALSE;
643 playlist[i].volume = PSND_MAX_VOLUME;
644 #if defined(PLATFORM_MSDOS)
645 playlist[i].loop = PSND_LOOP;
646 voice_stop_volumeramp(playlist[i].voice);
647 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
655 /* don't play sound more than n times simultaneously (with n == 2 for now) */
658 int longest = 0, longest_nr = 0;
660 /* look for oldest equal sound */
661 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
665 if (!playlist[i].active ||
666 i == audio.music_channel ||
667 playlist[i].nr != snd_ctrl.nr)
670 #if !defined(PLATFORM_MSDOS)
671 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
673 actual = playlist[i].playingpos;
675 if (actual >= longest)
682 #if defined(PLATFORM_MSDOS)
683 voice_set_volume(playlist[longest_nr].voice, 0);
684 deallocate_voice(playlist[longest_nr].voice);
686 playlist[longest_nr] = emptySoundControl;
690 /* add new sound to playlist */
691 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
693 if (!playlist[i].active ||
694 (snd_ctrl.music && i == audio.music_channel))
696 SoundInfo *snd_info =
697 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
699 snd_ctrl.data_ptr = snd_info->data_ptr;
700 snd_ctrl.data_len = snd_info->data_len;
702 playlist[i] = snd_ctrl;
705 #if defined(PLATFORM_MSDOS)
706 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
709 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
711 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
712 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
713 voice_start(playlist[i].voice);
719 #endif /* !PLATFORM_WIN32 */
722 void SoundServer_FadeSound(int nr)
729 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
730 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
731 playlist[i].fade_sound = TRUE;
735 #if !defined(PLATFORM_WIN32)
736 #if defined(PLATFORM_MSDOS)
737 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
739 int nr = snd_ctrl.nr;
745 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
747 if ((i == audio.music_channel && snd_ctrl.music) ||
748 (i != audio.music_channel && playlist[i].nr == nr))
750 #if defined(PLATFORM_MSDOS)
751 voice_set_volume(playlist[i].voice, 0);
752 deallocate_voice(playlist[i].voice);
754 playlist[i] = emptySoundControl;
759 #if !defined(PLATFORM_MSDOS)
761 close(audio.device_fd);
765 static void SoundServer_StopAllSounds()
769 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
771 #if defined(PLATFORM_MSDOS)
772 voice_set_volume(playlist[i].voice, 0);
773 deallocate_voice(playlist[i].voice);
775 playlist[i]=emptySoundControl;
779 #if !defined(PLATFORM_MSDOS)
780 close(audio.device_fd);
783 #endif /* PLATFORM_MSDOS */
784 #endif /* !PLATFORM_WIN32 */
787 /* ------------------------------------------------------------------------- */
788 /* platform dependant audio initialization code */
789 /* ------------------------------------------------------------------------- */
791 #if defined(AUDIO_LINUX_IOCTL)
792 static boolean InitAudioDevice_Linux(int fragment_size, int sample_rate)
794 /* "ioctl()" expects pointer to 'int' value for stereo flag
795 (boolean is defined as 'char', which will not work here) */
796 unsigned int fragment_spec = 0;
797 unsigned int audio_format = 0;
798 int fragment_size_query;
801 /* determine logarithm (log2) of the fragment size */
802 for (fragment_spec=0; (1 << fragment_spec) < fragment_size; fragment_spec++);
804 /* use two fragments (play one fragment, prepare the other);
805 one fragment would result in interrupted audio output, more
806 than two fragments would raise audio output latency to much */
807 fragment_spec |= 0x00020000;
809 /* Example for fragment specification:
810 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
811 - (with stereo the effective buffer size will shrink to 256)
812 => fragment_size = 0x00020009 */
814 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
815 Error(ERR_EXIT_SOUND_SERVER,
816 "cannot set fragment size of /dev/dsp -- no sounds");
818 audio_format = AFMT_S16_LE;
819 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) < 0)
820 Error(ERR_EXIT_SOUND_SERVER,
821 "cannot set audio format of /dev/dsp -- no sounds");
823 /* try if we can use stereo sound */
824 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
827 static boolean reported = FALSE;
831 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
838 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
839 Error(ERR_EXIT_SOUND_SERVER,
840 "cannot set sample rate of /dev/dsp -- no sounds");
842 /* get the real fragmentation size; this should return 512 */
843 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
844 Error(ERR_EXIT_SOUND_SERVER,
845 "cannot get fragment size of /dev/dsp -- no sounds");
846 if (fragment_size_query != fragment_size)
847 Error(ERR_EXIT_SOUND_SERVER,
848 "cannot set fragment size of /dev/dsp -- no sounds");
850 return (boolean)stereo;
852 #endif /* AUDIO_LINUX_IOCTL */
854 #if defined(PLATFORM_NETBSD)
855 static boolean InitAudioDevice_NetBSD(int fragment_size, int sample_rate)
858 boolean stereo = TRUE;
860 AUDIO_INITINFO(&a_info);
861 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
862 a_info.play.precision = 8;
863 a_info.play.channels = 2;
864 a_info.play.sample_rate = sample_rate;
865 a_info.blocksize = fragment_size;
867 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
869 /* try to disable stereo */
870 a_info.play.channels = 1;
873 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
874 Error(ERR_EXIT_SOUND_SERVER,
875 "cannot set sample rate of /dev/audio -- no sounds");
880 #endif /* PLATFORM_NETBSD */
882 #if defined(PLATFORM_HPUX)
883 static boolean InitAudioDevice_HPUX()
885 struct audio_describe ainfo;
888 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
890 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
892 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
893 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
895 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
896 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
898 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
899 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
903 return TRUE; /* to provide common interface for InitAudioDevice_...() */
905 #endif /* PLATFORM_HPUX */
907 #if defined(PLATFORM_UNIX)
908 static boolean InitAudioDevice_DSP(int fragment_size, int sample_rate)
910 #if defined(AUDIO_LINUX_IOCTL)
911 return InitAudioDevice_Linux(fragment_size, sample_rate);
912 #elif defined(PLATFORM_NETBSD)
913 return InitAudioDevice_NetBSD(fragment_size, sample_rate);
914 #elif defined(PLATFORM_HPUX)
915 return InitAudioDevice_HPUX();
918 #endif /* PLATFORM_UNIX */
920 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
922 /* these two are stolen from "sox"... :) */
925 ** This routine converts from linear to ulaw.
927 ** Craig Reese: IDA/Supercomputing Research Center
928 ** Joe Campbell: Department of Defense
932 ** 1) CCITT Recommendation G.711 (very difficult to follow)
933 ** 2) "A New Digital Technique for Implementation of Any
934 ** Continuous PCM Companding Law," Villeret, Michel,
935 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
936 ** 1973, pg. 11.12-11.17
937 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
938 ** for Analog-to_Digital Conversion Techniques,"
941 ** Input: Signed 16 bit linear sample
942 ** Output: 8 bit ulaw sample
945 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
946 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
949 static unsigned char linear_to_ulaw(int sample)
951 static int exp_lut[256] =
953 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
954 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
955 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
956 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
957 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
958 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
959 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
960 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
961 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
962 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
963 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
964 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
965 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
966 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
967 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
968 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
971 int sign, exponent, mantissa;
972 unsigned char ulawbyte;
974 /* Get the sample into sign-magnitude. */
975 sign = (sample >> 8) & 0x80; /* set aside the sign */
977 sample = -sample; /* get magnitude */
979 sample = CLIP; /* clip the magnitude */
981 /* Convert from 16 bit linear to ulaw. */
982 sample = sample + BIAS;
983 exponent = exp_lut[( sample >> 7 ) & 0xFF];
984 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
985 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
988 ulawbyte = 0x02; /* optional CCITT trap */
995 ** This routine converts from ulaw to 16 bit linear.
997 ** Craig Reese: IDA/Supercomputing Research Center
1001 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1002 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1003 ** for Analog-to_Digital Conversion Techniques,"
1006 ** Input: 8 bit ulaw sample
1007 ** Output: signed 16 bit linear sample
1010 static int ulaw_to_linear(unsigned char ulawbyte)
1012 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1013 int sign, exponent, mantissa, sample;
1015 ulawbyte = ~ ulawbyte;
1016 sign = ( ulawbyte & 0x80 );
1017 exponent = ( ulawbyte >> 4 ) & 0x07;
1018 mantissa = ulawbyte & 0x0F;
1019 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1025 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1028 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1029 /* ========================================================================= */
1030 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1032 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1033 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1035 static SoundInfo *Load_WAV(char *filename)
1037 SoundInfo *snd_info;
1038 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1039 byte sound_header_buffer[WAV_HEADER_SIZE];
1040 char chunk_name[CHUNK_ID_LEN + 1];
1047 if (!audio.sound_available)
1050 snd_info = checked_calloc(sizeof(SoundInfo));
1052 #if defined(TARGET_SDL)
1054 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1056 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1061 #elif defined(TARGET_ALLEGRO)
1063 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1065 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1070 #else /* PLATFORM_UNIX */
1072 if ((file = fopen(filename, MODE_READ)) == NULL)
1074 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1079 /* read chunk id "RIFF" */
1080 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1081 if (strcmp(chunk_name, "RIFF") != 0)
1083 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1089 /* read "RIFF" type id "WAVE" */
1090 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1091 if (strcmp(chunk_name, "WAVE") != 0)
1093 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1099 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1101 if (strcmp(chunk_name, "fmt ") == 0)
1103 /* read header information */
1104 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1105 sound_header_buffer[i] = fgetc(file);
1107 if (chunk_size > WAV_HEADER_SIZE)
1108 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1110 else if (strcmp(chunk_name, "data") == 0)
1112 snd_info->data_len = chunk_size;
1113 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1115 /* read sound data */
1116 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1119 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1121 free(snd_info->data_ptr);
1126 /* check for odd number of sample bytes (data chunk is word aligned) */
1127 if ((chunk_size % 2) == 1)
1128 ReadUnusedBytesFromFile(file, 1);
1130 else /* unknown chunk -- ignore */
1131 ReadUnusedBytesFromFile(file, chunk_size);
1136 if (snd_info->data_ptr == NULL)
1138 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1143 /* convert unsigned 8 bit sample data to signed 16 bit sample data */
1145 data_ptr = checked_malloc(snd_info->data_len * sizeof(short));
1147 for (i=0; i<snd_info->data_len; i++)
1148 data_ptr[i] = ((short)(((byte *)snd_info->data_ptr)[i] ^ 0x80)) << 8;
1150 free(snd_info->data_ptr);
1151 snd_info->data_ptr = data_ptr;
1153 #endif /* PLATFORM_UNIX */
1155 snd_info->type = SND_TYPE_WAV;
1156 snd_info->source_filename = getStringCopy(filename);
1161 SoundInfo *LoadCustomSound(char *basename)
1163 char *filename = getCustomSoundFilename(basename);
1165 if (filename == NULL)
1167 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1171 return Load_WAV(filename);
1174 void InitSoundList(int num_list_entries)
1176 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1177 num_sounds = num_list_entries;
1180 void LoadSoundToList(char *basename, int list_pos)
1182 if (Sound == NULL || list_pos >= num_sounds)
1185 if (Sound[list_pos])
1186 FreeSound(Sound[list_pos]);
1188 Sound[list_pos] = LoadCustomSound(basename);
1191 static MusicInfo *Load_MOD(char *filename)
1193 #if defined(TARGET_SDL)
1194 MusicInfo *mod_info;
1196 if (!audio.sound_available)
1199 mod_info = checked_calloc(sizeof(MusicInfo));
1201 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1203 Error(ERR_WARN, "cannot read music file '%s'", filename);
1208 mod_info->type = MUS_TYPE_MOD;
1209 mod_info->source_filename = getStringCopy(filename);
1217 void LoadCustomMusic(void)
1219 char *music_directory = getCustomMusicDirectory();
1221 struct dirent *dir_entry;
1223 if (!audio.sound_available)
1226 if ((dir = opendir(music_directory)) == NULL)
1228 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1229 audio.music_available = FALSE;
1233 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1235 char *basename = dir_entry->d_name;
1236 char *filename = getPath2(music_directory, basename);
1237 MusicInfo *mus_info = NULL;
1239 if (FileIsSound(basename))
1240 mus_info = Load_WAV(filename);
1241 else if (FileIsMusic(basename))
1242 mus_info = Load_MOD(filename);
1249 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1250 Music[num_music -1] = mus_info;
1257 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1261 void PlayMusic(int nr)
1263 if (!audio.music_available)
1266 #if defined(TARGET_SDL)
1268 nr = nr % num_music;
1270 if (Music[nr]->type == MUS_TYPE_MOD)
1272 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1273 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1275 else /* play WAV music loop */
1277 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1278 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1288 void PlaySound(int nr)
1290 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1293 void PlaySoundStereo(int nr, int stereo)
1295 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1298 void PlaySoundLoop(int nr)
1300 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1303 void PlaySoundMusic(int nr)
1305 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1308 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1310 struct SoundControl snd_ctrl = emptySoundControl;
1312 if (!audio.sound_available ||
1313 !audio.sound_enabled ||
1314 audio.sound_deactivated)
1317 if (volume < PSND_MIN_VOLUME)
1318 volume = PSND_MIN_VOLUME;
1319 else if (volume > PSND_MAX_VOLUME)
1320 volume = PSND_MAX_VOLUME;
1322 if (stereo < PSND_MAX_LEFT)
1323 stereo = PSND_MAX_LEFT;
1324 else if (stereo > PSND_MAX_RIGHT)
1325 stereo = PSND_MAX_RIGHT;
1328 snd_ctrl.volume = volume;
1329 snd_ctrl.stereo = stereo;
1330 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1331 snd_ctrl.music = (loop_type == PSND_MUSIC);
1332 snd_ctrl.active = TRUE;
1335 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1336 snd_ctrl.data_len = Sound[nr].data_len;
1339 #if defined(TARGET_SDL)
1340 Mix_Volume(-1, SOUND_MAX_VOLUME);
1341 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1342 #elif defined(PLATFORM_UNIX)
1343 if (audio.soundserver_pid == 0) /* we are child process */
1346 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1348 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1349 audio.sound_available = audio.sound_enabled = FALSE;
1352 #elif defined(PLATFORM_MSDOS)
1353 sound_handler(snd_ctrl);
1357 void FadeMusic(void)
1359 if (!audio.sound_available)
1362 #if defined(TARGET_SDL)
1363 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1364 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1366 StopSoundExt(-1, SSND_FADE_MUSIC);
1370 void FadeSound(int nr)
1372 StopSoundExt(nr, SSND_FADE_SOUND);
1378 StopSoundExt(-1, SSND_FADE_ALL);
1381 void StopMusic(void)
1383 #if defined(TARGET_SDL)
1384 if (!audio.sound_available)
1388 Mix_HaltChannel(audio.music_channel);
1390 StopSoundExt(-1, SSND_STOP_MUSIC);
1394 void StopSound(int nr)
1396 StopSoundExt(nr, SSND_STOP_SOUND);
1401 StopSoundExt(-1, SSND_STOP_ALL);
1404 void StopSoundExt(int nr, int method)
1406 struct SoundControl snd_ctrl = emptySoundControl;
1408 if (!audio.sound_available)
1411 if (method & SSND_FADING)
1412 snd_ctrl.fade_sound = TRUE;
1414 if (method & SSND_ALL)
1415 snd_ctrl.stop_all_sounds = TRUE;
1418 snd_ctrl.stop_sound = TRUE;
1422 if (method & SSND_MUSIC)
1423 snd_ctrl.music = TRUE;
1425 #if defined(TARGET_SDL)
1427 if (method & SSND_FADING)
1431 for (i=0; i<audio.channels; i++)
1432 if (i != audio.music_channel || snd_ctrl.music)
1433 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1435 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1441 for (i=0; i<audio.channels; i++)
1442 if (i != audio.music_channel || snd_ctrl.music)
1448 #elif !defined(PLATFORM_MSDOS)
1450 if (audio.soundserver_pid == 0) /* we are child process */
1453 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1455 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1456 audio.sound_available = audio.sound_enabled = FALSE;
1460 sound_handler(snd_ctrl);
1464 static void InitReloadSoundsOrMusic(char *set_name, int type)
1466 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1467 struct SoundControl snd_ctrl = emptySoundControl;
1469 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1470 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1471 unsigned long str_size2 = strlen(ti->basepath) + 1;
1472 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1475 if (!audio.sound_available)
1478 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1479 if (type == SND_RELOAD_SOUNDS)
1480 audio.func_reload_sounds();
1482 audio.func_reload_music();
1483 #elif defined(PLATFORM_UNIX)
1484 if (audio.soundserver_pid == 0) /* we are child process */
1487 if (leveldir_current == NULL) /* should never happen */
1488 Error(ERR_EXIT, "leveldir_current == NULL");
1490 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1491 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1492 snd_ctrl.data_len = strlen(set_name) + 1;
1494 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1495 sizeof(snd_ctrl)) < 0 ||
1496 write(audio.soundserver_pipe[1], set_name,
1497 snd_ctrl.data_len) < 0 ||
1498 write(audio.soundserver_pipe[1], leveldir_current,
1499 sizeof(TreeInfo)) < 0 ||
1500 write(audio.soundserver_pipe[1], ti,
1501 sizeof(TreeInfo)) < 0 ||
1502 write(audio.soundserver_pipe[1], &str_size1,
1503 sizeof(unsigned long)) < 0 ||
1504 write(audio.soundserver_pipe[1], &str_size2,
1505 sizeof(unsigned long)) < 0 ||
1506 write(audio.soundserver_pipe[1], &str_size3,
1507 sizeof(unsigned long)) < 0 ||
1508 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1510 write(audio.soundserver_pipe[1], ti->basepath,
1512 write(audio.soundserver_pipe[1], ti->fullpath,
1515 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1516 audio.sound_available = audio.sound_enabled = FALSE;
1522 void InitReloadSounds(char *set_name)
1524 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1527 void InitReloadMusic(char *set_name)
1529 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1532 void FreeSound(SoundInfo *sound)
1537 if (sound->data_ptr)
1539 #if defined(TARGET_SDL)
1540 Mix_FreeChunk(sound->data_ptr);
1541 #elif defined(TARGET_ALLEGRO)
1542 destroy_sample(sound->data_ptr);
1543 #else /* PLATFORM_UNIX */
1544 free(sound->data_ptr);
1551 void FreeMusic(MusicInfo *music)
1556 if (music->data_ptr)
1558 #if defined(TARGET_SDL)
1559 if (music->type == MUS_TYPE_MOD)
1560 Mix_FreeMusic(music->data_ptr);
1562 Mix_FreeChunk(music->data_ptr);
1563 #elif defined(TARGET_ALLEGRO)
1564 destroy_sample(music->data_ptr);
1565 #else /* PLATFORM_UNIX */
1566 free(music->data_ptr);
1573 void FreeAllSounds()
1580 for(i=0; i<num_sounds; i++)
1581 FreeSound(Sound[i]);
1596 for(i=0; i<num_music; i++)
1597 FreeMusic(Music[i]);
1605 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1606 /* ========================================================================= */