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(struct SoundControl);
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;
236 if (leveldir_current == NULL)
237 leveldir_current = checked_calloc(sizeof(TreeInfo));
239 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
240 if (leveldir_current->fullpath != NULL)
241 free(leveldir_current->fullpath);
242 if (ti->basepath != NULL)
244 if (ti->fullpath != NULL)
247 if (read(audio.soundserver_pipe[0], set_name,
248 snd_ctrl.data_len) != snd_ctrl.data_len ||
249 read(audio.soundserver_pipe[0], leveldir_current,
250 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
251 read(audio.soundserver_pipe[0], ti,
252 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
253 read(audio.soundserver_pipe[0], &str_size1,
254 sizeof(unsigned long)) != sizeof(unsigned long) ||
255 read(audio.soundserver_pipe[0], &str_size2,
256 sizeof(unsigned long)) != sizeof(unsigned long) ||
257 read(audio.soundserver_pipe[0], &str_size3,
258 sizeof(unsigned long)) != sizeof(unsigned long))
259 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
261 leveldir_current->fullpath = checked_calloc(str_size1);
262 ti->basepath = checked_calloc(str_size2);
263 ti->fullpath = checked_calloc(str_size3);
265 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
266 str_size1) != str_size1 ||
267 read(audio.soundserver_pipe[0], ti->basepath,
268 str_size2) != str_size2 ||
269 read(audio.soundserver_pipe[0], ti->fullpath,
270 str_size3) != str_size3)
271 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
275 close(audio.device_fd);
277 if (snd_ctrl.reload_sounds)
279 artwork.sounds_set_current = set_name;
280 audio.func_reload_sounds();
284 artwork.music_set_current = set_name;
285 audio.func_reload_music();
293 #if defined(AUDIO_STREAMING_DSP)
295 if (snd_ctrl.fade_sound)
301 playlist[audio.music_channel].fade_sound = TRUE;
303 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
304 if (snd_ctrl.stop_all_sounds ||
305 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
306 playlist[i].fade_sound = TRUE;
308 else if (snd_ctrl.stop_all_sounds)
313 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
314 playlist[i] = emptySoundControl;
317 close(audio.device_fd);
319 else if (snd_ctrl.stop_sound)
326 playlist[audio.music_channel] = emptySoundControl;
330 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
332 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
334 playlist[i] = emptySoundControl;
340 close(audio.device_fd);
343 if (playing_sounds || snd_ctrl.active)
345 struct timeval delay = { 0, 0 };
348 static long max_sample_size = 0;
349 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
350 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
351 static boolean stereo = TRUE;
353 if (playing_sounds ||
354 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
356 if (!playing_sounds) /* we just opened the audio device */
358 #if defined(AUDIO_LINUX_IOCTL)
359 stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
360 #elif defined(PLATFORM_NETBSD)
361 stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
363 max_sample_size = fragment_size / (stereo ? 2 : 1);
366 if (snd_ctrl.active) /* new sound has arrived */
367 SoundServer_InsertNewSound(snd_ctrl);
369 while (playing_sounds &&
370 select(audio.soundserver_pipe[0] + 1,
371 &sound_fdset, NULL, NULL, &delay) < 1)
373 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
375 /* first clear the last premixing buffer */
376 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
378 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
382 if (!playlist[i].active)
385 /* get pointer and size of the actual sound sample */
386 sample_ptr = playlist[i].data_ptr + playlist[i].playingpos;
387 sample_size = MIN(max_sample_size,
388 playlist[i].data_len - playlist[i].playingpos);
389 playlist[i].playingpos += sample_size;
391 /* fill the first mixing buffer with original sample */
392 memcpy(premix_first_buffer, sample_ptr, sample_size);
394 /* are we about to restart a looping sound? */
395 if (playlist[i].loop && sample_size < max_sample_size)
397 playlist[i].playingpos = max_sample_size - sample_size;
398 memcpy(premix_first_buffer + sample_size,
399 playlist[i].data_ptr, max_sample_size - sample_size);
400 sample_size = max_sample_size;
403 /* decrease volume if sound is fading out */
404 if (playlist[i].fade_sound &&
405 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
406 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
408 /* adjust volume of actual sound sample */
409 if (playlist[i].volume != PSND_MAX_VOLUME)
410 for(j=0; j<sample_size; j++)
411 premix_first_buffer[j] =
412 (playlist[i].volume * (int)premix_first_buffer[j])
413 >> PSND_MAX_VOLUME_BITS;
415 /* fill the last mixing buffer with stereo or mono sound */
418 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
419 int left_volume = stereo_volume[middle_pos +playlist[i].stereo];
420 int right_volume = stereo_volume[middle_pos -playlist[i].stereo];
422 for(j=0; j<sample_size; j++)
424 premix_left_buffer[j] =
425 (left_volume * (int)premix_first_buffer[j])
426 >> PSND_MAX_LEFT2RIGHT_BITS;
427 premix_right_buffer[j] =
428 (right_volume * (int)premix_first_buffer[j])
429 >> PSND_MAX_LEFT2RIGHT_BITS;
430 premix_last_buffer[2*j+0] += premix_left_buffer[j];
431 premix_last_buffer[2*j+1] += premix_right_buffer[j];
436 for(j=0;j<sample_size;j++)
437 premix_last_buffer[j] += (int)premix_first_buffer[j];
440 /* delete completed sound entries from the playlist */
441 if (playlist[i].playingpos >= playlist[i].data_len)
443 if (playlist[i].loop)
444 playlist[i].playingpos = 0;
447 playlist[i] = emptySoundControl;
451 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
453 playlist[i] = emptySoundControl;
458 /* put last mixing buffer to final playing buffer */
459 for(i=0; i<fragment_size; i++)
461 if (premix_last_buffer[i]<-255)
462 playing_buffer[i] = 0;
463 else if (premix_last_buffer[i]>255)
464 playing_buffer[i] = 255;
466 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
469 /* finally play the sound fragment */
470 write(audio.device_fd, playing_buffer, fragment_size);
473 /* if no sounds playing, free device for other sound programs */
475 close(audio.device_fd);
479 #else /* !AUDIO_STREAMING_DSP */
481 if (snd_ctrl.active && !snd_ctrl.loop)
483 struct timeval delay = { 0, 0 };
485 long sample_size, max_sample_size = SND_BLOCKSIZE;
486 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
487 int wait_percent = 90; /* wait 90% of the real playing time */
490 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
494 while (playing_sounds &&
495 select(audio.soundserver_pipe[0] + 1,
496 &sound_fdset, NULL, NULL, &delay) < 1)
498 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
500 /* get pointer and size of the actual sound sample */
501 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
503 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
504 snd_ctrl.playingpos += sample_size;
506 /* fill the first mixing buffer with original sample */
507 memcpy(premix_first_buffer,sample_ptr,sample_size);
509 /* adjust volume of actual sound sample */
510 if (snd_ctrl.volume != PSND_MAX_VOLUME)
511 for(i=0;i<sample_size;i++)
512 premix_first_buffer[i] =
513 (snd_ctrl.volume * (int)premix_first_buffer[i])
514 >> PSND_MAX_VOLUME_BITS;
516 for(i=0;i<sample_size;i++)
518 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
520 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
523 /* finally play the sound fragment */
524 write(audio.device_fd,playing_buffer,sample_size);
527 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
529 close(audio.device_fd);
532 #endif /* !AUDIO_STREAMING_DSP */
535 #endif /* PLATFORM_UNIX */
537 #if defined(PLATFORM_MSDOS)
538 static void sound_handler(struct SoundControl snd_ctrl)
542 if (snd_ctrl.fade_sound)
547 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
548 if ((snd_ctrl.stop_all_sounds ||
549 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
550 (i == audio.music_channel && snd_ctrl.music)) &&
551 !playlist[i].fade_sound)
553 playlist[i].fade_sound = TRUE;
554 if (voice_check(playlist[i].voice))
555 voice_ramp_volume(playlist[i].voice, 1000, 0);
556 playlist[i].loop = PSND_NO_LOOP;
559 else if (snd_ctrl.stop_all_sounds)
563 SoundServer_StopAllSounds();
565 else if (snd_ctrl.stop_sound)
569 SoundServer_StopSound(snd_ctrl);
572 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
574 if (!playlist[i].active || playlist[i].loop)
577 playlist[i].playingpos = voice_get_position(playlist[i].voice);
578 playlist[i].volume = voice_get_volume(playlist[i].voice);
579 if (playlist[i].playingpos == -1 || !playlist[i].volume)
581 deallocate_voice(playlist[i].voice);
582 playlist[i] = emptySoundControl;
588 SoundServer_InsertNewSound(snd_ctrl);
590 #endif /* PLATFORM_MSDOS */
592 #if !defined(PLATFORM_WIN32)
593 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
598 snd_ctrl.nr = snd_ctrl.nr % num_music;
600 /* if playlist is full, remove oldest sound */
601 if (playing_sounds == MAX_SOUNDS_PLAYING)
603 int longest = 0, longest_nr = 0;
605 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
607 #if !defined(PLATFORM_MSDOS)
608 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
610 int actual = playlist[i].playingpos;
613 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
619 #if defined(PLATFORM_MSDOS)
620 voice_set_volume(playlist[longest_nr].voice, 0);
621 deallocate_voice(playlist[longest_nr].voice);
623 playlist[longest_nr] = emptySoundControl;
627 /* check if sound is already being played (and how often) */
628 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
629 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
632 /* restart loop sounds only if they are just fading out */
633 if (k >= 1 && snd_ctrl.loop)
635 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
637 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
638 playlist[i].fade_sound)
640 playlist[i].fade_sound = FALSE;
641 playlist[i].volume = PSND_MAX_VOLUME;
642 #if defined(PLATFORM_MSDOS)
643 playlist[i].loop = PSND_LOOP;
644 voice_stop_volumeramp(playlist[i].voice);
645 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
653 /* don't play sound more than n times simultaneously (with n == 2 for now) */
656 int longest = 0, longest_nr = 0;
658 /* look for oldest equal sound */
659 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
663 if (!playlist[i].active ||
664 i == audio.music_channel ||
665 playlist[i].nr != snd_ctrl.nr)
668 #if !defined(PLATFORM_MSDOS)
669 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
671 actual = playlist[i].playingpos;
673 if (actual >= longest)
680 #if defined(PLATFORM_MSDOS)
681 voice_set_volume(playlist[longest_nr].voice, 0);
682 deallocate_voice(playlist[longest_nr].voice);
684 playlist[longest_nr] = emptySoundControl;
688 /* add new sound to playlist */
689 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
691 if (!playlist[i].active ||
692 (snd_ctrl.music && i == audio.music_channel))
694 SoundInfo *snd_info =
695 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
697 snd_ctrl.data_ptr = snd_info->data_ptr;
698 snd_ctrl.data_len = snd_info->data_len;
700 playlist[i] = snd_ctrl;
703 #if defined(PLATFORM_MSDOS)
704 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
707 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
709 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
710 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
711 voice_start(playlist[i].voice);
717 #endif /* !PLATFORM_WIN32 */
720 void SoundServer_FadeSound(int nr)
727 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
728 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
729 playlist[i].fade_sound = TRUE;
733 #if !defined(PLATFORM_WIN32)
734 #if defined(PLATFORM_MSDOS)
735 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
737 int nr = snd_ctrl.nr;
743 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
745 if ((i == audio.music_channel && snd_ctrl.music) ||
746 (i != audio.music_channel && playlist[i].nr == nr))
748 #if defined(PLATFORM_MSDOS)
749 voice_set_volume(playlist[i].voice, 0);
750 deallocate_voice(playlist[i].voice);
752 playlist[i] = emptySoundControl;
757 #if !defined(PLATFORM_MSDOS)
759 close(audio.device_fd);
763 static void SoundServer_StopAllSounds()
767 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
769 #if defined(PLATFORM_MSDOS)
770 voice_set_volume(playlist[i].voice, 0);
771 deallocate_voice(playlist[i].voice);
773 playlist[i]=emptySoundControl;
777 #if !defined(PLATFORM_MSDOS)
778 close(audio.device_fd);
781 #endif /* PLATFORM_MSDOS */
782 #endif /* !PLATFORM_WIN32 */
785 /* ------------------------------------------------------------------------- */
786 /* platform dependant audio initialization code */
787 /* ------------------------------------------------------------------------- */
789 #if defined(AUDIO_LINUX_IOCTL)
790 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
792 /* "ioctl()" expects pointer to 'int' value for stereo flag
793 (boolean is defined as 'char', which will not work here) */
795 unsigned long fragment_spec = 0;
797 /* determine logarithm (log2) of the fragment size */
798 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
801 /* use two fragments (play one fragment, prepare the other);
802 one fragment would result in interrupted audio output, more
803 than two fragments would raise audio output latency to much */
804 fragment_spec |= 0x00020000;
806 /* Example for fragment specification:
807 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
808 - (with stereo the effective buffer size will shrink to 256)
809 => fragment_size = 0x00020009 */
811 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
812 Error(ERR_EXIT_SOUND_SERVER,
813 "cannot set fragment size of /dev/dsp -- no sounds");
815 /* try if we can use stereo sound */
816 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
819 static boolean reported = FALSE;
823 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
830 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
831 Error(ERR_EXIT_SOUND_SERVER,
832 "cannot set sample rate of /dev/dsp -- no sounds");
834 /* get the real fragmentation size; this should return 512 */
835 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
836 Error(ERR_EXIT_SOUND_SERVER,
837 "cannot get fragment size of /dev/dsp -- no sounds");
839 return (boolean)stereo;
841 #endif /* AUDIO_LINUX_IOCTL */
843 #if defined(PLATFORM_NETBSD)
844 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
847 boolean stereo = TRUE;
849 AUDIO_INITINFO(&a_info);
850 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
851 a_info.play.precision = 8;
852 a_info.play.channels = 2;
853 a_info.play.sample_rate = sample_rate;
854 a_info.blocksize = fragment_size;
856 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
858 /* try to disable stereo */
859 a_info.play.channels = 1;
862 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
863 Error(ERR_EXIT_SOUND_SERVER,
864 "cannot set sample rate of /dev/audio -- no sounds");
869 #endif /* PLATFORM_NETBSD */
871 #if defined(PLATFORM_HPUX)
872 static boolean InitAudioDevice_HPUX()
874 struct audio_describe ainfo;
877 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
879 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
881 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
882 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
884 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
885 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
887 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
888 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
892 return TRUE; /* to provide common interface for InitAudioDevice_...() */
894 #endif /* PLATFORM_HPUX */
896 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
898 /* these two are stolen from "sox"... :) */
901 ** This routine converts from linear to ulaw.
903 ** Craig Reese: IDA/Supercomputing Research Center
904 ** Joe Campbell: Department of Defense
908 ** 1) CCITT Recommendation G.711 (very difficult to follow)
909 ** 2) "A New Digital Technique for Implementation of Any
910 ** Continuous PCM Companding Law," Villeret, Michel,
911 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
912 ** 1973, pg. 11.12-11.17
913 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
914 ** for Analog-to_Digital Conversion Techniques,"
917 ** Input: Signed 16 bit linear sample
918 ** Output: 8 bit ulaw sample
921 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
922 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
925 static unsigned char linear_to_ulaw(int sample)
927 static int exp_lut[256] =
929 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
930 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
931 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
932 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
933 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
934 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
935 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
936 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
937 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
938 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
939 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
940 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
941 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
942 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
943 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
944 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
947 int sign, exponent, mantissa;
948 unsigned char ulawbyte;
950 /* Get the sample into sign-magnitude. */
951 sign = (sample >> 8) & 0x80; /* set aside the sign */
953 sample = -sample; /* get magnitude */
955 sample = CLIP; /* clip the magnitude */
957 /* Convert from 16 bit linear to ulaw. */
958 sample = sample + BIAS;
959 exponent = exp_lut[( sample >> 7 ) & 0xFF];
960 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
961 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
964 ulawbyte = 0x02; /* optional CCITT trap */
971 ** This routine converts from ulaw to 16 bit linear.
973 ** Craig Reese: IDA/Supercomputing Research Center
977 ** 1) CCITT Recommendation G.711 (very difficult to follow)
978 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
979 ** for Analog-to_Digital Conversion Techniques,"
982 ** Input: 8 bit ulaw sample
983 ** Output: signed 16 bit linear sample
986 static int ulaw_to_linear(unsigned char ulawbyte)
988 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
989 int sign, exponent, mantissa, sample;
991 ulawbyte = ~ ulawbyte;
992 sign = ( ulawbyte & 0x80 );
993 exponent = ( ulawbyte >> 4 ) & 0x07;
994 mantissa = ulawbyte & 0x0F;
995 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1001 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1004 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1005 /* ========================================================================= */
1006 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1008 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1009 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1011 static SoundInfo *Load_WAV(char *filename)
1013 SoundInfo *snd_info;
1014 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1015 byte sound_header_buffer[WAV_HEADER_SIZE];
1016 char chunk_name[CHUNK_ID_LEN + 1];
1022 if (!audio.sound_available)
1025 snd_info = checked_calloc(sizeof(SoundInfo));
1027 #if defined(TARGET_SDL)
1029 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1031 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1036 #elif defined(TARGET_ALLEGRO)
1038 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1040 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1045 #else /* PLATFORM_UNIX */
1047 if ((file = fopen(filename, MODE_READ)) == NULL)
1049 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1054 /* read chunk id "RIFF" */
1055 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1056 if (strcmp(chunk_name, "RIFF") != 0)
1058 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1064 /* read "RIFF" type id "WAVE" */
1065 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1066 if (strcmp(chunk_name, "WAVE") != 0)
1068 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1074 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1076 if (strcmp(chunk_name, "fmt ") == 0)
1078 /* read header information */
1079 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1080 sound_header_buffer[i] = fgetc(file);
1082 if (chunk_size > WAV_HEADER_SIZE)
1083 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1085 else if (strcmp(chunk_name, "data") == 0)
1087 snd_info->data_len = chunk_size;
1088 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1090 /* read sound data */
1091 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1094 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1096 free(snd_info->data_ptr);
1101 /* check for odd number of sample bytes (data chunk is word aligned) */
1102 if ((chunk_size % 2) == 1)
1103 ReadUnusedBytesFromFile(file, 1);
1105 else /* unknown chunk -- ignore */
1106 ReadUnusedBytesFromFile(file, chunk_size);
1111 if (snd_info->data_ptr == NULL)
1113 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1118 for (i=0; i<snd_info->data_len; i++)
1119 ((byte *)snd_info->data_ptr)[i] = ((byte *)snd_info->data_ptr)[i] ^ 0x80;
1121 #endif /* PLATFORM_UNIX */
1123 snd_info->type = SND_TYPE_WAV;
1124 snd_info->source_filename = getStringCopy(filename);
1129 SoundInfo *LoadCustomSound(char *basename)
1131 char *filename = getCustomSoundFilename(basename);
1133 if (filename == NULL)
1135 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1139 return Load_WAV(filename);
1142 void InitSoundList(int num_list_entries)
1144 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1145 num_sounds = num_list_entries;
1148 void LoadSoundToList(char *basename, int list_pos)
1150 if (Sound == NULL || list_pos >= num_sounds)
1153 if (Sound[list_pos])
1154 FreeSound(Sound[list_pos]);
1156 Sound[list_pos] = LoadCustomSound(basename);
1159 static MusicInfo *Load_MOD(char *filename)
1161 #if defined(TARGET_SDL)
1162 MusicInfo *mod_info;
1164 if (!audio.sound_available)
1167 mod_info = checked_calloc(sizeof(MusicInfo));
1169 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1171 Error(ERR_WARN, "cannot read music file '%s'", filename);
1176 mod_info->type = MUS_TYPE_MOD;
1177 mod_info->source_filename = getStringCopy(filename);
1185 void LoadCustomMusic(void)
1187 char *music_directory = getCustomMusicDirectory();
1189 struct dirent *dir_entry;
1191 if (!audio.sound_available)
1194 if ((dir = opendir(music_directory)) == NULL)
1196 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1197 audio.music_available = FALSE;
1201 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1203 char *basename = dir_entry->d_name;
1204 char *filename = getPath2(music_directory, basename);
1205 MusicInfo *mus_info = NULL;
1207 if (FileIsSound(basename))
1208 mus_info = Load_WAV(filename);
1209 else if (FileIsMusic(basename))
1210 mus_info = Load_MOD(filename);
1217 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1218 Music[num_music -1] = mus_info;
1225 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1229 void PlayMusic(int nr)
1231 if (!audio.music_available)
1234 #if defined(TARGET_SDL)
1236 nr = nr % num_music;
1238 if (Music[nr]->type == MUS_TYPE_MOD)
1240 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1241 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1243 else /* play WAV music loop */
1245 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1246 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1256 void PlaySound(int nr)
1258 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1261 void PlaySoundStereo(int nr, int stereo)
1263 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1266 void PlaySoundLoop(int nr)
1268 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1271 void PlaySoundMusic(int nr)
1273 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1276 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1278 struct SoundControl snd_ctrl = emptySoundControl;
1280 if (!audio.sound_available ||
1281 !audio.sound_enabled ||
1282 audio.sound_deactivated)
1285 if (volume < PSND_MIN_VOLUME)
1286 volume = PSND_MIN_VOLUME;
1287 else if (volume > PSND_MAX_VOLUME)
1288 volume = PSND_MAX_VOLUME;
1290 if (stereo < PSND_MAX_LEFT)
1291 stereo = PSND_MAX_LEFT;
1292 else if (stereo > PSND_MAX_RIGHT)
1293 stereo = PSND_MAX_RIGHT;
1296 snd_ctrl.volume = volume;
1297 snd_ctrl.stereo = stereo;
1298 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1299 snd_ctrl.music = (loop_type == PSND_MUSIC);
1300 snd_ctrl.active = TRUE;
1303 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1304 snd_ctrl.data_len = Sound[nr].data_len;
1307 #if defined(TARGET_SDL)
1308 Mix_Volume(-1, SOUND_MAX_VOLUME);
1309 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1310 #elif defined(PLATFORM_UNIX)
1311 if (audio.soundserver_pid == 0) /* we are child process */
1314 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1316 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1317 audio.sound_available = audio.sound_enabled = FALSE;
1320 #elif defined(PLATFORM_MSDOS)
1321 sound_handler(snd_ctrl);
1325 void FadeMusic(void)
1327 if (!audio.sound_available)
1330 #if defined(TARGET_SDL)
1331 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1332 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1334 StopSoundExt(-1, SSND_FADE_MUSIC);
1338 void FadeSound(int nr)
1340 StopSoundExt(nr, SSND_FADE_SOUND);
1346 StopSoundExt(-1, SSND_FADE_ALL);
1349 void StopMusic(void)
1351 #if defined(TARGET_SDL)
1352 if (!audio.sound_available)
1356 Mix_HaltChannel(audio.music_channel);
1358 StopSoundExt(-1, SSND_STOP_MUSIC);
1362 void StopSound(int nr)
1364 StopSoundExt(nr, SSND_STOP_SOUND);
1369 StopSoundExt(-1, SSND_STOP_ALL);
1372 void StopSoundExt(int nr, int method)
1374 struct SoundControl snd_ctrl = emptySoundControl;
1376 if (!audio.sound_available)
1379 if (method & SSND_FADING)
1380 snd_ctrl.fade_sound = TRUE;
1382 if (method & SSND_ALL)
1383 snd_ctrl.stop_all_sounds = TRUE;
1386 snd_ctrl.stop_sound = TRUE;
1390 if (method & SSND_MUSIC)
1391 snd_ctrl.music = TRUE;
1393 #if defined(TARGET_SDL)
1395 if (method & SSND_FADING)
1399 for (i=0; i<audio.channels; i++)
1400 if (i != audio.music_channel || snd_ctrl.music)
1401 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1403 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1409 for (i=0; i<audio.channels; i++)
1410 if (i != audio.music_channel || snd_ctrl.music)
1416 #elif !defined(PLATFORM_MSDOS)
1418 if (audio.soundserver_pid == 0) /* we are child process */
1421 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1423 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1424 audio.sound_available = audio.sound_enabled = FALSE;
1428 sound_handler(snd_ctrl);
1432 static void InitReloadSoundsOrMusic(char *set_name, int type)
1434 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1435 struct SoundControl snd_ctrl = emptySoundControl;
1437 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1438 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1439 unsigned long str_size2 = strlen(ti->basepath) + 1;
1440 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1443 if (!audio.sound_available)
1446 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1447 if (type == SND_RELOAD_SOUNDS)
1448 audio.func_reload_sounds();
1450 audio.func_reload_music();
1451 #elif defined(PLATFORM_UNIX)
1452 if (audio.soundserver_pid == 0) /* we are child process */
1455 if (leveldir_current == NULL) /* should never happen */
1456 Error(ERR_EXIT, "leveldir_current == NULL");
1458 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1459 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1460 snd_ctrl.data_len = strlen(set_name) + 1;
1462 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1463 sizeof(snd_ctrl)) < 0 ||
1464 write(audio.soundserver_pipe[1], set_name,
1465 snd_ctrl.data_len) < 0 ||
1466 write(audio.soundserver_pipe[1], leveldir_current,
1467 sizeof(TreeInfo)) < 0 ||
1468 write(audio.soundserver_pipe[1], ti,
1469 sizeof(TreeInfo)) < 0 ||
1470 write(audio.soundserver_pipe[1], &str_size1,
1471 sizeof(unsigned long)) < 0 ||
1472 write(audio.soundserver_pipe[1], &str_size2,
1473 sizeof(unsigned long)) < 0 ||
1474 write(audio.soundserver_pipe[1], &str_size3,
1475 sizeof(unsigned long)) < 0 ||
1476 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1478 write(audio.soundserver_pipe[1], ti->basepath,
1480 write(audio.soundserver_pipe[1], ti->fullpath,
1483 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1484 audio.sound_available = audio.sound_enabled = FALSE;
1490 void InitReloadSounds(char *set_name)
1492 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1495 void InitReloadMusic(char *set_name)
1497 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1500 void FreeSound(SoundInfo *sound)
1505 if (sound->data_ptr)
1507 #if defined(TARGET_SDL)
1508 Mix_FreeChunk(sound->data_ptr);
1509 #elif defined(TARGET_ALLEGRO)
1510 destroy_sample(sound->data_ptr);
1511 #else /* PLATFORM_UNIX */
1512 free(sound->data_ptr);
1519 void FreeMusic(MusicInfo *music)
1524 if (music->data_ptr)
1526 #if defined(TARGET_SDL)
1527 if (music->type == MUS_TYPE_MOD)
1528 Mix_FreeMusic(music->data_ptr);
1530 Mix_FreeChunk(music->data_ptr);
1531 #elif defined(TARGET_ALLEGRO)
1532 destroy_sample(music->data_ptr);
1533 #else /* PLATFORM_UNIX */
1534 free(music->data_ptr);
1541 void FreeAllSounds()
1548 for(i=0; i<num_sounds; i++)
1549 FreeSound(Sound[i]);
1564 for(i=0; i<num_music; i++)
1565 FreeMusic(Music[i]);
1573 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1574 /* ========================================================================= */