1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
31 struct ListNode *next;
33 typedef struct ListNode ListNode;
35 static ListNode *newListNode(void);
36 static void addNodeToList(ListNode **, char *, void *);
37 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
38 static ListNode *getNodeFromKey(ListNode *, char *);
39 static int getNumNodes(ListNode *);
42 static struct SoundEffectInfo *sound_effect;
43 static ListNode *SoundFileList = NULL;
44 static SoundInfo **Sound = NULL;
45 static MusicInfo **Music = NULL;
46 static int num_sounds = 0, num_music = 0;
49 /* ========================================================================= */
50 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
52 static struct AudioFormatInfo afmt;
53 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
54 static int mixer_active_channels = 0;
56 /* forward declaration of internal functions */
57 static void InitAudioDevice(struct AudioFormatInfo *);
58 static void Mixer_Main(void);
60 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
61 static unsigned char linear_to_ulaw(int);
62 static int ulaw_to_linear(unsigned char);
65 static void ReloadCustomSounds();
66 static void ReloadCustomMusic();
67 static void FreeSound(void *);
69 #if defined(PLATFORM_UNIX)
70 static int OpenAudioDevice(char *audio_device_name)
74 /* check if desired audio device is accessible */
75 if (access(audio_device_name, W_OK) != 0)
78 /* try to open audio device in non-blocking mode */
79 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
80 return audio_device_fd;
82 /* re-open audio device in blocking mode */
83 close(audio_device_fd);
84 audio_device_fd = open(audio_device_name, O_WRONLY);
86 return audio_device_fd;
89 static void CloseAudioDevice(int *audio_device_fd)
91 if (*audio_device_fd == 0)
94 close(*audio_device_fd);
95 *audio_device_fd = -1;
98 static boolean TestAudioDevices(void)
100 static char *audio_device_name[] =
105 int audio_device_fd = -1;
108 /* look for available audio devices, starting with preferred ones */
109 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
110 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
113 if (audio_device_fd < 0)
115 Error(ERR_WARN, "cannot open audio device -- no sound");
119 close(audio_device_fd);
121 audio.device_name = audio_device_name[i];
126 #if !defined(TARGET_SDL)
127 static boolean ForkAudioProcess(void)
129 if (pipe(audio.mixer_pipe) < 0)
131 Error(ERR_WARN, "cannot create pipe -- no sounds");
135 if ((audio.mixer_pid = fork()) < 0)
137 Error(ERR_WARN, "cannot create sound server process -- no sounds");
141 if (audio.mixer_pid == 0) /* we are child process */
148 else /* we are parent */
149 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
155 void UnixOpenAudio(void)
157 if (!TestAudioDevices())
160 audio.sound_available = TRUE;
161 audio.sound_enabled = TRUE;
163 #if defined(AUDIO_STREAMING_DSP)
164 audio.music_available = TRUE;
165 audio.loops_available = TRUE;
168 audio.num_channels = NUM_MIXER_CHANNELS;
169 audio.music_channel = MUSIC_CHANNEL;
170 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
173 void UnixCloseAudio(void)
176 close(audio.device_fd);
178 if (audio.mixer_pid > 0) /* we are parent process */
179 kill(audio.mixer_pid, SIGTERM);
182 static void WriteSoundControlToPipe(struct SoundControl snd_ctrl)
184 if (audio.mixer_pid == 0) /* we are child process */
187 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(struct SoundControl)) < 0)
189 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
190 audio.sound_available = audio.sound_enabled = FALSE;
195 static void ReadSoundControlFromPipe(struct SoundControl *snd_ctrl)
197 if (audio.mixer_pid != 0) /* we are parent process */
200 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(struct SoundControl))
201 != sizeof(struct SoundControl))
202 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
205 static void WriteReloadInfoToPipe(char *set_name, int type)
207 struct SoundControl snd_ctrl;
208 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
209 artwork.mus_current);
210 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
211 unsigned long str_size2 = strlen(ti->basepath) + 1;
212 unsigned long str_size3 = strlen(ti->fullpath) + 1;
214 if (audio.mixer_pid == 0) /* we are child process */
217 if (leveldir_current == NULL) /* should never happen */
218 Error(ERR_EXIT, "leveldir_current == NULL");
220 snd_ctrl.active = FALSE;
221 snd_ctrl.state = type;
222 snd_ctrl.data_len = strlen(set_name) + 1;
224 if (write(audio.mixer_pipe[1], &snd_ctrl,
225 sizeof(snd_ctrl)) < 0 ||
226 write(audio.mixer_pipe[1], set_name,
227 snd_ctrl.data_len) < 0 ||
228 write(audio.mixer_pipe[1], leveldir_current,
229 sizeof(TreeInfo)) < 0 ||
230 write(audio.mixer_pipe[1], ti,
231 sizeof(TreeInfo)) < 0 ||
232 write(audio.mixer_pipe[1], &str_size1,
233 sizeof(unsigned long)) < 0 ||
234 write(audio.mixer_pipe[1], &str_size2,
235 sizeof(unsigned long)) < 0 ||
236 write(audio.mixer_pipe[1], &str_size3,
237 sizeof(unsigned long)) < 0 ||
238 write(audio.mixer_pipe[1], leveldir_current->fullpath,
240 write(audio.mixer_pipe[1], ti->basepath,
242 write(audio.mixer_pipe[1], ti->fullpath,
245 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
246 audio.sound_available = audio.sound_enabled = FALSE;
251 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
253 TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
254 &artwork.snd_current : &artwork.mus_current);
255 TreeInfo *ti = *ti_ptr;
256 unsigned long str_size1, str_size2, str_size3;
257 static char *set_name = NULL;
262 set_name = checked_malloc(snd_ctrl.data_len);
264 if (leveldir_current == NULL)
265 leveldir_current = checked_calloc(sizeof(TreeInfo));
267 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
268 if (leveldir_current->fullpath != NULL)
269 free(leveldir_current->fullpath);
270 if (ti->basepath != NULL)
272 if (ti->fullpath != NULL)
275 if (read(audio.mixer_pipe[0], set_name,
276 snd_ctrl.data_len) != snd_ctrl.data_len ||
277 read(audio.mixer_pipe[0], leveldir_current,
278 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
279 read(audio.mixer_pipe[0], ti,
280 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
281 read(audio.mixer_pipe[0], &str_size1,
282 sizeof(unsigned long)) != sizeof(unsigned long) ||
283 read(audio.mixer_pipe[0], &str_size2,
284 sizeof(unsigned long)) != sizeof(unsigned long) ||
285 read(audio.mixer_pipe[0], &str_size3,
286 sizeof(unsigned long)) != sizeof(unsigned long))
287 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
289 leveldir_current->fullpath = checked_calloc(str_size1);
290 ti->basepath = checked_calloc(str_size2);
291 ti->fullpath = checked_calloc(str_size3);
293 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
294 str_size1) != str_size1 ||
295 read(audio.mixer_pipe[0], ti->basepath,
296 str_size2) != str_size2 ||
297 read(audio.mixer_pipe[0], ti->fullpath,
298 str_size3) != str_size3)
299 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
301 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
302 artwork.sounds_set_current = set_name;
304 artwork.music_set_current = set_name;
306 #endif /* PLATFORM_UNIX */
308 void Mixer_InitChannels()
312 for(i=0; i<audio.num_channels; i++)
313 mixer[i].active = FALSE;
314 mixer_active_channels = 0;
317 static void Mixer_PlayChannel(int channel)
319 #if defined(PLATFORM_MSDOS)
320 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
322 if (mixer[channel].voice < 0)
325 if (IS_LOOP(mixer[channel]))
326 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
328 voice_set_volume(mixer[channel].voice, snd_ctrl.volume);
329 voice_set_pan(mixer[channel].voice, snd_ctrl.stereo);
330 voice_start(mixer[channel].voice);
334 static void Mixer_StopChannel(int channel)
336 #if defined(PLATFORM_MSDOS)
337 voice_set_volume(mixer[channel].voice, 0);
338 deallocate_voice(mixer[channel].voice);
342 static void Mixer_FadeChannel(int channel)
344 mixer[channel].state |= SND_CTRL_FADE;
346 #if defined(PLATFORM_MSDOS)
347 if (voice_check(mixer[channel].voice))
348 voice_ramp_volume(mixer[channel].voice, 1000, 0);
349 mixer[channel].state &= ~SND_CTRL_IS_LOOP;
353 static void Mixer_RemoveSound(int channel)
355 if (!mixer_active_channels || !mixer[channel].active)
359 printf("REMOVING MIXER SOUND %d\n", channel);
362 Mixer_StopChannel(channel);
364 mixer[channel].active = FALSE;
365 mixer_active_channels--;
368 static void Mixer_InsertSound(struct SoundControl snd_ctrl)
374 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
377 if (IS_MUSIC(snd_ctrl))
378 snd_ctrl.nr = snd_ctrl.nr % num_music;
379 else if (snd_ctrl.nr >= num_sounds)
382 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
383 if (snd_info == NULL)
386 printf("sound/music %d undefined\n", snd_ctrl.nr);
392 printf("-> %d\n", mixer_active_channels);
395 if (mixer_active_channels == audio.num_channels)
397 for (i=0; i<audio.num_channels; i++)
399 if (mixer[i].data_ptr == NULL)
402 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
405 Mixer_RemoveSound(i);
410 /* if mixer is full, remove oldest sound */
411 if (mixer_active_channels == audio.num_channels)
413 int longest = 0, longest_nr = audio.first_sound_channel;
415 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
417 #if !defined(PLATFORM_MSDOS)
418 int actual = 100 * mixer[i].playingpos / mixer[i].data_len;
420 int actual = mixer[i].playingpos;
423 if (!IS_LOOP(mixer[i]) && actual > longest)
430 Mixer_RemoveSound(longest_nr);
433 /* check if sound is already being played (and how often) */
434 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
435 if (mixer[i].nr == snd_ctrl.nr)
438 /* restart loop sounds only if they are just fading out */
439 if (k >= 1 && IS_LOOP(snd_ctrl))
441 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
443 if (mixer[i].nr == snd_ctrl.nr && IS_FADING(mixer[i]))
445 mixer[i].state &= ~SND_CTRL_FADE;
446 mixer[i].volume = PSND_MAX_VOLUME;
447 #if defined(PLATFORM_MSDOS)
448 mixer[i].state |= SND_CTRL_LOOP;
449 voice_stop_volumeramp(mixer[i].voice);
450 voice_ramp_volume(mixer[i].voice, mixer[i].volume, 1000);
458 /* don't play sound more than n times simultaneously (with n == 2 for now) */
461 int longest = 0, longest_nr = audio.first_sound_channel;
463 /* look for oldest equal sound */
464 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
468 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
471 #if !defined(PLATFORM_MSDOS)
472 actual = 100 * mixer[i].playingpos / mixer[i].data_len;
474 actual = mixer[i].playingpos;
476 if (actual >= longest)
483 Mixer_RemoveSound(longest_nr);
486 /* add new sound to mixer */
487 for(i=0; i<audio.num_channels; i++)
490 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
494 if (!mixer[i].active ||
495 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
497 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
498 (i != audio.music_channel && !mixer[i].active))
500 snd_ctrl.data_ptr = snd_info->data_ptr;
501 snd_ctrl.data_len = snd_info->data_len;
502 snd_ctrl.format = snd_info->format;
504 snd_ctrl.playingpos = 0;
505 snd_ctrl.playingtime = 0;
508 if (snd_info->data_len == 0)
510 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
515 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
517 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
520 Mixer_RemoveSound(i);
526 mixer_active_channels++;
529 printf("NEW SOUND %d ADDED TO MIXER\n", snd_ctrl.nr);
532 Mixer_PlayChannel(i);
539 static void HandleSoundRequest(struct SoundControl snd_ctrl)
543 #if defined(PLATFORM_MSDOS)
544 for (i=0; i<audio.num_channels; i++)
546 if (!mixer[i].active || IS_LOOP(mixer[i]))
549 mixer[i].playingpos = voice_get_position(mixer[i].voice);
550 mixer[i].volume = voice_get_volume(mixer[i].voice);
552 if (mixer[i].playingpos == -1 || mixer[i].volume == 0)
553 Mixer_RemoveSound(i);
555 #endif /* PLATFORM_MSDOS */
557 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
559 ReadReloadInfoFromPipe(snd_ctrl);
560 Mixer_InitChannels();
561 CloseAudioDevice(&audio.device_fd);
563 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
564 ReloadCustomSounds();
568 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
570 if (!mixer_active_channels)
573 if (IS_MUSIC(snd_ctrl))
575 Mixer_FadeChannel(audio.music_channel);
579 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
580 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
581 Mixer_FadeChannel(i);
583 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
585 if (!mixer_active_channels)
588 if (IS_MUSIC(snd_ctrl))
590 Mixer_RemoveSound(audio.music_channel);
594 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
595 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
596 Mixer_RemoveSound(i);
598 if (!mixer_active_channels)
599 CloseAudioDevice(&audio.device_fd);
601 else if (snd_ctrl.active) /* add new sound to mixer */
603 Mixer_InsertSound(snd_ctrl);
607 void StartMixer(void)
609 if (!audio.sound_available)
612 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
613 if (!ForkAudioProcess())
614 audio.sound_available = FALSE;
618 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
620 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
621 int sample_pos, int sample_size,
624 void *sample_ptr = snd_ctrl->data_ptr;
627 if (snd_ctrl->format == AUDIO_FORMAT_U8)
628 for (i=0; i<sample_size; i++)
630 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
631 else /* AUDIO_FORMAT_S16 */
632 for (i=0; i<sample_size; i++)
634 ((short *)sample_ptr)[sample_pos + i];
637 #if defined(AUDIO_STREAMING_DSP)
638 static void Mixer_Main_DSP()
640 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
641 static boolean stereo_volume_calculated = FALSE;
642 static short premix_first_buffer[SND_BLOCKSIZE];
643 static short premix_left_buffer[SND_BLOCKSIZE];
644 static short premix_right_buffer[SND_BLOCKSIZE];
645 static long premix_last_buffer[SND_BLOCKSIZE];
646 static byte playing_buffer[SND_BLOCKSIZE];
653 if (!stereo_volume_calculated)
655 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
657 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
659 stereo_volume_calculated = TRUE;
662 if (!mixer_active_channels)
665 if (audio.device_fd < 0)
667 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
670 InitAudioDevice(&afmt);
673 stereo = afmt.stereo;
674 fragment_size = afmt.fragment_size;
675 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
676 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
678 /* first clear the last premixing buffer */
679 memset(premix_last_buffer, 0,
680 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
682 for(i=0; i<audio.num_channels; i++)
689 if (!mixer[i].active)
692 /* pointer, lenght and actual playing position of sound sample */
693 sample_ptr = mixer[i].data_ptr;
694 sample_len = mixer[i].data_len;
695 sample_pos = mixer[i].playingpos;
696 sample_size = MIN(max_sample_size, sample_len - sample_pos);
697 mixer[i].playingpos += sample_size;
699 /* copy original sample to first mixing buffer */
700 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
701 premix_first_buffer);
703 /* are we about to restart a looping sound? */
704 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
706 while (sample_size < max_sample_size)
708 int restarted_sample_size =
709 MIN(max_sample_size - sample_size, sample_len);
711 if (mixer[i].format == AUDIO_FORMAT_U8)
712 for (j=0; j<restarted_sample_size; j++)
713 premix_first_buffer[sample_size + j] =
714 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
716 for (j=0; j<restarted_sample_size; j++)
717 premix_first_buffer[sample_size + j] =
718 ((short *)sample_ptr)[j];
720 mixer[i].playingpos = restarted_sample_size;
721 sample_size += restarted_sample_size;
725 /* decrease volume if sound is fading out */
726 if (IS_FADING(mixer[i]) &&
727 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
728 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
730 /* adjust volume of actual sound sample */
731 if (mixer[i].volume != PSND_MAX_VOLUME)
732 for(j=0; j<sample_size; j++)
733 premix_first_buffer[j] =
734 (mixer[i].volume * (long)premix_first_buffer[j])
735 >> PSND_MAX_VOLUME_BITS;
737 /* fill the last mixing buffer with stereo or mono sound */
740 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
741 int left_volume = stereo_volume[middle_pos + mixer[i].stereo];
742 int right_volume= stereo_volume[middle_pos - mixer[i].stereo];
744 for(j=0; j<sample_size; j++)
746 premix_left_buffer[j] =
747 (left_volume * premix_first_buffer[j])
748 >> PSND_MAX_LEFT2RIGHT_BITS;
749 premix_right_buffer[j] =
750 (right_volume * premix_first_buffer[j])
751 >> PSND_MAX_LEFT2RIGHT_BITS;
753 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
754 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
759 for(j=0; j<sample_size; j++)
760 premix_last_buffer[j] += premix_first_buffer[j];
763 /* delete completed sound entries from the mixer */
764 if (mixer[i].playingpos >= mixer[i].data_len)
766 if (IS_LOOP(mixer[i]))
767 mixer[i].playingpos = 0;
769 Mixer_RemoveSound(i);
771 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
772 Mixer_RemoveSound(i);
775 /* prepare final playing buffer according to system audio format */
776 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
778 /* cut off at 17 bit value */
779 if (premix_last_buffer[i] < -65535)
780 premix_last_buffer[i] = -65535;
781 else if (premix_last_buffer[i] > 65535)
782 premix_last_buffer[i] = 65535;
784 /* shift to 16 bit value */
785 premix_last_buffer[i] >>= 1;
787 if (afmt.format & AUDIO_FORMAT_U8)
789 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
791 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
793 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
794 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
796 else /* big endian */
798 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
799 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
803 /* finally play the sound fragment */
804 write(audio.device_fd, playing_buffer, fragment_size);
806 if (!mixer_active_channels)
807 CloseAudioDevice(&audio.device_fd);
810 #else /* !AUDIO_STREAMING_DSP */
812 static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
814 static short premix_first_buffer[SND_BLOCKSIZE];
815 static byte playing_buffer[SND_BLOCKSIZE];
816 int max_sample_size = SND_BLOCKSIZE;
825 /* pointer, lenght and actual playing position of sound sample */
826 sample_ptr = mixer[i].data_ptr;
827 sample_len = mixer[i].data_len;
828 sample_pos = mixer[i].playingpos;
829 sample_size = MIN(max_sample_size, sample_len - sample_pos);
830 mixer[i].playingpos += sample_size;
832 /* copy original sample to first mixing buffer */
833 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
834 premix_first_buffer);
836 /* adjust volume of actual sound sample */
837 if (mixer[i].volume != PSND_MAX_VOLUME)
838 for(j=0; j<sample_size; j++)
839 premix_first_buffer[j] =
840 (mixer[i].volume * (long)premix_first_buffer[j])
841 >> PSND_MAX_VOLUME_BITS;
843 /* might be needed for u-law /dev/audio */
845 for(j=0; j<sample_size; j++)
847 linear_to_ulaw(premix_first_buffer[j]);
850 /* delete completed sound entries from the mixer */
851 if (mixer[i].playingpos >= mixer[i].data_len)
852 Mixer_RemoveSound(i);
854 for(i=0; i<sample_size; i++)
855 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
857 /* finally play the sound fragment */
858 write(audio.device_fd, playing_buffer, sample_size);
862 #endif /* !AUDIO_STREAMING_DSP */
866 struct SoundControl snd_ctrl;
869 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
871 Mixer_InitChannels();
873 #if defined(PLATFORM_HPUX)
874 InitAudioDevice(&afmt);
877 FD_ZERO(&mixer_fdset);
878 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
880 while(1) /* wait for sound playing commands from client */
882 struct timeval delay = { 0, 0 };
884 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
885 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
886 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
889 ReadSoundControlFromPipe(&snd_ctrl);
891 HandleSoundRequest(snd_ctrl);
893 #if defined(AUDIO_STREAMING_DSP)
895 while (mixer_active_channels &&
896 select(audio.mixer_pipe[0] + 1,
897 &mixer_fdset, NULL, NULL, &delay) < 1)
899 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
904 #else /* !AUDIO_STREAMING_DSP */
906 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
907 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
910 InitAudioDevice(&afmt);
915 while (mixer_active_channels &&
916 select(audio.mixer_pipe[0] + 1,
917 &mixer_fdset, NULL, NULL, &delay) < 1)
919 int wait_percent = 90; /* wait 90% of the real playing time */
922 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
924 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
928 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
931 CloseAudioDevice(&audio.device_fd);
933 Mixer_InitChannels(); /* remove all sounds from mixer */
935 #endif /* !AUDIO_STREAMING_DSP */
938 #endif /* PLATFORM_UNIX */
941 /* ------------------------------------------------------------------------- */
942 /* platform dependant audio initialization code */
943 /* ------------------------------------------------------------------------- */
945 #if defined(AUDIO_LINUX_IOCTL)
946 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
948 /* "ioctl()" expects pointer to 'int' value for stereo flag
949 (boolean is defined as 'char', which will not work here) */
950 unsigned int fragment_spec = 0;
951 int fragment_size_query;
960 /* supported audio format in preferred order */
961 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
962 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
963 { AFMT_U8, AUDIO_FORMAT_U8 },
968 /* determine logarithm (log2) of the fragment size */
969 while ((1 << fragment_spec) < afmt->fragment_size)
972 /* use two fragments (play one fragment, prepare the other);
973 one fragment would result in interrupted audio output, more
974 than two fragments would raise audio output latency to much */
975 fragment_spec |= 0x00020000;
977 /* Example for fragment specification:
978 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
979 - (with stereo the effective buffer size will shrink to 256)
980 => fragment_size = 0x00020009 */
982 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
983 Error(ERR_EXIT_SOUND_SERVER,
984 "cannot set fragment size of /dev/dsp -- no sounds");
988 while (formats[i].format_result != -1)
990 unsigned int audio_format = formats[i].format_ioctl;
991 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
993 afmt->format = formats[i].format_result;
998 if (afmt->format == 0) /* no supported audio format found */
999 Error(ERR_EXIT_SOUND_SERVER,
1000 "cannot set audio format of /dev/dsp -- no sounds");
1002 /* try if we can use stereo sound */
1003 afmt->stereo = TRUE;
1004 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1005 afmt->stereo = FALSE;
1007 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1008 Error(ERR_EXIT_SOUND_SERVER,
1009 "cannot set sample rate of /dev/dsp -- no sounds");
1011 /* get the real fragmentation size; this should return 512 */
1012 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1013 Error(ERR_EXIT_SOUND_SERVER,
1014 "cannot get fragment size of /dev/dsp -- no sounds");
1015 if (fragment_size_query != afmt->fragment_size)
1016 Error(ERR_EXIT_SOUND_SERVER,
1017 "cannot set fragment size of /dev/dsp -- no sounds");
1019 #endif /* AUDIO_LINUX_IOCTL */
1021 #if defined(PLATFORM_NETBSD)
1022 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1024 audio_info_t a_info;
1025 boolean stereo = TRUE;
1027 AUDIO_INITINFO(&a_info);
1028 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1029 a_info.play.precision = 8;
1030 a_info.play.channels = 2;
1031 a_info.play.sample_rate = sample_rate;
1032 a_info.blocksize = fragment_size;
1034 afmt->format = AUDIO_FORMAT_U8;
1035 afmt->stereo = TRUE;
1037 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1039 /* try to disable stereo */
1040 a_info.play.channels = 1;
1042 afmt->stereo = FALSE;
1044 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1045 Error(ERR_EXIT_SOUND_SERVER,
1046 "cannot set sample rate of /dev/audio -- no sounds");
1049 #endif /* PLATFORM_NETBSD */
1051 #if defined(PLATFORM_HPUX)
1052 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1054 struct audio_describe ainfo;
1057 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1058 if (audio_ctl == -1)
1059 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1061 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1062 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1064 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1065 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1067 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1068 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1070 afmt->format = AUDIO_FORMAT_U8;
1071 afmt->stereo = FALSE;
1072 afmt->sample_rate = 8000;
1076 #endif /* PLATFORM_HPUX */
1078 #if defined(PLATFORM_UNIX)
1079 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1081 afmt->stereo = TRUE;
1082 afmt->format = AUDIO_FORMAT_UNKNOWN;
1083 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
1084 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1086 #if defined(AUDIO_LINUX_IOCTL)
1087 InitAudioDevice_Linux(afmt);
1088 #elif defined(PLATFORM_NETBSD)
1089 InitAudioDevice_NetBSD(afmt);
1090 #elif defined(PLATFORM_HPUX)
1091 InitAudioDevice_HPUX(afmt);
1093 /* generic /dev/audio stuff might be placed here */
1096 #endif /* PLATFORM_UNIX */
1098 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1100 /* these two are stolen from "sox"... :) */
1103 ** This routine converts from linear to ulaw.
1105 ** Craig Reese: IDA/Supercomputing Research Center
1106 ** Joe Campbell: Department of Defense
1107 ** 29 September 1989
1110 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1111 ** 2) "A New Digital Technique for Implementation of Any
1112 ** Continuous PCM Companding Law," Villeret, Michel,
1113 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1114 ** 1973, pg. 11.12-11.17
1115 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1116 ** for Analog-to_Digital Conversion Techniques,"
1119 ** Input: Signed 16 bit linear sample
1120 ** Output: 8 bit ulaw sample
1123 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1124 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1127 static unsigned char linear_to_ulaw(int sample)
1129 static int exp_lut[256] =
1131 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1132 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1133 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1134 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1135 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1136 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1137 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1138 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1139 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1140 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1141 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1142 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1143 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1144 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1145 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1146 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1149 int sign, exponent, mantissa;
1150 unsigned char ulawbyte;
1152 /* Get the sample into sign-magnitude. */
1153 sign = (sample >> 8) & 0x80; /* set aside the sign */
1155 sample = -sample; /* get magnitude */
1157 sample = CLIP; /* clip the magnitude */
1159 /* Convert from 16 bit linear to ulaw. */
1160 sample = sample + BIAS;
1161 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1162 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1163 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1166 ulawbyte = 0x02; /* optional CCITT trap */
1173 ** This routine converts from ulaw to 16 bit linear.
1175 ** Craig Reese: IDA/Supercomputing Research Center
1176 ** 29 September 1989
1179 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1180 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1181 ** for Analog-to_Digital Conversion Techniques,"
1184 ** Input: 8 bit ulaw sample
1185 ** Output: signed 16 bit linear sample
1188 static int ulaw_to_linear(unsigned char ulawbyte)
1190 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1191 int sign, exponent, mantissa, sample;
1193 ulawbyte = ~ ulawbyte;
1194 sign = ( ulawbyte & 0x80 );
1195 exponent = ( ulawbyte >> 4 ) & 0x07;
1196 mantissa = ulawbyte & 0x0F;
1197 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1203 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1206 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1207 /* ========================================================================= */
1208 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1210 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1211 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1213 static SoundInfo *Load_WAV(char *filename)
1215 SoundInfo *snd_info;
1216 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1217 byte sound_header_buffer[WAV_HEADER_SIZE];
1218 char chunk_name[CHUNK_ID_LEN + 1];
1224 if (!audio.sound_available)
1228 printf("loading WAV file '%s'\n", filename);
1231 snd_info = checked_calloc(sizeof(SoundInfo));
1233 #if defined(TARGET_SDL)
1235 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1237 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1242 #elif defined(TARGET_ALLEGRO)
1244 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1246 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1251 #else /* PLATFORM_UNIX */
1253 if ((file = fopen(filename, MODE_READ)) == NULL)
1255 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1260 /* read chunk id "RIFF" */
1261 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1262 if (strcmp(chunk_name, "RIFF") != 0)
1264 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1270 /* read "RIFF" type id "WAVE" */
1271 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1272 if (strcmp(chunk_name, "WAVE") != 0)
1274 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1280 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1282 if (strcmp(chunk_name, "fmt ") == 0)
1284 /* read header information */
1285 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1286 sound_header_buffer[i] = fgetc(file);
1288 if (chunk_size > WAV_HEADER_SIZE)
1289 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1291 else if (strcmp(chunk_name, "data") == 0)
1293 snd_info->data_len = chunk_size;
1294 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1296 /* read sound data */
1297 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1300 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1302 free(snd_info->data_ptr);
1307 /* check for odd number of sample bytes (data chunk is word aligned) */
1308 if ((chunk_size % 2) == 1)
1309 ReadUnusedBytesFromFile(file, 1);
1311 else /* unknown chunk -- ignore */
1312 ReadUnusedBytesFromFile(file, chunk_size);
1317 if (snd_info->data_ptr == NULL)
1319 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1324 snd_info->format = AUDIO_FORMAT_U8;
1326 #endif /* PLATFORM_UNIX */
1328 snd_info->type = SND_TYPE_WAV;
1329 snd_info->source_filename = getStringCopy(filename);
1334 static void deleteSoundEntry(SoundInfo **snd_info)
1338 char *filename = (*snd_info)->source_filename;
1341 printf("[decrementing reference counter of sound '%s']\n", filename);
1344 if (--(*snd_info)->num_references <= 0)
1347 printf("[deleting sound '%s']\n", filename);
1351 FreeSound(*snd_info);
1353 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1360 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1364 /* check if the old and the new sound file are the same */
1365 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1367 /* The old and new sound are the same (have the same filename and path).
1368 This usually means that this sound does not exist in this sound set
1369 and a fallback to the existing sound is done. */
1372 printf("[sound '%s' already exists (same list entry)]\n", filename);
1378 /* delete existing sound file entry */
1379 deleteSoundEntry(snd_info);
1381 /* check if the new sound file already exists in the list of sounds */
1382 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1385 printf("[sound '%s' already exists (other list entry)]\n", filename);
1388 *snd_info = (SoundInfo *)node->content;
1389 (*snd_info)->num_references++;
1391 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1393 (*snd_info)->num_references = 1;
1394 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1398 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1400 char *filename = getCustomSoundFilename(basename);
1402 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1404 deleteSoundEntry(snd_info);
1408 if (filename == NULL)
1410 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1414 replaceSoundEntry(snd_info, filename);
1417 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1420 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1422 sound_effect = sounds_list;
1423 num_sounds = num_list_entries;
1426 void LoadSoundToList(char *basename, int list_pos)
1428 if (Sound == NULL || list_pos >= num_sounds)
1432 printf("loading sound '%s' ... [%d]\n",
1433 basename, getNumNodes(SoundFileList));
1436 LoadCustomSound(&Sound[list_pos], basename);
1439 printf("loading sound '%s' done [%d]\n",
1440 basename, getNumNodes(SoundFileList));
1444 static MusicInfo *Load_MOD(char *filename)
1446 #if defined(TARGET_SDL)
1447 MusicInfo *mod_info;
1449 if (!audio.sound_available)
1452 mod_info = checked_calloc(sizeof(MusicInfo));
1454 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1456 Error(ERR_WARN, "cannot read music file '%s'", filename);
1461 mod_info->type = MUS_TYPE_MOD;
1462 mod_info->source_filename = getStringCopy(filename);
1470 void LoadCustomMusic(void)
1472 char *music_directory = getCustomMusicDirectory();
1474 struct dirent *dir_entry;
1476 if (!audio.sound_available)
1479 if ((dir = opendir(music_directory)) == NULL)
1481 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1482 audio.music_available = FALSE;
1486 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1488 char *basename = dir_entry->d_name;
1489 char *filename = getPath2(music_directory, basename);
1490 MusicInfo *mus_info = NULL;
1492 if (FileIsSound(basename))
1493 mus_info = Load_WAV(filename);
1494 else if (FileIsMusic(basename))
1495 mus_info = Load_MOD(filename);
1502 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1503 Music[num_music -1] = mus_info;
1510 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1514 void PlayMusic(int nr)
1516 if (!audio.music_available)
1519 #if defined(TARGET_SDL)
1521 nr = nr % num_music;
1523 if (Music[nr]->type == MUS_TYPE_MOD)
1525 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1526 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1528 else /* play WAV music loop */
1530 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1531 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1541 void PlaySound(int nr)
1543 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1546 void PlaySoundStereo(int nr, int stereo)
1548 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1551 void PlaySoundLoop(int nr)
1553 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1556 void PlaySoundMusic(int nr)
1558 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1561 void PlaySoundExt(int nr, int volume, int stereo, int state)
1563 struct SoundControl snd_ctrl;
1565 if (!audio.sound_available ||
1566 !audio.sound_enabled ||
1567 audio.sound_deactivated)
1570 if (volume < PSND_MIN_VOLUME)
1571 volume = PSND_MIN_VOLUME;
1572 else if (volume > PSND_MAX_VOLUME)
1573 volume = PSND_MAX_VOLUME;
1575 if (stereo < PSND_MAX_LEFT)
1576 stereo = PSND_MAX_LEFT;
1577 else if (stereo > PSND_MAX_RIGHT)
1578 stereo = PSND_MAX_RIGHT;
1580 snd_ctrl.active = TRUE;
1582 snd_ctrl.volume = volume;
1583 snd_ctrl.stereo = stereo;
1584 snd_ctrl.state = state;
1586 #if defined(TARGET_SDL)
1589 Mix_Volume(-1, SOUND_MAX_VOLUME);
1590 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1592 #elif defined(PLATFORM_UNIX)
1594 WriteSoundControlToPipe(snd_ctrl);
1596 #elif defined(PLATFORM_MSDOS)
1598 HandleSoundRequest(snd_ctrl);
1603 void FadeMusic(void)
1605 if (!audio.sound_available)
1608 #if defined(TARGET_SDL)
1609 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1610 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1612 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1616 void FadeSound(int nr)
1618 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1624 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1627 void StopMusic(void)
1629 #if defined(TARGET_SDL)
1630 if (!audio.sound_available)
1634 Mix_HaltChannel(audio.music_channel);
1636 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1640 void StopSound(int nr)
1642 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1648 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1651 void StopSoundExt(int nr, int state)
1653 struct SoundControl snd_ctrl;
1655 if (!audio.sound_available)
1658 snd_ctrl.active = FALSE;
1660 snd_ctrl.state = state;
1662 #if defined(TARGET_SDL)
1664 if (state & SND_CTRL_FADE)
1669 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
1672 for (i=0; i<audio.channels; i++)
1673 if (i != audio.music_channel || snd_ctrl.music)
1674 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1675 if (state & SND_CTRL_MUSIC)
1676 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1682 for (i=0; i<audio.channels; i++)
1683 if (i != audio.music_channel || snd_ctrl.music)
1685 if (state & SND_CTRL_MUSIC)
1689 #elif !defined(PLATFORM_MSDOS)
1691 WriteSoundControlToPipe(snd_ctrl);
1693 #else /* PLATFORM_MSDOS */
1695 HandleSoundRequest(snd_ctrl);
1700 ListNode *newListNode()
1702 return checked_calloc(sizeof(ListNode));
1705 void addNodeToList(ListNode **node_first, char *key, void *content)
1707 ListNode *node_new = newListNode();
1710 printf("LIST: adding node with key '%s'\n", key);
1713 node_new->key = getStringCopy(key);
1714 node_new->content = content;
1715 node_new->next = *node_first;
1716 *node_first = node_new;
1719 void deleteNodeFromList(ListNode **node_first, char *key,
1720 void (*destructor_function)(void *))
1722 if (node_first == NULL || *node_first == NULL)
1726 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1727 (*node_first)->key, key);
1730 if (strcmp((*node_first)->key, key) == 0)
1733 printf("[DELETING LIST ENTRY]\n");
1736 free((*node_first)->key);
1737 if (destructor_function)
1738 destructor_function((*node_first)->content);
1739 *node_first = (*node_first)->next;
1742 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1745 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1747 if (node_first == NULL)
1750 if (strcmp(node_first->key, key) == 0)
1753 return getNodeFromKey(node_first->next, key);
1756 int getNumNodes(ListNode *node_first)
1758 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1761 void dumpList(ListNode *node_first)
1763 ListNode *node = node_first;
1767 printf("['%s' (%d)]\n", node->key,
1768 ((SoundInfo *)node->content)->num_references);
1772 printf("[%d nodes]\n", getNumNodes(node_first));
1775 static void LoadSoundsInfo()
1777 char *filename = getCustomSoundConfigFilename();
1778 struct SetupFileList *setup_file_list;
1781 /* always start with reliable default values */
1782 for (i=0; i<num_sounds; i++)
1783 sound_effect[i].filename = NULL;
1785 if (filename == NULL)
1788 if ((setup_file_list = loadSetupFileList(filename)))
1790 for (i=0; i<num_sounds; i++)
1791 sound_effect[i].filename =
1792 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1794 freeSetupFileList(setup_file_list);
1797 for (i=0; i<num_sounds; i++)
1799 printf("'%s' ", sound_effect[i].text);
1800 if (sound_effect[i].filename)
1801 printf("-> '%s'\n", sound_effect[i].filename);
1803 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1809 static void ReloadCustomSounds()
1814 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1820 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1823 for(i=0; i<num_sounds; i++)
1825 if (sound_effect[i].filename)
1826 LoadSoundToList(sound_effect[i].filename, i);
1828 LoadSoundToList(sound_effect[i].default_filename, i);
1832 printf("list size == %d\n", getNumNodes(SoundFileList));
1836 dumpList(SoundFileList);
1840 static void ReloadCustomMusic()
1843 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1851 void InitReloadSounds(char *set_name)
1853 if (!audio.sound_available)
1856 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1857 ReloadCustomSounds();
1858 #elif defined(PLATFORM_UNIX)
1859 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
1863 void InitReloadMusic(char *set_name)
1865 if (!audio.music_available)
1868 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1869 ReloadCustomMusic();
1870 #elif defined(PLATFORM_UNIX)
1871 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
1875 void FreeSound(void *ptr)
1877 SoundInfo *sound = (SoundInfo *)ptr;
1882 if (sound->data_ptr)
1884 #if defined(TARGET_SDL)
1885 Mix_FreeChunk(sound->data_ptr);
1886 #elif defined(TARGET_ALLEGRO)
1887 destroy_sample(sound->data_ptr);
1888 #else /* PLATFORM_UNIX */
1889 free(sound->data_ptr);
1893 if (sound->source_filename)
1894 free(sound->source_filename);
1899 void FreeMusic(MusicInfo *music)
1904 if (music->data_ptr)
1906 #if defined(TARGET_SDL)
1907 if (music->type == MUS_TYPE_MOD)
1908 Mix_FreeMusic(music->data_ptr);
1910 Mix_FreeChunk(music->data_ptr);
1911 #elif defined(TARGET_ALLEGRO)
1912 destroy_sample(music->data_ptr);
1913 #else /* PLATFORM_UNIX */
1914 free(music->data_ptr);
1921 void FreeAllSounds()
1928 printf("%s: FREEING SOUNDS ...\n",
1929 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
1931 for(i=0; i<num_sounds; i++)
1932 deleteSoundEntry(&Sound[i]);
1934 FreeSound(Sound[i]);
1937 printf("%s: FREEING SOUNDS -- DONE\n",
1938 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
1953 for(i=0; i<num_music; i++)
1954 FreeMusic(Music[i]);
1962 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1963 /* ========================================================================= */