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 ***********************************************************/
24 #if defined(PLATFORM_LINUX)
25 #include <sys/ioctl.h>
26 #include <linux/soundcard.h>
27 #elif defined(PLATFORM_FREEBSD)
28 #include <machine/soundcard.h>
29 #elif defined(PLATFORM_NETBSD)
30 #include <sys/ioctl.h>
31 #include <sys/audioio.h>
32 #elif defined(PLATFORM_HPUX)
33 #include <sys/audio.h>
43 /* expiration time (in milliseconds) for sound loops */
44 #define SOUND_LOOP_EXPIRATION_TIME 200
46 /* one second fading interval == 1000 ticks (milliseconds) */
47 #define SOUND_FADING_INTERVAL 1000
49 #if defined(AUDIO_STREAMING_DSP)
50 #define SOUND_FADING_VOLUME_STEP (SOUND_MAX_VOLUME / 40)
51 #define SOUND_FADING_VOLUME_THRESHOLD (SOUND_FADING_VOLUME_STEP * 2)
54 #if !defined(PLATFORM_HPUX)
55 #define SND_BLOCKSIZE 4096
57 #define SND_BLOCKSIZE 32768
60 #define SND_TYPE_NONE 0
61 #define SND_TYPE_WAV 1
63 #define MUS_TYPE_NONE 0
64 #define MUS_TYPE_WAV 1
65 #define MUS_TYPE_MOD 2
67 #define DEVICENAME_DSP "/dev/dsp"
68 #define DEVICENAME_AUDIO "/dev/audio"
69 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
71 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
72 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
76 struct SoundHeader_SUN
79 unsigned long hdr_size;
80 unsigned long data_size;
81 unsigned long encoding;
82 unsigned long sample_rate;
83 unsigned long channels;
86 struct SoundHeader_8SVX
89 unsigned long chunk_size;
94 struct AudioFormatInfo
96 boolean stereo; /* availability of stereo sound */
97 int format; /* size and endianess of sample data */
98 int sample_rate; /* sample frequency */
99 int fragment_size; /* audio device fragment size in bytes */
104 char *source_filename;
112 typedef struct SampleInfo SoundInfo;
113 typedef struct SampleInfo MusicInfo;
125 unsigned long playing_starttime;
126 unsigned long playing_pos;
133 #if defined(TARGET_ALLEGRO)
137 typedef struct SoundControl SoundControl;
143 struct ListNode *next;
145 typedef struct ListNode ListNode;
147 static ListNode *newListNode(void);
148 static void addNodeToList(ListNode **, char *, void *);
149 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
150 static ListNode *getNodeFromKey(ListNode *, char *);
151 static int getNumNodes(ListNode *);
154 static struct SoundEffectInfo *sound_effect;
155 static ListNode *SoundFileList = NULL;
156 static SoundInfo **Sound = NULL;
157 static MusicInfo **Music = NULL;
158 static int num_sounds = 0, num_music = 0;
159 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
162 /* ========================================================================= */
163 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
165 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
166 static int mixer_active_channels = 0;
168 #if defined(AUDIO_UNIX_NATIVE)
169 static struct AudioFormatInfo afmt;
171 static void Mixer_Main(void);
172 #if !defined(AUDIO_STREAMING_DSP)
173 static unsigned char linear_to_ulaw(int);
174 static int ulaw_to_linear(unsigned char);
178 static void ReloadCustomSounds();
179 static void ReloadCustomMusic();
180 static void FreeSound(void *);
183 /* ------------------------------------------------------------------------- */
184 /* functions for native (non-SDL) Unix audio/mixer support */
185 /* ------------------------------------------------------------------------- */
187 #if defined(AUDIO_UNIX_NATIVE)
189 static int OpenAudioDevice(char *audio_device_name)
193 /* check if desired audio device is accessible */
194 if (access(audio_device_name, W_OK) != 0)
197 /* try to open audio device in non-blocking mode */
198 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
199 return audio_device_fd;
201 /* re-open audio device in blocking mode */
202 close(audio_device_fd);
203 audio_device_fd = open(audio_device_name, O_WRONLY);
205 return audio_device_fd;
208 static void CloseAudioDevice(int *audio_device_fd)
210 if (*audio_device_fd == 0)
213 close(*audio_device_fd);
214 *audio_device_fd = -1;
217 static boolean TestAudioDevices(void)
219 static char *audio_device_name[] =
224 int audio_device_fd = -1;
227 /* look for available audio devices, starting with preferred ones */
228 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
229 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
232 if (audio_device_fd < 0)
234 Error(ERR_WARN, "cannot open audio device -- no sound");
238 close(audio_device_fd);
240 audio.device_name = audio_device_name[i];
245 static boolean ForkAudioProcess(void)
247 if (pipe(audio.mixer_pipe) < 0)
249 Error(ERR_WARN, "cannot create pipe -- no sounds");
253 if ((audio.mixer_pid = fork()) < 0)
255 Error(ERR_WARN, "cannot create sound server process -- no sounds");
259 if (IS_CHILD_PROCESS(audio.mixer_pid))
260 Mixer_Main(); /* this function never returns */
262 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
267 void UnixOpenAudio(void)
269 if (!TestAudioDevices())
272 audio.sound_available = TRUE;
273 audio.sound_enabled = TRUE;
275 #if defined(AUDIO_STREAMING_DSP)
276 audio.music_available = TRUE;
277 audio.loops_available = TRUE;
280 audio.num_channels = NUM_MIXER_CHANNELS;
281 audio.music_channel = MUSIC_CHANNEL;
282 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
285 void UnixCloseAudio(void)
288 close(audio.device_fd);
290 if (IS_PARENT_PROCESS(audio.mixer_pid))
291 kill(audio.mixer_pid, SIGTERM);
295 /* ------------------------------------------------------------------------- */
296 /* functions for platform specific audio device initialization */
297 /* ------------------------------------------------------------------------- */
299 #if defined(AUDIO_LINUX_IOCTL)
300 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
302 /* "ioctl()" expects pointer to 'int' value for stereo flag
303 (boolean is defined as 'char', which will not work here) */
304 unsigned int fragment_spec = 0;
305 int fragment_size_query;
314 /* supported audio format in preferred order */
315 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
316 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
317 { AFMT_U8, AUDIO_FORMAT_U8 },
322 /* determine logarithm (log2) of the fragment size */
323 while ((1 << fragment_spec) < afmt->fragment_size)
326 /* use two fragments (play one fragment, prepare the other);
327 one fragment would result in interrupted audio output, more
328 than two fragments would raise audio output latency to much */
329 fragment_spec |= 0x00020000;
331 /* Example for fragment specification:
332 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
333 - (with stereo the effective buffer size will shrink to 256)
334 => fragment_size = 0x00020009 */
336 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
337 Error(ERR_EXIT_SOUND_SERVER,
338 "cannot set fragment size of /dev/dsp -- no sounds");
342 while (formats[i].format_result != -1)
344 unsigned int audio_format = formats[i].format_ioctl;
345 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
347 afmt->format = formats[i].format_result;
352 if (afmt->format == 0) /* no supported audio format found */
353 Error(ERR_EXIT_SOUND_SERVER,
354 "cannot set audio format of /dev/dsp -- no sounds");
356 /* try if we can use stereo sound */
358 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
359 afmt->stereo = FALSE;
361 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
362 Error(ERR_EXIT_SOUND_SERVER,
363 "cannot set sample rate of /dev/dsp -- no sounds");
365 /* get the real fragmentation size; this should return 512 */
366 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
367 Error(ERR_EXIT_SOUND_SERVER,
368 "cannot get fragment size of /dev/dsp -- no sounds");
369 if (fragment_size_query != afmt->fragment_size)
370 Error(ERR_EXIT_SOUND_SERVER,
371 "cannot set fragment size of /dev/dsp -- no sounds");
373 #endif /* AUDIO_LINUX_IOCTL */
375 #if defined(PLATFORM_NETBSD)
376 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
379 boolean stereo = TRUE;
381 AUDIO_INITINFO(&a_info);
382 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
383 a_info.play.precision = 8;
384 a_info.play.channels = 2;
385 a_info.play.sample_rate = sample_rate;
386 a_info.blocksize = fragment_size;
388 afmt->format = AUDIO_FORMAT_U8;
391 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
393 /* try to disable stereo */
394 a_info.play.channels = 1;
396 afmt->stereo = FALSE;
398 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
399 Error(ERR_EXIT_SOUND_SERVER,
400 "cannot set sample rate of /dev/audio -- no sounds");
403 #endif /* PLATFORM_NETBSD */
405 #if defined(PLATFORM_HPUX)
406 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
408 struct audio_describe ainfo;
411 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
413 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
415 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
416 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
418 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
419 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
421 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
422 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
424 afmt->format = AUDIO_FORMAT_U8;
425 afmt->stereo = FALSE;
426 afmt->sample_rate = 8000;
430 #endif /* PLATFORM_HPUX */
432 static void InitAudioDevice(struct AudioFormatInfo *afmt)
435 afmt->format = AUDIO_FORMAT_UNKNOWN;
436 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
437 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
439 #if defined(AUDIO_LINUX_IOCTL)
440 InitAudioDevice_Linux(afmt);
441 #elif defined(PLATFORM_NETBSD)
442 InitAudioDevice_NetBSD(afmt);
443 #elif defined(PLATFORM_HPUX)
444 InitAudioDevice_HPUX(afmt);
446 /* generic /dev/audio stuff might be placed here */
451 /* ------------------------------------------------------------------------- */
452 /* functions for communication between main process and sound mixer process */
453 /* ------------------------------------------------------------------------- */
455 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
457 if (IS_CHILD_PROCESS(audio.mixer_pid))
460 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
462 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
463 audio.sound_available = audio.sound_enabled = FALSE;
468 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
470 if (IS_PARENT_PROCESS(audio.mixer_pid))
473 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
474 != sizeof(SoundControl))
475 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
478 static void WriteReloadInfoToPipe(char *set_name, int type)
480 SoundControl snd_ctrl;
481 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
482 artwork.mus_current);
483 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
484 unsigned long str_size2 = strlen(ti->basepath) + 1;
485 unsigned long str_size3 = strlen(ti->fullpath) + 1;
487 if (IS_CHILD_PROCESS(audio.mixer_pid))
490 if (leveldir_current == NULL) /* should never happen */
491 Error(ERR_EXIT, "leveldir_current == NULL");
493 snd_ctrl.active = FALSE;
494 snd_ctrl.state = type;
495 snd_ctrl.data_len = strlen(set_name) + 1;
497 if (write(audio.mixer_pipe[1], &snd_ctrl,
498 sizeof(snd_ctrl)) < 0 ||
499 write(audio.mixer_pipe[1], set_name,
500 snd_ctrl.data_len) < 0 ||
501 write(audio.mixer_pipe[1], leveldir_current,
502 sizeof(TreeInfo)) < 0 ||
503 write(audio.mixer_pipe[1], ti,
504 sizeof(TreeInfo)) < 0 ||
505 write(audio.mixer_pipe[1], &str_size1,
506 sizeof(unsigned long)) < 0 ||
507 write(audio.mixer_pipe[1], &str_size2,
508 sizeof(unsigned long)) < 0 ||
509 write(audio.mixer_pipe[1], &str_size3,
510 sizeof(unsigned long)) < 0 ||
511 write(audio.mixer_pipe[1], leveldir_current->fullpath,
513 write(audio.mixer_pipe[1], ti->basepath,
515 write(audio.mixer_pipe[1], ti->fullpath,
518 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
519 audio.sound_available = audio.sound_enabled = FALSE;
524 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
526 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
527 &artwork.snd_current : &artwork.mus_current);
528 TreeInfo *ti = *ti_ptr;
529 unsigned long str_size1, str_size2, str_size3;
530 static char *set_name = NULL;
535 set_name = checked_malloc(snd_ctrl->data_len);
537 if (leveldir_current == NULL)
538 leveldir_current = checked_calloc(sizeof(TreeInfo));
540 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
541 if (leveldir_current->fullpath != NULL)
542 free(leveldir_current->fullpath);
543 if (ti->basepath != NULL)
545 if (ti->fullpath != NULL)
548 if (read(audio.mixer_pipe[0], set_name,
549 snd_ctrl->data_len) != snd_ctrl->data_len ||
550 read(audio.mixer_pipe[0], leveldir_current,
551 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
552 read(audio.mixer_pipe[0], ti,
553 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
554 read(audio.mixer_pipe[0], &str_size1,
555 sizeof(unsigned long)) != sizeof(unsigned long) ||
556 read(audio.mixer_pipe[0], &str_size2,
557 sizeof(unsigned long)) != sizeof(unsigned long) ||
558 read(audio.mixer_pipe[0], &str_size3,
559 sizeof(unsigned long)) != sizeof(unsigned long))
560 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
562 leveldir_current->fullpath = checked_calloc(str_size1);
563 ti->basepath = checked_calloc(str_size2);
564 ti->fullpath = checked_calloc(str_size3);
566 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
567 str_size1) != str_size1 ||
568 read(audio.mixer_pipe[0], ti->basepath,
569 str_size2) != str_size2 ||
570 read(audio.mixer_pipe[0], ti->fullpath,
571 str_size3) != str_size3)
572 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
574 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
575 artwork.sounds_set_current = set_name;
577 artwork.music_set_current = set_name;
580 #endif /* AUDIO_UNIX_NATIVE */
583 /* ------------------------------------------------------------------------- */
584 /* mixer functions */
585 /* ------------------------------------------------------------------------- */
587 void Mixer_InitChannels()
591 for(i=0; i<audio.num_channels; i++)
592 mixer[i].active = FALSE;
593 mixer_active_channels = 0;
596 static void Mixer_ResetChannelExpiration(int channel)
598 mixer[channel].playing_starttime = Counter();
600 #if defined(TARGET_SDL)
601 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
602 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
606 static boolean Mixer_ChannelExpired(int channel)
608 if (!mixer[channel].active)
611 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
612 DelayReached(&mixer[channel].playing_starttime,
613 SOUND_LOOP_EXPIRATION_TIME))
616 #if defined(TARGET_SDL)
618 if (!Mix_Playing(channel))
621 #elif defined(TARGET_ALLEGRO)
623 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
624 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
626 /* sound sample has completed playing or was completely faded out */
627 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
630 #endif /* TARGET_ALLEGRO */
635 static boolean Mixer_AllocateChannel(int channel)
637 #if defined(TARGET_ALLEGRO)
638 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
639 if (mixer[channel].voice < 0)
646 static void Mixer_SetChannelProperties(int channel)
648 #if defined(TARGET_SDL)
649 Mix_Volume(channel, mixer[channel].volume);
650 Mix_SetPanning(channel,
651 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
652 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
653 #elif defined(TARGET_ALLEGRO)
654 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
655 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
659 static void Mixer_StartChannel(int channel)
661 #if defined(TARGET_SDL)
662 Mix_PlayChannel(channel, mixer[channel].data_ptr,
663 IS_LOOP(mixer[channel]) ? -1 : 0);
664 #elif defined(TARGET_ALLEGRO)
665 if (IS_LOOP(mixer[channel]))
666 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
668 voice_start(mixer[channel].voice);
672 static void Mixer_PlayChannel(int channel)
674 /* start with inactive channel in case something goes wrong */
675 mixer[channel].active = FALSE;
677 if (mixer[channel].type != MUS_TYPE_WAV)
680 if (!Mixer_AllocateChannel(channel))
683 Mixer_SetChannelProperties(channel);
684 Mixer_StartChannel(channel);
686 Mixer_ResetChannelExpiration(channel);
688 mixer[channel].playing_pos = 0;
689 mixer[channel].active = TRUE;
690 mixer_active_channels++;
693 static void Mixer_PlayMusicChannel()
695 Mixer_PlayChannel(audio.music_channel);
697 #if defined(TARGET_SDL)
698 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
700 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
701 this looks like a bug in the SDL_mixer library */
702 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
703 Mix_VolumeMusic(SOUND_MAX_VOLUME);
708 static void Mixer_StopChannel(int channel)
710 if (!mixer[channel].active)
713 #if defined(TARGET_SDL)
714 Mix_HaltChannel(channel);
715 #elif defined(TARGET_ALLEGRO)
716 voice_set_volume(mixer[channel].voice, 0);
717 deallocate_voice(mixer[channel].voice);
720 mixer[channel].active = FALSE;
721 mixer_active_channels--;
724 static void Mixer_StopMusicChannel()
726 Mixer_StopChannel(audio.music_channel);
728 #if defined(TARGET_SDL)
733 static void Mixer_FadeChannel(int channel)
735 if (!mixer[channel].active)
738 mixer[channel].state |= SND_CTRL_FADE;
740 #if defined(TARGET_SDL)
741 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
742 #elif defined(TARGET_ALLEGRO)
743 if (voice_check(mixer[channel].voice))
744 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
748 static void Mixer_FadeMusicChannel()
750 Mixer_FadeChannel(audio.music_channel);
752 #if defined(TARGET_SDL)
753 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
757 static void Mixer_UnFadeChannel(int channel)
759 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
762 mixer[channel].state &= ~SND_CTRL_FADE;
763 mixer[channel].volume = SOUND_MAX_VOLUME;
765 #if defined(TARGET_SDL)
766 Mix_ExpireChannel(channel, -1);
767 Mix_Volume(channel, mixer[channel].volume);
768 #elif defined(TARGET_ALLEGRO)
769 voice_stop_volumeramp(mixer[channel].voice);
770 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
771 mixer[channel].volume);
775 static void Mixer_InsertSound(SoundControl snd_ctrl)
781 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
785 printf("%d ACTIVE CHANNELS\n", mixer_active_channels);
788 if (IS_MUSIC(snd_ctrl))
789 snd_ctrl.nr = snd_ctrl.nr % num_music;
790 else if (snd_ctrl.nr >= num_sounds)
793 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
794 if (snd_info == NULL)
797 /* copy sound sample and format information */
798 snd_ctrl.type = snd_info->type;
799 snd_ctrl.format = snd_info->format;
800 snd_ctrl.data_ptr = snd_info->data_ptr;
801 snd_ctrl.data_len = snd_info->data_len;
803 /* play music samples on a dedicated music channel */
804 if (IS_MUSIC(snd_ctrl))
807 printf("PLAY MUSIC WITH VOLUME/STEREO %d/%d\n",
808 snd_ctrl.volume, snd_ctrl.stereo_position);
811 mixer[audio.music_channel] = snd_ctrl;
812 Mixer_PlayMusicChannel();
817 /* check if sound is already being played (and how often) */
818 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
819 if (mixer[i].active && mixer[i].nr == snd_ctrl.nr)
823 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
826 /* reset expiration delay for already playing loop sounds */
827 if (k > 0 && IS_LOOP(snd_ctrl))
829 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
831 if (mixer[i].active && mixer[i].nr == snd_ctrl.nr)
834 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
837 if (IS_FADING(mixer[i]))
838 Mixer_UnFadeChannel(i);
840 /* restore settings like volume and stereo position */
841 mixer[i].volume = snd_ctrl.volume;
842 mixer[i].stereo_position = snd_ctrl.stereo_position;
844 Mixer_SetChannelProperties(i);
845 Mixer_ResetChannelExpiration(i);
848 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
849 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
857 /* don't play sound more than n times simultaneously (with n == 2 for now) */
860 unsigned long playing_current = Counter();
861 int longest = 0, longest_nr = audio.first_sound_channel;
863 /* look for oldest equal sound */
864 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
866 int playing_time = playing_current - mixer[i].playing_starttime;
869 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
872 actual = 1000 * playing_time / mixer[i].data_len;
874 if (actual >= longest)
881 Mixer_StopChannel(longest_nr);
884 /* If all (non-music) channels are active, stop the channel that has
885 played its sound sample most completely (in percent of the sample
886 length). As we cannot currently get the actual playing position
887 of the channel's sound sample when compiling with the SDL mixer
888 library, we use the current playing time (in milliseconds) instead. */
890 if (mixer_active_channels ==
891 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
893 unsigned long playing_current = Counter();
894 int longest = 0, longest_nr = audio.first_sound_channel;
896 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
898 int playing_time = playing_current - mixer[i].playing_starttime;
899 int actual = 1000 * playing_time / mixer[i].data_len;
901 if (!IS_LOOP(mixer[i]) && actual > longest)
908 Mixer_StopChannel(longest_nr);
911 /* add the new sound to the mixer */
912 for(i=0; i<audio.num_channels; i++)
915 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
919 if (!mixer[i].active ||
920 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
922 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
923 (i != audio.music_channel && !mixer[i].active))
926 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
930 #if defined(AUDIO_UNIX_NATIVE)
931 if (snd_info->data_len == 0)
933 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
939 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
941 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
944 Mixer_StopChannel(i);
950 Mixer_PlayChannel(i);
957 static void HandleSoundRequest(SoundControl snd_ctrl)
961 #if defined(AUDIO_UNIX_NATIVE)
962 if (IS_PARENT_PROCESS(audio.mixer_pid))
964 SendSoundControlToMixerProcess(&snd_ctrl);
969 /* deactivate channels that have expired since the last request */
970 for (i=0; i<audio.num_channels; i++)
971 if (mixer[i].active && Mixer_ChannelExpired(i))
972 Mixer_StopChannel(i);
974 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
976 Mixer_StopMusicChannel();
977 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
978 Mixer_StopChannel(i);
980 #if defined(AUDIO_UNIX_NATIVE)
981 CloseAudioDevice(&audio.device_fd);
982 ReadReloadInfoFromPipe(&snd_ctrl);
985 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
986 ReloadCustomSounds();
990 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
992 if (IS_MUSIC(snd_ctrl))
994 Mixer_FadeMusicChannel();
998 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
999 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
1000 Mixer_FadeChannel(i);
1002 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1004 if (IS_MUSIC(snd_ctrl))
1006 Mixer_StopMusicChannel();
1010 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1011 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
1012 Mixer_StopChannel(i);
1014 #if defined(AUDIO_UNIX_NATIVE)
1015 if (!mixer_active_channels)
1016 CloseAudioDevice(&audio.device_fd);
1019 else if (snd_ctrl.active) /* add new sound to mixer */
1021 Mixer_InsertSound(snd_ctrl);
1025 void StartMixer(void)
1030 SDL_version compile_version;
1031 const SDL_version *link_version;
1032 MIX_VERSION(&compile_version);
1033 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1034 compile_version.major,
1035 compile_version.minor,
1036 compile_version.patch);
1037 link_version = Mix_Linked_Version();
1038 printf("running with SDL_mixer version: %d.%d.%d\n",
1039 link_version->major,
1040 link_version->minor,
1041 link_version->patch);
1044 if (!audio.sound_available)
1047 /* initialize stereo position conversion information */
1048 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1050 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1052 #if defined(AUDIO_UNIX_NATIVE)
1053 if (!ForkAudioProcess())
1054 audio.sound_available = FALSE;
1058 #if defined(AUDIO_UNIX_NATIVE)
1060 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1061 int sample_pos, int sample_size,
1064 void *sample_ptr = snd_ctrl->data_ptr;
1067 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1068 for (i=0; i<sample_size; i++)
1070 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1071 else /* AUDIO_FORMAT_S16 */
1072 for (i=0; i<sample_size; i++)
1074 ((short *)sample_ptr)[sample_pos + i];
1077 #if defined(AUDIO_STREAMING_DSP)
1078 static void Mixer_Main_DSP()
1080 static short premix_first_buffer[SND_BLOCKSIZE];
1081 static short premix_left_buffer[SND_BLOCKSIZE];
1082 static short premix_right_buffer[SND_BLOCKSIZE];
1083 static long premix_last_buffer[SND_BLOCKSIZE];
1084 static byte playing_buffer[SND_BLOCKSIZE];
1088 int max_sample_size;
1091 if (!mixer_active_channels)
1094 if (audio.device_fd < 0)
1096 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1099 InitAudioDevice(&afmt);
1102 stereo = afmt.stereo;
1103 fragment_size = afmt.fragment_size;
1104 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1105 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1107 /* first clear the last premixing buffer */
1108 memset(premix_last_buffer, 0,
1109 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1111 for(i=0; i<audio.num_channels; i++)
1118 if (!mixer[i].active)
1121 if (Mixer_ChannelExpired(i))
1123 Mixer_StopChannel(i);
1127 /* pointer, lenght and actual playing position of sound sample */
1128 sample_ptr = mixer[i].data_ptr;
1129 sample_len = mixer[i].data_len;
1130 sample_pos = mixer[i].playing_pos;
1131 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1132 mixer[i].playing_pos += sample_size;
1134 /* copy original sample to first mixing buffer */
1135 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1136 premix_first_buffer);
1138 /* are we about to restart a looping sound? */
1139 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1141 while (sample_size < max_sample_size)
1143 int restarted_sample_size =
1144 MIN(max_sample_size - sample_size, sample_len);
1146 if (mixer[i].format == AUDIO_FORMAT_U8)
1147 for (j=0; j<restarted_sample_size; j++)
1148 premix_first_buffer[sample_size + j] =
1149 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1151 for (j=0; j<restarted_sample_size; j++)
1152 premix_first_buffer[sample_size + j] =
1153 ((short *)sample_ptr)[j];
1155 mixer[i].playing_pos = restarted_sample_size;
1156 sample_size += restarted_sample_size;
1160 /* decrease volume if sound is fading out */
1161 if (IS_FADING(mixer[i]) &&
1162 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1163 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1165 /* adjust volume of actual sound sample */
1166 if (mixer[i].volume != SOUND_MAX_VOLUME)
1167 for(j=0; j<sample_size; j++)
1168 premix_first_buffer[j] =
1169 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1171 /* fill the last mixing buffer with stereo or mono sound */
1174 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1175 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1177 for(j=0; j<sample_size; j++)
1179 premix_left_buffer[j] =
1180 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1181 premix_right_buffer[j] =
1182 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1184 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1185 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1190 for(j=0; j<sample_size; j++)
1191 premix_last_buffer[j] += premix_first_buffer[j];
1194 /* delete completed sound entries from the mixer */
1195 if (mixer[i].playing_pos >= mixer[i].data_len)
1197 if (IS_LOOP(mixer[i]))
1198 mixer[i].playing_pos = 0;
1200 Mixer_StopChannel(i);
1202 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1203 Mixer_StopChannel(i);
1206 /* prepare final playing buffer according to system audio format */
1207 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1209 /* cut off at 17 bit value */
1210 if (premix_last_buffer[i] < -65535)
1211 premix_last_buffer[i] = -65535;
1212 else if (premix_last_buffer[i] > 65535)
1213 premix_last_buffer[i] = 65535;
1215 /* shift to 16 bit value */
1216 premix_last_buffer[i] >>= 1;
1218 if (afmt.format & AUDIO_FORMAT_U8)
1220 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1222 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1224 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1225 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1227 else /* big endian */
1229 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1230 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1234 /* finally play the sound fragment */
1235 write(audio.device_fd, playing_buffer, fragment_size);
1237 if (!mixer_active_channels)
1238 CloseAudioDevice(&audio.device_fd);
1241 #else /* !AUDIO_STREAMING_DSP */
1243 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1245 static short premix_first_buffer[SND_BLOCKSIZE];
1246 static byte playing_buffer[SND_BLOCKSIZE];
1247 int max_sample_size = SND_BLOCKSIZE;
1256 /* pointer, lenght and actual playing position of sound sample */
1257 sample_ptr = mixer[i].data_ptr;
1258 sample_len = mixer[i].data_len;
1259 sample_pos = mixer[i].playing_pos;
1260 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1261 mixer[i].playing_pos += sample_size;
1263 /* copy original sample to first mixing buffer */
1264 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1265 premix_first_buffer);
1267 /* adjust volume of actual sound sample */
1268 if (mixer[i].volume != SOUND_MAX_VOLUME)
1269 for(j=0; j<sample_size; j++)
1270 premix_first_buffer[j] =
1271 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1273 /* might be needed for u-law /dev/audio */
1275 for(j=0; j<sample_size; j++)
1277 linear_to_ulaw(premix_first_buffer[j]);
1280 /* delete completed sound entries from the mixer */
1281 if (mixer[i].playing_pos >= mixer[i].data_len)
1282 Mixer_StopChannel(i);
1284 for(i=0; i<sample_size; i++)
1285 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1287 /* finally play the sound fragment */
1288 write(audio.device_fd, playing_buffer, sample_size);
1292 #endif /* !AUDIO_STREAMING_DSP */
1296 SoundControl snd_ctrl;
1299 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1301 Mixer_InitChannels();
1303 #if defined(PLATFORM_HPUX)
1304 InitAudioDevice(&afmt);
1307 FD_ZERO(&mixer_fdset);
1308 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1310 while(1) /* wait for sound playing commands from client */
1312 struct timeval delay = { 0, 0 };
1314 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1315 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1316 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1319 ReadSoundControlFromMainProcess(&snd_ctrl);
1321 HandleSoundRequest(snd_ctrl);
1323 #if defined(AUDIO_STREAMING_DSP)
1325 while (mixer_active_channels &&
1326 select(audio.mixer_pipe[0] + 1,
1327 &mixer_fdset, NULL, NULL, &delay) < 1)
1329 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1334 #else /* !AUDIO_STREAMING_DSP */
1336 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1337 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1340 InitAudioDevice(&afmt);
1345 while (mixer_active_channels &&
1346 select(audio.mixer_pipe[0] + 1,
1347 &mixer_fdset, NULL, NULL, &delay) < 1)
1349 int wait_percent = 90; /* wait 90% of the real playing time */
1352 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1354 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1358 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1361 CloseAudioDevice(&audio.device_fd);
1363 Mixer_InitChannels(); /* remove all sounds from mixer */
1365 #endif /* !AUDIO_STREAMING_DSP */
1368 #endif /* AUDIO_UNIX_NATIVE */
1371 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1373 /* these two are stolen from "sox"... :) */
1376 ** This routine converts from linear to ulaw.
1378 ** Craig Reese: IDA/Supercomputing Research Center
1379 ** Joe Campbell: Department of Defense
1380 ** 29 September 1989
1383 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1384 ** 2) "A New Digital Technique for Implementation of Any
1385 ** Continuous PCM Companding Law," Villeret, Michel,
1386 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1387 ** 1973, pg. 11.12-11.17
1388 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1389 ** for Analog-to_Digital Conversion Techniques,"
1392 ** Input: Signed 16 bit linear sample
1393 ** Output: 8 bit ulaw sample
1396 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1397 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1400 static unsigned char linear_to_ulaw(int sample)
1402 static int exp_lut[256] =
1404 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1405 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1406 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1407 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1408 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1409 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1410 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1411 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1412 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1413 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1414 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1415 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1416 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1417 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1418 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1419 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1422 int sign, exponent, mantissa;
1423 unsigned char ulawbyte;
1425 /* Get the sample into sign-magnitude. */
1426 sign = (sample >> 8) & 0x80; /* set aside the sign */
1428 sample = -sample; /* get magnitude */
1430 sample = CLIP; /* clip the magnitude */
1432 /* Convert from 16 bit linear to ulaw. */
1433 sample = sample + BIAS;
1434 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1435 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1436 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1439 ulawbyte = 0x02; /* optional CCITT trap */
1446 ** This routine converts from ulaw to 16 bit linear.
1448 ** Craig Reese: IDA/Supercomputing Research Center
1449 ** 29 September 1989
1452 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1453 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1454 ** for Analog-to_Digital Conversion Techniques,"
1457 ** Input: 8 bit ulaw sample
1458 ** Output: signed 16 bit linear sample
1461 static int ulaw_to_linear(unsigned char ulawbyte)
1463 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1464 int sign, exponent, mantissa, sample;
1466 ulawbyte = ~ ulawbyte;
1467 sign = ( ulawbyte & 0x80 );
1468 exponent = ( ulawbyte >> 4 ) & 0x07;
1469 mantissa = ulawbyte & 0x0F;
1470 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1476 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1479 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1480 /* ========================================================================= */
1481 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1483 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1484 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1486 static SoundInfo *Load_WAV(char *filename)
1488 SoundInfo *snd_info;
1489 #if defined(AUDIO_UNIX_NATIVE)
1490 byte sound_header_buffer[WAV_HEADER_SIZE];
1491 char chunk_name[CHUNK_ID_LEN + 1];
1497 if (!audio.sound_available)
1501 printf("loading WAV file '%s'\n", filename);
1504 snd_info = checked_calloc(sizeof(SoundInfo));
1506 #if defined(TARGET_SDL)
1508 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1510 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1515 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1517 #elif defined(TARGET_ALLEGRO)
1519 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1521 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1526 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1528 #else /* AUDIO_UNIX_NATIVE */
1530 if ((file = fopen(filename, MODE_READ)) == NULL)
1532 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1537 /* read chunk id "RIFF" */
1538 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1539 if (strcmp(chunk_name, "RIFF") != 0)
1541 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1547 /* read "RIFF" type id "WAVE" */
1548 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1549 if (strcmp(chunk_name, "WAVE") != 0)
1551 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1557 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1559 if (strcmp(chunk_name, "fmt ") == 0)
1561 /* read header information */
1562 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1563 sound_header_buffer[i] = fgetc(file);
1565 if (chunk_size > WAV_HEADER_SIZE)
1566 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1568 else if (strcmp(chunk_name, "data") == 0)
1570 snd_info->data_len = chunk_size;
1571 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1573 /* read sound data */
1574 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1577 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1579 free(snd_info->data_ptr);
1584 /* check for odd number of sample bytes (data chunk is word aligned) */
1585 if ((chunk_size % 2) == 1)
1586 ReadUnusedBytesFromFile(file, 1);
1588 else /* unknown chunk -- ignore */
1589 ReadUnusedBytesFromFile(file, chunk_size);
1594 if (snd_info->data_ptr == NULL)
1596 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1601 snd_info->format = AUDIO_FORMAT_U8;
1603 #endif /* AUDIO_UNIX_NATIVE */
1605 snd_info->type = SND_TYPE_WAV;
1606 snd_info->source_filename = getStringCopy(filename);
1611 static void deleteSoundEntry(SoundInfo **snd_info)
1615 char *filename = (*snd_info)->source_filename;
1618 printf("[decrementing reference counter of sound '%s']\n", filename);
1621 if (--(*snd_info)->num_references <= 0)
1624 printf("[deleting sound '%s']\n", filename);
1628 FreeSound(*snd_info);
1630 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1637 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1641 /* check if the old and the new sound file are the same */
1642 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1644 /* The old and new sound are the same (have the same filename and path).
1645 This usually means that this sound does not exist in this sound set
1646 and a fallback to the existing sound is done. */
1649 printf("[sound '%s' already exists (same list entry)]\n", filename);
1655 /* delete existing sound file entry */
1656 deleteSoundEntry(snd_info);
1658 /* check if the new sound file already exists in the list of sounds */
1659 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1662 printf("[sound '%s' already exists (other list entry)]\n", filename);
1665 *snd_info = (SoundInfo *)node->content;
1666 (*snd_info)->num_references++;
1668 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1670 (*snd_info)->num_references = 1;
1671 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1675 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1677 char *filename = getCustomSoundFilename(basename);
1680 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1683 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1685 deleteSoundEntry(snd_info);
1689 if (filename == NULL)
1691 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1695 replaceSoundEntry(snd_info, filename);
1698 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1701 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1703 sound_effect = sounds_list;
1704 num_sounds = num_list_entries;
1707 void LoadSoundToList(char *basename, int list_pos)
1709 if (Sound == NULL || list_pos >= num_sounds)
1713 printf("loading sound '%s' ... [%d]\n",
1714 basename, getNumNodes(SoundFileList));
1717 LoadCustomSound(&Sound[list_pos], basename);
1720 printf("loading sound '%s' done [%d]\n",
1721 basename, getNumNodes(SoundFileList));
1725 static MusicInfo *Load_MOD(char *filename)
1727 #if defined(TARGET_SDL)
1728 MusicInfo *mod_info;
1730 if (!audio.sound_available)
1733 mod_info = checked_calloc(sizeof(MusicInfo));
1735 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1737 Error(ERR_WARN, "cannot read music file '%s'", filename);
1742 mod_info->type = MUS_TYPE_MOD;
1743 mod_info->source_filename = getStringCopy(filename);
1751 void LoadCustomMusic(void)
1753 static boolean draw_init_text = TRUE; /* only draw at startup */
1754 char *music_directory = getCustomMusicDirectory();
1756 struct dirent *dir_entry;
1758 if (!audio.sound_available)
1761 if ((dir = opendir(music_directory)) == NULL)
1763 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1764 audio.music_available = FALSE;
1769 DrawInitText("Loading music:", 120, FC_GREEN);
1771 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1773 char *basename = dir_entry->d_name;
1774 char *filename = getPath2(music_directory, basename);
1775 MusicInfo *mus_info = NULL;
1778 DrawInitText(basename, 150, FC_YELLOW);
1780 if (FileIsSound(basename))
1781 mus_info = Load_WAV(filename);
1782 else if (FileIsMusic(basename))
1783 mus_info = Load_MOD(filename);
1790 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1791 Music[num_music -1] = mus_info;
1797 draw_init_text = FALSE;
1800 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1804 void PlayMusic(int nr)
1806 if (!audio.music_available)
1812 void PlaySound(int nr)
1814 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1817 void PlaySoundStereo(int nr, int stereo_position)
1819 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1822 void PlaySoundLoop(int nr)
1824 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1827 void PlaySoundMusic(int nr)
1829 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1832 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1834 SoundControl snd_ctrl;
1836 if (!audio.sound_available ||
1837 !audio.sound_enabled ||
1838 audio.sound_deactivated)
1841 if (volume < SOUND_MIN_VOLUME)
1842 volume = SOUND_MIN_VOLUME;
1843 else if (volume > SOUND_MAX_VOLUME)
1844 volume = SOUND_MAX_VOLUME;
1846 if (stereo_position < SOUND_MAX_LEFT)
1847 stereo_position = SOUND_MAX_LEFT;
1848 else if (stereo_position > SOUND_MAX_RIGHT)
1849 stereo_position = SOUND_MAX_RIGHT;
1851 snd_ctrl.active = TRUE;
1853 snd_ctrl.volume = volume;
1854 snd_ctrl.stereo_position = stereo_position;
1855 snd_ctrl.state = state;
1857 HandleSoundRequest(snd_ctrl);
1860 void FadeMusic(void)
1862 if (!audio.music_available)
1865 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1868 void FadeSound(int nr)
1870 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1876 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1879 void StopMusic(void)
1881 if (!audio.music_available)
1884 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1887 void StopSound(int nr)
1889 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1895 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1898 void StopSoundExt(int nr, int state)
1900 SoundControl snd_ctrl;
1902 if (!audio.sound_available)
1905 snd_ctrl.active = FALSE;
1907 snd_ctrl.state = state;
1909 HandleSoundRequest(snd_ctrl);
1912 ListNode *newListNode()
1914 return checked_calloc(sizeof(ListNode));
1917 void addNodeToList(ListNode **node_first, char *key, void *content)
1919 ListNode *node_new = newListNode();
1922 printf("LIST: adding node with key '%s'\n", key);
1925 node_new->key = getStringCopy(key);
1926 node_new->content = content;
1927 node_new->next = *node_first;
1928 *node_first = node_new;
1931 void deleteNodeFromList(ListNode **node_first, char *key,
1932 void (*destructor_function)(void *))
1934 if (node_first == NULL || *node_first == NULL)
1938 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1939 (*node_first)->key, key);
1942 if (strcmp((*node_first)->key, key) == 0)
1945 printf("[DELETING LIST ENTRY]\n");
1948 free((*node_first)->key);
1949 if (destructor_function)
1950 destructor_function((*node_first)->content);
1951 *node_first = (*node_first)->next;
1954 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1957 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1959 if (node_first == NULL)
1962 if (strcmp(node_first->key, key) == 0)
1965 return getNodeFromKey(node_first->next, key);
1968 int getNumNodes(ListNode *node_first)
1970 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1973 void dumpList(ListNode *node_first)
1975 ListNode *node = node_first;
1979 printf("['%s' (%d)]\n", node->key,
1980 ((SoundInfo *)node->content)->num_references);
1984 printf("[%d nodes]\n", getNumNodes(node_first));
1987 static void LoadSoundsInfo()
1989 char *filename = getCustomSoundConfigFilename();
1990 struct SetupFileList *setup_file_list;
1994 printf("GOT CUSTOM SOUND CONFIG FILE '%s'\n", filename);
1997 /* always start with reliable default values */
1998 for (i=0; i<num_sounds; i++)
1999 sound_effect[i].filename = NULL;
2001 if (filename == NULL)
2004 if ((setup_file_list = loadSetupFileList(filename)))
2006 for (i=0; i<num_sounds; i++)
2007 sound_effect[i].filename =
2008 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2010 freeSetupFileList(setup_file_list);
2013 for (i=0; i<num_sounds; i++)
2015 printf("'%s' ", sound_effect[i].text);
2016 if (sound_effect[i].filename)
2017 printf("-> '%s'\n", sound_effect[i].filename);
2019 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2025 static void ReloadCustomSounds()
2027 static boolean draw_init_text = TRUE; /* only draw at startup */
2031 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
2037 DrawInitText("Loading sounds:", 120, FC_GREEN);
2040 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2043 for(i=0; i<num_sounds; i++)
2046 DrawInitText(sound_effect[i].text, 150, FC_YELLOW);
2048 if (sound_effect[i].filename)
2049 LoadSoundToList(sound_effect[i].filename, i);
2051 LoadSoundToList(sound_effect[i].default_filename, i);
2054 draw_init_text = FALSE;
2057 printf("list size == %d\n", getNumNodes(SoundFileList));
2061 dumpList(SoundFileList);
2065 static void ReloadCustomMusic()
2068 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
2076 void InitReloadSounds(char *set_name)
2078 if (!audio.sound_available)
2081 #if defined(AUDIO_UNIX_NATIVE)
2082 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
2084 ReloadCustomSounds();
2088 void InitReloadMusic(char *set_name)
2090 if (!audio.music_available)
2093 #if defined(AUDIO_UNIX_NATIVE)
2094 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
2096 ReloadCustomMusic();
2100 void FreeSound(void *ptr)
2102 SoundInfo *sound = (SoundInfo *)ptr;
2107 if (sound->data_ptr)
2109 #if defined(TARGET_SDL)
2110 Mix_FreeChunk(sound->data_ptr);
2111 #elif defined(TARGET_ALLEGRO)
2112 destroy_sample(sound->data_ptr);
2113 #else /* AUDIO_UNIX_NATIVE */
2114 free(sound->data_ptr);
2118 if (sound->source_filename)
2119 free(sound->source_filename);
2124 void FreeMusic(MusicInfo *music)
2129 if (music->data_ptr)
2131 #if defined(TARGET_SDL)
2132 if (music->type == MUS_TYPE_MOD)
2133 Mix_FreeMusic(music->data_ptr);
2135 Mix_FreeChunk(music->data_ptr);
2136 #elif defined(TARGET_ALLEGRO)
2137 destroy_sample(music->data_ptr);
2138 #else /* AUDIO_UNIX_NATIVE */
2139 free(music->data_ptr);
2146 void FreeAllSounds()
2154 printf("%s: FREEING SOUNDS ...\n",
2155 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2158 for(i=0; i<num_sounds; i++)
2159 deleteSoundEntry(&Sound[i]);
2161 FreeSound(Sound[i]);
2165 printf("%s: FREEING SOUNDS -- DONE\n",
2166 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2182 for(i=0; i<num_music; i++)
2183 FreeMusic(Music[i]);
2191 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2192 /* ========================================================================= */