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))
813 snd_ctrl.nr = snd_ctrl.nr % num_music;
814 else if (snd_ctrl.nr >= num_sounds)
817 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
818 if (snd_info == NULL)
821 /* copy sound sample and format information */
822 snd_ctrl.type = snd_info->type;
823 snd_ctrl.format = snd_info->format;
824 snd_ctrl.data_ptr = snd_info->data_ptr;
825 snd_ctrl.data_len = snd_info->data_len;
827 /* play music samples on a dedicated music channel */
828 if (IS_MUSIC(snd_ctrl))
831 printf("PLAY MUSIC WITH VOLUME/STEREO %d/%d\n",
832 snd_ctrl.volume, snd_ctrl.stereo_position);
835 mixer[audio.music_channel] = snd_ctrl;
836 Mixer_PlayMusicChannel();
841 /* check if (and how often) this sound sample is already playing */
842 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
843 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
847 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
850 /* reset expiration delay for already playing loop sounds */
851 if (k > 0 && IS_LOOP(snd_ctrl))
853 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
855 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
858 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
861 if (IS_FADING(mixer[i]))
862 Mixer_UnFadeChannel(i);
864 /* restore settings like volume and stereo position */
865 mixer[i].volume = snd_ctrl.volume;
866 mixer[i].stereo_position = snd_ctrl.stereo_position;
868 Mixer_SetChannelProperties(i);
869 Mixer_ResetChannelExpiration(i);
872 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
873 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
882 printf("PLAYING NEW SOUND %d\n", snd_ctrl.nr);
885 /* don't play sound more than n times simultaneously (with n == 2 for now) */
888 unsigned long playing_current = Counter();
889 int longest = 0, longest_nr = audio.first_sound_channel;
891 /* look for oldest equal sound */
892 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
894 int playing_time = playing_current - mixer[i].playing_starttime;
897 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
900 actual = 1000 * playing_time / mixer[i].data_len;
902 if (actual >= longest)
909 Mixer_StopChannel(longest_nr);
912 /* If all (non-music) channels are active, stop the channel that has
913 played its sound sample most completely (in percent of the sample
914 length). As we cannot currently get the actual playing position
915 of the channel's sound sample when compiling with the SDL mixer
916 library, we use the current playing time (in milliseconds) instead. */
918 if (mixer_active_channels ==
919 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
921 unsigned long playing_current = Counter();
922 int longest = 0, longest_nr = audio.first_sound_channel;
924 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
926 int playing_time = playing_current - mixer[i].playing_starttime;
927 int actual = 1000 * playing_time / mixer[i].data_len;
929 if (!IS_LOOP(mixer[i]) && actual > longest)
936 Mixer_StopChannel(longest_nr);
939 /* add the new sound to the mixer */
940 for(i=0; i<audio.num_channels; i++)
943 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
947 if (!mixer[i].active ||
948 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
950 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
951 (i != audio.music_channel && !mixer[i].active))
954 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
958 #if defined(AUDIO_UNIX_NATIVE)
959 if (snd_info->data_len == 0)
961 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
967 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
969 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
972 Mixer_StopChannel(i);
978 Mixer_PlayChannel(i);
985 static void HandleSoundRequest(SoundControl snd_ctrl)
989 #if defined(AUDIO_UNIX_NATIVE)
990 if (IS_PARENT_PROCESS(audio.mixer_pid))
992 SendSoundControlToMixerProcess(&snd_ctrl);
997 /* deactivate channels that have expired since the last request */
998 for (i=0; i<audio.num_channels; i++)
999 if (mixer[i].active && Mixer_ChannelExpired(i))
1000 Mixer_StopChannel(i);
1002 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
1004 Mixer_StopMusicChannel();
1005 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1006 Mixer_StopChannel(i);
1008 #if defined(AUDIO_UNIX_NATIVE)
1009 CloseAudioDevice(&audio.device_fd);
1010 ReadReloadInfoFromPipe(&snd_ctrl);
1013 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1014 ReloadCustomSounds();
1016 ReloadCustomMusic();
1018 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1020 if (IS_MUSIC(snd_ctrl))
1022 Mixer_FadeMusicChannel();
1026 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1027 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1028 Mixer_FadeChannel(i);
1030 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1032 if (IS_MUSIC(snd_ctrl))
1034 Mixer_StopMusicChannel();
1038 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1039 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1040 Mixer_StopChannel(i);
1042 #if defined(AUDIO_UNIX_NATIVE)
1043 if (!mixer_active_channels)
1044 CloseAudioDevice(&audio.device_fd);
1047 else if (snd_ctrl.active) /* add new sound to mixer */
1049 Mixer_InsertSound(snd_ctrl);
1053 void StartMixer(void)
1058 SDL_version compile_version;
1059 const SDL_version *link_version;
1060 MIX_VERSION(&compile_version);
1061 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1062 compile_version.major,
1063 compile_version.minor,
1064 compile_version.patch);
1065 link_version = Mix_Linked_Version();
1066 printf("running with SDL_mixer version: %d.%d.%d\n",
1067 link_version->major,
1068 link_version->minor,
1069 link_version->patch);
1072 if (!audio.sound_available)
1075 /* initialize stereo position conversion information */
1076 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1078 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1080 #if defined(AUDIO_UNIX_NATIVE)
1081 if (!ForkAudioProcess())
1082 audio.sound_available = FALSE;
1086 #if defined(AUDIO_UNIX_NATIVE)
1088 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1089 int sample_pos, int sample_size,
1092 void *sample_ptr = snd_ctrl->data_ptr;
1095 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1096 for (i=0; i<sample_size; i++)
1098 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1099 else /* AUDIO_FORMAT_S16 */
1100 for (i=0; i<sample_size; i++)
1102 ((short *)sample_ptr)[sample_pos + i];
1105 #if defined(AUDIO_STREAMING_DSP)
1106 static void Mixer_Main_DSP()
1108 static short premix_first_buffer[SND_BLOCKSIZE];
1109 static short premix_left_buffer[SND_BLOCKSIZE];
1110 static short premix_right_buffer[SND_BLOCKSIZE];
1111 static long premix_last_buffer[SND_BLOCKSIZE];
1112 static byte playing_buffer[SND_BLOCKSIZE];
1116 int max_sample_size;
1119 if (!mixer_active_channels)
1122 if (audio.device_fd < 0)
1124 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1127 InitAudioDevice(&afmt);
1130 stereo = afmt.stereo;
1131 fragment_size = afmt.fragment_size;
1132 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1133 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1135 /* first clear the last premixing buffer */
1136 memset(premix_last_buffer, 0,
1137 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1139 for(i=0; i<audio.num_channels; i++)
1146 if (!mixer[i].active)
1149 if (Mixer_ChannelExpired(i))
1151 Mixer_StopChannel(i);
1155 /* pointer, lenght and actual playing position of sound sample */
1156 sample_ptr = mixer[i].data_ptr;
1157 sample_len = mixer[i].data_len;
1158 sample_pos = mixer[i].playing_pos;
1159 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1160 mixer[i].playing_pos += sample_size;
1162 /* copy original sample to first mixing buffer */
1163 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1164 premix_first_buffer);
1166 /* are we about to restart a looping sound? */
1167 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1169 while (sample_size < max_sample_size)
1171 int restarted_sample_size =
1172 MIN(max_sample_size - sample_size, sample_len);
1174 if (mixer[i].format == AUDIO_FORMAT_U8)
1175 for (j=0; j<restarted_sample_size; j++)
1176 premix_first_buffer[sample_size + j] =
1177 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1179 for (j=0; j<restarted_sample_size; j++)
1180 premix_first_buffer[sample_size + j] =
1181 ((short *)sample_ptr)[j];
1183 mixer[i].playing_pos = restarted_sample_size;
1184 sample_size += restarted_sample_size;
1188 /* decrease volume if sound is fading out */
1189 if (IS_FADING(mixer[i]) &&
1190 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1191 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1193 /* adjust volume of actual sound sample */
1194 if (mixer[i].volume != SOUND_MAX_VOLUME)
1195 for(j=0; j<sample_size; j++)
1196 premix_first_buffer[j] =
1197 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1199 /* fill the last mixing buffer with stereo or mono sound */
1202 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1203 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1205 for(j=0; j<sample_size; j++)
1207 premix_left_buffer[j] =
1208 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1209 premix_right_buffer[j] =
1210 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1212 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1213 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1218 for(j=0; j<sample_size; j++)
1219 premix_last_buffer[j] += premix_first_buffer[j];
1222 /* delete completed sound entries from the mixer */
1223 if (mixer[i].playing_pos >= mixer[i].data_len)
1225 if (IS_LOOP(mixer[i]))
1226 mixer[i].playing_pos = 0;
1228 Mixer_StopChannel(i);
1230 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1231 Mixer_StopChannel(i);
1234 /* prepare final playing buffer according to system audio format */
1235 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1237 /* cut off at 17 bit value */
1238 if (premix_last_buffer[i] < -65535)
1239 premix_last_buffer[i] = -65535;
1240 else if (premix_last_buffer[i] > 65535)
1241 premix_last_buffer[i] = 65535;
1243 /* shift to 16 bit value */
1244 premix_last_buffer[i] >>= 1;
1246 if (afmt.format & AUDIO_FORMAT_U8)
1248 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1250 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1252 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1253 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1255 else /* big endian */
1257 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1258 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1262 /* finally play the sound fragment */
1263 write(audio.device_fd, playing_buffer, fragment_size);
1265 if (!mixer_active_channels)
1266 CloseAudioDevice(&audio.device_fd);
1269 #else /* !AUDIO_STREAMING_DSP */
1271 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1273 static short premix_first_buffer[SND_BLOCKSIZE];
1274 static byte playing_buffer[SND_BLOCKSIZE];
1275 int max_sample_size = SND_BLOCKSIZE;
1284 /* pointer, lenght and actual playing position of sound sample */
1285 sample_ptr = mixer[i].data_ptr;
1286 sample_len = mixer[i].data_len;
1287 sample_pos = mixer[i].playing_pos;
1288 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1289 mixer[i].playing_pos += sample_size;
1291 /* copy original sample to first mixing buffer */
1292 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1293 premix_first_buffer);
1295 /* adjust volume of actual sound sample */
1296 if (mixer[i].volume != SOUND_MAX_VOLUME)
1297 for(j=0; j<sample_size; j++)
1298 premix_first_buffer[j] =
1299 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1301 /* might be needed for u-law /dev/audio */
1303 for(j=0; j<sample_size; j++)
1305 linear_to_ulaw(premix_first_buffer[j]);
1308 /* delete completed sound entries from the mixer */
1309 if (mixer[i].playing_pos >= mixer[i].data_len)
1310 Mixer_StopChannel(i);
1312 for(i=0; i<sample_size; i++)
1313 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1315 /* finally play the sound fragment */
1316 write(audio.device_fd, playing_buffer, sample_size);
1320 #endif /* !AUDIO_STREAMING_DSP */
1324 SoundControl snd_ctrl;
1327 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1329 Mixer_InitChannels();
1331 #if defined(PLATFORM_HPUX)
1332 InitAudioDevice(&afmt);
1335 FD_ZERO(&mixer_fdset);
1336 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1338 while(1) /* wait for sound playing commands from client */
1340 struct timeval delay = { 0, 0 };
1342 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1343 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1344 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1347 ReadSoundControlFromMainProcess(&snd_ctrl);
1349 HandleSoundRequest(snd_ctrl);
1351 #if defined(AUDIO_STREAMING_DSP)
1353 while (mixer_active_channels &&
1354 select(audio.mixer_pipe[0] + 1,
1355 &mixer_fdset, NULL, NULL, &delay) < 1)
1357 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1362 #else /* !AUDIO_STREAMING_DSP */
1364 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1365 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1368 InitAudioDevice(&afmt);
1373 while (mixer_active_channels &&
1374 select(audio.mixer_pipe[0] + 1,
1375 &mixer_fdset, NULL, NULL, &delay) < 1)
1377 int wait_percent = 90; /* wait 90% of the real playing time */
1380 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1382 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1386 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1389 CloseAudioDevice(&audio.device_fd);
1391 Mixer_InitChannels(); /* remove all sounds from mixer */
1393 #endif /* !AUDIO_STREAMING_DSP */
1396 #endif /* AUDIO_UNIX_NATIVE */
1399 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1401 /* these two are stolen from "sox"... :) */
1404 ** This routine converts from linear to ulaw.
1406 ** Craig Reese: IDA/Supercomputing Research Center
1407 ** Joe Campbell: Department of Defense
1408 ** 29 September 1989
1411 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1412 ** 2) "A New Digital Technique for Implementation of Any
1413 ** Continuous PCM Companding Law," Villeret, Michel,
1414 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1415 ** 1973, pg. 11.12-11.17
1416 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1417 ** for Analog-to_Digital Conversion Techniques,"
1420 ** Input: Signed 16 bit linear sample
1421 ** Output: 8 bit ulaw sample
1424 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1425 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1428 static unsigned char linear_to_ulaw(int sample)
1430 static int exp_lut[256] =
1432 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1433 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1434 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1435 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1436 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1437 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1438 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1439 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1440 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1441 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1442 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1443 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1444 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
1450 int sign, exponent, mantissa;
1451 unsigned char ulawbyte;
1453 /* Get the sample into sign-magnitude. */
1454 sign = (sample >> 8) & 0x80; /* set aside the sign */
1456 sample = -sample; /* get magnitude */
1458 sample = CLIP; /* clip the magnitude */
1460 /* Convert from 16 bit linear to ulaw. */
1461 sample = sample + BIAS;
1462 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1463 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1464 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1467 ulawbyte = 0x02; /* optional CCITT trap */
1474 ** This routine converts from ulaw to 16 bit linear.
1476 ** Craig Reese: IDA/Supercomputing Research Center
1477 ** 29 September 1989
1480 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1481 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1482 ** for Analog-to_Digital Conversion Techniques,"
1485 ** Input: 8 bit ulaw sample
1486 ** Output: signed 16 bit linear sample
1489 static int ulaw_to_linear(unsigned char ulawbyte)
1491 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1492 int sign, exponent, mantissa, sample;
1494 ulawbyte = ~ ulawbyte;
1495 sign = ( ulawbyte & 0x80 );
1496 exponent = ( ulawbyte >> 4 ) & 0x07;
1497 mantissa = ulawbyte & 0x0F;
1498 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1504 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1507 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1508 /* ========================================================================= */
1509 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1511 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1512 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1514 static SoundInfo *Load_WAV(char *filename)
1516 SoundInfo *snd_info;
1517 #if defined(AUDIO_UNIX_NATIVE)
1518 struct SoundHeader_WAV header;
1520 byte sound_header_buffer[WAV_HEADER_SIZE];
1523 char chunk_name[CHUNK_ID_LEN + 1];
1528 if (!audio.sound_available)
1532 printf("loading WAV file '%s'\n", filename);
1535 snd_info = checked_calloc(sizeof(SoundInfo));
1537 #if defined(TARGET_SDL)
1539 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1541 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1546 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1548 #elif defined(TARGET_ALLEGRO)
1550 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1552 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1557 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1559 #else /* AUDIO_UNIX_NATIVE */
1561 if ((file = fopen(filename, MODE_READ)) == NULL)
1563 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1568 /* read chunk id "RIFF" */
1569 getFileChunkLE(file, chunk_name, &chunk_size);
1570 if (strcmp(chunk_name, "RIFF") != 0)
1572 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1578 /* read "RIFF" type id "WAVE" */
1579 getFileChunkLE(file, chunk_name, NULL);
1580 if (strcmp(chunk_name, "WAVE") != 0)
1582 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1588 while (getFileChunkLE(file, chunk_name, &chunk_size))
1590 if (strcmp(chunk_name, "fmt ") == 0)
1592 if (chunk_size < WAV_HEADER_SIZE)
1594 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1600 header.compression_code = getFile16BitLE(file);
1601 header.num_channels = getFile16BitLE(file);
1602 header.sample_rate = getFile32BitLE(file);
1603 header.bytes_per_second = getFile32BitLE(file);
1604 header.block_align = getFile16BitLE(file);
1605 header.bits_per_sample = getFile16BitLE(file);
1607 if (chunk_size > WAV_HEADER_SIZE)
1608 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1610 if (header.compression_code != 1)
1612 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1613 filename, header.compression_code);
1619 if (header.num_channels != 1)
1621 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1622 filename, header.num_channels);
1628 if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1630 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1631 filename, header.bits_per_sample);
1637 /* warn, but accept wrong sample rate (may be only slightly different) */
1638 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1639 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1640 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1643 printf("WAV file: '%s'\n", filename);
1644 printf(" Compression code: %d'\n", header.compression_code);
1645 printf(" Number of channels: %d'\n", header.num_channels);
1646 printf(" Sample rate: %ld'\n", header.sample_rate);
1647 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1648 printf(" Block align: %d'\n", header.block_align);
1649 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1652 else if (strcmp(chunk_name, "data") == 0)
1654 snd_info->data_len = chunk_size;
1655 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1657 /* read sound data */
1658 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1661 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1663 free(snd_info->data_ptr);
1668 /* check for odd number of sample bytes (data chunk is word aligned) */
1669 if ((chunk_size % 2) == 1)
1670 ReadUnusedBytesFromFile(file, 1);
1672 else /* unknown chunk -- ignore */
1673 ReadUnusedBytesFromFile(file, chunk_size);
1678 if (snd_info->data_ptr == NULL)
1680 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1685 if (header.bits_per_sample == 8)
1686 snd_info->format = AUDIO_FORMAT_U8;
1687 else /* header.bits_per_sample == 16 */
1689 snd_info->format = AUDIO_FORMAT_S16;
1690 snd_info->data_len /= 2; /* correct number of samples */
1693 #endif /* AUDIO_UNIX_NATIVE */
1695 snd_info->type = SND_TYPE_WAV;
1696 snd_info->source_filename = getStringCopy(filename);
1701 static void deleteSoundEntry(SoundInfo **snd_info)
1705 char *filename = (*snd_info)->source_filename;
1708 printf("[decrementing reference counter of sound '%s']\n", filename);
1711 if (--(*snd_info)->num_references <= 0)
1714 printf("[deleting sound '%s']\n", filename);
1718 FreeSound(*snd_info);
1720 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1727 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1731 /* check if the old and the new sound file are the same */
1732 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1734 /* The old and new sound are the same (have the same filename and path).
1735 This usually means that this sound does not exist in this sound set
1736 and a fallback to the existing sound is done. */
1739 printf("[sound '%s' already exists (same list entry)]\n", filename);
1745 /* delete existing sound file entry */
1746 deleteSoundEntry(snd_info);
1748 /* check if the new sound file already exists in the list of sounds */
1749 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1752 printf("[sound '%s' already exists (other list entry)]\n", filename);
1755 *snd_info = (SoundInfo *)node->content;
1756 (*snd_info)->num_references++;
1758 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1760 (*snd_info)->num_references = 1;
1761 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1765 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1767 char *filename = getCustomSoundFilename(basename);
1770 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1773 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1775 deleteSoundEntry(snd_info);
1779 if (filename == NULL)
1781 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1785 replaceSoundEntry(snd_info, filename);
1788 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1791 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1793 sound_effect = sounds_list;
1794 num_sounds = num_list_entries;
1797 void LoadSoundToList(char *basename, int list_pos)
1799 if (Sound == NULL || list_pos >= num_sounds)
1803 printf("loading sound '%s' ... [%d]\n",
1804 basename, getNumNodes(SoundFileList));
1807 LoadCustomSound(&Sound[list_pos], basename);
1810 printf("loading sound '%s' done [%d]\n",
1811 basename, getNumNodes(SoundFileList));
1815 static MusicInfo *Load_MOD(char *filename)
1817 #if defined(TARGET_SDL)
1818 MusicInfo *mod_info;
1820 if (!audio.sound_available)
1823 mod_info = checked_calloc(sizeof(MusicInfo));
1825 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1827 Error(ERR_WARN, "cannot read music file '%s'", filename);
1832 mod_info->type = MUS_TYPE_MOD;
1833 mod_info->source_filename = getStringCopy(filename);
1841 void LoadCustomMusic(void)
1843 static boolean draw_init_text = TRUE; /* only draw at startup */
1844 static char *last_music_directory = NULL;
1845 char *music_directory = getCustomMusicDirectory();
1847 struct dirent *dir_entry;
1849 if (!audio.sound_available)
1852 if (last_music_directory != NULL &&
1853 strcmp(last_music_directory, music_directory) == 0)
1854 return; /* old and new music directory are the same */
1856 last_music_directory = music_directory;
1860 if ((dir = opendir(music_directory)) == NULL)
1862 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1863 audio.music_available = FALSE;
1868 DrawInitText("Loading music:", 120, FC_GREEN);
1870 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1872 char *basename = dir_entry->d_name;
1873 char *filename = getPath2(music_directory, basename);
1874 MusicInfo *mus_info = NULL;
1877 DrawInitText(basename, 150, FC_YELLOW);
1879 if (FileIsSound(basename))
1880 mus_info = Load_WAV(filename);
1881 else if (FileIsMusic(basename))
1882 mus_info = Load_MOD(filename);
1889 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1890 Music[num_music -1] = mus_info;
1896 draw_init_text = FALSE;
1899 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1903 void PlayMusic(int nr)
1905 if (!audio.music_available)
1911 void PlaySound(int nr)
1913 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1916 void PlaySoundStereo(int nr, int stereo_position)
1918 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1921 void PlaySoundLoop(int nr)
1923 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1926 void PlaySoundMusic(int nr)
1928 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1931 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1933 SoundControl snd_ctrl;
1935 if (!audio.sound_available ||
1936 !audio.sound_enabled ||
1937 audio.sound_deactivated)
1940 if (volume < SOUND_MIN_VOLUME)
1941 volume = SOUND_MIN_VOLUME;
1942 else if (volume > SOUND_MAX_VOLUME)
1943 volume = SOUND_MAX_VOLUME;
1945 if (stereo_position < SOUND_MAX_LEFT)
1946 stereo_position = SOUND_MAX_LEFT;
1947 else if (stereo_position > SOUND_MAX_RIGHT)
1948 stereo_position = SOUND_MAX_RIGHT;
1950 snd_ctrl.active = TRUE;
1952 snd_ctrl.volume = volume;
1953 snd_ctrl.stereo_position = stereo_position;
1954 snd_ctrl.state = state;
1956 HandleSoundRequest(snd_ctrl);
1959 void FadeMusic(void)
1961 if (!audio.music_available)
1964 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1967 void FadeSound(int nr)
1969 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1975 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1978 void StopMusic(void)
1980 if (!audio.music_available)
1983 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1986 void StopSound(int nr)
1988 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1994 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1997 void StopSoundExt(int nr, int state)
1999 SoundControl snd_ctrl;
2001 if (!audio.sound_available)
2004 snd_ctrl.active = FALSE;
2006 snd_ctrl.state = state;
2008 HandleSoundRequest(snd_ctrl);
2011 ListNode *newListNode()
2013 return checked_calloc(sizeof(ListNode));
2016 void addNodeToList(ListNode **node_first, char *key, void *content)
2018 ListNode *node_new = newListNode();
2021 printf("LIST: adding node with key '%s'\n", key);
2024 node_new->key = getStringCopy(key);
2025 node_new->content = content;
2026 node_new->next = *node_first;
2027 *node_first = node_new;
2030 void deleteNodeFromList(ListNode **node_first, char *key,
2031 void (*destructor_function)(void *))
2033 if (node_first == NULL || *node_first == NULL)
2037 printf("[CHECKING LIST KEY '%s' == '%s']\n",
2038 (*node_first)->key, key);
2041 if (strcmp((*node_first)->key, key) == 0)
2044 printf("[DELETING LIST ENTRY]\n");
2047 free((*node_first)->key);
2048 if (destructor_function)
2049 destructor_function((*node_first)->content);
2050 *node_first = (*node_first)->next;
2053 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
2056 ListNode *getNodeFromKey(ListNode *node_first, char *key)
2058 if (node_first == NULL)
2061 if (strcmp(node_first->key, key) == 0)
2064 return getNodeFromKey(node_first->next, key);
2067 int getNumNodes(ListNode *node_first)
2069 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
2072 void dumpList(ListNode *node_first)
2074 ListNode *node = node_first;
2078 printf("['%s' (%d)]\n", node->key,
2079 ((SoundInfo *)node->content)->num_references);
2083 printf("[%d nodes]\n", getNumNodes(node_first));
2086 static void LoadSoundsInfo()
2088 char *filename = getCustomSoundConfigFilename();
2089 struct SetupFileList *setup_file_list;
2093 printf("GOT CUSTOM SOUND CONFIG FILE '%s'\n", filename);
2096 /* always start with reliable default values */
2097 for (i=0; i<num_sounds; i++)
2098 sound_effect[i].filename = NULL;
2100 if (filename == NULL)
2103 if ((setup_file_list = loadSetupFileList(filename)))
2105 for (i=0; i<num_sounds; i++)
2106 sound_effect[i].filename =
2107 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2109 freeSetupFileList(setup_file_list);
2112 for (i=0; i<num_sounds; i++)
2114 printf("'%s' ", sound_effect[i].text);
2115 if (sound_effect[i].filename)
2116 printf("-> '%s'\n", sound_effect[i].filename);
2118 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2124 static void ReloadCustomSounds()
2126 static boolean draw_init_text = TRUE; /* only draw at startup */
2130 printf("DEBUG: reloading sounds '%s' ...\n",artwork.sounds_set_current_name);
2136 DrawInitText("Loading sounds:", 120, FC_GREEN);
2139 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2142 for(i=0; i<num_sounds; i++)
2145 DrawInitText(sound_effect[i].text, 150, FC_YELLOW);
2147 if (sound_effect[i].filename)
2148 LoadSoundToList(sound_effect[i].filename, i);
2150 LoadSoundToList(sound_effect[i].default_filename, i);
2153 draw_init_text = FALSE;
2156 printf("list size == %d\n", getNumNodes(SoundFileList));
2160 dumpList(SoundFileList);
2164 static void ReloadCustomMusic()
2167 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current_name);
2171 /* this is done directly in LoadCustomMusic() now */
2178 void InitReloadSounds(char *set_name)
2180 if (!audio.sound_available)
2183 #if defined(AUDIO_UNIX_NATIVE)
2184 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
2186 ReloadCustomSounds();
2190 void InitReloadMusic(char *set_name)
2192 if (!audio.music_available)
2195 #if defined(AUDIO_UNIX_NATIVE)
2196 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
2198 ReloadCustomMusic();
2202 void FreeSound(void *ptr)
2204 SoundInfo *sound = (SoundInfo *)ptr;
2209 if (sound->data_ptr)
2211 #if defined(TARGET_SDL)
2212 Mix_FreeChunk(sound->data_ptr);
2213 #elif defined(TARGET_ALLEGRO)
2214 destroy_sample(sound->data_ptr);
2215 #else /* AUDIO_UNIX_NATIVE */
2216 free(sound->data_ptr);
2220 if (sound->source_filename)
2221 free(sound->source_filename);
2226 void FreeMusic(MusicInfo *music)
2231 if (music->data_ptr)
2233 #if defined(TARGET_SDL)
2234 if (music->type == MUS_TYPE_MOD)
2235 Mix_FreeMusic(music->data_ptr);
2237 Mix_FreeChunk(music->data_ptr);
2238 #elif defined(TARGET_ALLEGRO)
2239 destroy_sample(music->data_ptr);
2240 #else /* AUDIO_UNIX_NATIVE */
2241 free(music->data_ptr);
2248 void FreeAllSounds()
2256 printf("%s: FREEING SOUNDS ...\n",
2257 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2260 for(i=0; i<num_sounds; i++)
2261 deleteSoundEntry(&Sound[i]);
2263 FreeSound(Sound[i]);
2267 printf("%s: FREEING SOUNDS -- DONE\n",
2268 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2284 for(i=0; i<num_music; i++)
2285 FreeMusic(Music[i]);
2293 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2294 /* ========================================================================= */