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];
61 static struct SoundControl emptySoundControl =
64 FALSE, -1, 0, 0, FALSE, 0, 0, 0, NULL
66 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
71 /* forward declaration of internal functions */
72 static void SoundServer_InsertNewSound(struct SoundControl);
73 static void InitAudioDevice(struct AudioFormatInfo *);
75 #if defined(PLATFORM_UNIX)
76 #if !defined(AUDIO_STREAMING_DSP)
77 static unsigned char linear_to_ulaw(int);
78 static int ulaw_to_linear(unsigned char);
80 #elif defined(PLATFORM_MSDOS)
81 static void SoundServer_InsertNewSound(struct SoundControl);
82 static void SoundServer_StopSound(struct SoundControl);
83 static void SoundServer_StopAllSounds();
86 static void ReloadCustomSounds();
87 static void ReloadCustomMusic();
88 static void FreeSound(void *);
90 #if defined(PLATFORM_UNIX)
91 static int OpenAudioDevice(char *audio_device_name)
95 /* check if desired audio device is accessible */
96 if (access(audio_device_name, W_OK) != 0)
99 /* try to open audio device in non-blocking mode */
100 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
101 return audio_device_fd;
103 /* re-open audio device in blocking mode */
104 close(audio_device_fd);
105 audio_device_fd = open(audio_device_name, O_WRONLY);
107 return audio_device_fd;
110 static void CloseAudioDevice(int *audio_device_fd)
112 if (*audio_device_fd == 0)
115 close(*audio_device_fd);
116 *audio_device_fd = -1;
119 static boolean TestAudioDevices(void)
121 static char *audio_device_name[] =
126 int audio_device_fd = -1;
129 /* look for available audio devices, starting with preferred ones */
130 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
131 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
134 if (audio_device_fd < 0)
136 Error(ERR_WARN, "cannot open audio device -- no sound");
140 close(audio_device_fd);
142 audio.device_name = audio_device_name[i];
147 #if !defined(TARGET_SDL)
148 static boolean ForkAudioProcess(void)
150 if (pipe(audio.soundserver_pipe) < 0)
152 Error(ERR_WARN, "cannot create pipe -- no sounds");
156 if ((audio.soundserver_pid = fork()) < 0)
158 Error(ERR_WARN, "cannot create sound server process -- no sounds");
162 if (audio.soundserver_pid == 0) /* we are child process */
169 else /* we are parent */
170 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
176 void UnixOpenAudio(void)
178 if (!TestAudioDevices())
181 audio.sound_available = TRUE;
182 audio.sound_enabled = TRUE;
184 #if defined(AUDIO_STREAMING_DSP)
185 audio.music_available = TRUE;
186 audio.loops_available = TRUE;
189 audio.num_channels = NUM_MIXER_CHANNELS;
190 audio.music_channel = MUSIC_CHANNEL;
191 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
194 void UnixCloseAudio(void)
197 close(audio.device_fd);
199 if (audio.soundserver_pid > 0) /* we are parent process */
200 kill(audio.soundserver_pid, SIGTERM);
203 static void WriteReloadInfoToPipe(char *set_name, int type)
205 struct SoundControl snd_ctrl;
206 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
207 artwork.mus_current);
208 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
209 unsigned long str_size2 = strlen(ti->basepath) + 1;
210 unsigned long str_size3 = strlen(ti->fullpath) + 1;
212 snd_ctrl.active = FALSE;
213 snd_ctrl.state = type;
214 snd_ctrl.data_len = strlen(set_name) + 1;
216 if (write(audio.soundserver_pipe[1], &snd_ctrl,
217 sizeof(snd_ctrl)) < 0 ||
218 write(audio.soundserver_pipe[1], set_name,
219 snd_ctrl.data_len) < 0 ||
220 write(audio.soundserver_pipe[1], leveldir_current,
221 sizeof(TreeInfo)) < 0 ||
222 write(audio.soundserver_pipe[1], ti,
223 sizeof(TreeInfo)) < 0 ||
224 write(audio.soundserver_pipe[1], &str_size1,
225 sizeof(unsigned long)) < 0 ||
226 write(audio.soundserver_pipe[1], &str_size2,
227 sizeof(unsigned long)) < 0 ||
228 write(audio.soundserver_pipe[1], &str_size3,
229 sizeof(unsigned long)) < 0 ||
230 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
232 write(audio.soundserver_pipe[1], ti->basepath,
234 write(audio.soundserver_pipe[1], ti->fullpath,
237 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
238 audio.sound_available = audio.sound_enabled = FALSE;
243 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
245 TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
246 &artwork.snd_current : &artwork.mus_current);
247 TreeInfo *ti = *ti_ptr;
248 unsigned long str_size1, str_size2, str_size3;
249 static char *set_name = NULL;
254 set_name = checked_malloc(snd_ctrl.data_len);
256 if (leveldir_current == NULL)
257 leveldir_current = checked_calloc(sizeof(TreeInfo));
259 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
260 if (leveldir_current->fullpath != NULL)
261 free(leveldir_current->fullpath);
262 if (ti->basepath != NULL)
264 if (ti->fullpath != NULL)
267 if (read(audio.soundserver_pipe[0], set_name,
268 snd_ctrl.data_len) != snd_ctrl.data_len ||
269 read(audio.soundserver_pipe[0], leveldir_current,
270 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
271 read(audio.soundserver_pipe[0], ti,
272 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
273 read(audio.soundserver_pipe[0], &str_size1,
274 sizeof(unsigned long)) != sizeof(unsigned long) ||
275 read(audio.soundserver_pipe[0], &str_size2,
276 sizeof(unsigned long)) != sizeof(unsigned long) ||
277 read(audio.soundserver_pipe[0], &str_size3,
278 sizeof(unsigned long)) != sizeof(unsigned long))
279 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
281 leveldir_current->fullpath = checked_calloc(str_size1);
282 ti->basepath = checked_calloc(str_size2);
283 ti->fullpath = checked_calloc(str_size3);
285 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
286 str_size1) != str_size1 ||
287 read(audio.soundserver_pipe[0], ti->basepath,
288 str_size2) != str_size2 ||
289 read(audio.soundserver_pipe[0], ti->fullpath,
290 str_size3) != str_size3)
291 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
293 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
294 artwork.sounds_set_current = set_name;
296 artwork.music_set_current = set_name;
298 #endif /* PLATFORM_UNIX */
300 void InitPlaylist(void)
304 for(i=0; i<audio.num_channels; i++)
305 playlist[i].active = FALSE;
309 static void PlaylistRemoveSound(int pos)
311 if (!playing_sounds || !playlist[pos].active)
314 playlist[pos].active = FALSE;
318 static void PlaylistInsertSound(struct SoundControl snd_ctrl)
324 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
327 if (IS_MUSIC(snd_ctrl))
328 snd_ctrl.nr = snd_ctrl.nr % num_music;
329 else if (snd_ctrl.nr >= num_sounds)
332 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
333 if (snd_info == NULL)
336 printf("sound/music %d undefined\n", snd_ctrl.nr);
342 printf("-> %d\n", playing_sounds);
345 if (playing_sounds == audio.num_channels)
347 for (i=0; i<audio.num_channels; i++)
349 if (playlist[i].data_ptr == NULL)
352 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
355 PlaylistRemoveSound(i);
360 /* if playlist is full, remove oldest sound */
361 if (playing_sounds == audio.num_channels)
363 int longest = 0, longest_nr = 0;
365 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
367 #if !defined(PLATFORM_MSDOS)
368 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
370 int actual = playlist[i].playingpos;
373 if (!IS_LOOP(playlist[i]) && actual > longest)
379 #if defined(PLATFORM_MSDOS)
380 voice_set_volume(playlist[longest_nr].voice, 0);
381 deallocate_voice(playlist[longest_nr].voice);
383 PlaylistRemoveSound(longest_nr);
386 /* check if sound is already being played (and how often) */
387 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
388 if (playlist[i].nr == snd_ctrl.nr)
391 /* restart loop sounds only if they are just fading out */
392 if (k >= 1 && IS_LOOP(snd_ctrl))
394 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
396 if (playlist[i].nr == snd_ctrl.nr && IS_FADING(playlist[i]))
398 playlist[i].state &= ~SND_CTRL_FADE;
399 playlist[i].volume = PSND_MAX_VOLUME;
400 #if defined(PLATFORM_MSDOS)
401 playlist[i].state |= SND_CTRL_LOOP;
402 voice_stop_volumeramp(playlist[i].voice);
403 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
411 /* don't play sound more than n times simultaneously (with n == 2 for now) */
414 int longest = 0, longest_nr = 0;
416 /* look for oldest equal sound */
417 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
421 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
424 #if !defined(PLATFORM_MSDOS)
425 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
427 actual = playlist[i].playingpos;
429 if (actual >= longest)
436 #if defined(PLATFORM_MSDOS)
437 voice_set_volume(playlist[longest_nr].voice, 0);
438 deallocate_voice(playlist[longest_nr].voice);
440 PlaylistRemoveSound(longest_nr);
443 /* add new sound to playlist */
444 for(i=0; i<audio.num_channels; i++)
447 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
451 if (!playlist[i].active ||
452 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
454 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
455 (i != audio.music_channel && !playlist[i].active))
457 snd_ctrl.data_ptr = snd_info->data_ptr;
458 snd_ctrl.data_len = snd_info->data_len;
459 snd_ctrl.format = snd_info->format;
462 if (snd_info->data_len == 0)
464 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
469 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && playlist[i].active)
471 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
474 PlaylistRemoveSound(i);
479 playlist[i] = snd_ctrl;
483 printf("NEW SOUND %d ADDED TO PLAYLIST\n", snd_ctrl.nr);
486 #if defined(PLATFORM_MSDOS)
487 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
490 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
492 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
493 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
494 voice_start(playlist[i].voice);
501 static void HandleSoundRequest(struct SoundControl snd_ctrl)
505 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
507 ReadReloadInfoFromPipe(snd_ctrl);
509 CloseAudioDevice(&audio.device_fd);
511 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
512 ReloadCustomSounds();
516 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
521 if (IS_MUSIC(snd_ctrl))
523 playlist[audio.music_channel].state |= SND_CTRL_FADE;
527 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
528 if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
529 playlist[i].state |= SND_CTRL_FADE;
531 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
536 if (IS_MUSIC(snd_ctrl))
538 PlaylistRemoveSound(audio.music_channel);
542 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
543 if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
544 PlaylistRemoveSound(i);
547 CloseAudioDevice(&audio.device_fd);
549 else if (snd_ctrl.active) /* add new sound to playlist */
551 SoundServer_InsertNewSound(snd_ctrl);
555 void StartSoundserver(void)
557 if (!audio.sound_available)
560 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
561 if (!ForkAudioProcess())
562 audio.sound_available = FALSE;
566 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
568 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
569 int sample_pos, int sample_size,
572 void *sample_ptr = snd_ctrl->data_ptr;
575 if (snd_ctrl->format == AUDIO_FORMAT_U8)
576 for (i=0; i<sample_size; i++)
578 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
579 else /* AUDIO_FORMAT_S16 */
580 for (i=0; i<sample_size; i++)
582 ((short *)sample_ptr)[sample_pos + i];
585 #if defined(AUDIO_STREAMING_DSP)
586 static void SoundServer_Mixer()
588 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
589 static boolean stereo_volume_calculated = FALSE;
590 static short premix_first_buffer[SND_BLOCKSIZE];
591 static short premix_left_buffer[SND_BLOCKSIZE];
592 static short premix_right_buffer[SND_BLOCKSIZE];
593 static long premix_last_buffer[SND_BLOCKSIZE];
594 static byte playing_buffer[SND_BLOCKSIZE];
596 int fragment_size = afmt.fragment_size;
597 int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
598 boolean stereo = afmt.stereo;
601 if (!stereo_volume_calculated)
603 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
605 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
607 stereo_volume_calculated = TRUE;
613 if (audio.device_fd < 0)
615 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
618 InitAudioDevice(&afmt);
621 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
623 /* first clear the last premixing buffer */
624 memset(premix_last_buffer, 0,
625 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
627 for(i=0; i<audio.num_channels; i++)
634 if (!playlist[i].active)
637 /* pointer, lenght and actual playing position of sound sample */
638 sample_ptr = playlist[i].data_ptr;
639 sample_len = playlist[i].data_len;
640 sample_pos = playlist[i].playingpos;
641 sample_size = MIN(max_sample_size, sample_len - sample_pos);
642 playlist[i].playingpos += sample_size;
644 /* copy original sample to first mixing buffer */
645 CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
646 premix_first_buffer);
648 /* are we about to restart a looping sound? */
649 if (IS_LOOP(playlist[i]) && sample_size < max_sample_size)
651 while (sample_size < max_sample_size)
653 int restarted_sample_size =
654 MIN(max_sample_size - sample_size, sample_len);
656 if (playlist[i].format == AUDIO_FORMAT_U8)
657 for (j=0; j<restarted_sample_size; j++)
658 premix_first_buffer[sample_size + j] =
659 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
661 for (j=0; j<restarted_sample_size; j++)
662 premix_first_buffer[sample_size + j] =
663 ((short *)sample_ptr)[j];
665 playlist[i].playingpos = restarted_sample_size;
666 sample_size += restarted_sample_size;
670 /* decrease volume if sound is fading out */
671 if (IS_FADING(playlist[i]) &&
672 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
673 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
675 /* adjust volume of actual sound sample */
676 if (playlist[i].volume != PSND_MAX_VOLUME)
677 for(j=0; j<sample_size; j++)
678 premix_first_buffer[j] =
679 (playlist[i].volume * (long)premix_first_buffer[j])
680 >> PSND_MAX_VOLUME_BITS;
682 /* fill the last mixing buffer with stereo or mono sound */
685 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
686 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
687 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
689 for(j=0; j<sample_size; j++)
691 premix_left_buffer[j] =
692 (left_volume * premix_first_buffer[j])
693 >> PSND_MAX_LEFT2RIGHT_BITS;
694 premix_right_buffer[j] =
695 (right_volume * premix_first_buffer[j])
696 >> PSND_MAX_LEFT2RIGHT_BITS;
698 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
699 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
704 for(j=0; j<sample_size; j++)
705 premix_last_buffer[j] += premix_first_buffer[j];
708 /* delete completed sound entries from the playlist */
709 if (playlist[i].playingpos >= playlist[i].data_len)
711 if (IS_LOOP(playlist[i]))
712 playlist[i].playingpos = 0;
714 PlaylistRemoveSound(i);
716 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
717 PlaylistRemoveSound(i);
720 /* prepare final playing buffer according to system audio format */
721 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
723 /* cut off at 17 bit value */
724 if (premix_last_buffer[i] < -65535)
725 premix_last_buffer[i] = -65535;
726 else if (premix_last_buffer[i] > 65535)
727 premix_last_buffer[i] = 65535;
729 /* shift to 16 bit value */
730 premix_last_buffer[i] >>= 1;
732 if (afmt.format & AUDIO_FORMAT_U8)
734 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
736 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
738 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
739 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
741 else /* big endian */
743 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
744 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
748 /* finally play the sound fragment */
749 write(audio.device_fd, playing_buffer, fragment_size);
752 CloseAudioDevice(&audio.device_fd);
755 #else /* !AUDIO_STREAMING_DSP */
757 static int SoundServer_SimpleAudio(struct SoundControl snd_ctrl)
759 static short premix_first_buffer[SND_BLOCKSIZE];
760 static byte playing_buffer[SND_BLOCKSIZE];
761 int max_sample_size = SND_BLOCKSIZE;
770 /* pointer, lenght and actual playing position of sound sample */
771 sample_ptr = playlist[i].data_ptr;
772 sample_len = playlist[i].data_len;
773 sample_pos = playlist[i].playingpos;
774 sample_size = MIN(max_sample_size, sample_len - sample_pos);
775 playlist[i].playingpos += sample_size;
777 /* copy original sample to first mixing buffer */
778 CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
779 premix_first_buffer);
781 /* adjust volume of actual sound sample */
782 if (playlist[i].volume != PSND_MAX_VOLUME)
783 for(j=0; j<sample_size; j++)
784 premix_first_buffer[j] =
785 (playlist[i].volume * (long)premix_first_buffer[j])
786 >> PSND_MAX_VOLUME_BITS;
788 /* might be needed for u-law /dev/audio */
790 for(j=0; j<sample_size; j++)
792 linear_to_ulaw(premix_first_buffer[j]);
795 /* delete completed sound entries from the playlist */
796 if (playlist[i].playingpos >= playlist[i].data_len)
797 PlaylistRemoveSound(i);
799 for(i=0; i<sample_size; i++)
800 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
802 /* finally play the sound fragment */
803 write(audio.device_fd, playing_buffer, sample_size);
807 #endif /* !AUDIO_STREAMING_DSP */
811 struct SoundControl snd_ctrl;
814 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
818 #if defined(PLATFORM_HPUX)
819 InitAudioDevice(&afmt);
822 FD_ZERO(&sound_fdset);
823 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
825 while(1) /* wait for sound playing commands from client */
827 struct timeval delay = { 0, 0 };
829 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
830 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
831 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
833 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
835 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
837 HandleSoundRequest(snd_ctrl);
839 #if defined(AUDIO_STREAMING_DSP)
841 while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
842 &sound_fdset, NULL, NULL, &delay) < 1)
844 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
849 #else /* !AUDIO_STREAMING_DSP */
851 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
852 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
855 InitAudioDevice(&afmt);
860 while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
861 &sound_fdset, NULL, NULL, &delay) < 1)
863 int wait_percent = 90; /* wait 90% of the real playing time */
866 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
868 sample_size = SoundServer_SimpleAudio(snd_ctrl);
872 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
875 CloseAudioDevice(&audio.device_fd);
877 /* delete all sounds from playlist */
880 #endif /* !AUDIO_STREAMING_DSP */
883 #endif /* PLATFORM_UNIX */
885 #if defined(PLATFORM_MSDOS)
886 static void sound_handler(struct SoundControl snd_ctrl)
890 if (snd_ctrl.fade_sound)
895 for (i=0; i<audio.num_channels; i++)
896 if ((snd_ctrl.stop_all_sounds ||
897 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
898 (i == audio.music_channel && snd_ctrl.music)) &&
899 !playlist[i].fade_sound)
901 playlist[i].fade_sound = TRUE;
902 if (voice_check(playlist[i].voice))
903 voice_ramp_volume(playlist[i].voice, 1000, 0);
904 playlist[i].state &= ~SND_CTRL_IS_LOOP;
907 else if (snd_ctrl.stop_all_sounds)
911 SoundServer_StopAllSounds();
913 else if (snd_ctrl.stop_sound)
917 SoundServer_StopSound(snd_ctrl);
920 for (i=0; i<audio.num_channels; i++)
922 if (!playlist[i].active || playlist[i].loop)
925 playlist[i].playingpos = voice_get_position(playlist[i].voice);
926 playlist[i].volume = voice_get_volume(playlist[i].voice);
927 if (playlist[i].playingpos == -1 || !playlist[i].volume)
929 deallocate_voice(playlist[i].voice);
930 PlaylistRemoveSound(i);
935 SoundServer_InsertNewSound(snd_ctrl);
937 #endif /* PLATFORM_MSDOS */
940 #if defined(TARGET_SDL)
941 static void sound_handler_SDL(struct SoundControl snd_ctrl)
943 /* copy sound_handler() here ... */
945 #endif /* TARGET_SDL */
948 #if !defined(PLATFORM_WIN32)
949 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
955 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
958 if (IS_MUSIC(snd_ctrl))
959 snd_ctrl.nr = snd_ctrl.nr % num_music;
960 else if (snd_ctrl.nr >= num_sounds)
963 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
964 if (snd_info == NULL)
967 printf("sound/music %d undefined\n", snd_ctrl.nr);
973 printf("-> %d\n", playing_sounds);
976 if (playing_sounds == audio.num_channels)
978 for (i=0; i<audio.num_channels; i++)
980 if (playlist[i].data_ptr == NULL)
983 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
986 PlaylistRemoveSound(i);
991 /* if playlist is full, remove oldest sound */
992 if (playing_sounds == audio.num_channels)
994 int longest = 0, longest_nr = 0;
996 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
998 #if !defined(PLATFORM_MSDOS)
999 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
1001 int actual = playlist[i].playingpos;
1004 if (!IS_LOOP(playlist[i]) && actual > longest)
1010 #if defined(PLATFORM_MSDOS)
1011 voice_set_volume(playlist[longest_nr].voice, 0);
1012 deallocate_voice(playlist[longest_nr].voice);
1014 PlaylistRemoveSound(longest_nr);
1017 /* check if sound is already being played (and how often) */
1018 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
1019 if (playlist[i].nr == snd_ctrl.nr)
1022 /* restart loop sounds only if they are just fading out */
1023 if (k >= 1 && IS_LOOP(snd_ctrl))
1025 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1027 if (playlist[i].nr == snd_ctrl.nr && IS_FADING(playlist[i]))
1029 playlist[i].state &= ~SND_CTRL_FADE;
1030 playlist[i].volume = PSND_MAX_VOLUME;
1031 #if defined(PLATFORM_MSDOS)
1032 playlist[i].state |= SND_CTRL_LOOP;
1033 voice_stop_volumeramp(playlist[i].voice);
1034 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
1042 /* don't play sound more than n times simultaneously (with n == 2 for now) */
1045 int longest = 0, longest_nr = 0;
1047 /* look for oldest equal sound */
1048 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1052 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
1055 #if !defined(PLATFORM_MSDOS)
1056 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
1058 actual = playlist[i].playingpos;
1060 if (actual >= longest)
1067 #if defined(PLATFORM_MSDOS)
1068 voice_set_volume(playlist[longest_nr].voice, 0);
1069 deallocate_voice(playlist[longest_nr].voice);
1071 PlaylistRemoveSound(longest_nr);
1074 /* add new sound to playlist */
1075 for(i=0; i<audio.num_channels; i++)
1078 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
1082 if (!playlist[i].active ||
1083 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
1085 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
1086 (i != audio.music_channel && !playlist[i].active))
1088 snd_ctrl.data_ptr = snd_info->data_ptr;
1089 snd_ctrl.data_len = snd_info->data_len;
1090 snd_ctrl.format = snd_info->format;
1092 snd_ctrl.playingpos = 0;
1093 snd_ctrl.playingtime = 0;
1096 if (snd_info->data_len == 0)
1098 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
1103 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && playlist[i].active)
1105 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
1108 PlaylistRemoveSound(i);
1113 playlist[i] = snd_ctrl;
1117 printf("NEW SOUND %d ADDED TO PLAYLIST\n", snd_ctrl.nr);
1120 #if defined(PLATFORM_MSDOS)
1121 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
1124 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
1126 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
1127 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
1128 voice_start(playlist[i].voice);
1134 #endif /* !PLATFORM_WIN32 */
1137 void SoundServer_FadeSound(int nr)
1141 if (!playing_sounds)
1144 for(i=0;i<audio.num_channels;i++)
1145 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
1146 playlist[i].fade_sound = TRUE;
1150 #if !defined(PLATFORM_WIN32)
1151 #if defined(PLATFORM_MSDOS)
1152 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
1154 int nr = snd_ctrl.nr;
1157 if (!playing_sounds)
1160 for(i=0; i<audio.num_channels; i++)
1162 if ((i == audio.music_channel && snd_ctrl.music) ||
1163 (i != audio.music_channel && playlist[i].nr == nr))
1165 #if defined(PLATFORM_MSDOS)
1166 voice_set_volume(playlist[i].voice, 0);
1167 deallocate_voice(playlist[i].voice);
1169 PlaylistRemoveSound(i);
1173 #if !defined(PLATFORM_MSDOS)
1174 if (!playing_sounds)
1175 close(audio.device_fd);
1179 static void SoundServer_StopAllSounds()
1183 for(i=0; i<audio.num_channels; i++)
1185 #if defined(PLATFORM_MSDOS)
1186 voice_set_volume(playlist[i].voice, 0);
1187 deallocate_voice(playlist[i].voice);
1189 PlaylistRemoveSound(i);
1193 #if !defined(PLATFORM_MSDOS)
1194 close(audio.device_fd);
1197 #endif /* PLATFORM_MSDOS */
1198 #endif /* !PLATFORM_WIN32 */
1201 /* ------------------------------------------------------------------------- */
1202 /* platform dependant audio initialization code */
1203 /* ------------------------------------------------------------------------- */
1205 #if defined(AUDIO_LINUX_IOCTL)
1206 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1208 /* "ioctl()" expects pointer to 'int' value for stereo flag
1209 (boolean is defined as 'char', which will not work here) */
1210 unsigned int fragment_spec = 0;
1211 int fragment_size_query;
1220 /* supported audio format in preferred order */
1221 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1222 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1223 { AFMT_U8, AUDIO_FORMAT_U8 },
1228 /* determine logarithm (log2) of the fragment size */
1229 while ((1 << fragment_spec) < afmt->fragment_size)
1232 /* use two fragments (play one fragment, prepare the other);
1233 one fragment would result in interrupted audio output, more
1234 than two fragments would raise audio output latency to much */
1235 fragment_spec |= 0x00020000;
1237 /* Example for fragment specification:
1238 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1239 - (with stereo the effective buffer size will shrink to 256)
1240 => fragment_size = 0x00020009 */
1242 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1243 Error(ERR_EXIT_SOUND_SERVER,
1244 "cannot set fragment size of /dev/dsp -- no sounds");
1248 while (formats[i].format_result != -1)
1250 unsigned int audio_format = formats[i].format_ioctl;
1251 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1253 afmt->format = formats[i].format_result;
1258 if (afmt->format == 0) /* no supported audio format found */
1259 Error(ERR_EXIT_SOUND_SERVER,
1260 "cannot set audio format of /dev/dsp -- no sounds");
1262 /* try if we can use stereo sound */
1263 afmt->stereo = TRUE;
1264 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1265 afmt->stereo = FALSE;
1267 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1268 Error(ERR_EXIT_SOUND_SERVER,
1269 "cannot set sample rate of /dev/dsp -- no sounds");
1271 /* get the real fragmentation size; this should return 512 */
1272 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1273 Error(ERR_EXIT_SOUND_SERVER,
1274 "cannot get fragment size of /dev/dsp -- no sounds");
1275 if (fragment_size_query != afmt->fragment_size)
1276 Error(ERR_EXIT_SOUND_SERVER,
1277 "cannot set fragment size of /dev/dsp -- no sounds");
1279 #endif /* AUDIO_LINUX_IOCTL */
1281 #if defined(PLATFORM_NETBSD)
1282 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1284 audio_info_t a_info;
1285 boolean stereo = TRUE;
1287 AUDIO_INITINFO(&a_info);
1288 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1289 a_info.play.precision = 8;
1290 a_info.play.channels = 2;
1291 a_info.play.sample_rate = sample_rate;
1292 a_info.blocksize = fragment_size;
1294 afmt->format = AUDIO_FORMAT_U8;
1295 afmt->stereo = TRUE;
1297 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1299 /* try to disable stereo */
1300 a_info.play.channels = 1;
1302 afmt->stereo = FALSE;
1304 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1305 Error(ERR_EXIT_SOUND_SERVER,
1306 "cannot set sample rate of /dev/audio -- no sounds");
1309 #endif /* PLATFORM_NETBSD */
1311 #if defined(PLATFORM_HPUX)
1312 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1314 struct audio_describe ainfo;
1317 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1318 if (audio_ctl == -1)
1319 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1321 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1322 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1324 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1325 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1327 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1328 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1330 afmt->format = AUDIO_FORMAT_U8;
1331 afmt->stereo = FALSE;
1332 afmt->sample_rate = 8000;
1336 #endif /* PLATFORM_HPUX */
1338 #if defined(PLATFORM_UNIX)
1339 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1341 #if defined(AUDIO_LINUX_IOCTL)
1342 InitAudioDevice_Linux(afmt);
1343 #elif defined(PLATFORM_NETBSD)
1344 InitAudioDevice_NetBSD(afmt);
1345 #elif defined(PLATFORM_HPUX)
1346 InitAudioDevice_HPUX(afmt);
1348 /* generic /dev/audio stuff might be placed here */
1351 #endif /* PLATFORM_UNIX */
1353 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1355 /* these two are stolen from "sox"... :) */
1358 ** This routine converts from linear to ulaw.
1360 ** Craig Reese: IDA/Supercomputing Research Center
1361 ** Joe Campbell: Department of Defense
1362 ** 29 September 1989
1365 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1366 ** 2) "A New Digital Technique for Implementation of Any
1367 ** Continuous PCM Companding Law," Villeret, Michel,
1368 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1369 ** 1973, pg. 11.12-11.17
1370 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1371 ** for Analog-to_Digital Conversion Techniques,"
1374 ** Input: Signed 16 bit linear sample
1375 ** Output: 8 bit ulaw sample
1378 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1379 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1382 static unsigned char linear_to_ulaw(int sample)
1384 static int exp_lut[256] =
1386 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1387 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1388 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1389 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1390 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1391 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1392 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1393 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1394 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1395 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1396 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1397 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1398 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1399 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1400 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1401 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1404 int sign, exponent, mantissa;
1405 unsigned char ulawbyte;
1407 /* Get the sample into sign-magnitude. */
1408 sign = (sample >> 8) & 0x80; /* set aside the sign */
1410 sample = -sample; /* get magnitude */
1412 sample = CLIP; /* clip the magnitude */
1414 /* Convert from 16 bit linear to ulaw. */
1415 sample = sample + BIAS;
1416 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1417 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1418 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1421 ulawbyte = 0x02; /* optional CCITT trap */
1428 ** This routine converts from ulaw to 16 bit linear.
1430 ** Craig Reese: IDA/Supercomputing Research Center
1431 ** 29 September 1989
1434 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1435 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1436 ** for Analog-to_Digital Conversion Techniques,"
1439 ** Input: 8 bit ulaw sample
1440 ** Output: signed 16 bit linear sample
1443 static int ulaw_to_linear(unsigned char ulawbyte)
1445 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1446 int sign, exponent, mantissa, sample;
1448 ulawbyte = ~ ulawbyte;
1449 sign = ( ulawbyte & 0x80 );
1450 exponent = ( ulawbyte >> 4 ) & 0x07;
1451 mantissa = ulawbyte & 0x0F;
1452 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1458 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1461 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1462 /* ========================================================================= */
1463 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1465 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1466 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1468 static SoundInfo *Load_WAV(char *filename)
1470 SoundInfo *snd_info;
1471 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1472 byte sound_header_buffer[WAV_HEADER_SIZE];
1473 char chunk_name[CHUNK_ID_LEN + 1];
1479 if (!audio.sound_available)
1483 printf("loading WAV file '%s'\n", filename);
1486 snd_info = checked_calloc(sizeof(SoundInfo));
1488 #if defined(TARGET_SDL)
1490 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1492 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1497 #elif defined(TARGET_ALLEGRO)
1499 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1501 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1506 #else /* PLATFORM_UNIX */
1508 if ((file = fopen(filename, MODE_READ)) == NULL)
1510 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1515 /* read chunk id "RIFF" */
1516 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1517 if (strcmp(chunk_name, "RIFF") != 0)
1519 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1525 /* read "RIFF" type id "WAVE" */
1526 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1527 if (strcmp(chunk_name, "WAVE") != 0)
1529 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1535 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1537 if (strcmp(chunk_name, "fmt ") == 0)
1539 /* read header information */
1540 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1541 sound_header_buffer[i] = fgetc(file);
1543 if (chunk_size > WAV_HEADER_SIZE)
1544 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1546 else if (strcmp(chunk_name, "data") == 0)
1548 snd_info->data_len = chunk_size;
1549 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1551 /* read sound data */
1552 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1555 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1557 free(snd_info->data_ptr);
1562 /* check for odd number of sample bytes (data chunk is word aligned) */
1563 if ((chunk_size % 2) == 1)
1564 ReadUnusedBytesFromFile(file, 1);
1566 else /* unknown chunk -- ignore */
1567 ReadUnusedBytesFromFile(file, chunk_size);
1572 if (snd_info->data_ptr == NULL)
1574 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1579 snd_info->format = AUDIO_FORMAT_U8;
1581 #endif /* PLATFORM_UNIX */
1583 snd_info->type = SND_TYPE_WAV;
1584 snd_info->source_filename = getStringCopy(filename);
1589 static void deleteSoundEntry(SoundInfo **snd_info)
1593 char *filename = (*snd_info)->source_filename;
1596 printf("[decrementing reference counter of sound '%s']\n", filename);
1599 if (--(*snd_info)->num_references <= 0)
1602 printf("[deleting sound '%s']\n", filename);
1606 FreeSound(*snd_info);
1608 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1615 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1619 /* check if the old and the new sound file are the same */
1620 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1622 /* The old and new sound are the same (have the same filename and path).
1623 This usually means that this sound does not exist in this sound set
1624 and a fallback to the existing sound is done. */
1627 printf("[sound '%s' already exists (same list entry)]\n", filename);
1633 /* delete existing sound file entry */
1634 deleteSoundEntry(snd_info);
1636 /* check if the new sound file already exists in the list of sounds */
1637 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1640 printf("[sound '%s' already exists (other list entry)]\n", filename);
1643 *snd_info = (SoundInfo *)node->content;
1644 (*snd_info)->num_references++;
1646 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1648 (*snd_info)->num_references = 1;
1649 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1653 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1655 char *filename = getCustomSoundFilename(basename);
1657 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1659 deleteSoundEntry(snd_info);
1663 if (filename == NULL)
1665 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1669 replaceSoundEntry(snd_info, filename);
1672 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1675 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1677 sound_effect = sounds_list;
1678 num_sounds = num_list_entries;
1681 void LoadSoundToList(char *basename, int list_pos)
1683 if (Sound == NULL || list_pos >= num_sounds)
1687 printf("loading sound '%s' ... [%d]\n",
1688 basename, getNumNodes(SoundFileList));
1691 LoadCustomSound(&Sound[list_pos], basename);
1694 printf("loading sound '%s' done [%d]\n",
1695 basename, getNumNodes(SoundFileList));
1699 static MusicInfo *Load_MOD(char *filename)
1701 #if defined(TARGET_SDL)
1702 MusicInfo *mod_info;
1704 if (!audio.sound_available)
1707 mod_info = checked_calloc(sizeof(MusicInfo));
1709 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1711 Error(ERR_WARN, "cannot read music file '%s'", filename);
1716 mod_info->type = MUS_TYPE_MOD;
1717 mod_info->source_filename = getStringCopy(filename);
1725 void LoadCustomMusic(void)
1727 char *music_directory = getCustomMusicDirectory();
1729 struct dirent *dir_entry;
1731 if (!audio.sound_available)
1734 if ((dir = opendir(music_directory)) == NULL)
1736 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1737 audio.music_available = FALSE;
1741 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1743 char *basename = dir_entry->d_name;
1744 char *filename = getPath2(music_directory, basename);
1745 MusicInfo *mus_info = NULL;
1747 if (FileIsSound(basename))
1748 mus_info = Load_WAV(filename);
1749 else if (FileIsMusic(basename))
1750 mus_info = Load_MOD(filename);
1757 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1758 Music[num_music -1] = mus_info;
1765 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1769 void PlayMusic(int nr)
1771 if (!audio.music_available)
1774 #if defined(TARGET_SDL)
1776 nr = nr % num_music;
1778 if (Music[nr]->type == MUS_TYPE_MOD)
1780 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1781 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1783 else /* play WAV music loop */
1785 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1786 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1796 void PlaySound(int nr)
1798 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1801 void PlaySoundStereo(int nr, int stereo)
1803 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1806 void PlaySoundLoop(int nr)
1808 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1811 void PlaySoundMusic(int nr)
1813 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1816 void PlaySoundExt(int nr, int volume, int stereo, int state)
1818 struct SoundControl snd_ctrl;
1820 if (!audio.sound_available ||
1821 !audio.sound_enabled ||
1822 audio.sound_deactivated)
1825 if (volume < PSND_MIN_VOLUME)
1826 volume = PSND_MIN_VOLUME;
1827 else if (volume > PSND_MAX_VOLUME)
1828 volume = PSND_MAX_VOLUME;
1830 if (stereo < PSND_MAX_LEFT)
1831 stereo = PSND_MAX_LEFT;
1832 else if (stereo > PSND_MAX_RIGHT)
1833 stereo = PSND_MAX_RIGHT;
1835 snd_ctrl.active = TRUE;
1837 snd_ctrl.volume = volume;
1838 snd_ctrl.stereo = stereo;
1839 snd_ctrl.state = state;
1841 #if defined(TARGET_SDL)
1844 Mix_Volume(-1, SOUND_MAX_VOLUME);
1845 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1847 #elif defined(PLATFORM_UNIX)
1848 if (audio.soundserver_pid == 0) /* we are child process */
1851 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1853 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1854 audio.sound_available = audio.sound_enabled = FALSE;
1857 #elif defined(PLATFORM_MSDOS)
1858 sound_handler(snd_ctrl);
1862 void FadeMusic(void)
1864 if (!audio.sound_available)
1867 #if defined(TARGET_SDL)
1868 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1869 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1871 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1875 void FadeSound(int nr)
1877 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1883 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1886 void StopMusic(void)
1888 #if defined(TARGET_SDL)
1889 if (!audio.sound_available)
1893 Mix_HaltChannel(audio.music_channel);
1895 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1899 void StopSound(int nr)
1901 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1907 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1910 void StopSoundExt(int nr, int state)
1912 struct SoundControl snd_ctrl;
1914 if (!audio.sound_available)
1917 snd_ctrl.active = FALSE;
1919 snd_ctrl.state = state;
1921 #if defined(TARGET_SDL)
1923 if (state & SND_CTRL_FADE)
1928 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
1931 for (i=0; i<audio.channels; i++)
1932 if (i != audio.music_channel || snd_ctrl.music)
1933 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1934 if (state & SND_CTRL_MUSIC)
1935 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1941 for (i=0; i<audio.channels; i++)
1942 if (i != audio.music_channel || snd_ctrl.music)
1944 if (state & SND_CTRL_MUSIC)
1948 #elif !defined(PLATFORM_MSDOS)
1950 if (audio.soundserver_pid == 0) /* we are child process */
1953 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1955 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1956 audio.sound_available = audio.sound_enabled = FALSE;
1959 #else /* PLATFORM_MSDOS */
1960 sound_handler(snd_ctrl);
1964 ListNode *newListNode()
1966 return checked_calloc(sizeof(ListNode));
1969 void addNodeToList(ListNode **node_first, char *key, void *content)
1971 ListNode *node_new = newListNode();
1974 printf("LIST: adding node with key '%s'\n", key);
1977 node_new->key = getStringCopy(key);
1978 node_new->content = content;
1979 node_new->next = *node_first;
1980 *node_first = node_new;
1983 void deleteNodeFromList(ListNode **node_first, char *key,
1984 void (*destructor_function)(void *))
1986 if (node_first == NULL || *node_first == NULL)
1990 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1991 (*node_first)->key, key);
1994 if (strcmp((*node_first)->key, key) == 0)
1997 printf("[DELETING LIST ENTRY]\n");
2000 free((*node_first)->key);
2001 if (destructor_function)
2002 destructor_function((*node_first)->content);
2003 *node_first = (*node_first)->next;
2006 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
2009 ListNode *getNodeFromKey(ListNode *node_first, char *key)
2011 if (node_first == NULL)
2014 if (strcmp(node_first->key, key) == 0)
2017 return getNodeFromKey(node_first->next, key);
2020 int getNumNodes(ListNode *node_first)
2022 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
2025 void dumpList(ListNode *node_first)
2027 ListNode *node = node_first;
2031 printf("['%s' (%d)]\n", node->key,
2032 ((SoundInfo *)node->content)->num_references);
2036 printf("[%d nodes]\n", getNumNodes(node_first));
2039 static void LoadSoundsInfo()
2041 char *filename = getCustomSoundConfigFilename();
2042 struct SetupFileList *setup_file_list;
2045 /* always start with reliable default values */
2046 for (i=0; i<num_sounds; i++)
2047 sound_effect[i].filename = NULL;
2049 if (filename == NULL)
2052 if ((setup_file_list = loadSetupFileList(filename)))
2054 for (i=0; i<num_sounds; i++)
2055 sound_effect[i].filename =
2056 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2058 freeSetupFileList(setup_file_list);
2061 for (i=0; i<num_sounds; i++)
2063 printf("'%s' ", sound_effect[i].text);
2064 if (sound_effect[i].filename)
2065 printf("-> '%s'\n", sound_effect[i].filename);
2067 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2073 static void ReloadCustomSounds()
2078 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
2084 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2087 for(i=0; i<num_sounds; i++)
2089 if (sound_effect[i].filename)
2090 LoadSoundToList(sound_effect[i].filename, i);
2092 LoadSoundToList(sound_effect[i].default_filename, i);
2096 printf("list size == %d\n", getNumNodes(SoundFileList));
2100 dumpList(SoundFileList);
2104 static void ReloadCustomMusic()
2107 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
2115 static void InitReloadSoundsOrMusic(char *set_name, int type)
2117 if (!audio.sound_available)
2120 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
2121 if (type == SND_CTRL_RELOAD_SOUNDS)
2122 ReloadCustomSounds();
2124 ReloadCustomMusic();
2125 #elif defined(PLATFORM_UNIX)
2126 if (audio.soundserver_pid == 0) /* we are child process */
2129 if (leveldir_current == NULL) /* should never happen */
2130 Error(ERR_EXIT, "leveldir_current == NULL");
2133 WriteReloadInfoToPipe(set_name, type);
2136 snd_ctrl.active = FALSE;
2137 snd_ctrl.state = type;
2138 snd_ctrl.data_len = strlen(set_name) + 1;
2140 if (write(audio.soundserver_pipe[1], &snd_ctrl,
2141 sizeof(snd_ctrl)) < 0 ||
2142 write(audio.soundserver_pipe[1], set_name,
2143 snd_ctrl.data_len) < 0 ||
2144 write(audio.soundserver_pipe[1], leveldir_current,
2145 sizeof(TreeInfo)) < 0 ||
2146 write(audio.soundserver_pipe[1], ti,
2147 sizeof(TreeInfo)) < 0 ||
2148 write(audio.soundserver_pipe[1], &str_size1,
2149 sizeof(unsigned long)) < 0 ||
2150 write(audio.soundserver_pipe[1], &str_size2,
2151 sizeof(unsigned long)) < 0 ||
2152 write(audio.soundserver_pipe[1], &str_size3,
2153 sizeof(unsigned long)) < 0 ||
2154 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
2156 write(audio.soundserver_pipe[1], ti->basepath,
2158 write(audio.soundserver_pipe[1], ti->fullpath,
2161 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
2162 audio.sound_available = audio.sound_enabled = FALSE;
2170 void InitReloadSounds(char *set_name)
2172 InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_SOUNDS);
2175 void InitReloadMusic(char *set_name)
2177 InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_MUSIC);
2180 void FreeSound(void *ptr)
2182 SoundInfo *sound = (SoundInfo *)ptr;
2187 if (sound->data_ptr)
2189 #if defined(TARGET_SDL)
2190 Mix_FreeChunk(sound->data_ptr);
2191 #elif defined(TARGET_ALLEGRO)
2192 destroy_sample(sound->data_ptr);
2193 #else /* PLATFORM_UNIX */
2194 free(sound->data_ptr);
2198 if (sound->source_filename)
2199 free(sound->source_filename);
2204 void FreeMusic(MusicInfo *music)
2209 if (music->data_ptr)
2211 #if defined(TARGET_SDL)
2212 if (music->type == MUS_TYPE_MOD)
2213 Mix_FreeMusic(music->data_ptr);
2215 Mix_FreeChunk(music->data_ptr);
2216 #elif defined(TARGET_ALLEGRO)
2217 destroy_sample(music->data_ptr);
2218 #else /* PLATFORM_UNIX */
2219 free(music->data_ptr);
2226 void FreeAllSounds()
2233 printf("%s: FREEING SOUNDS ...\n",
2234 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2236 for(i=0; i<num_sounds; i++)
2237 deleteSoundEntry(&Sound[i]);
2239 FreeSound(Sound[i]);
2242 printf("%s: FREEING SOUNDS -- DONE\n",
2243 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2258 for(i=0; i<num_music; i++)
2259 FreeMusic(Music[i]);
2267 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2268 /* ========================================================================= */