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 SoundControl mixer[NUM_MIXER_CHANNELS];
56 static int mixer_active_channels = 0;
58 #if defined(AUDIO_UNIX_NATIVE)
59 static struct AudioFormatInfo afmt;
61 static void Mixer_Main(void);
62 #if !defined(AUDIO_STREAMING_DSP)
63 static unsigned char linear_to_ulaw(int);
64 static int ulaw_to_linear(unsigned char);
68 static void ReloadCustomSounds();
69 static void ReloadCustomMusic();
70 static void FreeSound(void *);
73 /* ------------------------------------------------------------------------- */
74 /* functions for native (non-SDL) Unix audio/mixer support */
75 /* ------------------------------------------------------------------------- */
77 #if defined(AUDIO_UNIX_NATIVE)
79 static int OpenAudioDevice(char *audio_device_name)
83 /* check if desired audio device is accessible */
84 if (access(audio_device_name, W_OK) != 0)
87 /* try to open audio device in non-blocking mode */
88 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
89 return audio_device_fd;
91 /* re-open audio device in blocking mode */
92 close(audio_device_fd);
93 audio_device_fd = open(audio_device_name, O_WRONLY);
95 return audio_device_fd;
98 static void CloseAudioDevice(int *audio_device_fd)
100 if (*audio_device_fd == 0)
103 close(*audio_device_fd);
104 *audio_device_fd = -1;
107 static boolean TestAudioDevices(void)
109 static char *audio_device_name[] =
114 int audio_device_fd = -1;
117 /* look for available audio devices, starting with preferred ones */
118 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
119 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
122 if (audio_device_fd < 0)
124 Error(ERR_WARN, "cannot open audio device -- no sound");
128 close(audio_device_fd);
130 audio.device_name = audio_device_name[i];
135 static boolean ForkAudioProcess(void)
137 if (pipe(audio.mixer_pipe) < 0)
139 Error(ERR_WARN, "cannot create pipe -- no sounds");
143 if ((audio.mixer_pid = fork()) < 0)
145 Error(ERR_WARN, "cannot create sound server process -- no sounds");
149 if (IS_CHILD_PROCESS(audio.mixer_pid))
150 Mixer_Main(); /* this function never returns */
152 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
157 void UnixOpenAudio(void)
159 if (!TestAudioDevices())
162 audio.sound_available = TRUE;
163 audio.sound_enabled = TRUE;
165 #if defined(AUDIO_STREAMING_DSP)
166 audio.music_available = TRUE;
167 audio.loops_available = TRUE;
170 audio.num_channels = NUM_MIXER_CHANNELS;
171 audio.music_channel = MUSIC_CHANNEL;
172 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
175 void UnixCloseAudio(void)
178 close(audio.device_fd);
180 if (IS_PARENT_PROCESS(audio.mixer_pid))
181 kill(audio.mixer_pid, SIGTERM);
185 /* ------------------------------------------------------------------------- */
186 /* functions for platform specific audio device initialization */
187 /* ------------------------------------------------------------------------- */
189 #if defined(AUDIO_LINUX_IOCTL)
190 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
192 /* "ioctl()" expects pointer to 'int' value for stereo flag
193 (boolean is defined as 'char', which will not work here) */
194 unsigned int fragment_spec = 0;
195 int fragment_size_query;
204 /* supported audio format in preferred order */
205 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
206 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
207 { AFMT_U8, AUDIO_FORMAT_U8 },
212 /* determine logarithm (log2) of the fragment size */
213 while ((1 << fragment_spec) < afmt->fragment_size)
216 /* use two fragments (play one fragment, prepare the other);
217 one fragment would result in interrupted audio output, more
218 than two fragments would raise audio output latency to much */
219 fragment_spec |= 0x00020000;
221 /* Example for fragment specification:
222 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
223 - (with stereo the effective buffer size will shrink to 256)
224 => fragment_size = 0x00020009 */
226 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
227 Error(ERR_EXIT_SOUND_SERVER,
228 "cannot set fragment size of /dev/dsp -- no sounds");
232 while (formats[i].format_result != -1)
234 unsigned int audio_format = formats[i].format_ioctl;
235 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
237 afmt->format = formats[i].format_result;
242 if (afmt->format == 0) /* no supported audio format found */
243 Error(ERR_EXIT_SOUND_SERVER,
244 "cannot set audio format of /dev/dsp -- no sounds");
246 /* try if we can use stereo sound */
248 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
249 afmt->stereo = FALSE;
251 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
252 Error(ERR_EXIT_SOUND_SERVER,
253 "cannot set sample rate of /dev/dsp -- no sounds");
255 /* get the real fragmentation size; this should return 512 */
256 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
257 Error(ERR_EXIT_SOUND_SERVER,
258 "cannot get fragment size of /dev/dsp -- no sounds");
259 if (fragment_size_query != afmt->fragment_size)
260 Error(ERR_EXIT_SOUND_SERVER,
261 "cannot set fragment size of /dev/dsp -- no sounds");
263 #endif /* AUDIO_LINUX_IOCTL */
265 #if defined(PLATFORM_NETBSD)
266 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
269 boolean stereo = TRUE;
271 AUDIO_INITINFO(&a_info);
272 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
273 a_info.play.precision = 8;
274 a_info.play.channels = 2;
275 a_info.play.sample_rate = sample_rate;
276 a_info.blocksize = fragment_size;
278 afmt->format = AUDIO_FORMAT_U8;
281 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
283 /* try to disable stereo */
284 a_info.play.channels = 1;
286 afmt->stereo = FALSE;
288 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
289 Error(ERR_EXIT_SOUND_SERVER,
290 "cannot set sample rate of /dev/audio -- no sounds");
293 #endif /* PLATFORM_NETBSD */
295 #if defined(PLATFORM_HPUX)
296 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
298 struct audio_describe ainfo;
301 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
303 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
305 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
306 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
308 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
309 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
311 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
312 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
314 afmt->format = AUDIO_FORMAT_U8;
315 afmt->stereo = FALSE;
316 afmt->sample_rate = 8000;
320 #endif /* PLATFORM_HPUX */
322 static void InitAudioDevice(struct AudioFormatInfo *afmt)
325 afmt->format = AUDIO_FORMAT_UNKNOWN;
326 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
327 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
329 #if defined(AUDIO_LINUX_IOCTL)
330 InitAudioDevice_Linux(afmt);
331 #elif defined(PLATFORM_NETBSD)
332 InitAudioDevice_NetBSD(afmt);
333 #elif defined(PLATFORM_HPUX)
334 InitAudioDevice_HPUX(afmt);
336 /* generic /dev/audio stuff might be placed here */
341 /* ------------------------------------------------------------------------- */
342 /* functions for communication between main process and sound mixer process */
343 /* ------------------------------------------------------------------------- */
345 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
347 if (IS_CHILD_PROCESS(audio.mixer_pid))
350 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
352 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
353 audio.sound_available = audio.sound_enabled = FALSE;
358 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
360 if (IS_PARENT_PROCESS(audio.mixer_pid))
363 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
364 != sizeof(SoundControl))
365 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
368 static void WriteReloadInfoToPipe(char *set_name, int type)
370 SoundControl snd_ctrl;
371 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
372 artwork.mus_current);
373 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
374 unsigned long str_size2 = strlen(ti->basepath) + 1;
375 unsigned long str_size3 = strlen(ti->fullpath) + 1;
377 if (IS_CHILD_PROCESS(audio.mixer_pid))
380 if (leveldir_current == NULL) /* should never happen */
381 Error(ERR_EXIT, "leveldir_current == NULL");
383 snd_ctrl.active = FALSE;
384 snd_ctrl.state = type;
385 snd_ctrl.data_len = strlen(set_name) + 1;
387 if (write(audio.mixer_pipe[1], &snd_ctrl,
388 sizeof(snd_ctrl)) < 0 ||
389 write(audio.mixer_pipe[1], set_name,
390 snd_ctrl.data_len) < 0 ||
391 write(audio.mixer_pipe[1], leveldir_current,
392 sizeof(TreeInfo)) < 0 ||
393 write(audio.mixer_pipe[1], ti,
394 sizeof(TreeInfo)) < 0 ||
395 write(audio.mixer_pipe[1], &str_size1,
396 sizeof(unsigned long)) < 0 ||
397 write(audio.mixer_pipe[1], &str_size2,
398 sizeof(unsigned long)) < 0 ||
399 write(audio.mixer_pipe[1], &str_size3,
400 sizeof(unsigned long)) < 0 ||
401 write(audio.mixer_pipe[1], leveldir_current->fullpath,
403 write(audio.mixer_pipe[1], ti->basepath,
405 write(audio.mixer_pipe[1], ti->fullpath,
408 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
409 audio.sound_available = audio.sound_enabled = FALSE;
414 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
416 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
417 &artwork.snd_current : &artwork.mus_current);
418 TreeInfo *ti = *ti_ptr;
419 unsigned long str_size1, str_size2, str_size3;
420 static char *set_name = NULL;
425 set_name = checked_malloc(snd_ctrl->data_len);
427 if (leveldir_current == NULL)
428 leveldir_current = checked_calloc(sizeof(TreeInfo));
430 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
431 if (leveldir_current->fullpath != NULL)
432 free(leveldir_current->fullpath);
433 if (ti->basepath != NULL)
435 if (ti->fullpath != NULL)
438 if (read(audio.mixer_pipe[0], set_name,
439 snd_ctrl->data_len) != snd_ctrl->data_len ||
440 read(audio.mixer_pipe[0], leveldir_current,
441 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
442 read(audio.mixer_pipe[0], ti,
443 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
444 read(audio.mixer_pipe[0], &str_size1,
445 sizeof(unsigned long)) != sizeof(unsigned long) ||
446 read(audio.mixer_pipe[0], &str_size2,
447 sizeof(unsigned long)) != sizeof(unsigned long) ||
448 read(audio.mixer_pipe[0], &str_size3,
449 sizeof(unsigned long)) != sizeof(unsigned long))
450 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
452 leveldir_current->fullpath = checked_calloc(str_size1);
453 ti->basepath = checked_calloc(str_size2);
454 ti->fullpath = checked_calloc(str_size3);
456 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
457 str_size1) != str_size1 ||
458 read(audio.mixer_pipe[0], ti->basepath,
459 str_size2) != str_size2 ||
460 read(audio.mixer_pipe[0], ti->fullpath,
461 str_size3) != str_size3)
462 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
464 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
465 artwork.sounds_set_current = set_name;
467 artwork.music_set_current = set_name;
470 #endif /* AUDIO_UNIX_NATIVE */
473 /* ------------------------------------------------------------------------- */
474 /* mixer functions */
475 /* ------------------------------------------------------------------------- */
477 void Mixer_InitChannels()
481 for(i=0; i<audio.num_channels; i++)
482 mixer[i].active = FALSE;
483 mixer_active_channels = 0;
486 static void Mixer_PlayChannel(int channel)
488 /* start with inactive channel in case something goes wrong */
489 mixer[channel].active = FALSE;
491 if (mixer[channel].type != MUS_TYPE_WAV)
494 mixer[channel].playingpos = 0;
495 mixer[channel].playingtime = 0;
497 #if defined(TARGET_SDL)
498 Mix_Volume(channel, SOUND_MAX_VOLUME);
499 Mix_PlayChannel(channel, mixer[channel].data_ptr,
500 IS_LOOP(mixer[channel]) ? -1 : 0);
501 #elif defined(PLATFORM_MSDOS)
502 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
503 if (mixer[channel].voice < 0)
506 if (IS_LOOP(mixer[channel]))
507 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
509 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
510 voice_set_pan(mixer[channel].voice, mixer[channel].stereo);
511 voice_start(mixer[channel].voice);
514 mixer[channel].active = TRUE;
515 mixer_active_channels++;
518 static void Mixer_PlayMusicChannel()
520 Mixer_PlayChannel(audio.music_channel);
522 #if defined(TARGET_SDL)
523 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
525 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
526 this looks like a bug in the SDL_mixer library */
527 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
528 Mix_VolumeMusic(SOUND_MAX_VOLUME);
533 static void Mixer_StopChannel(int channel)
536 #if defined(TARGET_SDL)
537 printf("----------> %d [%d]\n", Mix_Playing(channel), Mix_Playing(0));
541 if (!mixer_active_channels || !mixer[channel].active)
544 #if defined(TARGET_SDL)
545 Mix_HaltChannel(channel);
546 #elif defined(PLATFORM_MSDOS)
547 voice_set_volume(mixer[channel].voice, 0);
548 deallocate_voice(mixer[channel].voice);
551 mixer[channel].active = FALSE;
552 mixer_active_channels--;
555 static void Mixer_StopMusicChannel()
557 Mixer_StopChannel(audio.music_channel);
559 #if defined(TARGET_SDL)
564 static void Mixer_FadeChannel(int channel)
566 if (!mixer_active_channels || !mixer[channel].active)
569 mixer[channel].state |= SND_CTRL_FADE;
571 #if defined(TARGET_SDL)
574 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
576 Mix_ExpireChannel(channel, SOUND_FADING_INTERVAL);
579 #elif defined(PLATFORM_MSDOS)
580 if (voice_check(mixer[channel].voice))
581 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
582 mixer[channel].state &= ~SND_CTRL_IS_LOOP;
586 static void Mixer_FadeMusicChannel()
588 Mixer_FadeChannel(audio.music_channel);
590 #if defined(TARGET_SDL)
591 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
595 static void Mixer_InsertSound(SoundControl snd_ctrl)
601 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
604 if (IS_MUSIC(snd_ctrl))
605 snd_ctrl.nr = snd_ctrl.nr % num_music;
606 else if (snd_ctrl.nr >= num_sounds)
609 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
610 if (snd_info == NULL)
613 /* copy sound sample and format information */
614 snd_ctrl.type = snd_info->type;
615 snd_ctrl.format = snd_info->format;
616 snd_ctrl.data_ptr = snd_info->data_ptr;
617 snd_ctrl.data_len = snd_info->data_len;
619 /* play music samples on a dedicated music channel */
620 if (IS_MUSIC(snd_ctrl))
622 mixer[audio.music_channel] = snd_ctrl;
623 Mixer_PlayMusicChannel();
628 if (mixer_active_channels == audio.num_channels)
630 for (i=0; i<audio.num_channels; i++)
632 if (mixer[i].data_ptr == NULL ||
633 mixer[i].data_len == 0)
636 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
639 Mixer_StopChannel(i);
645 printf("%d ACTIVE CHANNELS\n", mixer_active_channels);
648 /* if all channels are active, remove oldest sound sample */
649 if (mixer_active_channels == audio.num_channels)
651 int longest = 0, longest_nr = audio.first_sound_channel;
653 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
655 int actual = 100 * mixer[i].playingpos / mixer[i].data_len;
657 if (!IS_LOOP(mixer[i]) && actual > longest)
664 Mixer_StopChannel(longest_nr);
667 /* check if sound is already being played (and how often) */
668 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
669 if (mixer[i].nr == snd_ctrl.nr)
672 /* restart loop sounds only if they are just fading out */
673 if (k >= 1 && IS_LOOP(snd_ctrl))
675 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
677 if (mixer[i].nr == snd_ctrl.nr && IS_FADING(mixer[i]))
679 mixer[i].state &= ~SND_CTRL_FADE;
680 mixer[i].volume = PSND_MAX_VOLUME;
681 #if defined(PLATFORM_MSDOS)
682 mixer[i].state |= SND_CTRL_LOOP;
683 voice_stop_volumeramp(mixer[i].voice);
684 voice_ramp_volume(mixer[i].voice, mixer[i].volume, 1000);
692 /* don't play sound more than n times simultaneously (with n == 2 for now) */
695 int longest = 0, longest_nr = audio.first_sound_channel;
697 /* look for oldest equal sound */
698 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
702 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
705 actual = 100 * mixer[i].playingpos / mixer[i].data_len;
707 if (actual >= longest)
714 Mixer_StopChannel(longest_nr);
717 /* add new sound to mixer */
718 for(i=0; i<audio.num_channels; i++)
721 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
725 if (!mixer[i].active ||
726 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
728 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
729 (i != audio.music_channel && !mixer[i].active))
732 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
736 #if defined(AUDIO_UNIX_NATIVE)
737 if (snd_info->data_len == 0)
739 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
745 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
747 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
750 Mixer_StopChannel(i);
756 Mixer_PlayChannel(i);
763 static void HandleSoundRequest(SoundControl snd_ctrl)
767 #if defined(AUDIO_UNIX_NATIVE)
768 if (IS_PARENT_PROCESS(audio.mixer_pid))
770 SendSoundControlToMixerProcess(&snd_ctrl);
773 #elif defined(TARGET_SDL)
774 for (i=0; i<audio.num_channels; i++)
776 Mixer_StopChannel(i);
777 #elif defined(TARGET_ALLEGRO)
778 for (i=0; i<audio.num_channels; i++)
780 if (!mixer[i].active || IS_LOOP(mixer[i]))
783 mixer[i].playingpos = voice_get_position(mixer[i].voice);
784 mixer[i].volume = voice_get_volume(mixer[i].voice);
786 if (mixer[i].playingpos == -1 || mixer[i].volume == 0)
787 Mixer_StopChannel(i);
789 #endif /* TARGET_ALLEGRO */
791 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
793 Mixer_StopMusicChannel();
794 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
795 Mixer_StopChannel(i);
797 #if defined(AUDIO_UNIX_NATIVE)
798 CloseAudioDevice(&audio.device_fd);
799 ReadReloadInfoFromPipe(&snd_ctrl);
802 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
803 ReloadCustomSounds();
807 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
809 if (!mixer_active_channels)
812 if (IS_MUSIC(snd_ctrl))
814 Mixer_FadeMusicChannel();
818 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
819 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
820 Mixer_FadeChannel(i);
822 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
824 if (!mixer_active_channels)
827 if (IS_MUSIC(snd_ctrl))
829 Mixer_StopMusicChannel();
833 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
834 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
835 Mixer_StopChannel(i);
837 #if defined(AUDIO_UNIX_NATIVE)
838 if (!mixer_active_channels)
839 CloseAudioDevice(&audio.device_fd);
842 else if (snd_ctrl.active) /* add new sound to mixer */
844 Mixer_InsertSound(snd_ctrl);
848 void StartMixer(void)
851 SDL_version compile_version;
852 const SDL_version *link_version;
853 MIX_VERSION(&compile_version);
854 printf("compiled with SDL_mixer version: %d.%d.%d\n",
855 compile_version.major,
856 compile_version.minor,
857 compile_version.patch);
858 link_version = Mix_Linked_Version();
859 printf("running with SDL_mixer version: %d.%d.%d\n",
862 link_version->patch);
865 if (!audio.sound_available)
868 #if defined(AUDIO_UNIX_NATIVE)
869 if (!ForkAudioProcess())
870 audio.sound_available = FALSE;
874 #if defined(AUDIO_UNIX_NATIVE)
876 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
877 int sample_pos, int sample_size,
880 void *sample_ptr = snd_ctrl->data_ptr;
883 if (snd_ctrl->format == AUDIO_FORMAT_U8)
884 for (i=0; i<sample_size; i++)
886 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
887 else /* AUDIO_FORMAT_S16 */
888 for (i=0; i<sample_size; i++)
890 ((short *)sample_ptr)[sample_pos + i];
893 #if defined(AUDIO_STREAMING_DSP)
894 static void Mixer_Main_DSP()
896 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
897 static boolean stereo_volume_calculated = FALSE;
898 static short premix_first_buffer[SND_BLOCKSIZE];
899 static short premix_left_buffer[SND_BLOCKSIZE];
900 static short premix_right_buffer[SND_BLOCKSIZE];
901 static long premix_last_buffer[SND_BLOCKSIZE];
902 static byte playing_buffer[SND_BLOCKSIZE];
909 if (!stereo_volume_calculated)
911 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
913 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
915 stereo_volume_calculated = TRUE;
918 if (!mixer_active_channels)
921 if (audio.device_fd < 0)
923 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
926 InitAudioDevice(&afmt);
929 stereo = afmt.stereo;
930 fragment_size = afmt.fragment_size;
931 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
932 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
934 /* first clear the last premixing buffer */
935 memset(premix_last_buffer, 0,
936 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
938 for(i=0; i<audio.num_channels; i++)
945 if (!mixer[i].active)
948 /* pointer, lenght and actual playing position of sound sample */
949 sample_ptr = mixer[i].data_ptr;
950 sample_len = mixer[i].data_len;
951 sample_pos = mixer[i].playingpos;
952 sample_size = MIN(max_sample_size, sample_len - sample_pos);
953 mixer[i].playingpos += sample_size;
955 /* copy original sample to first mixing buffer */
956 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
957 premix_first_buffer);
959 /* are we about to restart a looping sound? */
960 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
962 while (sample_size < max_sample_size)
964 int restarted_sample_size =
965 MIN(max_sample_size - sample_size, sample_len);
967 if (mixer[i].format == AUDIO_FORMAT_U8)
968 for (j=0; j<restarted_sample_size; j++)
969 premix_first_buffer[sample_size + j] =
970 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
972 for (j=0; j<restarted_sample_size; j++)
973 premix_first_buffer[sample_size + j] =
974 ((short *)sample_ptr)[j];
976 mixer[i].playingpos = restarted_sample_size;
977 sample_size += restarted_sample_size;
981 /* decrease volume if sound is fading out */
982 if (IS_FADING(mixer[i]) &&
983 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
984 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
986 /* adjust volume of actual sound sample */
987 if (mixer[i].volume != PSND_MAX_VOLUME)
988 for(j=0; j<sample_size; j++)
989 premix_first_buffer[j] =
990 (mixer[i].volume * (long)premix_first_buffer[j])
991 >> PSND_MAX_VOLUME_BITS;
993 /* fill the last mixing buffer with stereo or mono sound */
996 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
997 int left_volume = stereo_volume[middle_pos + mixer[i].stereo];
998 int right_volume= stereo_volume[middle_pos - mixer[i].stereo];
1000 for(j=0; j<sample_size; j++)
1002 premix_left_buffer[j] =
1003 (left_volume * premix_first_buffer[j])
1004 >> PSND_MAX_LEFT2RIGHT_BITS;
1005 premix_right_buffer[j] =
1006 (right_volume * premix_first_buffer[j])
1007 >> PSND_MAX_LEFT2RIGHT_BITS;
1009 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1010 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1015 for(j=0; j<sample_size; j++)
1016 premix_last_buffer[j] += premix_first_buffer[j];
1019 /* delete completed sound entries from the mixer */
1020 if (mixer[i].playingpos >= mixer[i].data_len)
1022 if (IS_LOOP(mixer[i]))
1023 mixer[i].playingpos = 0;
1025 Mixer_StopChannel(i);
1027 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1028 Mixer_StopChannel(i);
1031 /* prepare final playing buffer according to system audio format */
1032 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1034 /* cut off at 17 bit value */
1035 if (premix_last_buffer[i] < -65535)
1036 premix_last_buffer[i] = -65535;
1037 else if (premix_last_buffer[i] > 65535)
1038 premix_last_buffer[i] = 65535;
1040 /* shift to 16 bit value */
1041 premix_last_buffer[i] >>= 1;
1043 if (afmt.format & AUDIO_FORMAT_U8)
1045 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1047 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1049 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1050 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1052 else /* big endian */
1054 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1055 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1059 /* finally play the sound fragment */
1060 write(audio.device_fd, playing_buffer, fragment_size);
1062 if (!mixer_active_channels)
1063 CloseAudioDevice(&audio.device_fd);
1066 #else /* !AUDIO_STREAMING_DSP */
1068 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1070 static short premix_first_buffer[SND_BLOCKSIZE];
1071 static byte playing_buffer[SND_BLOCKSIZE];
1072 int max_sample_size = SND_BLOCKSIZE;
1081 /* pointer, lenght and actual playing position of sound sample */
1082 sample_ptr = mixer[i].data_ptr;
1083 sample_len = mixer[i].data_len;
1084 sample_pos = mixer[i].playingpos;
1085 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1086 mixer[i].playingpos += sample_size;
1088 /* copy original sample to first mixing buffer */
1089 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1090 premix_first_buffer);
1092 /* adjust volume of actual sound sample */
1093 if (mixer[i].volume != PSND_MAX_VOLUME)
1094 for(j=0; j<sample_size; j++)
1095 premix_first_buffer[j] =
1096 (mixer[i].volume * (long)premix_first_buffer[j])
1097 >> PSND_MAX_VOLUME_BITS;
1099 /* might be needed for u-law /dev/audio */
1101 for(j=0; j<sample_size; j++)
1103 linear_to_ulaw(premix_first_buffer[j]);
1106 /* delete completed sound entries from the mixer */
1107 if (mixer[i].playingpos >= mixer[i].data_len)
1108 Mixer_StopChannel(i);
1110 for(i=0; i<sample_size; i++)
1111 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1113 /* finally play the sound fragment */
1114 write(audio.device_fd, playing_buffer, sample_size);
1118 #endif /* !AUDIO_STREAMING_DSP */
1122 SoundControl snd_ctrl;
1125 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1127 Mixer_InitChannels();
1129 #if defined(PLATFORM_HPUX)
1130 InitAudioDevice(&afmt);
1133 FD_ZERO(&mixer_fdset);
1134 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1136 while(1) /* wait for sound playing commands from client */
1138 struct timeval delay = { 0, 0 };
1140 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1141 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1142 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1145 ReadSoundControlFromMainProcess(&snd_ctrl);
1147 HandleSoundRequest(snd_ctrl);
1149 #if defined(AUDIO_STREAMING_DSP)
1151 while (mixer_active_channels &&
1152 select(audio.mixer_pipe[0] + 1,
1153 &mixer_fdset, NULL, NULL, &delay) < 1)
1155 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1160 #else /* !AUDIO_STREAMING_DSP */
1162 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1163 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1166 InitAudioDevice(&afmt);
1171 while (mixer_active_channels &&
1172 select(audio.mixer_pipe[0] + 1,
1173 &mixer_fdset, NULL, NULL, &delay) < 1)
1175 int wait_percent = 90; /* wait 90% of the real playing time */
1178 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1180 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1184 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1187 CloseAudioDevice(&audio.device_fd);
1189 Mixer_InitChannels(); /* remove all sounds from mixer */
1191 #endif /* !AUDIO_STREAMING_DSP */
1194 #endif /* AUDIO_UNIX_NATIVE */
1197 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1199 /* these two are stolen from "sox"... :) */
1202 ** This routine converts from linear to ulaw.
1204 ** Craig Reese: IDA/Supercomputing Research Center
1205 ** Joe Campbell: Department of Defense
1206 ** 29 September 1989
1209 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1210 ** 2) "A New Digital Technique for Implementation of Any
1211 ** Continuous PCM Companding Law," Villeret, Michel,
1212 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1213 ** 1973, pg. 11.12-11.17
1214 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1215 ** for Analog-to_Digital Conversion Techniques,"
1218 ** Input: Signed 16 bit linear sample
1219 ** Output: 8 bit ulaw sample
1222 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1223 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1226 static unsigned char linear_to_ulaw(int sample)
1228 static int exp_lut[256] =
1230 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1231 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1232 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1233 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1234 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1235 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1236 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1237 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1238 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1239 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1240 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1241 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1242 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1243 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1244 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1245 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1248 int sign, exponent, mantissa;
1249 unsigned char ulawbyte;
1251 /* Get the sample into sign-magnitude. */
1252 sign = (sample >> 8) & 0x80; /* set aside the sign */
1254 sample = -sample; /* get magnitude */
1256 sample = CLIP; /* clip the magnitude */
1258 /* Convert from 16 bit linear to ulaw. */
1259 sample = sample + BIAS;
1260 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1261 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1262 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1265 ulawbyte = 0x02; /* optional CCITT trap */
1272 ** This routine converts from ulaw to 16 bit linear.
1274 ** Craig Reese: IDA/Supercomputing Research Center
1275 ** 29 September 1989
1278 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1279 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1280 ** for Analog-to_Digital Conversion Techniques,"
1283 ** Input: 8 bit ulaw sample
1284 ** Output: signed 16 bit linear sample
1287 static int ulaw_to_linear(unsigned char ulawbyte)
1289 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1290 int sign, exponent, mantissa, sample;
1292 ulawbyte = ~ ulawbyte;
1293 sign = ( ulawbyte & 0x80 );
1294 exponent = ( ulawbyte >> 4 ) & 0x07;
1295 mantissa = ulawbyte & 0x0F;
1296 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1302 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1305 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1306 /* ========================================================================= */
1307 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1309 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1310 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1312 static SoundInfo *Load_WAV(char *filename)
1314 SoundInfo *snd_info;
1315 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1316 byte sound_header_buffer[WAV_HEADER_SIZE];
1317 char chunk_name[CHUNK_ID_LEN + 1];
1323 if (!audio.sound_available)
1327 printf("loading WAV file '%s'\n", filename);
1330 snd_info = checked_calloc(sizeof(SoundInfo));
1332 #if defined(TARGET_SDL)
1334 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1336 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1341 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1343 #elif defined(TARGET_ALLEGRO)
1345 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1347 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1352 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1354 #else /* AUDIO_UNIX_NATIVE */
1356 if ((file = fopen(filename, MODE_READ)) == NULL)
1358 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1363 /* read chunk id "RIFF" */
1364 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1365 if (strcmp(chunk_name, "RIFF") != 0)
1367 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1373 /* read "RIFF" type id "WAVE" */
1374 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1375 if (strcmp(chunk_name, "WAVE") != 0)
1377 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1383 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1385 if (strcmp(chunk_name, "fmt ") == 0)
1387 /* read header information */
1388 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1389 sound_header_buffer[i] = fgetc(file);
1391 if (chunk_size > WAV_HEADER_SIZE)
1392 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1394 else if (strcmp(chunk_name, "data") == 0)
1396 snd_info->data_len = chunk_size;
1397 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1399 /* read sound data */
1400 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1403 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1405 free(snd_info->data_ptr);
1410 /* check for odd number of sample bytes (data chunk is word aligned) */
1411 if ((chunk_size % 2) == 1)
1412 ReadUnusedBytesFromFile(file, 1);
1414 else /* unknown chunk -- ignore */
1415 ReadUnusedBytesFromFile(file, chunk_size);
1420 if (snd_info->data_ptr == NULL)
1422 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1427 snd_info->format = AUDIO_FORMAT_U8;
1429 #endif /* AUDIO_UNIX_NATIVE */
1431 snd_info->type = SND_TYPE_WAV;
1432 snd_info->source_filename = getStringCopy(filename);
1437 static void deleteSoundEntry(SoundInfo **snd_info)
1441 char *filename = (*snd_info)->source_filename;
1444 printf("[decrementing reference counter of sound '%s']\n", filename);
1447 if (--(*snd_info)->num_references <= 0)
1450 printf("[deleting sound '%s']\n", filename);
1454 FreeSound(*snd_info);
1456 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1463 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1467 /* check if the old and the new sound file are the same */
1468 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1470 /* The old and new sound are the same (have the same filename and path).
1471 This usually means that this sound does not exist in this sound set
1472 and a fallback to the existing sound is done. */
1475 printf("[sound '%s' already exists (same list entry)]\n", filename);
1481 /* delete existing sound file entry */
1482 deleteSoundEntry(snd_info);
1484 /* check if the new sound file already exists in the list of sounds */
1485 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1488 printf("[sound '%s' already exists (other list entry)]\n", filename);
1491 *snd_info = (SoundInfo *)node->content;
1492 (*snd_info)->num_references++;
1494 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1496 (*snd_info)->num_references = 1;
1497 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1501 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1503 char *filename = getCustomSoundFilename(basename);
1505 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1507 deleteSoundEntry(snd_info);
1511 if (filename == NULL)
1513 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1517 replaceSoundEntry(snd_info, filename);
1520 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1523 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1525 sound_effect = sounds_list;
1526 num_sounds = num_list_entries;
1529 void LoadSoundToList(char *basename, int list_pos)
1531 if (Sound == NULL || list_pos >= num_sounds)
1535 printf("loading sound '%s' ... [%d]\n",
1536 basename, getNumNodes(SoundFileList));
1539 LoadCustomSound(&Sound[list_pos], basename);
1542 printf("loading sound '%s' done [%d]\n",
1543 basename, getNumNodes(SoundFileList));
1547 static MusicInfo *Load_MOD(char *filename)
1549 #if defined(TARGET_SDL)
1550 MusicInfo *mod_info;
1552 if (!audio.sound_available)
1555 mod_info = checked_calloc(sizeof(MusicInfo));
1557 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1559 Error(ERR_WARN, "cannot read music file '%s'", filename);
1564 mod_info->type = MUS_TYPE_MOD;
1565 mod_info->source_filename = getStringCopy(filename);
1573 void LoadCustomMusic(void)
1575 char *music_directory = getCustomMusicDirectory();
1577 struct dirent *dir_entry;
1579 if (!audio.sound_available)
1582 if ((dir = opendir(music_directory)) == NULL)
1584 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1585 audio.music_available = FALSE;
1589 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1591 char *basename = dir_entry->d_name;
1592 char *filename = getPath2(music_directory, basename);
1593 MusicInfo *mus_info = NULL;
1595 if (FileIsSound(basename))
1596 mus_info = Load_WAV(filename);
1597 else if (FileIsMusic(basename))
1598 mus_info = Load_MOD(filename);
1605 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1606 Music[num_music -1] = mus_info;
1613 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1617 void PlayMusic(int nr)
1619 if (!audio.music_available)
1625 void PlaySound(int nr)
1627 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1630 void PlaySoundStereo(int nr, int stereo)
1632 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1635 void PlaySoundLoop(int nr)
1637 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1640 void PlaySoundMusic(int nr)
1642 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1645 void PlaySoundExt(int nr, int volume, int stereo, int state)
1647 SoundControl snd_ctrl;
1649 if (!audio.sound_available ||
1650 !audio.sound_enabled ||
1651 audio.sound_deactivated)
1654 if (volume < PSND_MIN_VOLUME)
1655 volume = PSND_MIN_VOLUME;
1656 else if (volume > PSND_MAX_VOLUME)
1657 volume = PSND_MAX_VOLUME;
1659 if (stereo < PSND_MAX_LEFT)
1660 stereo = PSND_MAX_LEFT;
1661 else if (stereo > PSND_MAX_RIGHT)
1662 stereo = PSND_MAX_RIGHT;
1664 snd_ctrl.active = TRUE;
1666 snd_ctrl.volume = volume;
1667 snd_ctrl.stereo = stereo;
1668 snd_ctrl.state = state;
1670 HandleSoundRequest(snd_ctrl);
1673 void FadeMusic(void)
1675 if (!audio.sound_available)
1678 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1681 void FadeSound(int nr)
1683 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1689 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1692 void StopMusic(void)
1694 if (!audio.music_available)
1697 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1700 void StopSound(int nr)
1702 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1708 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1711 void StopSoundExt(int nr, int state)
1713 SoundControl snd_ctrl;
1715 if (!audio.sound_available)
1718 snd_ctrl.active = FALSE;
1720 snd_ctrl.state = state;
1722 HandleSoundRequest(snd_ctrl);
1725 ListNode *newListNode()
1727 return checked_calloc(sizeof(ListNode));
1730 void addNodeToList(ListNode **node_first, char *key, void *content)
1732 ListNode *node_new = newListNode();
1735 printf("LIST: adding node with key '%s'\n", key);
1738 node_new->key = getStringCopy(key);
1739 node_new->content = content;
1740 node_new->next = *node_first;
1741 *node_first = node_new;
1744 void deleteNodeFromList(ListNode **node_first, char *key,
1745 void (*destructor_function)(void *))
1747 if (node_first == NULL || *node_first == NULL)
1751 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1752 (*node_first)->key, key);
1755 if (strcmp((*node_first)->key, key) == 0)
1758 printf("[DELETING LIST ENTRY]\n");
1761 free((*node_first)->key);
1762 if (destructor_function)
1763 destructor_function((*node_first)->content);
1764 *node_first = (*node_first)->next;
1767 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1770 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1772 if (node_first == NULL)
1775 if (strcmp(node_first->key, key) == 0)
1778 return getNodeFromKey(node_first->next, key);
1781 int getNumNodes(ListNode *node_first)
1783 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1786 void dumpList(ListNode *node_first)
1788 ListNode *node = node_first;
1792 printf("['%s' (%d)]\n", node->key,
1793 ((SoundInfo *)node->content)->num_references);
1797 printf("[%d nodes]\n", getNumNodes(node_first));
1800 static void LoadSoundsInfo()
1802 char *filename = getCustomSoundConfigFilename();
1803 struct SetupFileList *setup_file_list;
1806 /* always start with reliable default values */
1807 for (i=0; i<num_sounds; i++)
1808 sound_effect[i].filename = NULL;
1810 if (filename == NULL)
1813 if ((setup_file_list = loadSetupFileList(filename)))
1815 for (i=0; i<num_sounds; i++)
1816 sound_effect[i].filename =
1817 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1819 freeSetupFileList(setup_file_list);
1822 for (i=0; i<num_sounds; i++)
1824 printf("'%s' ", sound_effect[i].text);
1825 if (sound_effect[i].filename)
1826 printf("-> '%s'\n", sound_effect[i].filename);
1828 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1834 static void ReloadCustomSounds()
1839 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1845 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1848 for(i=0; i<num_sounds; i++)
1850 if (sound_effect[i].filename)
1851 LoadSoundToList(sound_effect[i].filename, i);
1853 LoadSoundToList(sound_effect[i].default_filename, i);
1857 printf("list size == %d\n", getNumNodes(SoundFileList));
1861 dumpList(SoundFileList);
1865 static void ReloadCustomMusic()
1868 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1876 void InitReloadSounds(char *set_name)
1878 if (!audio.sound_available)
1881 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1882 ReloadCustomSounds();
1883 #elif defined(AUDIO_UNIX_NATIVE)
1884 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
1888 void InitReloadMusic(char *set_name)
1890 if (!audio.music_available)
1893 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1894 ReloadCustomMusic();
1895 #elif defined(AUDIO_UNIX_NATIVE)
1896 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
1900 void FreeSound(void *ptr)
1902 SoundInfo *sound = (SoundInfo *)ptr;
1907 if (sound->data_ptr)
1909 #if defined(TARGET_SDL)
1910 Mix_FreeChunk(sound->data_ptr);
1911 #elif defined(TARGET_ALLEGRO)
1912 destroy_sample(sound->data_ptr);
1913 #else /* AUDIO_UNIX_NATIVE */
1914 free(sound->data_ptr);
1918 if (sound->source_filename)
1919 free(sound->source_filename);
1924 void FreeMusic(MusicInfo *music)
1929 if (music->data_ptr)
1931 #if defined(TARGET_SDL)
1932 if (music->type == MUS_TYPE_MOD)
1933 Mix_FreeMusic(music->data_ptr);
1935 Mix_FreeChunk(music->data_ptr);
1936 #elif defined(TARGET_ALLEGRO)
1937 destroy_sample(music->data_ptr);
1938 #else /* AUDIO_UNIX_NATIVE */
1939 free(music->data_ptr);
1946 void FreeAllSounds()
1953 printf("%s: FREEING SOUNDS ...\n",
1954 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
1956 for(i=0; i<num_sounds; i++)
1957 deleteSoundEntry(&Sound[i]);
1959 FreeSound(Sound[i]);
1962 printf("%s: FREEING SOUNDS -- DONE\n",
1963 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
1978 for(i=0; i<num_music; i++)
1979 FreeMusic(Music[i]);
1987 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1988 /* ========================================================================= */