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 ***********************************************************/
31 struct ListNode *next;
33 typedef struct ListNode ListNode;
35 static ListNode *newListNode(void);
36 static void addNodeToList(ListNode **, char *, void *);
37 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
38 static ListNode *getNodeFromKey(ListNode *, char *);
39 static int getNumNodes(ListNode *);
42 static struct SoundEffectInfo *sound_effect;
43 static ListNode *SoundFileList = NULL;
44 static SoundInfo **Sound = NULL;
45 static MusicInfo **Music = NULL;
46 static int num_sounds = 0, num_music = 0;
49 /* ========================================================================= */
50 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
52 static struct AudioFormatInfo afmt;
53 static struct SoundControl playlist[NUM_MIXER_CHANNELS];
54 static int playing_sounds = 0;
56 /* forward declaration of internal functions */
57 static void SoundServer_InsertNewSound(struct SoundControl);
58 static void InitAudioDevice(struct AudioFormatInfo *);
60 #if defined(PLATFORM_UNIX)
61 #if !defined(AUDIO_STREAMING_DSP)
62 static unsigned char linear_to_ulaw(int);
63 static int ulaw_to_linear(unsigned char);
65 #elif defined(PLATFORM_MSDOS)
66 static void SoundServer_InsertNewSound(struct SoundControl);
67 static void SoundServer_StopSound(struct SoundControl);
68 static void SoundServer_StopAllSounds();
71 static void ReloadCustomSounds();
72 static void ReloadCustomMusic();
73 static void FreeSound(void *);
75 #if defined(PLATFORM_UNIX)
76 static int OpenAudioDevice(char *audio_device_name)
80 /* check if desired audio device is accessible */
81 if (access(audio_device_name, W_OK) != 0)
84 /* try to open audio device in non-blocking mode */
85 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
86 return audio_device_fd;
88 /* re-open audio device in blocking mode */
89 close(audio_device_fd);
90 audio_device_fd = open(audio_device_name, O_WRONLY);
92 return audio_device_fd;
95 static void CloseAudioDevice(int *audio_device_fd)
97 if (*audio_device_fd == 0)
100 close(*audio_device_fd);
101 *audio_device_fd = -1;
104 static boolean TestAudioDevices(void)
106 static char *audio_device_name[] =
111 int audio_device_fd = -1;
114 /* look for available audio devices, starting with preferred ones */
115 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
116 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
119 if (audio_device_fd < 0)
121 Error(ERR_WARN, "cannot open audio device -- no sound");
125 close(audio_device_fd);
127 audio.device_name = audio_device_name[i];
132 #if !defined(TARGET_SDL)
133 static boolean ForkAudioProcess(void)
135 if (pipe(audio.soundserver_pipe) < 0)
137 Error(ERR_WARN, "cannot create pipe -- no sounds");
141 if ((audio.soundserver_pid = fork()) < 0)
143 Error(ERR_WARN, "cannot create sound server process -- no sounds");
147 if (audio.soundserver_pid == 0) /* we are child process */
154 else /* we are parent */
155 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
161 void UnixOpenAudio(void)
163 if (!TestAudioDevices())
166 audio.sound_available = TRUE;
167 audio.sound_enabled = TRUE;
169 #if defined(AUDIO_STREAMING_DSP)
170 audio.music_available = TRUE;
171 audio.loops_available = TRUE;
174 audio.num_channels = NUM_MIXER_CHANNELS;
175 audio.music_channel = MUSIC_CHANNEL;
176 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
179 void UnixCloseAudio(void)
182 close(audio.device_fd);
184 if (audio.soundserver_pid > 0) /* we are parent process */
185 kill(audio.soundserver_pid, SIGTERM);
188 static void WriteReloadInfoToPipe(char *set_name, int type)
190 struct SoundControl snd_ctrl;
191 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
192 artwork.mus_current);
193 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
194 unsigned long str_size2 = strlen(ti->basepath) + 1;
195 unsigned long str_size3 = strlen(ti->fullpath) + 1;
197 snd_ctrl.active = FALSE;
198 snd_ctrl.state = type;
199 snd_ctrl.data_len = strlen(set_name) + 1;
201 if (write(audio.soundserver_pipe[1], &snd_ctrl,
202 sizeof(snd_ctrl)) < 0 ||
203 write(audio.soundserver_pipe[1], set_name,
204 snd_ctrl.data_len) < 0 ||
205 write(audio.soundserver_pipe[1], leveldir_current,
206 sizeof(TreeInfo)) < 0 ||
207 write(audio.soundserver_pipe[1], ti,
208 sizeof(TreeInfo)) < 0 ||
209 write(audio.soundserver_pipe[1], &str_size1,
210 sizeof(unsigned long)) < 0 ||
211 write(audio.soundserver_pipe[1], &str_size2,
212 sizeof(unsigned long)) < 0 ||
213 write(audio.soundserver_pipe[1], &str_size3,
214 sizeof(unsigned long)) < 0 ||
215 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
217 write(audio.soundserver_pipe[1], ti->basepath,
219 write(audio.soundserver_pipe[1], ti->fullpath,
222 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
223 audio.sound_available = audio.sound_enabled = FALSE;
228 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
230 TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
231 &artwork.snd_current : &artwork.mus_current);
232 TreeInfo *ti = *ti_ptr;
233 unsigned long str_size1, str_size2, str_size3;
234 static char *set_name = NULL;
239 set_name = checked_malloc(snd_ctrl.data_len);
241 if (leveldir_current == NULL)
242 leveldir_current = checked_calloc(sizeof(TreeInfo));
244 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
245 if (leveldir_current->fullpath != NULL)
246 free(leveldir_current->fullpath);
247 if (ti->basepath != NULL)
249 if (ti->fullpath != NULL)
252 if (read(audio.soundserver_pipe[0], set_name,
253 snd_ctrl.data_len) != snd_ctrl.data_len ||
254 read(audio.soundserver_pipe[0], leveldir_current,
255 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
256 read(audio.soundserver_pipe[0], ti,
257 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
258 read(audio.soundserver_pipe[0], &str_size1,
259 sizeof(unsigned long)) != sizeof(unsigned long) ||
260 read(audio.soundserver_pipe[0], &str_size2,
261 sizeof(unsigned long)) != sizeof(unsigned long) ||
262 read(audio.soundserver_pipe[0], &str_size3,
263 sizeof(unsigned long)) != sizeof(unsigned long))
264 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
266 leveldir_current->fullpath = checked_calloc(str_size1);
267 ti->basepath = checked_calloc(str_size2);
268 ti->fullpath = checked_calloc(str_size3);
270 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
271 str_size1) != str_size1 ||
272 read(audio.soundserver_pipe[0], ti->basepath,
273 str_size2) != str_size2 ||
274 read(audio.soundserver_pipe[0], ti->fullpath,
275 str_size3) != str_size3)
276 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
278 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
279 artwork.sounds_set_current = set_name;
281 artwork.music_set_current = set_name;
283 #endif /* PLATFORM_UNIX */
285 void InitPlaylist(void)
289 for(i=0; i<audio.num_channels; i++)
290 playlist[i].active = FALSE;
294 static void PlaylistRemoveSound(int pos)
296 if (!playing_sounds || !playlist[pos].active)
300 printf("REMOVING PLAYLIST SOUND %d\n", pos);
303 playlist[pos].active = FALSE;
307 static void PlaylistInsertSound(struct SoundControl snd_ctrl)
313 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
316 if (IS_MUSIC(snd_ctrl))
317 snd_ctrl.nr = snd_ctrl.nr % num_music;
318 else if (snd_ctrl.nr >= num_sounds)
321 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
322 if (snd_info == NULL)
325 printf("sound/music %d undefined\n", snd_ctrl.nr);
331 printf("-> %d\n", playing_sounds);
334 if (playing_sounds == audio.num_channels)
336 for (i=0; i<audio.num_channels; i++)
338 if (playlist[i].data_ptr == NULL)
341 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
344 PlaylistRemoveSound(i);
349 /* if playlist is full, remove oldest sound */
350 if (playing_sounds == audio.num_channels)
352 int longest = 0, longest_nr = audio.first_sound_channel;
354 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
356 #if !defined(PLATFORM_MSDOS)
357 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
359 int actual = playlist[i].playingpos;
362 if (!IS_LOOP(playlist[i]) && actual > longest)
368 #if defined(PLATFORM_MSDOS)
369 voice_set_volume(playlist[longest_nr].voice, 0);
370 deallocate_voice(playlist[longest_nr].voice);
372 PlaylistRemoveSound(longest_nr);
375 /* check if sound is already being played (and how often) */
376 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
377 if (playlist[i].nr == snd_ctrl.nr)
380 /* restart loop sounds only if they are just fading out */
381 if (k >= 1 && IS_LOOP(snd_ctrl))
383 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
385 if (playlist[i].nr == snd_ctrl.nr && IS_FADING(playlist[i]))
387 playlist[i].state &= ~SND_CTRL_FADE;
388 playlist[i].volume = PSND_MAX_VOLUME;
389 #if defined(PLATFORM_MSDOS)
390 playlist[i].state |= SND_CTRL_LOOP;
391 voice_stop_volumeramp(playlist[i].voice);
392 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
400 /* don't play sound more than n times simultaneously (with n == 2 for now) */
403 int longest = 0, longest_nr = audio.first_sound_channel;
405 /* look for oldest equal sound */
406 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
410 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
413 #if !defined(PLATFORM_MSDOS)
414 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
416 actual = playlist[i].playingpos;
418 if (actual >= longest)
425 #if defined(PLATFORM_MSDOS)
426 voice_set_volume(playlist[longest_nr].voice, 0);
427 deallocate_voice(playlist[longest_nr].voice);
429 PlaylistRemoveSound(longest_nr);
432 /* add new sound to playlist */
433 for(i=0; i<audio.num_channels; i++)
436 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
440 if (!playlist[i].active ||
441 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
443 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
444 (i != audio.music_channel && !playlist[i].active))
446 snd_ctrl.data_ptr = snd_info->data_ptr;
447 snd_ctrl.data_len = snd_info->data_len;
448 snd_ctrl.format = snd_info->format;
450 snd_ctrl.playingpos = 0;
451 snd_ctrl.playingtime = 0;
454 if (snd_info->data_len == 0)
456 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
461 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && playlist[i].active)
463 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
466 PlaylistRemoveSound(i);
471 playlist[i] = snd_ctrl;
475 printf("NEW SOUND %d ADDED TO PLAYLIST\n", snd_ctrl.nr);
478 #if defined(PLATFORM_MSDOS)
479 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
482 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
484 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
485 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
486 voice_start(playlist[i].voice);
493 static void HandleSoundRequest(struct SoundControl snd_ctrl)
497 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
499 ReadReloadInfoFromPipe(snd_ctrl);
501 CloseAudioDevice(&audio.device_fd);
503 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
504 ReloadCustomSounds();
508 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
513 if (IS_MUSIC(snd_ctrl))
515 playlist[audio.music_channel].state |= SND_CTRL_FADE;
519 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
520 if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
521 playlist[i].state |= SND_CTRL_FADE;
523 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
528 if (IS_MUSIC(snd_ctrl))
530 PlaylistRemoveSound(audio.music_channel);
534 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
535 if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
536 PlaylistRemoveSound(i);
539 CloseAudioDevice(&audio.device_fd);
541 else if (snd_ctrl.active) /* add new sound to playlist */
543 SoundServer_InsertNewSound(snd_ctrl);
547 void StartSoundserver(void)
549 if (!audio.sound_available)
552 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
553 if (!ForkAudioProcess())
554 audio.sound_available = FALSE;
558 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
560 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
561 int sample_pos, int sample_size,
564 void *sample_ptr = snd_ctrl->data_ptr;
567 if (snd_ctrl->format == AUDIO_FORMAT_U8)
568 for (i=0; i<sample_size; i++)
570 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
571 else /* AUDIO_FORMAT_S16 */
572 for (i=0; i<sample_size; i++)
574 ((short *)sample_ptr)[sample_pos + i];
577 #if defined(AUDIO_STREAMING_DSP)
578 static void SoundServer_Mixer()
580 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
581 static boolean stereo_volume_calculated = FALSE;
582 static short premix_first_buffer[SND_BLOCKSIZE];
583 static short premix_left_buffer[SND_BLOCKSIZE];
584 static short premix_right_buffer[SND_BLOCKSIZE];
585 static long premix_last_buffer[SND_BLOCKSIZE];
586 static byte playing_buffer[SND_BLOCKSIZE];
593 if (!stereo_volume_calculated)
595 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
597 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
599 stereo_volume_calculated = TRUE;
605 if (audio.device_fd < 0)
607 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
610 InitAudioDevice(&afmt);
613 stereo = afmt.stereo;
614 fragment_size = afmt.fragment_size;
615 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
616 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
618 /* first clear the last premixing buffer */
619 memset(premix_last_buffer, 0,
620 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
622 for(i=0; i<audio.num_channels; i++)
629 if (!playlist[i].active)
632 /* pointer, lenght and actual playing position of sound sample */
633 sample_ptr = playlist[i].data_ptr;
634 sample_len = playlist[i].data_len;
635 sample_pos = playlist[i].playingpos;
636 sample_size = MIN(max_sample_size, sample_len - sample_pos);
637 playlist[i].playingpos += sample_size;
639 /* copy original sample to first mixing buffer */
640 CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
641 premix_first_buffer);
643 /* are we about to restart a looping sound? */
644 if (IS_LOOP(playlist[i]) && sample_size < max_sample_size)
646 while (sample_size < max_sample_size)
648 int restarted_sample_size =
649 MIN(max_sample_size - sample_size, sample_len);
651 if (playlist[i].format == AUDIO_FORMAT_U8)
652 for (j=0; j<restarted_sample_size; j++)
653 premix_first_buffer[sample_size + j] =
654 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
656 for (j=0; j<restarted_sample_size; j++)
657 premix_first_buffer[sample_size + j] =
658 ((short *)sample_ptr)[j];
660 playlist[i].playingpos = restarted_sample_size;
661 sample_size += restarted_sample_size;
665 /* decrease volume if sound is fading out */
666 if (IS_FADING(playlist[i]) &&
667 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
668 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
670 /* adjust volume of actual sound sample */
671 if (playlist[i].volume != PSND_MAX_VOLUME)
672 for(j=0; j<sample_size; j++)
673 premix_first_buffer[j] =
674 (playlist[i].volume * (long)premix_first_buffer[j])
675 >> PSND_MAX_VOLUME_BITS;
677 /* fill the last mixing buffer with stereo or mono sound */
680 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
681 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
682 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
684 for(j=0; j<sample_size; j++)
686 premix_left_buffer[j] =
687 (left_volume * premix_first_buffer[j])
688 >> PSND_MAX_LEFT2RIGHT_BITS;
689 premix_right_buffer[j] =
690 (right_volume * premix_first_buffer[j])
691 >> PSND_MAX_LEFT2RIGHT_BITS;
693 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
694 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
699 for(j=0; j<sample_size; j++)
700 premix_last_buffer[j] += premix_first_buffer[j];
703 /* delete completed sound entries from the playlist */
704 if (playlist[i].playingpos >= playlist[i].data_len)
706 if (IS_LOOP(playlist[i]))
707 playlist[i].playingpos = 0;
709 PlaylistRemoveSound(i);
711 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
712 PlaylistRemoveSound(i);
715 /* prepare final playing buffer according to system audio format */
716 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
718 /* cut off at 17 bit value */
719 if (premix_last_buffer[i] < -65535)
720 premix_last_buffer[i] = -65535;
721 else if (premix_last_buffer[i] > 65535)
722 premix_last_buffer[i] = 65535;
724 /* shift to 16 bit value */
725 premix_last_buffer[i] >>= 1;
727 if (afmt.format & AUDIO_FORMAT_U8)
729 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
731 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
733 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
734 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
736 else /* big endian */
738 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
739 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
743 /* finally play the sound fragment */
744 write(audio.device_fd, playing_buffer, fragment_size);
747 CloseAudioDevice(&audio.device_fd);
750 #else /* !AUDIO_STREAMING_DSP */
752 static int SoundServer_SimpleAudio(struct SoundControl snd_ctrl)
754 static short premix_first_buffer[SND_BLOCKSIZE];
755 static byte playing_buffer[SND_BLOCKSIZE];
756 int max_sample_size = SND_BLOCKSIZE;
765 /* pointer, lenght and actual playing position of sound sample */
766 sample_ptr = playlist[i].data_ptr;
767 sample_len = playlist[i].data_len;
768 sample_pos = playlist[i].playingpos;
769 sample_size = MIN(max_sample_size, sample_len - sample_pos);
770 playlist[i].playingpos += sample_size;
772 /* copy original sample to first mixing buffer */
773 CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
774 premix_first_buffer);
776 /* adjust volume of actual sound sample */
777 if (playlist[i].volume != PSND_MAX_VOLUME)
778 for(j=0; j<sample_size; j++)
779 premix_first_buffer[j] =
780 (playlist[i].volume * (long)premix_first_buffer[j])
781 >> PSND_MAX_VOLUME_BITS;
783 /* might be needed for u-law /dev/audio */
785 for(j=0; j<sample_size; j++)
787 linear_to_ulaw(premix_first_buffer[j]);
790 /* delete completed sound entries from the playlist */
791 if (playlist[i].playingpos >= playlist[i].data_len)
792 PlaylistRemoveSound(i);
794 for(i=0; i<sample_size; i++)
795 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
797 /* finally play the sound fragment */
798 write(audio.device_fd, playing_buffer, sample_size);
802 #endif /* !AUDIO_STREAMING_DSP */
806 struct SoundControl snd_ctrl;
809 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
813 #if defined(PLATFORM_HPUX)
814 InitAudioDevice(&afmt);
817 FD_ZERO(&sound_fdset);
818 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
820 while(1) /* wait for sound playing commands from client */
822 struct timeval delay = { 0, 0 };
824 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
825 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
826 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
828 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
830 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
832 HandleSoundRequest(snd_ctrl);
834 #if defined(AUDIO_STREAMING_DSP)
836 while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
837 &sound_fdset, NULL, NULL, &delay) < 1)
839 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
844 #else /* !AUDIO_STREAMING_DSP */
846 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
847 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
850 InitAudioDevice(&afmt);
855 while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
856 &sound_fdset, NULL, NULL, &delay) < 1)
858 int wait_percent = 90; /* wait 90% of the real playing time */
861 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
863 sample_size = SoundServer_SimpleAudio(snd_ctrl);
867 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
870 CloseAudioDevice(&audio.device_fd);
872 /* delete all sounds from playlist */
875 #endif /* !AUDIO_STREAMING_DSP */
878 #endif /* PLATFORM_UNIX */
880 #if defined(PLATFORM_MSDOS)
881 static void sound_handler(struct SoundControl snd_ctrl)
885 if (snd_ctrl.fade_sound)
890 for (i=0; i<audio.num_channels; i++)
891 if ((snd_ctrl.stop_all_sounds ||
892 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
893 (i == audio.music_channel && snd_ctrl.music)) &&
894 !playlist[i].fade_sound)
896 playlist[i].fade_sound = TRUE;
897 if (voice_check(playlist[i].voice))
898 voice_ramp_volume(playlist[i].voice, 1000, 0);
899 playlist[i].state &= ~SND_CTRL_IS_LOOP;
902 else if (snd_ctrl.stop_all_sounds)
906 SoundServer_StopAllSounds();
908 else if (snd_ctrl.stop_sound)
912 SoundServer_StopSound(snd_ctrl);
915 for (i=0; i<audio.num_channels; i++)
917 if (!playlist[i].active || playlist[i].loop)
920 playlist[i].playingpos = voice_get_position(playlist[i].voice);
921 playlist[i].volume = voice_get_volume(playlist[i].voice);
922 if (playlist[i].playingpos == -1 || !playlist[i].volume)
924 deallocate_voice(playlist[i].voice);
925 PlaylistRemoveSound(i);
930 SoundServer_InsertNewSound(snd_ctrl);
932 #endif /* PLATFORM_MSDOS */
935 #if defined(TARGET_SDL)
936 static void sound_handler_SDL(struct SoundControl snd_ctrl)
938 /* copy sound_handler() here ... */
940 #endif /* TARGET_SDL */
943 #if !defined(PLATFORM_WIN32)
944 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
946 PlaylistInsertSound(snd_ctrl);
948 #endif /* !PLATFORM_WIN32 */
951 void SoundServer_FadeSound(int nr)
958 for(i=0;i<audio.num_channels;i++)
959 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
960 playlist[i].fade_sound = TRUE;
964 #if !defined(PLATFORM_WIN32)
965 #if defined(PLATFORM_MSDOS)
966 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
968 int nr = snd_ctrl.nr;
974 for(i=0; i<audio.num_channels; i++)
976 if ((i == audio.music_channel && snd_ctrl.music) ||
977 (i != audio.music_channel && playlist[i].nr == nr))
979 #if defined(PLATFORM_MSDOS)
980 voice_set_volume(playlist[i].voice, 0);
981 deallocate_voice(playlist[i].voice);
983 PlaylistRemoveSound(i);
987 #if !defined(PLATFORM_MSDOS)
989 close(audio.device_fd);
993 static void SoundServer_StopAllSounds()
997 for(i=0; i<audio.num_channels; i++)
999 #if defined(PLATFORM_MSDOS)
1000 voice_set_volume(playlist[i].voice, 0);
1001 deallocate_voice(playlist[i].voice);
1003 PlaylistRemoveSound(i);
1007 #if !defined(PLATFORM_MSDOS)
1008 close(audio.device_fd);
1011 #endif /* PLATFORM_MSDOS */
1012 #endif /* !PLATFORM_WIN32 */
1015 /* ------------------------------------------------------------------------- */
1016 /* platform dependant audio initialization code */
1017 /* ------------------------------------------------------------------------- */
1019 #if defined(AUDIO_LINUX_IOCTL)
1020 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1022 /* "ioctl()" expects pointer to 'int' value for stereo flag
1023 (boolean is defined as 'char', which will not work here) */
1024 unsigned int fragment_spec = 0;
1025 int fragment_size_query;
1034 /* supported audio format in preferred order */
1035 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1036 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1037 { AFMT_U8, AUDIO_FORMAT_U8 },
1042 /* determine logarithm (log2) of the fragment size */
1043 while ((1 << fragment_spec) < afmt->fragment_size)
1046 /* use two fragments (play one fragment, prepare the other);
1047 one fragment would result in interrupted audio output, more
1048 than two fragments would raise audio output latency to much */
1049 fragment_spec |= 0x00020000;
1051 /* Example for fragment specification:
1052 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1053 - (with stereo the effective buffer size will shrink to 256)
1054 => fragment_size = 0x00020009 */
1056 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1057 Error(ERR_EXIT_SOUND_SERVER,
1058 "cannot set fragment size of /dev/dsp -- no sounds");
1062 while (formats[i].format_result != -1)
1064 unsigned int audio_format = formats[i].format_ioctl;
1065 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1067 afmt->format = formats[i].format_result;
1072 if (afmt->format == 0) /* no supported audio format found */
1073 Error(ERR_EXIT_SOUND_SERVER,
1074 "cannot set audio format of /dev/dsp -- no sounds");
1076 /* try if we can use stereo sound */
1077 afmt->stereo = TRUE;
1078 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1079 afmt->stereo = FALSE;
1081 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1082 Error(ERR_EXIT_SOUND_SERVER,
1083 "cannot set sample rate of /dev/dsp -- no sounds");
1085 /* get the real fragmentation size; this should return 512 */
1086 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1087 Error(ERR_EXIT_SOUND_SERVER,
1088 "cannot get fragment size of /dev/dsp -- no sounds");
1089 if (fragment_size_query != afmt->fragment_size)
1090 Error(ERR_EXIT_SOUND_SERVER,
1091 "cannot set fragment size of /dev/dsp -- no sounds");
1093 #endif /* AUDIO_LINUX_IOCTL */
1095 #if defined(PLATFORM_NETBSD)
1096 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1098 audio_info_t a_info;
1099 boolean stereo = TRUE;
1101 AUDIO_INITINFO(&a_info);
1102 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1103 a_info.play.precision = 8;
1104 a_info.play.channels = 2;
1105 a_info.play.sample_rate = sample_rate;
1106 a_info.blocksize = fragment_size;
1108 afmt->format = AUDIO_FORMAT_U8;
1109 afmt->stereo = TRUE;
1111 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1113 /* try to disable stereo */
1114 a_info.play.channels = 1;
1116 afmt->stereo = FALSE;
1118 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1119 Error(ERR_EXIT_SOUND_SERVER,
1120 "cannot set sample rate of /dev/audio -- no sounds");
1123 #endif /* PLATFORM_NETBSD */
1125 #if defined(PLATFORM_HPUX)
1126 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1128 struct audio_describe ainfo;
1131 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1132 if (audio_ctl == -1)
1133 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1135 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1136 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1138 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1139 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1141 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1142 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1144 afmt->format = AUDIO_FORMAT_U8;
1145 afmt->stereo = FALSE;
1146 afmt->sample_rate = 8000;
1150 #endif /* PLATFORM_HPUX */
1152 #if defined(PLATFORM_UNIX)
1153 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1155 afmt->stereo = TRUE;
1156 afmt->format = AUDIO_FORMAT_UNKNOWN;
1157 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
1158 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1160 #if defined(AUDIO_LINUX_IOCTL)
1161 InitAudioDevice_Linux(afmt);
1162 #elif defined(PLATFORM_NETBSD)
1163 InitAudioDevice_NetBSD(afmt);
1164 #elif defined(PLATFORM_HPUX)
1165 InitAudioDevice_HPUX(afmt);
1167 /* generic /dev/audio stuff might be placed here */
1170 #endif /* PLATFORM_UNIX */
1172 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1174 /* these two are stolen from "sox"... :) */
1177 ** This routine converts from linear to ulaw.
1179 ** Craig Reese: IDA/Supercomputing Research Center
1180 ** Joe Campbell: Department of Defense
1181 ** 29 September 1989
1184 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1185 ** 2) "A New Digital Technique for Implementation of Any
1186 ** Continuous PCM Companding Law," Villeret, Michel,
1187 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1188 ** 1973, pg. 11.12-11.17
1189 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1190 ** for Analog-to_Digital Conversion Techniques,"
1193 ** Input: Signed 16 bit linear sample
1194 ** Output: 8 bit ulaw sample
1197 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1198 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1201 static unsigned char linear_to_ulaw(int sample)
1203 static int exp_lut[256] =
1205 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1206 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1207 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1208 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1209 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1210 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1211 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1212 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1213 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1214 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1215 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1216 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1217 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1218 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1219 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1220 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1223 int sign, exponent, mantissa;
1224 unsigned char ulawbyte;
1226 /* Get the sample into sign-magnitude. */
1227 sign = (sample >> 8) & 0x80; /* set aside the sign */
1229 sample = -sample; /* get magnitude */
1231 sample = CLIP; /* clip the magnitude */
1233 /* Convert from 16 bit linear to ulaw. */
1234 sample = sample + BIAS;
1235 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1236 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1237 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1240 ulawbyte = 0x02; /* optional CCITT trap */
1247 ** This routine converts from ulaw to 16 bit linear.
1249 ** Craig Reese: IDA/Supercomputing Research Center
1250 ** 29 September 1989
1253 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1254 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1255 ** for Analog-to_Digital Conversion Techniques,"
1258 ** Input: 8 bit ulaw sample
1259 ** Output: signed 16 bit linear sample
1262 static int ulaw_to_linear(unsigned char ulawbyte)
1264 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1265 int sign, exponent, mantissa, sample;
1267 ulawbyte = ~ ulawbyte;
1268 sign = ( ulawbyte & 0x80 );
1269 exponent = ( ulawbyte >> 4 ) & 0x07;
1270 mantissa = ulawbyte & 0x0F;
1271 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1277 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1280 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1281 /* ========================================================================= */
1282 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1284 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1285 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1287 static SoundInfo *Load_WAV(char *filename)
1289 SoundInfo *snd_info;
1290 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1291 byte sound_header_buffer[WAV_HEADER_SIZE];
1292 char chunk_name[CHUNK_ID_LEN + 1];
1298 if (!audio.sound_available)
1302 printf("loading WAV file '%s'\n", filename);
1305 snd_info = checked_calloc(sizeof(SoundInfo));
1307 #if defined(TARGET_SDL)
1309 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1311 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1316 #elif defined(TARGET_ALLEGRO)
1318 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1320 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1325 #else /* PLATFORM_UNIX */
1327 if ((file = fopen(filename, MODE_READ)) == NULL)
1329 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1334 /* read chunk id "RIFF" */
1335 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1336 if (strcmp(chunk_name, "RIFF") != 0)
1338 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1344 /* read "RIFF" type id "WAVE" */
1345 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1346 if (strcmp(chunk_name, "WAVE") != 0)
1348 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1354 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1356 if (strcmp(chunk_name, "fmt ") == 0)
1358 /* read header information */
1359 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1360 sound_header_buffer[i] = fgetc(file);
1362 if (chunk_size > WAV_HEADER_SIZE)
1363 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1365 else if (strcmp(chunk_name, "data") == 0)
1367 snd_info->data_len = chunk_size;
1368 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1370 /* read sound data */
1371 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1374 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1376 free(snd_info->data_ptr);
1381 /* check for odd number of sample bytes (data chunk is word aligned) */
1382 if ((chunk_size % 2) == 1)
1383 ReadUnusedBytesFromFile(file, 1);
1385 else /* unknown chunk -- ignore */
1386 ReadUnusedBytesFromFile(file, chunk_size);
1391 if (snd_info->data_ptr == NULL)
1393 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1398 snd_info->format = AUDIO_FORMAT_U8;
1400 #endif /* PLATFORM_UNIX */
1402 snd_info->type = SND_TYPE_WAV;
1403 snd_info->source_filename = getStringCopy(filename);
1408 static void deleteSoundEntry(SoundInfo **snd_info)
1412 char *filename = (*snd_info)->source_filename;
1415 printf("[decrementing reference counter of sound '%s']\n", filename);
1418 if (--(*snd_info)->num_references <= 0)
1421 printf("[deleting sound '%s']\n", filename);
1425 FreeSound(*snd_info);
1427 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1434 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1438 /* check if the old and the new sound file are the same */
1439 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1441 /* The old and new sound are the same (have the same filename and path).
1442 This usually means that this sound does not exist in this sound set
1443 and a fallback to the existing sound is done. */
1446 printf("[sound '%s' already exists (same list entry)]\n", filename);
1452 /* delete existing sound file entry */
1453 deleteSoundEntry(snd_info);
1455 /* check if the new sound file already exists in the list of sounds */
1456 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1459 printf("[sound '%s' already exists (other list entry)]\n", filename);
1462 *snd_info = (SoundInfo *)node->content;
1463 (*snd_info)->num_references++;
1465 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1467 (*snd_info)->num_references = 1;
1468 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1472 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1474 char *filename = getCustomSoundFilename(basename);
1476 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1478 deleteSoundEntry(snd_info);
1482 if (filename == NULL)
1484 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1488 replaceSoundEntry(snd_info, filename);
1491 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1494 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1496 sound_effect = sounds_list;
1497 num_sounds = num_list_entries;
1500 void LoadSoundToList(char *basename, int list_pos)
1502 if (Sound == NULL || list_pos >= num_sounds)
1506 printf("loading sound '%s' ... [%d]\n",
1507 basename, getNumNodes(SoundFileList));
1510 LoadCustomSound(&Sound[list_pos], basename);
1513 printf("loading sound '%s' done [%d]\n",
1514 basename, getNumNodes(SoundFileList));
1518 static MusicInfo *Load_MOD(char *filename)
1520 #if defined(TARGET_SDL)
1521 MusicInfo *mod_info;
1523 if (!audio.sound_available)
1526 mod_info = checked_calloc(sizeof(MusicInfo));
1528 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1530 Error(ERR_WARN, "cannot read music file '%s'", filename);
1535 mod_info->type = MUS_TYPE_MOD;
1536 mod_info->source_filename = getStringCopy(filename);
1544 void LoadCustomMusic(void)
1546 char *music_directory = getCustomMusicDirectory();
1548 struct dirent *dir_entry;
1550 if (!audio.sound_available)
1553 if ((dir = opendir(music_directory)) == NULL)
1555 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1556 audio.music_available = FALSE;
1560 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1562 char *basename = dir_entry->d_name;
1563 char *filename = getPath2(music_directory, basename);
1564 MusicInfo *mus_info = NULL;
1566 if (FileIsSound(basename))
1567 mus_info = Load_WAV(filename);
1568 else if (FileIsMusic(basename))
1569 mus_info = Load_MOD(filename);
1576 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1577 Music[num_music -1] = mus_info;
1584 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1588 void PlayMusic(int nr)
1590 if (!audio.music_available)
1593 #if defined(TARGET_SDL)
1595 nr = nr % num_music;
1597 if (Music[nr]->type == MUS_TYPE_MOD)
1599 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1600 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1602 else /* play WAV music loop */
1604 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1605 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1615 void PlaySound(int nr)
1617 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1620 void PlaySoundStereo(int nr, int stereo)
1622 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1625 void PlaySoundLoop(int nr)
1627 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1630 void PlaySoundMusic(int nr)
1632 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1635 void PlaySoundExt(int nr, int volume, int stereo, int state)
1637 struct SoundControl snd_ctrl;
1639 if (!audio.sound_available ||
1640 !audio.sound_enabled ||
1641 audio.sound_deactivated)
1644 if (volume < PSND_MIN_VOLUME)
1645 volume = PSND_MIN_VOLUME;
1646 else if (volume > PSND_MAX_VOLUME)
1647 volume = PSND_MAX_VOLUME;
1649 if (stereo < PSND_MAX_LEFT)
1650 stereo = PSND_MAX_LEFT;
1651 else if (stereo > PSND_MAX_RIGHT)
1652 stereo = PSND_MAX_RIGHT;
1654 snd_ctrl.active = TRUE;
1656 snd_ctrl.volume = volume;
1657 snd_ctrl.stereo = stereo;
1658 snd_ctrl.state = state;
1660 #if defined(TARGET_SDL)
1663 Mix_Volume(-1, SOUND_MAX_VOLUME);
1664 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1666 #elif defined(PLATFORM_UNIX)
1667 if (audio.soundserver_pid == 0) /* we are child process */
1670 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1672 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1673 audio.sound_available = audio.sound_enabled = FALSE;
1676 #elif defined(PLATFORM_MSDOS)
1677 sound_handler(snd_ctrl);
1681 void FadeMusic(void)
1683 if (!audio.sound_available)
1686 #if defined(TARGET_SDL)
1687 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1688 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1690 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1694 void FadeSound(int nr)
1696 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1702 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1705 void StopMusic(void)
1707 #if defined(TARGET_SDL)
1708 if (!audio.sound_available)
1712 Mix_HaltChannel(audio.music_channel);
1714 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1718 void StopSound(int nr)
1720 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1726 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1729 void StopSoundExt(int nr, int state)
1731 struct SoundControl snd_ctrl;
1733 if (!audio.sound_available)
1736 snd_ctrl.active = FALSE;
1738 snd_ctrl.state = state;
1740 #if defined(TARGET_SDL)
1742 if (state & SND_CTRL_FADE)
1747 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
1750 for (i=0; i<audio.channels; i++)
1751 if (i != audio.music_channel || snd_ctrl.music)
1752 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1753 if (state & SND_CTRL_MUSIC)
1754 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1760 for (i=0; i<audio.channels; i++)
1761 if (i != audio.music_channel || snd_ctrl.music)
1763 if (state & SND_CTRL_MUSIC)
1767 #elif !defined(PLATFORM_MSDOS)
1769 if (audio.soundserver_pid == 0) /* we are child process */
1772 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1774 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1775 audio.sound_available = audio.sound_enabled = FALSE;
1778 #else /* PLATFORM_MSDOS */
1779 sound_handler(snd_ctrl);
1783 ListNode *newListNode()
1785 return checked_calloc(sizeof(ListNode));
1788 void addNodeToList(ListNode **node_first, char *key, void *content)
1790 ListNode *node_new = newListNode();
1793 printf("LIST: adding node with key '%s'\n", key);
1796 node_new->key = getStringCopy(key);
1797 node_new->content = content;
1798 node_new->next = *node_first;
1799 *node_first = node_new;
1802 void deleteNodeFromList(ListNode **node_first, char *key,
1803 void (*destructor_function)(void *))
1805 if (node_first == NULL || *node_first == NULL)
1809 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1810 (*node_first)->key, key);
1813 if (strcmp((*node_first)->key, key) == 0)
1816 printf("[DELETING LIST ENTRY]\n");
1819 free((*node_first)->key);
1820 if (destructor_function)
1821 destructor_function((*node_first)->content);
1822 *node_first = (*node_first)->next;
1825 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1828 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1830 if (node_first == NULL)
1833 if (strcmp(node_first->key, key) == 0)
1836 return getNodeFromKey(node_first->next, key);
1839 int getNumNodes(ListNode *node_first)
1841 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1844 void dumpList(ListNode *node_first)
1846 ListNode *node = node_first;
1850 printf("['%s' (%d)]\n", node->key,
1851 ((SoundInfo *)node->content)->num_references);
1855 printf("[%d nodes]\n", getNumNodes(node_first));
1858 static void LoadSoundsInfo()
1860 char *filename = getCustomSoundConfigFilename();
1861 struct SetupFileList *setup_file_list;
1864 /* always start with reliable default values */
1865 for (i=0; i<num_sounds; i++)
1866 sound_effect[i].filename = NULL;
1868 if (filename == NULL)
1871 if ((setup_file_list = loadSetupFileList(filename)))
1873 for (i=0; i<num_sounds; i++)
1874 sound_effect[i].filename =
1875 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1877 freeSetupFileList(setup_file_list);
1880 for (i=0; i<num_sounds; i++)
1882 printf("'%s' ", sound_effect[i].text);
1883 if (sound_effect[i].filename)
1884 printf("-> '%s'\n", sound_effect[i].filename);
1886 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1892 static void ReloadCustomSounds()
1897 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1903 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1906 for(i=0; i<num_sounds; i++)
1908 if (sound_effect[i].filename)
1909 LoadSoundToList(sound_effect[i].filename, i);
1911 LoadSoundToList(sound_effect[i].default_filename, i);
1915 printf("list size == %d\n", getNumNodes(SoundFileList));
1919 dumpList(SoundFileList);
1923 static void ReloadCustomMusic()
1926 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1934 static void InitReloadSoundsOrMusic(char *set_name, int type)
1936 if (!audio.sound_available)
1939 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1940 if (type == SND_CTRL_RELOAD_SOUNDS)
1941 ReloadCustomSounds();
1943 ReloadCustomMusic();
1944 #elif defined(PLATFORM_UNIX)
1945 if (audio.soundserver_pid == 0) /* we are child process */
1948 if (leveldir_current == NULL) /* should never happen */
1949 Error(ERR_EXIT, "leveldir_current == NULL");
1952 WriteReloadInfoToPipe(set_name, type);
1955 snd_ctrl.active = FALSE;
1956 snd_ctrl.state = type;
1957 snd_ctrl.data_len = strlen(set_name) + 1;
1959 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1960 sizeof(snd_ctrl)) < 0 ||
1961 write(audio.soundserver_pipe[1], set_name,
1962 snd_ctrl.data_len) < 0 ||
1963 write(audio.soundserver_pipe[1], leveldir_current,
1964 sizeof(TreeInfo)) < 0 ||
1965 write(audio.soundserver_pipe[1], ti,
1966 sizeof(TreeInfo)) < 0 ||
1967 write(audio.soundserver_pipe[1], &str_size1,
1968 sizeof(unsigned long)) < 0 ||
1969 write(audio.soundserver_pipe[1], &str_size2,
1970 sizeof(unsigned long)) < 0 ||
1971 write(audio.soundserver_pipe[1], &str_size3,
1972 sizeof(unsigned long)) < 0 ||
1973 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1975 write(audio.soundserver_pipe[1], ti->basepath,
1977 write(audio.soundserver_pipe[1], ti->fullpath,
1980 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1981 audio.sound_available = audio.sound_enabled = FALSE;
1989 void InitReloadSounds(char *set_name)
1991 InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_SOUNDS);
1994 void InitReloadMusic(char *set_name)
1996 InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_MUSIC);
1999 void FreeSound(void *ptr)
2001 SoundInfo *sound = (SoundInfo *)ptr;
2006 if (sound->data_ptr)
2008 #if defined(TARGET_SDL)
2009 Mix_FreeChunk(sound->data_ptr);
2010 #elif defined(TARGET_ALLEGRO)
2011 destroy_sample(sound->data_ptr);
2012 #else /* PLATFORM_UNIX */
2013 free(sound->data_ptr);
2017 if (sound->source_filename)
2018 free(sound->source_filename);
2023 void FreeMusic(MusicInfo *music)
2028 if (music->data_ptr)
2030 #if defined(TARGET_SDL)
2031 if (music->type == MUS_TYPE_MOD)
2032 Mix_FreeMusic(music->data_ptr);
2034 Mix_FreeChunk(music->data_ptr);
2035 #elif defined(TARGET_ALLEGRO)
2036 destroy_sample(music->data_ptr);
2037 #else /* PLATFORM_UNIX */
2038 free(music->data_ptr);
2045 void FreeAllSounds()
2052 printf("%s: FREEING SOUNDS ...\n",
2053 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2055 for(i=0; i<num_sounds; i++)
2056 deleteSoundEntry(&Sound[i]);
2058 FreeSound(Sound[i]);
2061 printf("%s: FREEING SOUNDS -- DONE\n",
2062 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2077 for(i=0; i<num_music; i++)
2078 FreeMusic(Music[i]);
2086 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2087 /* ========================================================================= */