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 =
54 TRUE, 0, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_FRAGMENT_SIZE
57 static int playing_sounds = 0;
58 static struct SoundControl playlist[NUM_MIXER_CHANNELS];
59 static struct SoundControl emptySoundControl =
61 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
64 #if defined(PLATFORM_UNIX)
65 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
66 static short premix_first_buffer[SND_BLOCKSIZE];
67 #if defined(AUDIO_STREAMING_DSP)
68 static short premix_left_buffer[SND_BLOCKSIZE];
69 static short premix_right_buffer[SND_BLOCKSIZE];
70 static long premix_last_buffer[SND_BLOCKSIZE];
72 static byte playing_buffer[SND_BLOCKSIZE];
75 /* forward declaration of internal functions */
76 #if defined(AUDIO_STREAMING_DSP)
77 static void SoundServer_InsertNewSound(struct SoundControl);
78 static void InitAudioDevice_DSP(struct AudioFormatInfo *);
79 #elif defined(PLATFORM_HPUX)
80 static void InitAudioDevice_HPUX(struct AudioFormatInfo *);
81 #elif defined(PLATFORM_UNIX)
82 static unsigned char linear_to_ulaw(int);
83 static int ulaw_to_linear(unsigned char);
84 #elif defined(PLATFORM_MSDOS)
85 static void SoundServer_InsertNewSound(struct SoundControl);
86 static void SoundServer_StopSound(struct SoundControl);
87 static void SoundServer_StopAllSounds();
90 static void ReloadCustomSounds();
91 static void ReloadCustomMusic();
92 static void FreeSound(void *);
94 #if defined(PLATFORM_UNIX)
95 static int OpenAudioDevice(char *audio_device_name)
99 /* check if desired audio device is accessible */
100 if (access(audio_device_name, W_OK) != 0)
103 /* try to open audio device in non-blocking mode */
104 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
107 /* re-open audio device in blocking mode */
109 audio_fd = open(audio_device_name, O_WRONLY);
114 static boolean TestAudioDevices(void)
116 static char *audio_device_name[] =
124 /* look for available audio devices, starting with preferred ones */
125 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
126 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
131 Error(ERR_WARN, "cannot open audio device -- no sound");
137 audio.device_name = audio_device_name[i];
142 #if !defined(TARGET_SDL)
143 static boolean ForkAudioProcess(void)
145 if (pipe(audio.soundserver_pipe) < 0)
147 Error(ERR_WARN, "cannot create pipe -- no sounds");
151 if ((audio.soundserver_pid = fork()) < 0)
153 Error(ERR_WARN, "cannot create sound server process -- no sounds");
157 if (audio.soundserver_pid == 0) /* we are child process */
164 else /* we are parent */
165 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
171 void UnixOpenAudio(void)
173 if (!TestAudioDevices())
176 audio.sound_available = TRUE;
177 audio.sound_enabled = TRUE;
179 #if defined(AUDIO_STREAMING_DSP)
180 audio.music_available = TRUE;
181 audio.loops_available = TRUE;
185 void UnixCloseAudio(void)
188 close(audio.device_fd);
190 if (audio.soundserver_pid > 0) /* we are parent process */
191 kill(audio.soundserver_pid, SIGTERM);
193 #endif /* PLATFORM_UNIX */
195 void InitPlaylist(void)
199 for(i=0; i<NUM_MIXER_CHANNELS; i++)
200 playlist[i] = emptySoundControl;
205 static void HandleSoundRequest(struct SoundControl snd_ctrl)
209 if (snd_ctrl.fade_sound)
215 playlist[audio.music_channel].fade_sound = TRUE;
217 for(i=0; i<NUM_MIXER_CHANNELS; i++)
218 if (snd_ctrl.stop_all_sounds ||
219 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
220 playlist[i].fade_sound = TRUE;
222 else if (snd_ctrl.stop_all_sounds)
227 for(i=0; i<NUM_MIXER_CHANNELS; i++)
228 playlist[i] = emptySoundControl;
231 close(audio.device_fd);
233 else if (snd_ctrl.stop_sound)
240 playlist[audio.music_channel] = emptySoundControl;
244 for(i=0; i<NUM_MIXER_CHANNELS; i++)
246 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
248 playlist[i] = emptySoundControl;
254 close(audio.device_fd);
259 void StartSoundserver(void)
261 if (!audio.sound_available)
264 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
265 if (!ForkAudioProcess())
266 audio.sound_available = FALSE;
270 #if defined(PLATFORM_UNIX)
271 void SoundServer(void)
275 struct SoundControl snd_ctrl;
278 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
282 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
283 for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
285 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
287 #if defined(PLATFORM_HPUX)
288 InitAudioDevice_HPUX(&afmt);
291 FD_ZERO(&sound_fdset);
292 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
294 while(1) /* wait for sound playing commands from client */
296 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
297 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
298 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
300 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
302 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
304 if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
306 char *set_name = checked_malloc(snd_ctrl.data_len);
308 (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
309 TreeInfo *ti = *ti_ptr;
310 unsigned long str_size1, str_size2, str_size3;
312 if (leveldir_current == NULL)
313 leveldir_current = checked_calloc(sizeof(TreeInfo));
315 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
316 if (leveldir_current->fullpath != NULL)
317 free(leveldir_current->fullpath);
318 if (ti->basepath != NULL)
320 if (ti->fullpath != NULL)
323 if (read(audio.soundserver_pipe[0], set_name,
324 snd_ctrl.data_len) != snd_ctrl.data_len ||
325 read(audio.soundserver_pipe[0], leveldir_current,
326 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
327 read(audio.soundserver_pipe[0], ti,
328 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
329 read(audio.soundserver_pipe[0], &str_size1,
330 sizeof(unsigned long)) != sizeof(unsigned long) ||
331 read(audio.soundserver_pipe[0], &str_size2,
332 sizeof(unsigned long)) != sizeof(unsigned long) ||
333 read(audio.soundserver_pipe[0], &str_size3,
334 sizeof(unsigned long)) != sizeof(unsigned long))
335 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
337 leveldir_current->fullpath = checked_calloc(str_size1);
338 ti->basepath = checked_calloc(str_size2);
339 ti->fullpath = checked_calloc(str_size3);
341 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
342 str_size1) != str_size1 ||
343 read(audio.soundserver_pipe[0], ti->basepath,
344 str_size2) != str_size2 ||
345 read(audio.soundserver_pipe[0], ti->fullpath,
346 str_size3) != str_size3)
347 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
351 close(audio.device_fd);
353 if (snd_ctrl.reload_sounds)
355 artwork.sounds_set_current = set_name;
356 ReloadCustomSounds();
360 artwork.music_set_current = set_name;
369 #if defined(AUDIO_STREAMING_DSP)
372 HandleSoundRequest(snd_ctrl);
375 if (snd_ctrl.fade_sound)
381 playlist[audio.music_channel].fade_sound = TRUE;
383 for(i=0; i<NUM_MIXER_CHANNELS; i++)
384 if (snd_ctrl.stop_all_sounds ||
385 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
386 playlist[i].fade_sound = TRUE;
388 else if (snd_ctrl.stop_all_sounds)
393 for(i=0; i<NUM_MIXER_CHANNELS; i++)
394 playlist[i] = emptySoundControl;
397 close(audio.device_fd);
399 else if (snd_ctrl.stop_sound)
406 if (playlist[audio.music_channel].active)
408 playlist[audio.music_channel] = emptySoundControl;
413 for(i=0; i<NUM_MIXER_CHANNELS; i++)
415 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
417 playlist[i] = emptySoundControl;
423 close(audio.device_fd);
427 if (playing_sounds || snd_ctrl.active)
429 if (playing_sounds ||
430 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
432 struct timeval delay = { 0, 0 };
434 if (!playing_sounds) /* we just opened the audio device */
435 InitAudioDevice_DSP(&afmt);
437 if (snd_ctrl.active) /* new sound has arrived */
438 SoundServer_InsertNewSound(snd_ctrl);
440 while (playing_sounds &&
441 select(audio.soundserver_pipe[0] + 1,
442 &sound_fdset, NULL, NULL, &delay) < 1)
445 int fragment_size = afmt.fragment_size;
446 int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
447 boolean stereo = afmt.stereo;
449 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
451 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
453 /* first clear the last premixing buffer */
454 memset(premix_last_buffer, 0,
455 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
457 for(i=0; i<NUM_MIXER_CHANNELS; i++)
465 if (!playlist[i].active)
468 /* pointer, lenght and actual playing position of sound sample */
469 sample_ptr = playlist[i].data_ptr;
470 sample_len = playlist[i].data_len;
471 sample_pos = playlist[i].playingpos;
472 sample_size = MIN(max_sample_size, sample_len - sample_pos);
473 playlist[i].playingpos += sample_size;
475 /* copy original sample to first mixing buffer */
476 if (playlist[i].format == AUDIO_FORMAT_U8)
477 for (j=0; j<sample_size; j++)
478 premix_first_buffer[j] =
479 ((short)(((byte *)sample_ptr)[sample_pos + j] ^ 0x80)) << 8;
480 else /* AUDIO_FORMAT_S16 */
481 for (j=0; j<sample_size; j++)
482 premix_first_buffer[j] =
483 ((short *)sample_ptr)[sample_pos + j];
485 /* are we about to restart a looping sound? */
486 if (playlist[i].loop && sample_size < max_sample_size)
488 while (sample_size < max_sample_size)
490 int restarted_sample_size =
491 MIN(max_sample_size - sample_size, sample_len);
493 if (playlist[i].format == AUDIO_FORMAT_U8)
494 for (j=0; j<restarted_sample_size; j++)
495 premix_first_buffer[sample_size + j] =
496 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
498 for (j=0; j<restarted_sample_size; j++)
499 premix_first_buffer[sample_size + j] =
500 ((short *)sample_ptr)[j];
502 playlist[i].playingpos = restarted_sample_size;
503 sample_size += restarted_sample_size;
507 /* decrease volume if sound is fading out */
508 if (playlist[i].fade_sound &&
509 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
510 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
512 /* adjust volume of actual sound sample */
513 if (playlist[i].volume != PSND_MAX_VOLUME)
514 for(j=0; j<sample_size; j++)
515 premix_first_buffer[j] =
516 (playlist[i].volume * (long)premix_first_buffer[j])
517 >> PSND_MAX_VOLUME_BITS;
519 /* fill the last mixing buffer with stereo or mono sound */
522 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
523 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
524 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
526 for(j=0; j<sample_size; j++)
528 premix_left_buffer[j] =
529 (left_volume * premix_first_buffer[j])
530 >> PSND_MAX_LEFT2RIGHT_BITS;
531 premix_right_buffer[j] =
532 (right_volume * premix_first_buffer[j])
533 >> PSND_MAX_LEFT2RIGHT_BITS;
535 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
536 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
541 for(j=0; j<sample_size; j++)
542 premix_last_buffer[j] += premix_first_buffer[j];
545 /* delete completed sound entries from the playlist */
546 if (playlist[i].playingpos >= playlist[i].data_len)
548 if (playlist[i].loop)
549 playlist[i].playingpos = 0;
552 playlist[i] = emptySoundControl;
556 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
558 playlist[i] = emptySoundControl;
563 /* prepare final playing buffer according to system audio format */
564 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
566 /* cut off at 17 bit value */
567 if (premix_last_buffer[i] < -65535)
568 premix_last_buffer[i] = -65535;
569 else if (premix_last_buffer[i] > 65535)
570 premix_last_buffer[i] = 65535;
572 /* shift to 16 bit value */
573 premix_last_buffer[i] >>= 1;
575 if (afmt.format & AUDIO_FORMAT_U8)
577 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
579 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
581 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
582 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
584 else /* big endian */
586 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
587 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
591 /* finally play the sound fragment */
592 write(audio.device_fd, playing_buffer, fragment_size);
595 /* if no sounds playing, free device for other sound programs */
597 close(audio.device_fd);
601 #else /* !AUDIO_STREAMING_DSP */
603 if (snd_ctrl.active && !snd_ctrl.loop)
605 struct timeval delay = { 0, 0 };
607 long sample_size, max_sample_size = SND_BLOCKSIZE;
608 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
609 int wait_percent = 90; /* wait 90% of the real playing time */
612 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
616 while (playing_sounds &&
617 select(audio.soundserver_pipe[0] + 1,
618 &sound_fdset, NULL, NULL, &delay) < 1)
620 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
622 /* get pointer and size of the actual sound sample */
623 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
625 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
626 snd_ctrl.playingpos += sample_size;
628 /* fill the first mixing buffer with original sample */
629 memcpy(premix_first_buffer,sample_ptr,sample_size);
631 /* adjust volume of actual sound sample */
632 if (snd_ctrl.volume != PSND_MAX_VOLUME)
633 for(i=0;i<sample_size;i++)
634 premix_first_buffer[i] =
635 (snd_ctrl.volume * (int)premix_first_buffer[i])
636 >> PSND_MAX_VOLUME_BITS;
638 for(i=0;i<sample_size;i++)
640 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
642 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
645 /* finally play the sound fragment */
646 write(audio.device_fd,playing_buffer,sample_size);
649 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
651 close(audio.device_fd);
654 #endif /* !AUDIO_STREAMING_DSP */
657 #endif /* PLATFORM_UNIX */
659 #if defined(PLATFORM_MSDOS)
660 static void sound_handler(struct SoundControl snd_ctrl)
664 if (snd_ctrl.fade_sound)
669 for (i=0; i<NUM_MIXER_CHANNELS; i++)
670 if ((snd_ctrl.stop_all_sounds ||
671 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
672 (i == audio.music_channel && snd_ctrl.music)) &&
673 !playlist[i].fade_sound)
675 playlist[i].fade_sound = TRUE;
676 if (voice_check(playlist[i].voice))
677 voice_ramp_volume(playlist[i].voice, 1000, 0);
678 playlist[i].loop = PSND_NO_LOOP;
681 else if (snd_ctrl.stop_all_sounds)
685 SoundServer_StopAllSounds();
687 else if (snd_ctrl.stop_sound)
691 SoundServer_StopSound(snd_ctrl);
694 for (i=0; i<NUM_MIXER_CHANNELS; i++)
696 if (!playlist[i].active || playlist[i].loop)
699 playlist[i].playingpos = voice_get_position(playlist[i].voice);
700 playlist[i].volume = voice_get_volume(playlist[i].voice);
701 if (playlist[i].playingpos == -1 || !playlist[i].volume)
703 deallocate_voice(playlist[i].voice);
704 playlist[i] = emptySoundControl;
710 SoundServer_InsertNewSound(snd_ctrl);
712 #endif /* PLATFORM_MSDOS */
715 #if defined(TARGET_SDL)
716 static void sound_handler_SDL(struct SoundControl snd_ctrl)
720 if (snd_ctrl.fade_sound)
725 for (i=0; i<NUM_MIXER_CHANNELS; i++)
726 if ((snd_ctrl.stop_all_sounds ||
727 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
728 (i == audio.music_channel && snd_ctrl.music)) &&
729 !playlist[i].fade_sound)
731 playlist[i].fade_sound = TRUE;
732 if (voice_check(playlist[i].voice))
733 voice_ramp_volume(playlist[i].voice, 1000, 0);
734 playlist[i].loop = PSND_NO_LOOP;
737 else if (snd_ctrl.stop_all_sounds)
741 SoundServer_StopAllSounds();
743 else if (snd_ctrl.stop_sound)
747 SoundServer_StopSound(snd_ctrl);
750 for (i=0; i<NUM_MIXER_CHANNELS; i++)
752 if (!playlist[i].active || playlist[i].loop)
755 playlist[i].playingpos = voice_get_position(playlist[i].voice);
756 playlist[i].volume = voice_get_volume(playlist[i].voice);
757 if (playlist[i].playingpos == -1 || !playlist[i].volume)
759 deallocate_voice(playlist[i].voice);
760 playlist[i] = emptySoundControl;
766 SoundServer_InsertNewSound(snd_ctrl);
768 #endif /* TARGET_SDL */
771 #if !defined(PLATFORM_WIN32)
772 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
778 snd_ctrl.nr = snd_ctrl.nr % num_music;
779 else if (snd_ctrl.nr >= num_sounds)
782 snd_info = (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
783 if (snd_info == NULL)
786 printf("sound/music %d undefined\n", snd_ctrl.nr);
792 printf("-> %d\n", playing_sounds);
795 if (playing_sounds == NUM_MIXER_CHANNELS)
797 for (i=0; i<NUM_MIXER_CHANNELS; i++)
799 if (playlist[i].data_ptr == NULL)
802 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
805 playlist[i] = emptySoundControl;
811 /* if playlist is full, remove oldest sound */
812 if (playing_sounds == NUM_MIXER_CHANNELS)
814 int longest = 0, longest_nr = 0;
816 for (i=0; i<NUM_MIXER_CHANNELS; i++)
818 #if !defined(PLATFORM_MSDOS)
819 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
821 int actual = playlist[i].playingpos;
824 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
830 #if defined(PLATFORM_MSDOS)
831 voice_set_volume(playlist[longest_nr].voice, 0);
832 deallocate_voice(playlist[longest_nr].voice);
834 playlist[longest_nr] = emptySoundControl;
838 /* check if sound is already being played (and how often) */
839 for (k=0,i=0; i<NUM_MIXER_CHANNELS; i++)
840 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
843 /* restart loop sounds only if they are just fading out */
844 if (k >= 1 && snd_ctrl.loop)
846 for(i=0; i<NUM_MIXER_CHANNELS; i++)
848 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
849 playlist[i].fade_sound)
851 playlist[i].fade_sound = FALSE;
852 playlist[i].volume = PSND_MAX_VOLUME;
853 #if defined(PLATFORM_MSDOS)
854 playlist[i].loop = PSND_LOOP;
855 voice_stop_volumeramp(playlist[i].voice);
856 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
864 /* don't play sound more than n times simultaneously (with n == 2 for now) */
867 int longest = 0, longest_nr = 0;
869 /* look for oldest equal sound */
870 for(i=0; i<NUM_MIXER_CHANNELS; i++)
874 if (!playlist[i].active ||
875 i == audio.music_channel ||
876 playlist[i].nr != snd_ctrl.nr)
879 #if !defined(PLATFORM_MSDOS)
880 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
882 actual = playlist[i].playingpos;
884 if (actual >= longest)
891 #if defined(PLATFORM_MSDOS)
892 voice_set_volume(playlist[longest_nr].voice, 0);
893 deallocate_voice(playlist[longest_nr].voice);
895 playlist[longest_nr] = emptySoundControl;
899 /* add new sound to playlist */
900 for(i=0; i<NUM_MIXER_CHANNELS; i++)
902 if (!playlist[i].active ||
903 (snd_ctrl.music && i == audio.music_channel))
905 snd_ctrl.data_ptr = snd_info->data_ptr;
906 snd_ctrl.data_len = snd_info->data_len;
907 snd_ctrl.format = snd_info->format;
910 if (snd_info->data_len == 0)
912 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
917 if (snd_ctrl.music && i == audio.music_channel && playlist[i].active)
919 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
922 playlist[i] = emptySoundControl;
928 playlist[i] = snd_ctrl;
931 #if defined(PLATFORM_MSDOS)
932 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
935 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
937 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
938 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
939 voice_start(playlist[i].voice);
945 #endif /* !PLATFORM_WIN32 */
948 void SoundServer_FadeSound(int nr)
955 for(i=0;i<NUM_MIXER_CHANNELS;i++)
956 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
957 playlist[i].fade_sound = TRUE;
961 #if !defined(PLATFORM_WIN32)
962 #if defined(PLATFORM_MSDOS)
963 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
965 int nr = snd_ctrl.nr;
971 for(i=0; i<NUM_MIXER_CHANNELS; i++)
973 if ((i == audio.music_channel && snd_ctrl.music) ||
974 (i != audio.music_channel && playlist[i].nr == nr))
976 #if defined(PLATFORM_MSDOS)
977 voice_set_volume(playlist[i].voice, 0);
978 deallocate_voice(playlist[i].voice);
980 playlist[i] = emptySoundControl;
985 #if !defined(PLATFORM_MSDOS)
987 close(audio.device_fd);
991 static void SoundServer_StopAllSounds()
995 for(i=0; i<NUM_MIXER_CHANNELS; i++)
997 #if defined(PLATFORM_MSDOS)
998 voice_set_volume(playlist[i].voice, 0);
999 deallocate_voice(playlist[i].voice);
1001 playlist[i] = emptySoundControl;
1005 #if !defined(PLATFORM_MSDOS)
1006 close(audio.device_fd);
1009 #endif /* PLATFORM_MSDOS */
1010 #endif /* !PLATFORM_WIN32 */
1013 /* ------------------------------------------------------------------------- */
1014 /* platform dependant audio initialization code */
1015 /* ------------------------------------------------------------------------- */
1017 #if defined(AUDIO_LINUX_IOCTL)
1018 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1020 /* "ioctl()" expects pointer to 'int' value for stereo flag
1021 (boolean is defined as 'char', which will not work here) */
1022 unsigned int fragment_spec = 0;
1023 int fragment_size_query;
1032 /* supported audio format in preferred order */
1033 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1034 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1035 { AFMT_U8, AUDIO_FORMAT_U8 },
1040 /* determine logarithm (log2) of the fragment size */
1041 while ((1 << fragment_spec) < afmt->fragment_size)
1044 /* use two fragments (play one fragment, prepare the other);
1045 one fragment would result in interrupted audio output, more
1046 than two fragments would raise audio output latency to much */
1047 fragment_spec |= 0x00020000;
1049 /* Example for fragment specification:
1050 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1051 - (with stereo the effective buffer size will shrink to 256)
1052 => fragment_size = 0x00020009 */
1054 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1055 Error(ERR_EXIT_SOUND_SERVER,
1056 "cannot set fragment size of /dev/dsp -- no sounds");
1060 while (formats[i].format_result != -1)
1062 unsigned int audio_format = formats[i].format_ioctl;
1063 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1065 afmt->format = formats[i].format_result;
1070 if (afmt->format == 0) /* no supported audio format found */
1071 Error(ERR_EXIT_SOUND_SERVER,
1072 "cannot set audio format of /dev/dsp -- no sounds");
1074 /* try if we can use stereo sound */
1075 afmt->stereo = TRUE;
1076 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1077 afmt->stereo = FALSE;
1079 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1080 Error(ERR_EXIT_SOUND_SERVER,
1081 "cannot set sample rate of /dev/dsp -- no sounds");
1083 /* get the real fragmentation size; this should return 512 */
1084 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1085 Error(ERR_EXIT_SOUND_SERVER,
1086 "cannot get fragment size of /dev/dsp -- no sounds");
1087 if (fragment_size_query != afmt->fragment_size)
1088 Error(ERR_EXIT_SOUND_SERVER,
1089 "cannot set fragment size of /dev/dsp -- no sounds");
1091 #endif /* AUDIO_LINUX_IOCTL */
1093 #if defined(PLATFORM_NETBSD)
1094 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1096 audio_info_t a_info;
1097 boolean stereo = TRUE;
1099 AUDIO_INITINFO(&a_info);
1100 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1101 a_info.play.precision = 8;
1102 a_info.play.channels = 2;
1103 a_info.play.sample_rate = sample_rate;
1104 a_info.blocksize = fragment_size;
1106 afmt->format = AUDIO_FORMAT_U8;
1107 afmt->stereo = TRUE;
1109 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1111 /* try to disable stereo */
1112 a_info.play.channels = 1;
1114 afmt->stereo = FALSE;
1116 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1117 Error(ERR_EXIT_SOUND_SERVER,
1118 "cannot set sample rate of /dev/audio -- no sounds");
1121 #endif /* PLATFORM_NETBSD */
1123 #if defined(PLATFORM_HPUX)
1124 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1126 struct audio_describe ainfo;
1129 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1130 if (audio_ctl == -1)
1131 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1133 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1134 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1136 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1137 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1139 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1140 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1142 afmt->format = AUDIO_FORMAT_U8;
1143 afmt->stereo = FALSE;
1144 afmt->sample_rate = 8000;
1148 #endif /* PLATFORM_HPUX */
1150 #if defined(PLATFORM_UNIX)
1151 static void InitAudioDevice_DSP(struct AudioFormatInfo *afmt)
1153 #if defined(AUDIO_LINUX_IOCTL)
1154 InitAudioDevice_Linux(afmt);
1155 #elif defined(PLATFORM_NETBSD)
1156 InitAudioDevice_NetBSD(afmt);
1157 #elif defined(PLATFORM_HPUX)
1158 InitAudioDevice_HPUX(afmt);
1161 #endif /* PLATFORM_UNIX */
1163 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1165 /* these two are stolen from "sox"... :) */
1168 ** This routine converts from linear to ulaw.
1170 ** Craig Reese: IDA/Supercomputing Research Center
1171 ** Joe Campbell: Department of Defense
1172 ** 29 September 1989
1175 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1176 ** 2) "A New Digital Technique for Implementation of Any
1177 ** Continuous PCM Companding Law," Villeret, Michel,
1178 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1179 ** 1973, pg. 11.12-11.17
1180 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1181 ** for Analog-to_Digital Conversion Techniques,"
1184 ** Input: Signed 16 bit linear sample
1185 ** Output: 8 bit ulaw sample
1188 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1189 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1192 static unsigned char linear_to_ulaw(int sample)
1194 static int exp_lut[256] =
1196 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1197 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1198 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1199 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1200 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1201 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1202 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1203 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1204 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1205 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1206 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1207 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1208 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1209 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1210 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1211 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1214 int sign, exponent, mantissa;
1215 unsigned char ulawbyte;
1217 /* Get the sample into sign-magnitude. */
1218 sign = (sample >> 8) & 0x80; /* set aside the sign */
1220 sample = -sample; /* get magnitude */
1222 sample = CLIP; /* clip the magnitude */
1224 /* Convert from 16 bit linear to ulaw. */
1225 sample = sample + BIAS;
1226 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1227 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1228 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1231 ulawbyte = 0x02; /* optional CCITT trap */
1238 ** This routine converts from ulaw to 16 bit linear.
1240 ** Craig Reese: IDA/Supercomputing Research Center
1241 ** 29 September 1989
1244 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1245 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1246 ** for Analog-to_Digital Conversion Techniques,"
1249 ** Input: 8 bit ulaw sample
1250 ** Output: signed 16 bit linear sample
1253 static int ulaw_to_linear(unsigned char ulawbyte)
1255 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1256 int sign, exponent, mantissa, sample;
1258 ulawbyte = ~ ulawbyte;
1259 sign = ( ulawbyte & 0x80 );
1260 exponent = ( ulawbyte >> 4 ) & 0x07;
1261 mantissa = ulawbyte & 0x0F;
1262 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1268 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1271 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1272 /* ========================================================================= */
1273 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1275 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1276 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1278 static SoundInfo *Load_WAV(char *filename)
1280 SoundInfo *snd_info;
1281 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1282 byte sound_header_buffer[WAV_HEADER_SIZE];
1283 char chunk_name[CHUNK_ID_LEN + 1];
1289 if (!audio.sound_available)
1293 printf("loading WAV file '%s'\n", filename);
1296 snd_info = checked_calloc(sizeof(SoundInfo));
1298 #if defined(TARGET_SDL)
1300 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1302 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1307 #elif defined(TARGET_ALLEGRO)
1309 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1311 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1316 #else /* PLATFORM_UNIX */
1318 if ((file = fopen(filename, MODE_READ)) == NULL)
1320 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1325 /* read chunk id "RIFF" */
1326 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1327 if (strcmp(chunk_name, "RIFF") != 0)
1329 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1335 /* read "RIFF" type id "WAVE" */
1336 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1337 if (strcmp(chunk_name, "WAVE") != 0)
1339 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1345 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1347 if (strcmp(chunk_name, "fmt ") == 0)
1349 /* read header information */
1350 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1351 sound_header_buffer[i] = fgetc(file);
1353 if (chunk_size > WAV_HEADER_SIZE)
1354 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1356 else if (strcmp(chunk_name, "data") == 0)
1358 snd_info->data_len = chunk_size;
1359 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1361 /* read sound data */
1362 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1365 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1367 free(snd_info->data_ptr);
1372 /* check for odd number of sample bytes (data chunk is word aligned) */
1373 if ((chunk_size % 2) == 1)
1374 ReadUnusedBytesFromFile(file, 1);
1376 else /* unknown chunk -- ignore */
1377 ReadUnusedBytesFromFile(file, chunk_size);
1382 if (snd_info->data_ptr == NULL)
1384 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1389 snd_info->format = AUDIO_FORMAT_U8;
1391 #endif /* PLATFORM_UNIX */
1393 snd_info->type = SND_TYPE_WAV;
1394 snd_info->source_filename = getStringCopy(filename);
1399 static void deleteSoundEntry(SoundInfo **snd_info)
1403 char *filename = (*snd_info)->source_filename;
1406 printf("[decrementing reference counter of sound '%s']\n", filename);
1409 if (--(*snd_info)->num_references <= 0)
1412 printf("[deleting sound '%s']\n", filename);
1416 FreeSound(*snd_info);
1418 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1425 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1429 /* check if the old and the new sound file are the same */
1430 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1432 /* The old and new sound are the same (have the same filename and path).
1433 This usually means that this sound does not exist in this sound set
1434 and a fallback to the existing sound is done. */
1437 printf("[sound '%s' already exists (same list entry)]\n", filename);
1443 /* delete existing sound file entry */
1444 deleteSoundEntry(snd_info);
1446 /* check if the new sound file already exists in the list of sounds */
1447 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1450 printf("[sound '%s' already exists (other list entry)]\n", filename);
1453 *snd_info = (SoundInfo *)node->content;
1454 (*snd_info)->num_references++;
1456 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1458 (*snd_info)->num_references = 1;
1459 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1463 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1465 char *filename = getCustomSoundFilename(basename);
1467 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1469 deleteSoundEntry(snd_info);
1473 if (filename == NULL)
1475 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1479 replaceSoundEntry(snd_info, filename);
1482 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1485 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1487 sound_effect = sounds_list;
1488 num_sounds = num_list_entries;
1491 void LoadSoundToList(char *basename, int list_pos)
1493 if (Sound == NULL || list_pos >= num_sounds)
1497 printf("loading sound '%s' ... [%d]\n",
1498 basename, getNumNodes(SoundFileList));
1501 LoadCustomSound(&Sound[list_pos], basename);
1504 printf("loading sound '%s' done [%d]\n",
1505 basename, getNumNodes(SoundFileList));
1509 static MusicInfo *Load_MOD(char *filename)
1511 #if defined(TARGET_SDL)
1512 MusicInfo *mod_info;
1514 if (!audio.sound_available)
1517 mod_info = checked_calloc(sizeof(MusicInfo));
1519 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1521 Error(ERR_WARN, "cannot read music file '%s'", filename);
1526 mod_info->type = MUS_TYPE_MOD;
1527 mod_info->source_filename = getStringCopy(filename);
1535 void LoadCustomMusic(void)
1537 char *music_directory = getCustomMusicDirectory();
1539 struct dirent *dir_entry;
1541 if (!audio.sound_available)
1544 if ((dir = opendir(music_directory)) == NULL)
1546 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1547 audio.music_available = FALSE;
1551 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1553 char *basename = dir_entry->d_name;
1554 char *filename = getPath2(music_directory, basename);
1555 MusicInfo *mus_info = NULL;
1557 if (FileIsSound(basename))
1558 mus_info = Load_WAV(filename);
1559 else if (FileIsMusic(basename))
1560 mus_info = Load_MOD(filename);
1567 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1568 Music[num_music -1] = mus_info;
1575 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1579 void PlayMusic(int nr)
1581 if (!audio.music_available)
1584 #if defined(TARGET_SDL)
1586 nr = nr % num_music;
1588 if (Music[nr]->type == MUS_TYPE_MOD)
1590 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1591 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1593 else /* play WAV music loop */
1595 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1596 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1606 void PlaySound(int nr)
1608 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1611 void PlaySoundStereo(int nr, int stereo)
1613 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1616 void PlaySoundLoop(int nr)
1618 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1621 void PlaySoundMusic(int nr)
1623 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1626 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1628 struct SoundControl snd_ctrl = emptySoundControl;
1630 if (!audio.sound_available ||
1631 !audio.sound_enabled ||
1632 audio.sound_deactivated)
1635 if (volume < PSND_MIN_VOLUME)
1636 volume = PSND_MIN_VOLUME;
1637 else if (volume > PSND_MAX_VOLUME)
1638 volume = PSND_MAX_VOLUME;
1640 if (stereo < PSND_MAX_LEFT)
1641 stereo = PSND_MAX_LEFT;
1642 else if (stereo > PSND_MAX_RIGHT)
1643 stereo = PSND_MAX_RIGHT;
1646 snd_ctrl.volume = volume;
1647 snd_ctrl.stereo = stereo;
1648 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1649 snd_ctrl.music = (loop_type == PSND_MUSIC);
1650 snd_ctrl.active = TRUE;
1653 /* now only used internally in sound server child process */
1654 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1655 snd_ctrl.data_len = Sound[nr].data_len;
1658 #if defined(TARGET_SDL)
1661 Mix_Volume(-1, SOUND_MAX_VOLUME);
1662 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1664 #elif defined(PLATFORM_UNIX)
1665 if (audio.soundserver_pid == 0) /* we are child process */
1668 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1670 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1671 audio.sound_available = audio.sound_enabled = FALSE;
1674 #elif defined(PLATFORM_MSDOS)
1675 sound_handler(snd_ctrl);
1679 void FadeMusic(void)
1681 if (!audio.sound_available)
1684 #if defined(TARGET_SDL)
1685 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1686 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1688 StopSoundExt(-1, SSND_FADE_MUSIC);
1692 void FadeSound(int nr)
1694 StopSoundExt(nr, SSND_FADE_SOUND);
1700 StopSoundExt(-1, SSND_FADE_ALL);
1703 void StopMusic(void)
1705 #if defined(TARGET_SDL)
1706 if (!audio.sound_available)
1710 Mix_HaltChannel(audio.music_channel);
1712 StopSoundExt(-1, SSND_STOP_MUSIC);
1716 void StopSound(int nr)
1718 StopSoundExt(nr, SSND_STOP_SOUND);
1723 StopSoundExt(-1, SSND_STOP_ALL);
1726 void StopSoundExt(int nr, int method)
1728 struct SoundControl snd_ctrl = emptySoundControl;
1730 if (!audio.sound_available)
1733 if (method & SSND_FADING)
1734 snd_ctrl.fade_sound = TRUE;
1736 if (method & SSND_ALL)
1737 snd_ctrl.stop_all_sounds = TRUE;
1740 snd_ctrl.stop_sound = TRUE;
1744 if (method & SSND_MUSIC)
1745 snd_ctrl.music = TRUE;
1747 #if defined(TARGET_SDL)
1749 if (method & SSND_FADING)
1753 for (i=0; i<audio.channels; i++)
1754 if (i != audio.music_channel || snd_ctrl.music)
1755 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1757 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1763 for (i=0; i<audio.channels; i++)
1764 if (i != audio.music_channel || snd_ctrl.music)
1770 #elif !defined(PLATFORM_MSDOS)
1772 if (audio.soundserver_pid == 0) /* we are child process */
1775 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1777 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1778 audio.sound_available = audio.sound_enabled = FALSE;
1781 #else /* PLATFORM_MSDOS */
1782 sound_handler(snd_ctrl);
1786 ListNode *newListNode()
1788 return checked_calloc(sizeof(ListNode));
1791 void addNodeToList(ListNode **node_first, char *key, void *content)
1793 ListNode *node_new = newListNode();
1796 printf("LIST: adding node with key '%s'\n", key);
1799 node_new->key = getStringCopy(key);
1800 node_new->content = content;
1801 node_new->next = *node_first;
1802 *node_first = node_new;
1805 void deleteNodeFromList(ListNode **node_first, char *key,
1806 void (*destructor_function)(void *))
1808 if (node_first == NULL || *node_first == NULL)
1812 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1813 (*node_first)->key, key);
1816 if (strcmp((*node_first)->key, key) == 0)
1819 printf("[DELETING LIST ENTRY]\n");
1822 free((*node_first)->key);
1823 if (destructor_function)
1824 destructor_function((*node_first)->content);
1825 *node_first = (*node_first)->next;
1828 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1831 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1833 if (node_first == NULL)
1836 if (strcmp(node_first->key, key) == 0)
1839 return getNodeFromKey(node_first->next, key);
1842 int getNumNodes(ListNode *node_first)
1844 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1847 void dumpList(ListNode *node_first)
1849 ListNode *node = node_first;
1853 printf("['%s' (%d)]\n", node->key,
1854 ((SoundInfo *)node->content)->num_references);
1858 printf("[%d nodes]\n", getNumNodes(node_first));
1861 static void LoadSoundsInfo()
1863 char *filename = getCustomSoundConfigFilename();
1864 struct SetupFileList *setup_file_list;
1867 /* always start with reliable default values */
1868 for (i=0; i<num_sounds; i++)
1869 sound_effect[i].filename = NULL;
1871 if (filename == NULL)
1874 if ((setup_file_list = loadSetupFileList(filename)))
1876 for (i=0; i<num_sounds; i++)
1877 sound_effect[i].filename =
1878 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1880 freeSetupFileList(setup_file_list);
1883 for (i=0; i<num_sounds; i++)
1885 printf("'%s' ", sound_effect[i].text);
1886 if (sound_effect[i].filename)
1887 printf("-> '%s'\n", sound_effect[i].filename);
1889 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1895 static void ReloadCustomSounds()
1900 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1905 for(i=0; i<num_sounds; i++)
1907 if (sound_effect[i].filename)
1908 LoadSoundToList(sound_effect[i].filename, i);
1910 LoadSoundToList(sound_effect[i].default_filename, i);
1914 printf("list size == %d\n", getNumNodes(SoundFileList));
1918 dumpList(SoundFileList);
1922 static void ReloadCustomMusic()
1925 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1933 static void InitReloadSoundsOrMusic(char *set_name, int type)
1935 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1936 struct SoundControl snd_ctrl = emptySoundControl;
1938 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1939 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1940 unsigned long str_size2 = strlen(ti->basepath) + 1;
1941 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1944 if (!audio.sound_available)
1947 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1948 if (type == SND_RELOAD_SOUNDS)
1949 ReloadCustomSounds();
1951 ReloadCustomMusic();
1952 #elif defined(PLATFORM_UNIX)
1953 if (audio.soundserver_pid == 0) /* we are child process */
1956 if (leveldir_current == NULL) /* should never happen */
1957 Error(ERR_EXIT, "leveldir_current == NULL");
1959 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1960 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1961 snd_ctrl.data_len = strlen(set_name) + 1;
1963 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1964 sizeof(snd_ctrl)) < 0 ||
1965 write(audio.soundserver_pipe[1], set_name,
1966 snd_ctrl.data_len) < 0 ||
1967 write(audio.soundserver_pipe[1], leveldir_current,
1968 sizeof(TreeInfo)) < 0 ||
1969 write(audio.soundserver_pipe[1], ti,
1970 sizeof(TreeInfo)) < 0 ||
1971 write(audio.soundserver_pipe[1], &str_size1,
1972 sizeof(unsigned long)) < 0 ||
1973 write(audio.soundserver_pipe[1], &str_size2,
1974 sizeof(unsigned long)) < 0 ||
1975 write(audio.soundserver_pipe[1], &str_size3,
1976 sizeof(unsigned long)) < 0 ||
1977 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1979 write(audio.soundserver_pipe[1], ti->basepath,
1981 write(audio.soundserver_pipe[1], ti->fullpath,
1984 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1985 audio.sound_available = audio.sound_enabled = FALSE;
1991 void InitReloadSounds(char *set_name)
1993 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1996 void InitReloadMusic(char *set_name)
1998 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
2001 void FreeSound(void *ptr)
2003 SoundInfo *sound = (SoundInfo *)ptr;
2008 if (sound->data_ptr)
2010 #if defined(TARGET_SDL)
2011 Mix_FreeChunk(sound->data_ptr);
2012 #elif defined(TARGET_ALLEGRO)
2013 destroy_sample(sound->data_ptr);
2014 #else /* PLATFORM_UNIX */
2015 free(sound->data_ptr);
2019 if (sound->source_filename)
2020 free(sound->source_filename);
2025 void FreeMusic(MusicInfo *music)
2030 if (music->data_ptr)
2032 #if defined(TARGET_SDL)
2033 if (music->type == MUS_TYPE_MOD)
2034 Mix_FreeMusic(music->data_ptr);
2036 Mix_FreeChunk(music->data_ptr);
2037 #elif defined(TARGET_ALLEGRO)
2038 destroy_sample(music->data_ptr);
2039 #else /* PLATFORM_UNIX */
2040 free(music->data_ptr);
2047 void FreeAllSounds()
2054 printf("%s: FREEING SOUNDS ...\n",
2055 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2057 for(i=0; i<num_sounds; i++)
2058 deleteSoundEntry(&Sound[i]);
2060 FreeSound(Sound[i]);
2063 printf("%s: FREEING SOUNDS -- DONE\n",
2064 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2079 for(i=0; i<num_music; i++)
2080 FreeMusic(Music[i]);
2088 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2089 /* ========================================================================= */