1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
27 #define IS_PARENT_PROCESS(pid) ((pid) > 0)
28 #define IS_CHILD_PROCESS(pid) ((pid) == 0)
34 struct ListNode *next;
36 typedef struct ListNode ListNode;
38 static ListNode *newListNode(void);
39 static void addNodeToList(ListNode **, char *, void *);
40 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
41 static ListNode *getNodeFromKey(ListNode *, char *);
42 static int getNumNodes(ListNode *);
45 static struct SoundEffectInfo *sound_effect;
46 static ListNode *SoundFileList = NULL;
47 static SoundInfo **Sound = NULL;
48 static MusicInfo **Music = NULL;
49 static int num_sounds = 0, num_music = 0;
52 /* ========================================================================= */
53 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
55 static struct AudioFormatInfo afmt;
56 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
57 static int mixer_active_channels = 0;
59 /* forward declaration of internal functions */
60 static void InitAudioDevice(struct AudioFormatInfo *);
61 static void Mixer_Main(void);
63 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
64 static unsigned char linear_to_ulaw(int);
65 static int ulaw_to_linear(unsigned char);
68 static void ReloadCustomSounds();
69 static void ReloadCustomMusic();
70 static void FreeSound(void *);
72 #if defined(PLATFORM_UNIX)
73 static int OpenAudioDevice(char *audio_device_name)
77 /* check if desired audio device is accessible */
78 if (access(audio_device_name, W_OK) != 0)
81 /* try to open audio device in non-blocking mode */
82 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
83 return audio_device_fd;
85 /* re-open audio device in blocking mode */
86 close(audio_device_fd);
87 audio_device_fd = open(audio_device_name, O_WRONLY);
89 return audio_device_fd;
92 static void CloseAudioDevice(int *audio_device_fd)
94 if (*audio_device_fd == 0)
97 close(*audio_device_fd);
98 *audio_device_fd = -1;
101 static boolean TestAudioDevices(void)
103 static char *audio_device_name[] =
108 int audio_device_fd = -1;
111 /* look for available audio devices, starting with preferred ones */
112 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
113 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
116 if (audio_device_fd < 0)
118 Error(ERR_WARN, "cannot open audio device -- no sound");
122 close(audio_device_fd);
124 audio.device_name = audio_device_name[i];
129 #if !defined(TARGET_SDL)
130 static boolean ForkAudioProcess(void)
132 if (pipe(audio.mixer_pipe) < 0)
134 Error(ERR_WARN, "cannot create pipe -- no sounds");
138 if ((audio.mixer_pid = fork()) < 0)
140 Error(ERR_WARN, "cannot create sound server process -- no sounds");
144 if (IS_CHILD_PROCESS(audio.mixer_pid))
145 Mixer_Main(); /* this function never returns */
147 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
153 void UnixOpenAudio(void)
155 if (!TestAudioDevices())
158 audio.sound_available = TRUE;
159 audio.sound_enabled = TRUE;
161 #if defined(AUDIO_STREAMING_DSP)
162 audio.music_available = TRUE;
163 audio.loops_available = TRUE;
166 audio.num_channels = NUM_MIXER_CHANNELS;
167 audio.music_channel = MUSIC_CHANNEL;
168 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
171 void UnixCloseAudio(void)
174 close(audio.device_fd);
176 if (IS_PARENT_PROCESS(audio.mixer_pid))
177 kill(audio.mixer_pid, SIGTERM);
180 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
182 if (IS_CHILD_PROCESS(audio.mixer_pid))
185 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
187 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
188 audio.sound_available = audio.sound_enabled = FALSE;
193 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
195 if (IS_PARENT_PROCESS(audio.mixer_pid))
198 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
199 != sizeof(SoundControl))
200 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
203 static void WriteReloadInfoToPipe(char *set_name, int type)
205 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 if (IS_CHILD_PROCESS(audio.mixer_pid))
215 if (leveldir_current == NULL) /* should never happen */
216 Error(ERR_EXIT, "leveldir_current == NULL");
218 snd_ctrl.active = FALSE;
219 snd_ctrl.state = type;
220 snd_ctrl.data_len = strlen(set_name) + 1;
222 if (write(audio.mixer_pipe[1], &snd_ctrl,
223 sizeof(snd_ctrl)) < 0 ||
224 write(audio.mixer_pipe[1], set_name,
225 snd_ctrl.data_len) < 0 ||
226 write(audio.mixer_pipe[1], leveldir_current,
227 sizeof(TreeInfo)) < 0 ||
228 write(audio.mixer_pipe[1], ti,
229 sizeof(TreeInfo)) < 0 ||
230 write(audio.mixer_pipe[1], &str_size1,
231 sizeof(unsigned long)) < 0 ||
232 write(audio.mixer_pipe[1], &str_size2,
233 sizeof(unsigned long)) < 0 ||
234 write(audio.mixer_pipe[1], &str_size3,
235 sizeof(unsigned long)) < 0 ||
236 write(audio.mixer_pipe[1], leveldir_current->fullpath,
238 write(audio.mixer_pipe[1], ti->basepath,
240 write(audio.mixer_pipe[1], ti->fullpath,
243 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
244 audio.sound_available = audio.sound_enabled = FALSE;
249 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
251 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
252 &artwork.snd_current : &artwork.mus_current);
253 TreeInfo *ti = *ti_ptr;
254 unsigned long str_size1, str_size2, str_size3;
255 static char *set_name = NULL;
260 set_name = checked_malloc(snd_ctrl->data_len);
262 if (leveldir_current == NULL)
263 leveldir_current = checked_calloc(sizeof(TreeInfo));
265 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
266 if (leveldir_current->fullpath != NULL)
267 free(leveldir_current->fullpath);
268 if (ti->basepath != NULL)
270 if (ti->fullpath != NULL)
273 if (read(audio.mixer_pipe[0], set_name,
274 snd_ctrl->data_len) != snd_ctrl->data_len ||
275 read(audio.mixer_pipe[0], leveldir_current,
276 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
277 read(audio.mixer_pipe[0], ti,
278 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
279 read(audio.mixer_pipe[0], &str_size1,
280 sizeof(unsigned long)) != sizeof(unsigned long) ||
281 read(audio.mixer_pipe[0], &str_size2,
282 sizeof(unsigned long)) != sizeof(unsigned long) ||
283 read(audio.mixer_pipe[0], &str_size3,
284 sizeof(unsigned long)) != sizeof(unsigned long))
285 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
287 leveldir_current->fullpath = checked_calloc(str_size1);
288 ti->basepath = checked_calloc(str_size2);
289 ti->fullpath = checked_calloc(str_size3);
291 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
292 str_size1) != str_size1 ||
293 read(audio.mixer_pipe[0], ti->basepath,
294 str_size2) != str_size2 ||
295 read(audio.mixer_pipe[0], ti->fullpath,
296 str_size3) != str_size3)
297 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
299 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
300 artwork.sounds_set_current = set_name;
302 artwork.music_set_current = set_name;
304 #endif /* PLATFORM_UNIX */
306 void Mixer_InitChannels()
310 for(i=0; i<audio.num_channels; i++)
311 mixer[i].active = FALSE;
312 mixer_active_channels = 0;
315 static void Mixer_PlayChannel(int channel)
317 /* start with inactive channel in case something goes wrong */
318 mixer[channel].active = FALSE;
320 if (IS_MUSIC_MODULE(mixer[channel]))
323 mixer[channel].playingpos = 0;
324 mixer[channel].playingtime = 0;
326 #if defined(TARGET_SDL)
327 Mix_Volume(channel, SOUND_MAX_VOLUME);
328 Mix_PlayChannel(channel, mixer[channel].data_ptr,
329 IS_LOOP(mixer[channel]) ? -1 : 0);
330 #elif defined(PLATFORM_MSDOS)
331 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
332 if (mixer[channel].voice < 0)
335 if (IS_LOOP(mixer[channel]))
336 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
338 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
339 voice_set_pan(mixer[channel].voice, mixer[channel].stereo);
340 voice_start(mixer[channel].voice);
343 mixer[channel].active = TRUE;
344 mixer_active_channels++;
347 static void Mixer_PlayMusicChannel()
349 Mixer_PlayChannel(audio.music_channel);
351 #if defined(TARGET_SDL)
352 if (IS_MUSIC_MODULE(mixer[audio.music_channel]))
354 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
355 this looks like a bug in the SDL_mixer library */
356 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
357 Mix_VolumeMusic(SOUND_MAX_VOLUME);
362 static void Mixer_StopChannel(int channel)
364 if (!mixer_active_channels || !mixer[channel].active)
367 #if defined(TARGET_SDL)
368 Mix_HaltChannel(channel);
369 #elif defined(PLATFORM_MSDOS)
370 voice_set_volume(mixer[channel].voice, 0);
371 deallocate_voice(mixer[channel].voice);
374 mixer[channel].active = FALSE;
375 mixer_active_channels--;
378 static void Mixer_StopMusicChannel()
380 Mixer_StopChannel(audio.music_channel);
382 #if defined(TARGET_SDL)
387 static void Mixer_FadeChannel(int channel)
389 mixer[channel].state |= SND_CTRL_FADE;
391 #if defined(TARGET_SDL)
392 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
393 #elif defined(PLATFORM_MSDOS)
394 if (voice_check(mixer[channel].voice))
395 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
396 mixer[channel].state &= ~SND_CTRL_IS_LOOP;
400 static void Mixer_FadeMusicChannel()
402 Mixer_FadeChannel(audio.music_channel);
404 #if defined(TARGET_SDL)
405 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
409 static void Mixer_InsertSound(SoundControl snd_ctrl)
415 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
418 if (IS_MUSIC(snd_ctrl))
419 snd_ctrl.nr = snd_ctrl.nr % num_music;
420 else if (snd_ctrl.nr >= num_sounds)
423 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
424 if (snd_info == NULL)
427 /* copy sound sample and format information */
428 snd_ctrl.data_ptr = snd_info->data_ptr;
429 snd_ctrl.data_len = snd_info->data_len;
430 snd_ctrl.format = snd_info->format;
432 if (IS_MUSIC(snd_ctrl))
434 mixer[audio.music_channel] = snd_ctrl;
436 Mixer_PlayChannel(audio.music_channel);
442 printf("-> %d\n", mixer_active_channels);
445 if (mixer_active_channels == audio.num_channels)
447 for (i=0; i<audio.num_channels; i++)
449 if (mixer[i].data_ptr == NULL)
452 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
455 Mixer_StopChannel(i);
460 /* if mixer is full, remove oldest sound */
461 if (mixer_active_channels == audio.num_channels)
463 int longest = 0, longest_nr = audio.first_sound_channel;
465 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
467 #if !defined(PLATFORM_MSDOS)
468 int actual = 100 * mixer[i].playingpos / mixer[i].data_len;
470 int actual = mixer[i].playingpos;
473 if (!IS_LOOP(mixer[i]) && actual > longest)
480 Mixer_StopChannel(longest_nr);
483 /* check if sound is already being played (and how often) */
484 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
485 if (mixer[i].nr == snd_ctrl.nr)
488 /* restart loop sounds only if they are just fading out */
489 if (k >= 1 && IS_LOOP(snd_ctrl))
491 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
493 if (mixer[i].nr == snd_ctrl.nr && IS_FADING(mixer[i]))
495 mixer[i].state &= ~SND_CTRL_FADE;
496 mixer[i].volume = PSND_MAX_VOLUME;
497 #if defined(PLATFORM_MSDOS)
498 mixer[i].state |= SND_CTRL_LOOP;
499 voice_stop_volumeramp(mixer[i].voice);
500 voice_ramp_volume(mixer[i].voice, mixer[i].volume, 1000);
508 /* don't play sound more than n times simultaneously (with n == 2 for now) */
511 int longest = 0, longest_nr = audio.first_sound_channel;
513 /* look for oldest equal sound */
514 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
518 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
521 #if !defined(PLATFORM_MSDOS)
522 actual = 100 * mixer[i].playingpos / mixer[i].data_len;
524 actual = mixer[i].playingpos;
526 if (actual >= longest)
533 Mixer_StopChannel(longest_nr);
536 /* add new sound to mixer */
537 for(i=0; i<audio.num_channels; i++)
540 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
544 if (!mixer[i].active ||
545 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
547 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
548 (i != audio.music_channel && !mixer[i].active))
551 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
555 if (snd_info->data_len == 0)
557 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
562 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
564 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
567 Mixer_StopChannel(i);
573 snd_ctrl.data_ptr = snd_info->data_ptr;
574 snd_ctrl.data_len = snd_info->data_len;
575 snd_ctrl.format = snd_info->format;
580 Mixer_PlayChannel(i);
587 static void HandleSoundRequest(SoundControl snd_ctrl)
591 #if defined(AUDIO_UNIX_NATIVE)
592 if (IS_PARENT_PROCESS(audio.mixer_pid))
594 SendSoundControlToMixerProcess(&snd_ctrl);
597 #elif defined(TARGET_ALLEGRO)
598 for (i=0; i<audio.num_channels; i++)
600 if (!mixer[i].active || IS_LOOP(mixer[i]))
603 mixer[i].playingpos = voice_get_position(mixer[i].voice);
604 mixer[i].volume = voice_get_volume(mixer[i].voice);
606 if (mixer[i].playingpos == -1 || mixer[i].volume == 0)
607 Mixer_StopChannel(i);
609 #endif /* TARGET_ALLEGRO */
611 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
613 ReadReloadInfoFromPipe(&snd_ctrl);
614 Mixer_InitChannels();
615 CloseAudioDevice(&audio.device_fd);
617 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
618 ReloadCustomSounds();
622 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
624 if (!mixer_active_channels)
627 if (IS_MUSIC(snd_ctrl))
629 Mixer_FadeChannel(audio.music_channel);
633 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
634 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
635 Mixer_FadeChannel(i);
637 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
639 if (!mixer_active_channels)
642 if (IS_MUSIC(snd_ctrl))
644 Mixer_StopChannel(audio.music_channel);
648 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
649 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
650 Mixer_StopChannel(i);
652 if (!mixer_active_channels)
653 CloseAudioDevice(&audio.device_fd);
655 else if (snd_ctrl.active) /* add new sound to mixer */
657 Mixer_InsertSound(snd_ctrl);
661 void StartMixer(void)
663 if (!audio.sound_available)
666 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
667 if (!ForkAudioProcess())
668 audio.sound_available = FALSE;
672 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
674 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
675 int sample_pos, int sample_size,
678 void *sample_ptr = snd_ctrl->data_ptr;
681 if (snd_ctrl->format == AUDIO_FORMAT_U8)
682 for (i=0; i<sample_size; i++)
684 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
685 else /* AUDIO_FORMAT_S16 */
686 for (i=0; i<sample_size; i++)
688 ((short *)sample_ptr)[sample_pos + i];
691 #if defined(AUDIO_STREAMING_DSP)
692 static void Mixer_Main_DSP()
694 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
695 static boolean stereo_volume_calculated = FALSE;
696 static short premix_first_buffer[SND_BLOCKSIZE];
697 static short premix_left_buffer[SND_BLOCKSIZE];
698 static short premix_right_buffer[SND_BLOCKSIZE];
699 static long premix_last_buffer[SND_BLOCKSIZE];
700 static byte playing_buffer[SND_BLOCKSIZE];
707 if (!stereo_volume_calculated)
709 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
711 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
713 stereo_volume_calculated = TRUE;
716 if (!mixer_active_channels)
719 if (audio.device_fd < 0)
721 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
724 InitAudioDevice(&afmt);
727 stereo = afmt.stereo;
728 fragment_size = afmt.fragment_size;
729 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
730 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
732 /* first clear the last premixing buffer */
733 memset(premix_last_buffer, 0,
734 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
736 for(i=0; i<audio.num_channels; i++)
743 if (!mixer[i].active)
746 /* pointer, lenght and actual playing position of sound sample */
747 sample_ptr = mixer[i].data_ptr;
748 sample_len = mixer[i].data_len;
749 sample_pos = mixer[i].playingpos;
750 sample_size = MIN(max_sample_size, sample_len - sample_pos);
751 mixer[i].playingpos += sample_size;
753 /* copy original sample to first mixing buffer */
754 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
755 premix_first_buffer);
757 /* are we about to restart a looping sound? */
758 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
760 while (sample_size < max_sample_size)
762 int restarted_sample_size =
763 MIN(max_sample_size - sample_size, sample_len);
765 if (mixer[i].format == AUDIO_FORMAT_U8)
766 for (j=0; j<restarted_sample_size; j++)
767 premix_first_buffer[sample_size + j] =
768 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
770 for (j=0; j<restarted_sample_size; j++)
771 premix_first_buffer[sample_size + j] =
772 ((short *)sample_ptr)[j];
774 mixer[i].playingpos = restarted_sample_size;
775 sample_size += restarted_sample_size;
779 /* decrease volume if sound is fading out */
780 if (IS_FADING(mixer[i]) &&
781 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
782 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
784 /* adjust volume of actual sound sample */
785 if (mixer[i].volume != PSND_MAX_VOLUME)
786 for(j=0; j<sample_size; j++)
787 premix_first_buffer[j] =
788 (mixer[i].volume * (long)premix_first_buffer[j])
789 >> PSND_MAX_VOLUME_BITS;
791 /* fill the last mixing buffer with stereo or mono sound */
794 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
795 int left_volume = stereo_volume[middle_pos + mixer[i].stereo];
796 int right_volume= stereo_volume[middle_pos - mixer[i].stereo];
798 for(j=0; j<sample_size; j++)
800 premix_left_buffer[j] =
801 (left_volume * premix_first_buffer[j])
802 >> PSND_MAX_LEFT2RIGHT_BITS;
803 premix_right_buffer[j] =
804 (right_volume * premix_first_buffer[j])
805 >> PSND_MAX_LEFT2RIGHT_BITS;
807 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
808 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
813 for(j=0; j<sample_size; j++)
814 premix_last_buffer[j] += premix_first_buffer[j];
817 /* delete completed sound entries from the mixer */
818 if (mixer[i].playingpos >= mixer[i].data_len)
820 if (IS_LOOP(mixer[i]))
821 mixer[i].playingpos = 0;
823 Mixer_StopChannel(i);
825 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
826 Mixer_StopChannel(i);
829 /* prepare final playing buffer according to system audio format */
830 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
832 /* cut off at 17 bit value */
833 if (premix_last_buffer[i] < -65535)
834 premix_last_buffer[i] = -65535;
835 else if (premix_last_buffer[i] > 65535)
836 premix_last_buffer[i] = 65535;
838 /* shift to 16 bit value */
839 premix_last_buffer[i] >>= 1;
841 if (afmt.format & AUDIO_FORMAT_U8)
843 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
845 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
847 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
848 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
850 else /* big endian */
852 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
853 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
857 /* finally play the sound fragment */
858 write(audio.device_fd, playing_buffer, fragment_size);
860 if (!mixer_active_channels)
861 CloseAudioDevice(&audio.device_fd);
864 #else /* !AUDIO_STREAMING_DSP */
866 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
868 static short premix_first_buffer[SND_BLOCKSIZE];
869 static byte playing_buffer[SND_BLOCKSIZE];
870 int max_sample_size = SND_BLOCKSIZE;
879 /* pointer, lenght and actual playing position of sound sample */
880 sample_ptr = mixer[i].data_ptr;
881 sample_len = mixer[i].data_len;
882 sample_pos = mixer[i].playingpos;
883 sample_size = MIN(max_sample_size, sample_len - sample_pos);
884 mixer[i].playingpos += sample_size;
886 /* copy original sample to first mixing buffer */
887 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
888 premix_first_buffer);
890 /* adjust volume of actual sound sample */
891 if (mixer[i].volume != PSND_MAX_VOLUME)
892 for(j=0; j<sample_size; j++)
893 premix_first_buffer[j] =
894 (mixer[i].volume * (long)premix_first_buffer[j])
895 >> PSND_MAX_VOLUME_BITS;
897 /* might be needed for u-law /dev/audio */
899 for(j=0; j<sample_size; j++)
901 linear_to_ulaw(premix_first_buffer[j]);
904 /* delete completed sound entries from the mixer */
905 if (mixer[i].playingpos >= mixer[i].data_len)
906 Mixer_StopChannel(i);
908 for(i=0; i<sample_size; i++)
909 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
911 /* finally play the sound fragment */
912 write(audio.device_fd, playing_buffer, sample_size);
916 #endif /* !AUDIO_STREAMING_DSP */
920 SoundControl snd_ctrl;
923 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
925 Mixer_InitChannels();
927 #if defined(PLATFORM_HPUX)
928 InitAudioDevice(&afmt);
931 FD_ZERO(&mixer_fdset);
932 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
934 while(1) /* wait for sound playing commands from client */
936 struct timeval delay = { 0, 0 };
938 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
939 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
940 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
943 ReadSoundControlFromMainProcess(&snd_ctrl);
945 HandleSoundRequest(snd_ctrl);
947 #if defined(AUDIO_STREAMING_DSP)
949 while (mixer_active_channels &&
950 select(audio.mixer_pipe[0] + 1,
951 &mixer_fdset, NULL, NULL, &delay) < 1)
953 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
958 #else /* !AUDIO_STREAMING_DSP */
960 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
961 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
964 InitAudioDevice(&afmt);
969 while (mixer_active_channels &&
970 select(audio.mixer_pipe[0] + 1,
971 &mixer_fdset, NULL, NULL, &delay) < 1)
973 int wait_percent = 90; /* wait 90% of the real playing time */
976 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
978 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
982 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
985 CloseAudioDevice(&audio.device_fd);
987 Mixer_InitChannels(); /* remove all sounds from mixer */
989 #endif /* !AUDIO_STREAMING_DSP */
992 #endif /* PLATFORM_UNIX */
995 /* ------------------------------------------------------------------------- */
996 /* platform dependant audio initialization code */
997 /* ------------------------------------------------------------------------- */
999 #if defined(AUDIO_LINUX_IOCTL)
1000 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1002 /* "ioctl()" expects pointer to 'int' value for stereo flag
1003 (boolean is defined as 'char', which will not work here) */
1004 unsigned int fragment_spec = 0;
1005 int fragment_size_query;
1014 /* supported audio format in preferred order */
1015 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1016 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1017 { AFMT_U8, AUDIO_FORMAT_U8 },
1022 /* determine logarithm (log2) of the fragment size */
1023 while ((1 << fragment_spec) < afmt->fragment_size)
1026 /* use two fragments (play one fragment, prepare the other);
1027 one fragment would result in interrupted audio output, more
1028 than two fragments would raise audio output latency to much */
1029 fragment_spec |= 0x00020000;
1031 /* Example for fragment specification:
1032 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1033 - (with stereo the effective buffer size will shrink to 256)
1034 => fragment_size = 0x00020009 */
1036 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1037 Error(ERR_EXIT_SOUND_SERVER,
1038 "cannot set fragment size of /dev/dsp -- no sounds");
1042 while (formats[i].format_result != -1)
1044 unsigned int audio_format = formats[i].format_ioctl;
1045 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1047 afmt->format = formats[i].format_result;
1052 if (afmt->format == 0) /* no supported audio format found */
1053 Error(ERR_EXIT_SOUND_SERVER,
1054 "cannot set audio format of /dev/dsp -- no sounds");
1056 /* try if we can use stereo sound */
1057 afmt->stereo = TRUE;
1058 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1059 afmt->stereo = FALSE;
1061 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1062 Error(ERR_EXIT_SOUND_SERVER,
1063 "cannot set sample rate of /dev/dsp -- no sounds");
1065 /* get the real fragmentation size; this should return 512 */
1066 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1067 Error(ERR_EXIT_SOUND_SERVER,
1068 "cannot get fragment size of /dev/dsp -- no sounds");
1069 if (fragment_size_query != afmt->fragment_size)
1070 Error(ERR_EXIT_SOUND_SERVER,
1071 "cannot set fragment size of /dev/dsp -- no sounds");
1073 #endif /* AUDIO_LINUX_IOCTL */
1075 #if defined(PLATFORM_NETBSD)
1076 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1078 audio_info_t a_info;
1079 boolean stereo = TRUE;
1081 AUDIO_INITINFO(&a_info);
1082 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1083 a_info.play.precision = 8;
1084 a_info.play.channels = 2;
1085 a_info.play.sample_rate = sample_rate;
1086 a_info.blocksize = fragment_size;
1088 afmt->format = AUDIO_FORMAT_U8;
1089 afmt->stereo = TRUE;
1091 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1093 /* try to disable stereo */
1094 a_info.play.channels = 1;
1096 afmt->stereo = FALSE;
1098 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1099 Error(ERR_EXIT_SOUND_SERVER,
1100 "cannot set sample rate of /dev/audio -- no sounds");
1103 #endif /* PLATFORM_NETBSD */
1105 #if defined(PLATFORM_HPUX)
1106 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1108 struct audio_describe ainfo;
1111 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1112 if (audio_ctl == -1)
1113 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1115 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1116 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1118 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1119 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1121 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1122 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1124 afmt->format = AUDIO_FORMAT_U8;
1125 afmt->stereo = FALSE;
1126 afmt->sample_rate = 8000;
1130 #endif /* PLATFORM_HPUX */
1132 #if defined(PLATFORM_UNIX)
1133 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1135 afmt->stereo = TRUE;
1136 afmt->format = AUDIO_FORMAT_UNKNOWN;
1137 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
1138 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1140 #if defined(AUDIO_LINUX_IOCTL)
1141 InitAudioDevice_Linux(afmt);
1142 #elif defined(PLATFORM_NETBSD)
1143 InitAudioDevice_NetBSD(afmt);
1144 #elif defined(PLATFORM_HPUX)
1145 InitAudioDevice_HPUX(afmt);
1147 /* generic /dev/audio stuff might be placed here */
1150 #endif /* PLATFORM_UNIX */
1152 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1154 /* these two are stolen from "sox"... :) */
1157 ** This routine converts from linear to ulaw.
1159 ** Craig Reese: IDA/Supercomputing Research Center
1160 ** Joe Campbell: Department of Defense
1161 ** 29 September 1989
1164 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1165 ** 2) "A New Digital Technique for Implementation of Any
1166 ** Continuous PCM Companding Law," Villeret, Michel,
1167 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1168 ** 1973, pg. 11.12-11.17
1169 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1170 ** for Analog-to_Digital Conversion Techniques,"
1173 ** Input: Signed 16 bit linear sample
1174 ** Output: 8 bit ulaw sample
1177 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1178 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1181 static unsigned char linear_to_ulaw(int sample)
1183 static int exp_lut[256] =
1185 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1186 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1187 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1188 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1189 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1190 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1191 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1192 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1193 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1194 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1195 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1196 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1197 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1198 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1199 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1200 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1203 int sign, exponent, mantissa;
1204 unsigned char ulawbyte;
1206 /* Get the sample into sign-magnitude. */
1207 sign = (sample >> 8) & 0x80; /* set aside the sign */
1209 sample = -sample; /* get magnitude */
1211 sample = CLIP; /* clip the magnitude */
1213 /* Convert from 16 bit linear to ulaw. */
1214 sample = sample + BIAS;
1215 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1216 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1217 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1220 ulawbyte = 0x02; /* optional CCITT trap */
1227 ** This routine converts from ulaw to 16 bit linear.
1229 ** Craig Reese: IDA/Supercomputing Research Center
1230 ** 29 September 1989
1233 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1234 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1235 ** for Analog-to_Digital Conversion Techniques,"
1238 ** Input: 8 bit ulaw sample
1239 ** Output: signed 16 bit linear sample
1242 static int ulaw_to_linear(unsigned char ulawbyte)
1244 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1245 int sign, exponent, mantissa, sample;
1247 ulawbyte = ~ ulawbyte;
1248 sign = ( ulawbyte & 0x80 );
1249 exponent = ( ulawbyte >> 4 ) & 0x07;
1250 mantissa = ulawbyte & 0x0F;
1251 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1257 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1260 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1261 /* ========================================================================= */
1262 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1264 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1265 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1267 static SoundInfo *Load_WAV(char *filename)
1269 SoundInfo *snd_info;
1270 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1271 byte sound_header_buffer[WAV_HEADER_SIZE];
1272 char chunk_name[CHUNK_ID_LEN + 1];
1278 if (!audio.sound_available)
1282 printf("loading WAV file '%s'\n", filename);
1285 snd_info = checked_calloc(sizeof(SoundInfo));
1287 #if defined(TARGET_SDL)
1289 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1291 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1296 #elif defined(TARGET_ALLEGRO)
1298 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1300 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1305 #else /* PLATFORM_UNIX */
1307 if ((file = fopen(filename, MODE_READ)) == NULL)
1309 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1314 /* read chunk id "RIFF" */
1315 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1316 if (strcmp(chunk_name, "RIFF") != 0)
1318 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1324 /* read "RIFF" type id "WAVE" */
1325 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1326 if (strcmp(chunk_name, "WAVE") != 0)
1328 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1334 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1336 if (strcmp(chunk_name, "fmt ") == 0)
1338 /* read header information */
1339 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1340 sound_header_buffer[i] = fgetc(file);
1342 if (chunk_size > WAV_HEADER_SIZE)
1343 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1345 else if (strcmp(chunk_name, "data") == 0)
1347 snd_info->data_len = chunk_size;
1348 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1350 /* read sound data */
1351 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1354 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1356 free(snd_info->data_ptr);
1361 /* check for odd number of sample bytes (data chunk is word aligned) */
1362 if ((chunk_size % 2) == 1)
1363 ReadUnusedBytesFromFile(file, 1);
1365 else /* unknown chunk -- ignore */
1366 ReadUnusedBytesFromFile(file, chunk_size);
1371 if (snd_info->data_ptr == NULL)
1373 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1378 snd_info->format = AUDIO_FORMAT_U8;
1380 #endif /* PLATFORM_UNIX */
1382 snd_info->type = SND_TYPE_WAV;
1383 snd_info->source_filename = getStringCopy(filename);
1388 static void deleteSoundEntry(SoundInfo **snd_info)
1392 char *filename = (*snd_info)->source_filename;
1395 printf("[decrementing reference counter of sound '%s']\n", filename);
1398 if (--(*snd_info)->num_references <= 0)
1401 printf("[deleting sound '%s']\n", filename);
1405 FreeSound(*snd_info);
1407 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1414 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1418 /* check if the old and the new sound file are the same */
1419 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1421 /* The old and new sound are the same (have the same filename and path).
1422 This usually means that this sound does not exist in this sound set
1423 and a fallback to the existing sound is done. */
1426 printf("[sound '%s' already exists (same list entry)]\n", filename);
1432 /* delete existing sound file entry */
1433 deleteSoundEntry(snd_info);
1435 /* check if the new sound file already exists in the list of sounds */
1436 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1439 printf("[sound '%s' already exists (other list entry)]\n", filename);
1442 *snd_info = (SoundInfo *)node->content;
1443 (*snd_info)->num_references++;
1445 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1447 (*snd_info)->num_references = 1;
1448 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1452 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1454 char *filename = getCustomSoundFilename(basename);
1456 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1458 deleteSoundEntry(snd_info);
1462 if (filename == NULL)
1464 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1468 replaceSoundEntry(snd_info, filename);
1471 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1474 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1476 sound_effect = sounds_list;
1477 num_sounds = num_list_entries;
1480 void LoadSoundToList(char *basename, int list_pos)
1482 if (Sound == NULL || list_pos >= num_sounds)
1486 printf("loading sound '%s' ... [%d]\n",
1487 basename, getNumNodes(SoundFileList));
1490 LoadCustomSound(&Sound[list_pos], basename);
1493 printf("loading sound '%s' done [%d]\n",
1494 basename, getNumNodes(SoundFileList));
1498 static MusicInfo *Load_MOD(char *filename)
1500 #if defined(TARGET_SDL)
1501 MusicInfo *mod_info;
1503 if (!audio.sound_available)
1506 mod_info = checked_calloc(sizeof(MusicInfo));
1508 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1510 Error(ERR_WARN, "cannot read music file '%s'", filename);
1515 mod_info->type = MUS_TYPE_MOD;
1516 mod_info->source_filename = getStringCopy(filename);
1524 void LoadCustomMusic(void)
1526 char *music_directory = getCustomMusicDirectory();
1528 struct dirent *dir_entry;
1530 if (!audio.sound_available)
1533 if ((dir = opendir(music_directory)) == NULL)
1535 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1536 audio.music_available = FALSE;
1540 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1542 char *basename = dir_entry->d_name;
1543 char *filename = getPath2(music_directory, basename);
1544 MusicInfo *mus_info = NULL;
1546 if (FileIsSound(basename))
1547 mus_info = Load_WAV(filename);
1548 else if (FileIsMusic(basename))
1549 mus_info = Load_MOD(filename);
1556 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1557 Music[num_music -1] = mus_info;
1564 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1568 void PlayMusic(int nr)
1570 if (!audio.music_available)
1573 #if defined(TARGET_SDL)
1575 nr = nr % num_music;
1577 if (Music[nr]->type == MUS_TYPE_MOD)
1579 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1580 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1582 else /* play WAV music loop */
1584 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1585 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1595 void PlaySound(int nr)
1597 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1600 void PlaySoundStereo(int nr, int stereo)
1602 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1605 void PlaySoundLoop(int nr)
1607 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1610 void PlaySoundMusic(int nr)
1612 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1615 void PlaySoundExt(int nr, int volume, int stereo, int state)
1617 SoundControl snd_ctrl;
1619 if (!audio.sound_available ||
1620 !audio.sound_enabled ||
1621 audio.sound_deactivated)
1624 if (volume < PSND_MIN_VOLUME)
1625 volume = PSND_MIN_VOLUME;
1626 else if (volume > PSND_MAX_VOLUME)
1627 volume = PSND_MAX_VOLUME;
1629 if (stereo < PSND_MAX_LEFT)
1630 stereo = PSND_MAX_LEFT;
1631 else if (stereo > PSND_MAX_RIGHT)
1632 stereo = PSND_MAX_RIGHT;
1634 snd_ctrl.active = TRUE;
1636 snd_ctrl.volume = volume;
1637 snd_ctrl.stereo = stereo;
1638 snd_ctrl.state = state;
1640 HandleSoundRequest(snd_ctrl);
1643 void FadeMusic(void)
1645 if (!audio.sound_available)
1648 #if defined(TARGET_SDL)
1649 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1650 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1652 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1656 void FadeSound(int nr)
1658 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1664 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1667 void StopMusic(void)
1669 #if defined(TARGET_SDL)
1670 if (!audio.sound_available)
1674 Mix_HaltChannel(audio.music_channel);
1676 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1680 void StopSound(int nr)
1682 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1688 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1691 void StopSoundExt(int nr, int state)
1693 SoundControl snd_ctrl;
1695 if (!audio.sound_available)
1698 snd_ctrl.active = FALSE;
1700 snd_ctrl.state = state;
1702 HandleSoundRequest(snd_ctrl);
1705 ListNode *newListNode()
1707 return checked_calloc(sizeof(ListNode));
1710 void addNodeToList(ListNode **node_first, char *key, void *content)
1712 ListNode *node_new = newListNode();
1715 printf("LIST: adding node with key '%s'\n", key);
1718 node_new->key = getStringCopy(key);
1719 node_new->content = content;
1720 node_new->next = *node_first;
1721 *node_first = node_new;
1724 void deleteNodeFromList(ListNode **node_first, char *key,
1725 void (*destructor_function)(void *))
1727 if (node_first == NULL || *node_first == NULL)
1731 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1732 (*node_first)->key, key);
1735 if (strcmp((*node_first)->key, key) == 0)
1738 printf("[DELETING LIST ENTRY]\n");
1741 free((*node_first)->key);
1742 if (destructor_function)
1743 destructor_function((*node_first)->content);
1744 *node_first = (*node_first)->next;
1747 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1750 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1752 if (node_first == NULL)
1755 if (strcmp(node_first->key, key) == 0)
1758 return getNodeFromKey(node_first->next, key);
1761 int getNumNodes(ListNode *node_first)
1763 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1766 void dumpList(ListNode *node_first)
1768 ListNode *node = node_first;
1772 printf("['%s' (%d)]\n", node->key,
1773 ((SoundInfo *)node->content)->num_references);
1777 printf("[%d nodes]\n", getNumNodes(node_first));
1780 static void LoadSoundsInfo()
1782 char *filename = getCustomSoundConfigFilename();
1783 struct SetupFileList *setup_file_list;
1786 /* always start with reliable default values */
1787 for (i=0; i<num_sounds; i++)
1788 sound_effect[i].filename = NULL;
1790 if (filename == NULL)
1793 if ((setup_file_list = loadSetupFileList(filename)))
1795 for (i=0; i<num_sounds; i++)
1796 sound_effect[i].filename =
1797 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1799 freeSetupFileList(setup_file_list);
1802 for (i=0; i<num_sounds; i++)
1804 printf("'%s' ", sound_effect[i].text);
1805 if (sound_effect[i].filename)
1806 printf("-> '%s'\n", sound_effect[i].filename);
1808 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1814 static void ReloadCustomSounds()
1819 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1825 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1828 for(i=0; i<num_sounds; i++)
1830 if (sound_effect[i].filename)
1831 LoadSoundToList(sound_effect[i].filename, i);
1833 LoadSoundToList(sound_effect[i].default_filename, i);
1837 printf("list size == %d\n", getNumNodes(SoundFileList));
1841 dumpList(SoundFileList);
1845 static void ReloadCustomMusic()
1848 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1856 void InitReloadSounds(char *set_name)
1858 if (!audio.sound_available)
1861 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1862 ReloadCustomSounds();
1863 #elif defined(PLATFORM_UNIX)
1864 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
1868 void InitReloadMusic(char *set_name)
1870 if (!audio.music_available)
1873 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1874 ReloadCustomMusic();
1875 #elif defined(PLATFORM_UNIX)
1876 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
1880 void FreeSound(void *ptr)
1882 SoundInfo *sound = (SoundInfo *)ptr;
1887 if (sound->data_ptr)
1889 #if defined(TARGET_SDL)
1890 Mix_FreeChunk(sound->data_ptr);
1891 #elif defined(TARGET_ALLEGRO)
1892 destroy_sample(sound->data_ptr);
1893 #else /* PLATFORM_UNIX */
1894 free(sound->data_ptr);
1898 if (sound->source_filename)
1899 free(sound->source_filename);
1904 void FreeMusic(MusicInfo *music)
1909 if (music->data_ptr)
1911 #if defined(TARGET_SDL)
1912 if (music->type == MUS_TYPE_MOD)
1913 Mix_FreeMusic(music->data_ptr);
1915 Mix_FreeChunk(music->data_ptr);
1916 #elif defined(TARGET_ALLEGRO)
1917 destroy_sample(music->data_ptr);
1918 #else /* PLATFORM_UNIX */
1919 free(music->data_ptr);
1926 void FreeAllSounds()
1933 printf("%s: FREEING SOUNDS ...\n",
1934 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
1936 for(i=0; i<num_sounds; i++)
1937 deleteSoundEntry(&Sound[i]);
1939 FreeSound(Sound[i]);
1942 printf("%s: FREEING SOUNDS -- DONE\n",
1943 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
1958 for(i=0; i<num_music; i++)
1959 FreeMusic(Music[i]);
1967 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1968 /* ========================================================================= */