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])
74 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
75 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
78 struct SoundHeader_SUN
81 unsigned long hdr_size;
82 unsigned long data_size;
83 unsigned long encoding;
84 unsigned long sample_rate;
85 unsigned long channels;
88 struct SoundHeader_8SVX
91 unsigned long chunk_size;
96 #if defined(AUDIO_UNIX_NATIVE)
97 struct SoundHeader_WAV
99 unsigned short compression_code;
100 unsigned short num_channels;
101 unsigned long sample_rate;
102 unsigned long bytes_per_second;
103 unsigned short block_align;
104 unsigned short bits_per_sample;
108 struct AudioFormatInfo
110 boolean stereo; /* availability of stereo sound */
111 int format; /* size and endianess of sample data */
112 int sample_rate; /* sample frequency */
113 int fragment_size; /* audio device fragment size in bytes */
118 char *source_filename;
123 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
124 long data_len; /* number of samples, NOT number of bytes */
126 typedef struct SampleInfo SoundInfo;
127 typedef struct SampleInfo MusicInfo;
139 unsigned long playing_starttime;
140 unsigned long playing_pos;
144 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
145 long data_len; /* number of samples, NOT number of bytes */
147 #if defined(TARGET_ALLEGRO)
151 typedef struct SoundControl SoundControl;
157 struct ListNode *next;
159 typedef struct ListNode ListNode;
161 static ListNode *newListNode(void);
162 static void addNodeToList(ListNode **, char *, void *);
163 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
164 static ListNode *getNodeFromKey(ListNode *, char *);
165 static int getNumNodes(ListNode *);
168 static struct SoundEffectInfo *sound_effect;
169 static ListNode *SoundFileList = NULL;
170 static SoundInfo **Sound = NULL;
171 static MusicInfo **Music = NULL;
172 static int num_sounds = 0, num_music = 0;
173 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
176 /* ========================================================================= */
177 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
179 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
180 static int mixer_active_channels = 0;
182 #if defined(AUDIO_UNIX_NATIVE)
183 static struct AudioFormatInfo afmt;
185 static void Mixer_Main(void);
186 #if !defined(AUDIO_STREAMING_DSP)
187 static unsigned char linear_to_ulaw(int);
188 static int ulaw_to_linear(unsigned char);
192 static void ReloadCustomSounds();
193 static void ReloadCustomMusic();
194 static void FreeSound(void *);
197 /* ------------------------------------------------------------------------- */
198 /* functions for native (non-SDL) Unix audio/mixer support */
199 /* ------------------------------------------------------------------------- */
201 #if defined(AUDIO_UNIX_NATIVE)
203 static int OpenAudioDevice(char *audio_device_name)
207 /* check if desired audio device is accessible */
208 if (access(audio_device_name, W_OK) != 0)
211 /* try to open audio device in non-blocking mode */
212 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
213 return audio_device_fd;
215 /* re-open audio device in blocking mode */
216 close(audio_device_fd);
217 audio_device_fd = open(audio_device_name, O_WRONLY);
219 return audio_device_fd;
222 static void CloseAudioDevice(int *audio_device_fd)
224 if (*audio_device_fd == 0)
227 close(*audio_device_fd);
228 *audio_device_fd = -1;
231 static boolean TestAudioDevices(void)
233 static char *audio_device_name[] =
238 int audio_device_fd = -1;
241 /* look for available audio devices, starting with preferred ones */
242 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
243 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
246 if (audio_device_fd < 0)
248 Error(ERR_WARN, "cannot open audio device -- no sound");
252 close(audio_device_fd);
254 audio.device_name = audio_device_name[i];
259 static boolean ForkAudioProcess(void)
261 if (pipe(audio.mixer_pipe) < 0)
263 Error(ERR_WARN, "cannot create pipe -- no sounds");
267 if ((audio.mixer_pid = fork()) < 0)
269 Error(ERR_WARN, "cannot create sound server process -- no sounds");
273 if (IS_CHILD_PROCESS(audio.mixer_pid))
274 Mixer_Main(); /* this function never returns */
276 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
281 void UnixOpenAudio(void)
283 if (!TestAudioDevices())
286 audio.sound_available = TRUE;
287 audio.sound_enabled = TRUE;
289 #if defined(AUDIO_STREAMING_DSP)
290 audio.music_available = TRUE;
291 audio.loops_available = TRUE;
294 audio.num_channels = NUM_MIXER_CHANNELS;
295 audio.music_channel = MUSIC_CHANNEL;
296 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
299 void UnixCloseAudio(void)
302 close(audio.device_fd);
304 if (IS_PARENT_PROCESS(audio.mixer_pid))
305 kill(audio.mixer_pid, SIGTERM);
309 /* ------------------------------------------------------------------------- */
310 /* functions for platform specific audio device initialization */
311 /* ------------------------------------------------------------------------- */
313 #if defined(AUDIO_LINUX_IOCTL)
314 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
316 /* "ioctl()" expects pointer to 'int' value for stereo flag
317 (boolean is defined as 'char', which will not work here) */
318 unsigned int fragment_spec = 0;
319 int fragment_size_query;
328 /* supported audio format in preferred order */
329 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
330 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
331 { AFMT_U8, AUDIO_FORMAT_U8 },
336 /* determine logarithm (log2) of the fragment size */
337 while ((1 << fragment_spec) < afmt->fragment_size)
340 /* use two fragments (play one fragment, prepare the other);
341 one fragment would result in interrupted audio output, more
342 than two fragments would raise audio output latency to much */
343 fragment_spec |= 0x00020000;
345 /* Example for fragment specification:
346 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
347 - (with stereo the effective buffer size will shrink to 256)
348 => fragment_size = 0x00020009 */
350 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
351 Error(ERR_EXIT_SOUND_SERVER,
352 "cannot set fragment size of /dev/dsp -- no sounds");
356 while (formats[i].format_result != -1)
358 unsigned int audio_format = formats[i].format_ioctl;
359 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
361 afmt->format = formats[i].format_result;
366 if (afmt->format == 0) /* no supported audio format found */
367 Error(ERR_EXIT_SOUND_SERVER,
368 "cannot set audio format of /dev/dsp -- no sounds");
370 /* try if we can use stereo sound */
372 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
373 afmt->stereo = FALSE;
375 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
376 Error(ERR_EXIT_SOUND_SERVER,
377 "cannot set sample rate of /dev/dsp -- no sounds");
379 /* get the real fragmentation size; this should return 512 */
380 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
381 Error(ERR_EXIT_SOUND_SERVER,
382 "cannot get fragment size of /dev/dsp -- no sounds");
383 if (fragment_size_query != afmt->fragment_size)
384 Error(ERR_EXIT_SOUND_SERVER,
385 "cannot set fragment size of /dev/dsp -- no sounds");
387 #endif /* AUDIO_LINUX_IOCTL */
389 #if defined(PLATFORM_NETBSD)
390 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
393 boolean stereo = TRUE;
395 AUDIO_INITINFO(&a_info);
396 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
397 a_info.play.precision = 8;
398 a_info.play.channels = 2;
399 a_info.play.sample_rate = sample_rate;
400 a_info.blocksize = fragment_size;
402 afmt->format = AUDIO_FORMAT_U8;
405 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
407 /* try to disable stereo */
408 a_info.play.channels = 1;
410 afmt->stereo = FALSE;
412 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
413 Error(ERR_EXIT_SOUND_SERVER,
414 "cannot set sample rate of /dev/audio -- no sounds");
417 #endif /* PLATFORM_NETBSD */
419 #if defined(PLATFORM_HPUX)
420 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
422 struct audio_describe ainfo;
425 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
427 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
429 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
430 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
432 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
433 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
435 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
436 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
438 afmt->format = AUDIO_FORMAT_U8;
439 afmt->stereo = FALSE;
440 afmt->sample_rate = 8000;
444 #endif /* PLATFORM_HPUX */
446 static void InitAudioDevice(struct AudioFormatInfo *afmt)
449 afmt->format = AUDIO_FORMAT_UNKNOWN;
450 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
451 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
453 #if defined(AUDIO_LINUX_IOCTL)
454 InitAudioDevice_Linux(afmt);
455 #elif defined(PLATFORM_NETBSD)
456 InitAudioDevice_NetBSD(afmt);
457 #elif defined(PLATFORM_HPUX)
458 InitAudioDevice_HPUX(afmt);
460 /* generic /dev/audio stuff might be placed here */
465 /* ------------------------------------------------------------------------- */
466 /* functions for communication between main process and sound mixer process */
467 /* ------------------------------------------------------------------------- */
469 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
471 if (IS_CHILD_PROCESS(audio.mixer_pid))
474 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
476 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
477 audio.sound_available = audio.sound_enabled = FALSE;
482 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
484 if (IS_PARENT_PROCESS(audio.mixer_pid))
487 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
488 != sizeof(SoundControl))
489 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
492 static void WriteReloadInfoToPipe(char *set_name, int type)
494 SoundControl snd_ctrl;
495 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
496 artwork.mus_current);
497 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
498 unsigned long str_size2 = strlen(ti->basepath) + 1;
499 unsigned long str_size3 = strlen(ti->fullpath) + 1;
500 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
501 setup.override_level_sounds :
502 setup.override_level_music);
504 if (IS_CHILD_PROCESS(audio.mixer_pid))
507 if (leveldir_current == NULL) /* should never happen */
508 Error(ERR_EXIT, "leveldir_current == NULL");
510 snd_ctrl.active = FALSE;
511 snd_ctrl.state = type;
512 snd_ctrl.data_len = strlen(set_name) + 1;
514 if (write(audio.mixer_pipe[1], &snd_ctrl,
515 sizeof(snd_ctrl)) < 0 ||
516 write(audio.mixer_pipe[1], set_name,
517 snd_ctrl.data_len) < 0 ||
518 write(audio.mixer_pipe[1], &override_level_artwork,
519 sizeof(boolean)) < 0 ||
520 write(audio.mixer_pipe[1], leveldir_current,
521 sizeof(TreeInfo)) < 0 ||
522 write(audio.mixer_pipe[1], ti,
523 sizeof(TreeInfo)) < 0 ||
524 write(audio.mixer_pipe[1], &str_size1,
525 sizeof(unsigned long)) < 0 ||
526 write(audio.mixer_pipe[1], &str_size2,
527 sizeof(unsigned long)) < 0 ||
528 write(audio.mixer_pipe[1], &str_size3,
529 sizeof(unsigned long)) < 0 ||
530 write(audio.mixer_pipe[1], leveldir_current->fullpath,
532 write(audio.mixer_pipe[1], ti->basepath,
534 write(audio.mixer_pipe[1], ti->fullpath,
537 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
538 audio.sound_available = audio.sound_enabled = FALSE;
543 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
545 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
546 &artwork.snd_current : &artwork.mus_current);
547 TreeInfo *ti = *ti_ptr;
548 unsigned long str_size1, str_size2, str_size3;
549 static char *set_name = NULL;
550 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
551 &setup.override_level_sounds :
552 &setup.override_level_music);
557 set_name = checked_malloc(snd_ctrl->data_len);
559 if (leveldir_current == NULL)
560 leveldir_current = checked_calloc(sizeof(TreeInfo));
562 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
563 if (leveldir_current->fullpath != NULL)
564 free(leveldir_current->fullpath);
565 if (ti->basepath != NULL)
567 if (ti->fullpath != NULL)
570 if (read(audio.mixer_pipe[0], set_name,
571 snd_ctrl->data_len) != snd_ctrl->data_len ||
572 read(audio.mixer_pipe[0], override_level_artwork,
573 sizeof(boolean)) != sizeof(boolean) ||
574 read(audio.mixer_pipe[0], leveldir_current,
575 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
576 read(audio.mixer_pipe[0], ti,
577 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
578 read(audio.mixer_pipe[0], &str_size1,
579 sizeof(unsigned long)) != sizeof(unsigned long) ||
580 read(audio.mixer_pipe[0], &str_size2,
581 sizeof(unsigned long)) != sizeof(unsigned long) ||
582 read(audio.mixer_pipe[0], &str_size3,
583 sizeof(unsigned long)) != sizeof(unsigned long))
584 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
586 leveldir_current->fullpath = checked_calloc(str_size1);
587 ti->basepath = checked_calloc(str_size2);
588 ti->fullpath = checked_calloc(str_size3);
590 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
591 str_size1) != str_size1 ||
592 read(audio.mixer_pipe[0], ti->basepath,
593 str_size2) != str_size2 ||
594 read(audio.mixer_pipe[0], ti->fullpath,
595 str_size3) != str_size3)
596 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
598 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
599 artwork.sounds_set_current_name = set_name;
601 artwork.music_set_current_name = set_name;
604 #endif /* AUDIO_UNIX_NATIVE */
607 /* ------------------------------------------------------------------------- */
608 /* mixer functions */
609 /* ------------------------------------------------------------------------- */
611 void Mixer_InitChannels()
615 for(i=0; i<audio.num_channels; i++)
616 mixer[i].active = FALSE;
617 mixer_active_channels = 0;
620 static void Mixer_ResetChannelExpiration(int channel)
622 mixer[channel].playing_starttime = Counter();
624 #if defined(TARGET_SDL)
625 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
626 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
630 static boolean Mixer_ChannelExpired(int channel)
632 if (!mixer[channel].active)
635 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
636 DelayReached(&mixer[channel].playing_starttime,
637 SOUND_LOOP_EXPIRATION_TIME))
640 #if defined(TARGET_SDL)
642 if (!Mix_Playing(channel))
645 #elif defined(TARGET_ALLEGRO)
647 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
648 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
650 /* sound sample has completed playing or was completely faded out */
651 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
654 #endif /* TARGET_ALLEGRO */
659 static boolean Mixer_AllocateChannel(int channel)
661 #if defined(TARGET_ALLEGRO)
662 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
663 if (mixer[channel].voice < 0)
670 static void Mixer_SetChannelProperties(int channel)
672 #if defined(TARGET_SDL)
673 Mix_Volume(channel, mixer[channel].volume);
674 Mix_SetPanning(channel,
675 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
676 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
677 #elif defined(TARGET_ALLEGRO)
678 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
679 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
683 static void Mixer_StartChannel(int channel)
685 #if defined(TARGET_SDL)
686 Mix_PlayChannel(channel, mixer[channel].data_ptr,
687 IS_LOOP(mixer[channel]) ? -1 : 0);
688 #elif defined(TARGET_ALLEGRO)
689 if (IS_LOOP(mixer[channel]))
690 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
692 voice_start(mixer[channel].voice);
696 static void Mixer_PlayChannel(int channel)
698 /* start with inactive channel in case something goes wrong */
699 mixer[channel].active = FALSE;
701 if (mixer[channel].type != MUS_TYPE_WAV)
704 if (!Mixer_AllocateChannel(channel))
707 Mixer_SetChannelProperties(channel);
708 Mixer_StartChannel(channel);
710 Mixer_ResetChannelExpiration(channel);
712 mixer[channel].playing_pos = 0;
713 mixer[channel].active = TRUE;
714 mixer_active_channels++;
717 static void Mixer_PlayMusicChannel()
719 Mixer_PlayChannel(audio.music_channel);
721 #if defined(TARGET_SDL)
722 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
724 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
725 this looks like a bug in the SDL_mixer library */
726 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
727 Mix_VolumeMusic(SOUND_MAX_VOLUME);
732 static void Mixer_StopChannel(int channel)
734 if (!mixer[channel].active)
737 #if defined(TARGET_SDL)
738 Mix_HaltChannel(channel);
739 #elif defined(TARGET_ALLEGRO)
740 voice_set_volume(mixer[channel].voice, 0);
741 deallocate_voice(mixer[channel].voice);
744 mixer[channel].active = FALSE;
745 mixer_active_channels--;
748 static void Mixer_StopMusicChannel()
750 Mixer_StopChannel(audio.music_channel);
752 #if defined(TARGET_SDL)
757 static void Mixer_FadeChannel(int channel)
759 if (!mixer[channel].active)
762 mixer[channel].state |= SND_CTRL_FADE;
764 #if defined(TARGET_SDL)
765 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
766 #elif defined(TARGET_ALLEGRO)
767 if (voice_check(mixer[channel].voice))
768 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
772 static void Mixer_FadeMusicChannel()
774 Mixer_FadeChannel(audio.music_channel);
776 #if defined(TARGET_SDL)
777 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
781 static void Mixer_UnFadeChannel(int channel)
783 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
786 mixer[channel].state &= ~SND_CTRL_FADE;
787 mixer[channel].volume = SOUND_MAX_VOLUME;
789 #if defined(TARGET_SDL)
790 Mix_ExpireChannel(channel, -1);
791 Mix_Volume(channel, mixer[channel].volume);
792 #elif defined(TARGET_ALLEGRO)
793 voice_stop_volumeramp(mixer[channel].voice);
794 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
795 mixer[channel].volume);
799 static void Mixer_InsertSound(SoundControl snd_ctrl)
805 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
809 printf("%d ACTIVE CHANNELS\n", mixer_active_channels);
812 if (IS_MUSIC(snd_ctrl))
817 snd_ctrl.nr = snd_ctrl.nr % num_music;
819 else if (snd_ctrl.nr >= num_sounds)
822 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
823 if (snd_info == NULL)
826 /* copy sound sample and format information */
827 snd_ctrl.type = snd_info->type;
828 snd_ctrl.format = snd_info->format;
829 snd_ctrl.data_ptr = snd_info->data_ptr;
830 snd_ctrl.data_len = snd_info->data_len;
832 /* play music samples on a dedicated music channel */
833 if (IS_MUSIC(snd_ctrl))
836 printf("PLAY MUSIC WITH VOLUME/STEREO %d/%d\n",
837 snd_ctrl.volume, snd_ctrl.stereo_position);
840 mixer[audio.music_channel] = snd_ctrl;
841 Mixer_PlayMusicChannel();
846 /* check if (and how often) this sound sample is already playing */
847 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
848 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
852 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
855 /* reset expiration delay for already playing loop sounds */
856 if (k > 0 && IS_LOOP(snd_ctrl))
858 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
860 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
863 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
866 if (IS_FADING(mixer[i]))
867 Mixer_UnFadeChannel(i);
869 /* restore settings like volume and stereo position */
870 mixer[i].volume = snd_ctrl.volume;
871 mixer[i].stereo_position = snd_ctrl.stereo_position;
873 Mixer_SetChannelProperties(i);
874 Mixer_ResetChannelExpiration(i);
877 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
878 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
887 printf("PLAYING NEW SOUND %d\n", snd_ctrl.nr);
890 /* don't play sound more than n times simultaneously (with n == 2 for now) */
893 unsigned long playing_current = Counter();
894 int longest = 0, longest_nr = audio.first_sound_channel;
896 /* look for oldest equal sound */
897 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
899 int playing_time = playing_current - mixer[i].playing_starttime;
902 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
905 actual = 1000 * playing_time / mixer[i].data_len;
907 if (actual >= longest)
914 Mixer_StopChannel(longest_nr);
917 /* If all (non-music) channels are active, stop the channel that has
918 played its sound sample most completely (in percent of the sample
919 length). As we cannot currently get the actual playing position
920 of the channel's sound sample when compiling with the SDL mixer
921 library, we use the current playing time (in milliseconds) instead. */
923 if (mixer_active_channels ==
924 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
926 unsigned long playing_current = Counter();
927 int longest = 0, longest_nr = audio.first_sound_channel;
929 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
931 int playing_time = playing_current - mixer[i].playing_starttime;
932 int actual = 1000 * playing_time / mixer[i].data_len;
934 if (!IS_LOOP(mixer[i]) && actual > longest)
941 Mixer_StopChannel(longest_nr);
944 /* add the new sound to the mixer */
945 for(i=0; i<audio.num_channels; i++)
948 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
952 if (!mixer[i].active ||
953 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
955 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
956 (i != audio.music_channel && !mixer[i].active))
959 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
963 #if defined(AUDIO_UNIX_NATIVE)
964 if (snd_info->data_len == 0)
966 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
972 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
974 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
977 Mixer_StopChannel(i);
983 Mixer_PlayChannel(i);
990 static void HandleSoundRequest(SoundControl snd_ctrl)
994 #if defined(AUDIO_UNIX_NATIVE)
995 if (IS_PARENT_PROCESS(audio.mixer_pid))
997 SendSoundControlToMixerProcess(&snd_ctrl);
1002 /* deactivate channels that have expired since the last request */
1003 for (i=0; i<audio.num_channels; i++)
1004 if (mixer[i].active && Mixer_ChannelExpired(i))
1005 Mixer_StopChannel(i);
1007 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
1009 Mixer_StopMusicChannel();
1010 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1011 Mixer_StopChannel(i);
1013 #if defined(AUDIO_UNIX_NATIVE)
1014 CloseAudioDevice(&audio.device_fd);
1015 ReadReloadInfoFromPipe(&snd_ctrl);
1018 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1019 ReloadCustomSounds();
1021 ReloadCustomMusic();
1023 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1025 if (IS_MUSIC(snd_ctrl))
1027 Mixer_FadeMusicChannel();
1031 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1032 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1033 Mixer_FadeChannel(i);
1035 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1037 if (IS_MUSIC(snd_ctrl))
1039 Mixer_StopMusicChannel();
1043 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1044 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1045 Mixer_StopChannel(i);
1047 #if defined(AUDIO_UNIX_NATIVE)
1048 if (!mixer_active_channels)
1049 CloseAudioDevice(&audio.device_fd);
1052 else if (snd_ctrl.active) /* add new sound to mixer */
1054 Mixer_InsertSound(snd_ctrl);
1058 void StartMixer(void)
1063 SDL_version compile_version;
1064 const SDL_version *link_version;
1065 MIX_VERSION(&compile_version);
1066 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1067 compile_version.major,
1068 compile_version.minor,
1069 compile_version.patch);
1070 link_version = Mix_Linked_Version();
1071 printf("running with SDL_mixer version: %d.%d.%d\n",
1072 link_version->major,
1073 link_version->minor,
1074 link_version->patch);
1077 if (!audio.sound_available)
1080 /* initialize stereo position conversion information */
1081 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1083 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1085 #if defined(AUDIO_UNIX_NATIVE)
1086 if (!ForkAudioProcess())
1087 audio.sound_available = FALSE;
1091 #if defined(AUDIO_UNIX_NATIVE)
1093 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1094 int sample_pos, int sample_size,
1097 void *sample_ptr = snd_ctrl->data_ptr;
1100 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1101 for (i=0; i<sample_size; i++)
1103 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1104 else /* AUDIO_FORMAT_S16 */
1105 for (i=0; i<sample_size; i++)
1107 ((short *)sample_ptr)[sample_pos + i];
1110 #if defined(AUDIO_STREAMING_DSP)
1111 static void Mixer_Main_DSP()
1113 static short premix_first_buffer[SND_BLOCKSIZE];
1114 static short premix_left_buffer[SND_BLOCKSIZE];
1115 static short premix_right_buffer[SND_BLOCKSIZE];
1116 static long premix_last_buffer[SND_BLOCKSIZE];
1117 static byte playing_buffer[SND_BLOCKSIZE];
1121 int max_sample_size;
1124 if (!mixer_active_channels)
1127 if (audio.device_fd < 0)
1129 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1132 InitAudioDevice(&afmt);
1135 stereo = afmt.stereo;
1136 fragment_size = afmt.fragment_size;
1137 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1138 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1140 /* first clear the last premixing buffer */
1141 memset(premix_last_buffer, 0,
1142 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1144 for(i=0; i<audio.num_channels; i++)
1151 if (!mixer[i].active)
1154 if (Mixer_ChannelExpired(i))
1156 Mixer_StopChannel(i);
1160 /* pointer, lenght and actual playing position of sound sample */
1161 sample_ptr = mixer[i].data_ptr;
1162 sample_len = mixer[i].data_len;
1163 sample_pos = mixer[i].playing_pos;
1164 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1165 mixer[i].playing_pos += sample_size;
1167 /* copy original sample to first mixing buffer */
1168 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1169 premix_first_buffer);
1171 /* are we about to restart a looping sound? */
1172 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1174 while (sample_size < max_sample_size)
1176 int restarted_sample_size =
1177 MIN(max_sample_size - sample_size, sample_len);
1179 if (mixer[i].format == AUDIO_FORMAT_U8)
1180 for (j=0; j<restarted_sample_size; j++)
1181 premix_first_buffer[sample_size + j] =
1182 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1184 for (j=0; j<restarted_sample_size; j++)
1185 premix_first_buffer[sample_size + j] =
1186 ((short *)sample_ptr)[j];
1188 mixer[i].playing_pos = restarted_sample_size;
1189 sample_size += restarted_sample_size;
1193 /* decrease volume if sound is fading out */
1194 if (IS_FADING(mixer[i]) &&
1195 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1196 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1198 /* adjust volume of actual sound sample */
1199 if (mixer[i].volume != SOUND_MAX_VOLUME)
1200 for(j=0; j<sample_size; j++)
1201 premix_first_buffer[j] =
1202 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1204 /* fill the last mixing buffer with stereo or mono sound */
1207 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1208 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1210 for(j=0; j<sample_size; j++)
1212 premix_left_buffer[j] =
1213 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1214 premix_right_buffer[j] =
1215 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1217 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1218 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1223 for(j=0; j<sample_size; j++)
1224 premix_last_buffer[j] += premix_first_buffer[j];
1227 /* delete completed sound entries from the mixer */
1228 if (mixer[i].playing_pos >= mixer[i].data_len)
1230 if (IS_LOOP(mixer[i]))
1231 mixer[i].playing_pos = 0;
1233 Mixer_StopChannel(i);
1235 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1236 Mixer_StopChannel(i);
1239 /* prepare final playing buffer according to system audio format */
1240 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1242 /* cut off at 17 bit value */
1243 if (premix_last_buffer[i] < -65535)
1244 premix_last_buffer[i] = -65535;
1245 else if (premix_last_buffer[i] > 65535)
1246 premix_last_buffer[i] = 65535;
1248 /* shift to 16 bit value */
1249 premix_last_buffer[i] >>= 1;
1251 if (afmt.format & AUDIO_FORMAT_U8)
1253 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1255 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1257 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1258 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1260 else /* big endian */
1262 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1263 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1267 /* finally play the sound fragment */
1268 write(audio.device_fd, playing_buffer, fragment_size);
1270 if (!mixer_active_channels)
1271 CloseAudioDevice(&audio.device_fd);
1274 #else /* !AUDIO_STREAMING_DSP */
1276 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1278 static short premix_first_buffer[SND_BLOCKSIZE];
1279 static byte playing_buffer[SND_BLOCKSIZE];
1280 int max_sample_size = SND_BLOCKSIZE;
1289 /* pointer, lenght and actual playing position of sound sample */
1290 sample_ptr = mixer[i].data_ptr;
1291 sample_len = mixer[i].data_len;
1292 sample_pos = mixer[i].playing_pos;
1293 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1294 mixer[i].playing_pos += sample_size;
1296 /* copy original sample to first mixing buffer */
1297 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1298 premix_first_buffer);
1300 /* adjust volume of actual sound sample */
1301 if (mixer[i].volume != SOUND_MAX_VOLUME)
1302 for(j=0; j<sample_size; j++)
1303 premix_first_buffer[j] =
1304 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1306 /* might be needed for u-law /dev/audio */
1308 for(j=0; j<sample_size; j++)
1310 linear_to_ulaw(premix_first_buffer[j]);
1313 /* delete completed sound entries from the mixer */
1314 if (mixer[i].playing_pos >= mixer[i].data_len)
1315 Mixer_StopChannel(i);
1317 for(i=0; i<sample_size; i++)
1318 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1320 /* finally play the sound fragment */
1321 write(audio.device_fd, playing_buffer, sample_size);
1325 #endif /* !AUDIO_STREAMING_DSP */
1329 SoundControl snd_ctrl;
1332 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1334 Mixer_InitChannels();
1336 #if defined(PLATFORM_HPUX)
1337 InitAudioDevice(&afmt);
1340 FD_ZERO(&mixer_fdset);
1341 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1343 while(1) /* wait for sound playing commands from client */
1345 struct timeval delay = { 0, 0 };
1347 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1348 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1349 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1352 ReadSoundControlFromMainProcess(&snd_ctrl);
1354 HandleSoundRequest(snd_ctrl);
1356 #if defined(AUDIO_STREAMING_DSP)
1358 while (mixer_active_channels &&
1359 select(audio.mixer_pipe[0] + 1,
1360 &mixer_fdset, NULL, NULL, &delay) < 1)
1362 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1367 #else /* !AUDIO_STREAMING_DSP */
1369 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1370 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1373 InitAudioDevice(&afmt);
1378 while (mixer_active_channels &&
1379 select(audio.mixer_pipe[0] + 1,
1380 &mixer_fdset, NULL, NULL, &delay) < 1)
1382 int wait_percent = 90; /* wait 90% of the real playing time */
1385 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1387 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1391 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1394 CloseAudioDevice(&audio.device_fd);
1396 Mixer_InitChannels(); /* remove all sounds from mixer */
1398 #endif /* !AUDIO_STREAMING_DSP */
1401 #endif /* AUDIO_UNIX_NATIVE */
1404 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1406 /* these two are stolen from "sox"... :) */
1409 ** This routine converts from linear to ulaw.
1411 ** Craig Reese: IDA/Supercomputing Research Center
1412 ** Joe Campbell: Department of Defense
1413 ** 29 September 1989
1416 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1417 ** 2) "A New Digital Technique for Implementation of Any
1418 ** Continuous PCM Companding Law," Villeret, Michel,
1419 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1420 ** 1973, pg. 11.12-11.17
1421 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1422 ** for Analog-to_Digital Conversion Techniques,"
1425 ** Input: Signed 16 bit linear sample
1426 ** Output: 8 bit ulaw sample
1429 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1430 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1433 static unsigned char linear_to_ulaw(int sample)
1435 static int exp_lut[256] =
1437 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1438 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1439 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1440 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1441 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1442 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1443 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1444 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1445 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1446 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1447 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1448 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1449 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1450 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1451 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1452 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1455 int sign, exponent, mantissa;
1456 unsigned char ulawbyte;
1458 /* Get the sample into sign-magnitude. */
1459 sign = (sample >> 8) & 0x80; /* set aside the sign */
1461 sample = -sample; /* get magnitude */
1463 sample = CLIP; /* clip the magnitude */
1465 /* Convert from 16 bit linear to ulaw. */
1466 sample = sample + BIAS;
1467 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1468 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1469 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1472 ulawbyte = 0x02; /* optional CCITT trap */
1479 ** This routine converts from ulaw to 16 bit linear.
1481 ** Craig Reese: IDA/Supercomputing Research Center
1482 ** 29 September 1989
1485 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1486 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1487 ** for Analog-to_Digital Conversion Techniques,"
1490 ** Input: 8 bit ulaw sample
1491 ** Output: signed 16 bit linear sample
1494 static int ulaw_to_linear(unsigned char ulawbyte)
1496 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1497 int sign, exponent, mantissa, sample;
1499 ulawbyte = ~ ulawbyte;
1500 sign = ( ulawbyte & 0x80 );
1501 exponent = ( ulawbyte >> 4 ) & 0x07;
1502 mantissa = ulawbyte & 0x0F;
1503 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1509 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1512 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1513 /* ========================================================================= */
1514 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1516 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1517 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1519 static SoundInfo *Load_WAV(char *filename)
1521 SoundInfo *snd_info;
1522 #if defined(AUDIO_UNIX_NATIVE)
1523 struct SoundHeader_WAV header;
1525 byte sound_header_buffer[WAV_HEADER_SIZE];
1528 char chunk_name[CHUNK_ID_LEN + 1];
1533 if (!audio.sound_available)
1537 printf("loading WAV file '%s'\n", filename);
1540 snd_info = checked_calloc(sizeof(SoundInfo));
1542 #if defined(TARGET_SDL)
1544 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1546 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1551 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1553 #elif defined(TARGET_ALLEGRO)
1555 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1557 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1562 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1564 #else /* AUDIO_UNIX_NATIVE */
1566 if ((file = fopen(filename, MODE_READ)) == NULL)
1568 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1573 /* read chunk id "RIFF" */
1574 getFileChunkLE(file, chunk_name, &chunk_size);
1575 if (strcmp(chunk_name, "RIFF") != 0)
1577 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1583 /* read "RIFF" type id "WAVE" */
1584 getFileChunkLE(file, chunk_name, NULL);
1585 if (strcmp(chunk_name, "WAVE") != 0)
1587 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1593 while (getFileChunkLE(file, chunk_name, &chunk_size))
1595 if (strcmp(chunk_name, "fmt ") == 0)
1597 if (chunk_size < WAV_HEADER_SIZE)
1599 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1605 header.compression_code = getFile16BitLE(file);
1606 header.num_channels = getFile16BitLE(file);
1607 header.sample_rate = getFile32BitLE(file);
1608 header.bytes_per_second = getFile32BitLE(file);
1609 header.block_align = getFile16BitLE(file);
1610 header.bits_per_sample = getFile16BitLE(file);
1612 if (chunk_size > WAV_HEADER_SIZE)
1613 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1615 if (header.compression_code != 1)
1617 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1618 filename, header.compression_code);
1624 if (header.num_channels != 1)
1626 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1627 filename, header.num_channels);
1633 if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1635 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1636 filename, header.bits_per_sample);
1642 /* warn, but accept wrong sample rate (may be only slightly different) */
1643 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1644 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1645 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1648 printf("WAV file: '%s'\n", filename);
1649 printf(" Compression code: %d'\n", header.compression_code);
1650 printf(" Number of channels: %d'\n", header.num_channels);
1651 printf(" Sample rate: %ld'\n", header.sample_rate);
1652 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1653 printf(" Block align: %d'\n", header.block_align);
1654 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1657 else if (strcmp(chunk_name, "data") == 0)
1659 snd_info->data_len = chunk_size;
1660 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1662 /* read sound data */
1663 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1666 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1668 free(snd_info->data_ptr);
1673 /* check for odd number of sample bytes (data chunk is word aligned) */
1674 if ((chunk_size % 2) == 1)
1675 ReadUnusedBytesFromFile(file, 1);
1677 else /* unknown chunk -- ignore */
1678 ReadUnusedBytesFromFile(file, chunk_size);
1683 if (snd_info->data_ptr == NULL)
1685 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1690 if (header.bits_per_sample == 8)
1691 snd_info->format = AUDIO_FORMAT_U8;
1692 else /* header.bits_per_sample == 16 */
1694 snd_info->format = AUDIO_FORMAT_S16;
1695 snd_info->data_len /= 2; /* correct number of samples */
1698 #endif /* AUDIO_UNIX_NATIVE */
1700 snd_info->type = SND_TYPE_WAV;
1701 snd_info->source_filename = getStringCopy(filename);
1706 static void deleteSoundEntry(SoundInfo **snd_info)
1710 char *filename = (*snd_info)->source_filename;
1713 printf("[decrementing reference counter of sound '%s']\n", filename);
1716 if (--(*snd_info)->num_references <= 0)
1719 printf("[deleting sound '%s']\n", filename);
1723 FreeSound(*snd_info);
1725 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1732 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1736 /* check if the old and the new sound file are the same */
1737 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1739 /* The old and new sound are the same (have the same filename and path).
1740 This usually means that this sound does not exist in this sound set
1741 and a fallback to the existing sound is done. */
1744 printf("[sound '%s' already exists (same list entry)]\n", filename);
1750 /* delete existing sound file entry */
1751 deleteSoundEntry(snd_info);
1753 /* check if the new sound file already exists in the list of sounds */
1754 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1757 printf("[sound '%s' already exists (other list entry)]\n", filename);
1760 *snd_info = (SoundInfo *)node->content;
1761 (*snd_info)->num_references++;
1763 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1765 (*snd_info)->num_references = 1;
1766 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1770 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1772 char *filename = getCustomSoundFilename(basename);
1775 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1778 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1780 deleteSoundEntry(snd_info);
1784 if (filename == NULL)
1786 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1790 replaceSoundEntry(snd_info, filename);
1793 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1796 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1798 sound_effect = sounds_list;
1799 num_sounds = num_list_entries;
1802 void LoadSoundToList(char *basename, int list_pos)
1804 if (Sound == NULL || list_pos >= num_sounds)
1808 printf("loading sound '%s' ... [%d]\n",
1809 basename, getNumNodes(SoundFileList));
1812 LoadCustomSound(&Sound[list_pos], basename);
1815 printf("loading sound '%s' done [%d]\n",
1816 basename, getNumNodes(SoundFileList));
1820 static MusicInfo *Load_MOD(char *filename)
1822 #if defined(TARGET_SDL)
1823 MusicInfo *mod_info;
1825 if (!audio.sound_available)
1828 mod_info = checked_calloc(sizeof(MusicInfo));
1830 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1832 Error(ERR_WARN, "cannot read music file '%s'", filename);
1837 mod_info->type = MUS_TYPE_MOD;
1838 mod_info->source_filename = getStringCopy(filename);
1846 void LoadCustomMusic(void)
1848 static boolean draw_init_text = TRUE; /* only draw at startup */
1849 static char *last_music_directory = NULL;
1850 char *music_directory = getCustomMusicDirectory();
1852 struct dirent *dir_entry;
1854 if (!audio.sound_available)
1857 if (last_music_directory != NULL &&
1858 strcmp(last_music_directory, music_directory) == 0)
1859 return; /* old and new music directory are the same */
1861 last_music_directory = music_directory;
1865 if ((dir = opendir(music_directory)) == NULL)
1867 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1868 audio.music_available = FALSE;
1873 DrawInitText("Loading music:", 120, FC_GREEN);
1875 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1877 char *basename = dir_entry->d_name;
1878 char *filename = getPath2(music_directory, basename);
1879 MusicInfo *mus_info = NULL;
1882 DrawInitText(basename, 150, FC_YELLOW);
1884 if (FileIsSound(basename))
1885 mus_info = Load_WAV(filename);
1886 else if (FileIsMusic(basename))
1887 mus_info = Load_MOD(filename);
1894 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1895 Music[num_music -1] = mus_info;
1901 draw_init_text = FALSE;
1904 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1908 void PlayMusic(int nr)
1910 if (!audio.music_available)
1916 void PlaySound(int nr)
1918 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1921 void PlaySoundStereo(int nr, int stereo_position)
1923 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1926 void PlaySoundLoop(int nr)
1928 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1931 void PlaySoundMusic(int nr)
1933 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1936 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1938 SoundControl snd_ctrl;
1940 if (!audio.sound_available ||
1941 !audio.sound_enabled ||
1942 audio.sound_deactivated)
1945 if (volume < SOUND_MIN_VOLUME)
1946 volume = SOUND_MIN_VOLUME;
1947 else if (volume > SOUND_MAX_VOLUME)
1948 volume = SOUND_MAX_VOLUME;
1950 if (stereo_position < SOUND_MAX_LEFT)
1951 stereo_position = SOUND_MAX_LEFT;
1952 else if (stereo_position > SOUND_MAX_RIGHT)
1953 stereo_position = SOUND_MAX_RIGHT;
1955 snd_ctrl.active = TRUE;
1957 snd_ctrl.volume = volume;
1958 snd_ctrl.stereo_position = stereo_position;
1959 snd_ctrl.state = state;
1961 HandleSoundRequest(snd_ctrl);
1964 void FadeMusic(void)
1966 if (!audio.music_available)
1969 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1972 void FadeSound(int nr)
1974 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1980 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1983 void StopMusic(void)
1985 if (!audio.music_available)
1988 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1991 void StopSound(int nr)
1993 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1999 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2002 void StopSoundExt(int nr, int state)
2004 SoundControl snd_ctrl;
2006 if (!audio.sound_available)
2009 snd_ctrl.active = FALSE;
2011 snd_ctrl.state = state;
2013 HandleSoundRequest(snd_ctrl);
2016 ListNode *newListNode()
2018 return checked_calloc(sizeof(ListNode));
2021 void addNodeToList(ListNode **node_first, char *key, void *content)
2023 ListNode *node_new = newListNode();
2026 printf("LIST: adding node with key '%s'\n", key);
2029 node_new->key = getStringCopy(key);
2030 node_new->content = content;
2031 node_new->next = *node_first;
2032 *node_first = node_new;
2035 void deleteNodeFromList(ListNode **node_first, char *key,
2036 void (*destructor_function)(void *))
2038 if (node_first == NULL || *node_first == NULL)
2042 printf("[CHECKING LIST KEY '%s' == '%s']\n",
2043 (*node_first)->key, key);
2046 if (strcmp((*node_first)->key, key) == 0)
2049 printf("[DELETING LIST ENTRY]\n");
2052 free((*node_first)->key);
2053 if (destructor_function)
2054 destructor_function((*node_first)->content);
2055 *node_first = (*node_first)->next;
2058 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
2061 ListNode *getNodeFromKey(ListNode *node_first, char *key)
2063 if (node_first == NULL)
2066 if (strcmp(node_first->key, key) == 0)
2069 return getNodeFromKey(node_first->next, key);
2072 int getNumNodes(ListNode *node_first)
2074 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
2077 void dumpList(ListNode *node_first)
2079 ListNode *node = node_first;
2083 printf("['%s' (%d)]\n", node->key,
2084 ((SoundInfo *)node->content)->num_references);
2088 printf("[%d nodes]\n", getNumNodes(node_first));
2091 static void LoadSoundsInfo()
2093 char *filename = getCustomSoundConfigFilename();
2094 struct SetupFileList *setup_file_list;
2098 printf("GOT CUSTOM SOUND CONFIG FILE '%s'\n", filename);
2101 /* always start with reliable default values */
2102 for (i=0; i<num_sounds; i++)
2103 sound_effect[i].filename = NULL;
2105 if (filename == NULL)
2108 if ((setup_file_list = loadSetupFileList(filename)))
2110 for (i=0; i<num_sounds; i++)
2111 sound_effect[i].filename =
2112 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2114 freeSetupFileList(setup_file_list);
2117 for (i=0; i<num_sounds; i++)
2119 printf("'%s' ", sound_effect[i].text);
2120 if (sound_effect[i].filename)
2121 printf("-> '%s'\n", sound_effect[i].filename);
2123 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2129 static void ReloadCustomSounds()
2131 static boolean draw_init_text = TRUE; /* only draw at startup */
2135 printf("DEBUG: reloading sounds '%s' ...\n",artwork.sounds_set_current_name);
2141 DrawInitText("Loading sounds:", 120, FC_GREEN);
2144 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2147 for(i=0; i<num_sounds; i++)
2150 DrawInitText(sound_effect[i].text, 150, FC_YELLOW);
2152 if (sound_effect[i].filename)
2153 LoadSoundToList(sound_effect[i].filename, i);
2155 LoadSoundToList(sound_effect[i].default_filename, i);
2158 draw_init_text = FALSE;
2161 printf("list size == %d\n", getNumNodes(SoundFileList));
2165 dumpList(SoundFileList);
2169 static void ReloadCustomMusic()
2172 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current_name);
2176 /* this is done directly in LoadCustomMusic() now */
2183 void InitReloadSounds(char *set_name)
2185 if (!audio.sound_available)
2188 #if defined(AUDIO_UNIX_NATIVE)
2189 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
2191 ReloadCustomSounds();
2195 void InitReloadMusic(char *set_name)
2197 if (!audio.music_available)
2200 #if defined(AUDIO_UNIX_NATIVE)
2201 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
2203 ReloadCustomMusic();
2207 void FreeSound(void *ptr)
2209 SoundInfo *sound = (SoundInfo *)ptr;
2214 if (sound->data_ptr)
2216 #if defined(TARGET_SDL)
2217 Mix_FreeChunk(sound->data_ptr);
2218 #elif defined(TARGET_ALLEGRO)
2219 destroy_sample(sound->data_ptr);
2220 #else /* AUDIO_UNIX_NATIVE */
2221 free(sound->data_ptr);
2225 if (sound->source_filename)
2226 free(sound->source_filename);
2231 void FreeMusic(MusicInfo *music)
2236 if (music->data_ptr)
2238 #if defined(TARGET_SDL)
2239 if (music->type == MUS_TYPE_MOD)
2240 Mix_FreeMusic(music->data_ptr);
2242 Mix_FreeChunk(music->data_ptr);
2243 #elif defined(TARGET_ALLEGRO)
2244 destroy_sample(music->data_ptr);
2245 #else /* AUDIO_UNIX_NATIVE */
2246 free(music->data_ptr);
2253 void FreeAllSounds()
2261 printf("%s: FREEING SOUNDS ...\n",
2262 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2265 for(i=0; i<num_sounds; i++)
2266 deleteSoundEntry(&Sound[i]);
2268 FreeSound(Sound[i]);
2272 printf("%s: FREEING SOUNDS -- DONE\n",
2273 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2289 for(i=0; i<num_music; i++)
2290 FreeMusic(Music[i]);
2298 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2299 /* ========================================================================= */