1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
24 #if defined(PLATFORM_LINUX)
25 #include <sys/ioctl.h>
26 #include <linux/soundcard.h>
27 #elif defined(PLATFORM_FREEBSD)
28 #include <machine/soundcard.h>
29 #elif defined(PLATFORM_NETBSD)
30 #include <sys/ioctl.h>
31 #include <sys/audioio.h>
32 #elif defined(PLATFORM_HPUX)
33 #include <sys/audio.h>
43 /* expiration time (in milliseconds) for sound loops */
44 #define SOUND_LOOP_EXPIRATION_TIME 200
46 /* one second fading interval == 1000 ticks (milliseconds) */
47 #define SOUND_FADING_INTERVAL 1000
49 #if defined(AUDIO_STREAMING_DSP)
50 #define SOUND_FADING_VOLUME_STEP (SOUND_MAX_VOLUME / 40)
51 #define SOUND_FADING_VOLUME_THRESHOLD (SOUND_FADING_VOLUME_STEP * 2)
54 #if !defined(PLATFORM_HPUX)
55 #define SND_BLOCKSIZE 4096
57 #define SND_BLOCKSIZE 32768
60 #define SND_TYPE_NONE 0
61 #define SND_TYPE_WAV 1
63 #define MUS_TYPE_NONE 0
64 #define MUS_TYPE_WAV 1
65 #define MUS_TYPE_MOD 2
67 #define DEVICENAME_DSP "/dev/dsp"
68 #define DEVICENAME_AUDIO "/dev/audio"
69 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
71 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
72 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
76 struct SoundHeader_SUN
79 unsigned long hdr_size;
80 unsigned long data_size;
81 unsigned long encoding;
82 unsigned long sample_rate;
83 unsigned long channels;
86 struct SoundHeader_8SVX
89 unsigned long chunk_size;
94 #if defined(AUDIO_UNIX_NATIVE)
95 struct SoundHeader_WAV
97 unsigned short compression_code;
98 unsigned short num_channels;
99 unsigned long sample_rate;
100 unsigned long bytes_per_second;
101 unsigned short block_align;
102 unsigned short bits_per_sample;
106 struct AudioFormatInfo
108 boolean stereo; /* availability of stereo sound */
109 int format; /* size and endianess of sample data */
110 int sample_rate; /* sample frequency */
111 int fragment_size; /* audio device fragment size in bytes */
116 char *source_filename;
121 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
122 long data_len; /* number of samples, NOT number of bytes */
124 typedef struct SampleInfo SoundInfo;
125 typedef struct SampleInfo MusicInfo;
137 unsigned long playing_starttime;
138 unsigned long playing_pos;
142 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
143 long data_len; /* number of samples, NOT number of bytes */
145 #if defined(TARGET_ALLEGRO)
149 typedef struct SoundControl SoundControl;
155 struct ListNode *next;
157 typedef struct ListNode ListNode;
159 static ListNode *newListNode(void);
160 static void addNodeToList(ListNode **, char *, void *);
161 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
162 static ListNode *getNodeFromKey(ListNode *, char *);
163 static int getNumNodes(ListNode *);
166 static struct SoundEffectInfo *sound_effect;
167 static ListNode *SoundFileList = NULL;
168 static SoundInfo **Sound = NULL;
169 static MusicInfo **Music = NULL;
170 static int num_sounds = 0, num_music = 0;
171 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
174 /* ========================================================================= */
175 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
177 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
178 static int mixer_active_channels = 0;
180 #if defined(AUDIO_UNIX_NATIVE)
181 static struct AudioFormatInfo afmt;
183 static void Mixer_Main(void);
184 #if !defined(AUDIO_STREAMING_DSP)
185 static unsigned char linear_to_ulaw(int);
186 static int ulaw_to_linear(unsigned char);
190 static void ReloadCustomSounds();
191 static void ReloadCustomMusic();
192 static void FreeSound(void *);
195 /* ------------------------------------------------------------------------- */
196 /* functions for native (non-SDL) Unix audio/mixer support */
197 /* ------------------------------------------------------------------------- */
199 #if defined(AUDIO_UNIX_NATIVE)
201 static int OpenAudioDevice(char *audio_device_name)
205 /* check if desired audio device is accessible */
206 if (access(audio_device_name, W_OK) != 0)
209 /* try to open audio device in non-blocking mode */
210 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
211 return audio_device_fd;
213 /* re-open audio device in blocking mode */
214 close(audio_device_fd);
215 audio_device_fd = open(audio_device_name, O_WRONLY);
217 return audio_device_fd;
220 static void CloseAudioDevice(int *audio_device_fd)
222 if (*audio_device_fd == 0)
225 close(*audio_device_fd);
226 *audio_device_fd = -1;
229 static boolean TestAudioDevices(void)
231 static char *audio_device_name[] =
236 int audio_device_fd = -1;
239 /* look for available audio devices, starting with preferred ones */
240 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
241 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
244 if (audio_device_fd < 0)
246 Error(ERR_WARN, "cannot open audio device -- no sound");
250 close(audio_device_fd);
252 audio.device_name = audio_device_name[i];
257 static boolean ForkAudioProcess(void)
259 if (pipe(audio.mixer_pipe) < 0)
261 Error(ERR_WARN, "cannot create pipe -- no sounds");
265 if ((audio.mixer_pid = fork()) < 0)
267 Error(ERR_WARN, "cannot create sound server process -- no sounds");
271 if (IS_CHILD_PROCESS(audio.mixer_pid))
272 Mixer_Main(); /* this function never returns */
274 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
279 void UnixOpenAudio(void)
281 if (!TestAudioDevices())
284 audio.sound_available = TRUE;
285 audio.sound_enabled = TRUE;
287 #if defined(AUDIO_STREAMING_DSP)
288 audio.music_available = TRUE;
289 audio.loops_available = TRUE;
292 audio.num_channels = NUM_MIXER_CHANNELS;
293 audio.music_channel = MUSIC_CHANNEL;
294 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
297 void UnixCloseAudio(void)
300 close(audio.device_fd);
302 if (IS_PARENT_PROCESS(audio.mixer_pid))
303 kill(audio.mixer_pid, SIGTERM);
307 /* ------------------------------------------------------------------------- */
308 /* functions for platform specific audio device initialization */
309 /* ------------------------------------------------------------------------- */
311 #if defined(AUDIO_LINUX_IOCTL)
312 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
314 /* "ioctl()" expects pointer to 'int' value for stereo flag
315 (boolean is defined as 'char', which will not work here) */
316 unsigned int fragment_spec = 0;
317 int fragment_size_query;
326 /* supported audio format in preferred order */
327 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
328 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
329 { AFMT_U8, AUDIO_FORMAT_U8 },
334 /* determine logarithm (log2) of the fragment size */
335 while ((1 << fragment_spec) < afmt->fragment_size)
338 /* use two fragments (play one fragment, prepare the other);
339 one fragment would result in interrupted audio output, more
340 than two fragments would raise audio output latency to much */
341 fragment_spec |= 0x00020000;
343 /* Example for fragment specification:
344 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
345 - (with stereo the effective buffer size will shrink to 256)
346 => fragment_size = 0x00020009 */
348 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
349 Error(ERR_EXIT_SOUND_SERVER,
350 "cannot set fragment size of /dev/dsp -- no sounds");
354 while (formats[i].format_result != -1)
356 unsigned int audio_format = formats[i].format_ioctl;
357 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
359 afmt->format = formats[i].format_result;
364 if (afmt->format == 0) /* no supported audio format found */
365 Error(ERR_EXIT_SOUND_SERVER,
366 "cannot set audio format of /dev/dsp -- no sounds");
368 /* try if we can use stereo sound */
370 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
371 afmt->stereo = FALSE;
373 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
374 Error(ERR_EXIT_SOUND_SERVER,
375 "cannot set sample rate of /dev/dsp -- no sounds");
377 /* get the real fragmentation size; this should return 512 */
378 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
379 Error(ERR_EXIT_SOUND_SERVER,
380 "cannot get fragment size of /dev/dsp -- no sounds");
381 if (fragment_size_query != afmt->fragment_size)
382 Error(ERR_EXIT_SOUND_SERVER,
383 "cannot set fragment size of /dev/dsp -- no sounds");
385 #endif /* AUDIO_LINUX_IOCTL */
387 #if defined(PLATFORM_NETBSD)
388 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
391 boolean stereo = TRUE;
393 AUDIO_INITINFO(&a_info);
394 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
395 a_info.play.precision = 8;
396 a_info.play.channels = 2;
397 a_info.play.sample_rate = sample_rate;
398 a_info.blocksize = fragment_size;
400 afmt->format = AUDIO_FORMAT_U8;
403 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
405 /* try to disable stereo */
406 a_info.play.channels = 1;
408 afmt->stereo = FALSE;
410 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
411 Error(ERR_EXIT_SOUND_SERVER,
412 "cannot set sample rate of /dev/audio -- no sounds");
415 #endif /* PLATFORM_NETBSD */
417 #if defined(PLATFORM_HPUX)
418 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
420 struct audio_describe ainfo;
423 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
425 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
427 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
428 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
430 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
431 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
433 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
434 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
436 afmt->format = AUDIO_FORMAT_U8;
437 afmt->stereo = FALSE;
438 afmt->sample_rate = 8000;
442 #endif /* PLATFORM_HPUX */
444 static void InitAudioDevice(struct AudioFormatInfo *afmt)
447 afmt->format = AUDIO_FORMAT_UNKNOWN;
448 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
449 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
451 #if defined(AUDIO_LINUX_IOCTL)
452 InitAudioDevice_Linux(afmt);
453 #elif defined(PLATFORM_NETBSD)
454 InitAudioDevice_NetBSD(afmt);
455 #elif defined(PLATFORM_HPUX)
456 InitAudioDevice_HPUX(afmt);
458 /* generic /dev/audio stuff might be placed here */
463 /* ------------------------------------------------------------------------- */
464 /* functions for communication between main process and sound mixer process */
465 /* ------------------------------------------------------------------------- */
467 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
469 if (IS_CHILD_PROCESS(audio.mixer_pid))
472 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
474 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
475 audio.sound_available = audio.sound_enabled = FALSE;
480 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
482 if (IS_PARENT_PROCESS(audio.mixer_pid))
485 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
486 != sizeof(SoundControl))
487 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
490 static void WriteReloadInfoToPipe(char *set_name, int type)
492 SoundControl snd_ctrl;
493 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
494 artwork.mus_current);
495 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
496 unsigned long str_size2 = strlen(ti->basepath) + 1;
497 unsigned long str_size3 = strlen(ti->fullpath) + 1;
499 if (IS_CHILD_PROCESS(audio.mixer_pid))
502 if (leveldir_current == NULL) /* should never happen */
503 Error(ERR_EXIT, "leveldir_current == NULL");
505 snd_ctrl.active = FALSE;
506 snd_ctrl.state = type;
507 snd_ctrl.data_len = strlen(set_name) + 1;
509 if (write(audio.mixer_pipe[1], &snd_ctrl,
510 sizeof(snd_ctrl)) < 0 ||
511 write(audio.mixer_pipe[1], set_name,
512 snd_ctrl.data_len) < 0 ||
513 write(audio.mixer_pipe[1], leveldir_current,
514 sizeof(TreeInfo)) < 0 ||
515 write(audio.mixer_pipe[1], ti,
516 sizeof(TreeInfo)) < 0 ||
517 write(audio.mixer_pipe[1], &str_size1,
518 sizeof(unsigned long)) < 0 ||
519 write(audio.mixer_pipe[1], &str_size2,
520 sizeof(unsigned long)) < 0 ||
521 write(audio.mixer_pipe[1], &str_size3,
522 sizeof(unsigned long)) < 0 ||
523 write(audio.mixer_pipe[1], leveldir_current->fullpath,
525 write(audio.mixer_pipe[1], ti->basepath,
527 write(audio.mixer_pipe[1], ti->fullpath,
530 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
531 audio.sound_available = audio.sound_enabled = FALSE;
536 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
538 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
539 &artwork.snd_current : &artwork.mus_current);
540 TreeInfo *ti = *ti_ptr;
541 unsigned long str_size1, str_size2, str_size3;
542 static char *set_name = NULL;
547 set_name = checked_malloc(snd_ctrl->data_len);
549 if (leveldir_current == NULL)
550 leveldir_current = checked_calloc(sizeof(TreeInfo));
552 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
553 if (leveldir_current->fullpath != NULL)
554 free(leveldir_current->fullpath);
555 if (ti->basepath != NULL)
557 if (ti->fullpath != NULL)
560 if (read(audio.mixer_pipe[0], set_name,
561 snd_ctrl->data_len) != snd_ctrl->data_len ||
562 read(audio.mixer_pipe[0], leveldir_current,
563 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
564 read(audio.mixer_pipe[0], ti,
565 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
566 read(audio.mixer_pipe[0], &str_size1,
567 sizeof(unsigned long)) != sizeof(unsigned long) ||
568 read(audio.mixer_pipe[0], &str_size2,
569 sizeof(unsigned long)) != sizeof(unsigned long) ||
570 read(audio.mixer_pipe[0], &str_size3,
571 sizeof(unsigned long)) != sizeof(unsigned long))
572 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
574 leveldir_current->fullpath = checked_calloc(str_size1);
575 ti->basepath = checked_calloc(str_size2);
576 ti->fullpath = checked_calloc(str_size3);
578 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
579 str_size1) != str_size1 ||
580 read(audio.mixer_pipe[0], ti->basepath,
581 str_size2) != str_size2 ||
582 read(audio.mixer_pipe[0], ti->fullpath,
583 str_size3) != str_size3)
584 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
586 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
587 artwork.sounds_set_current = set_name;
589 artwork.music_set_current = set_name;
592 #endif /* AUDIO_UNIX_NATIVE */
595 /* ------------------------------------------------------------------------- */
596 /* mixer functions */
597 /* ------------------------------------------------------------------------- */
599 void Mixer_InitChannels()
603 for(i=0; i<audio.num_channels; i++)
604 mixer[i].active = FALSE;
605 mixer_active_channels = 0;
608 static void Mixer_ResetChannelExpiration(int channel)
610 mixer[channel].playing_starttime = Counter();
612 #if defined(TARGET_SDL)
613 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
614 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
618 static boolean Mixer_ChannelExpired(int channel)
620 if (!mixer[channel].active)
623 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
624 DelayReached(&mixer[channel].playing_starttime,
625 SOUND_LOOP_EXPIRATION_TIME))
628 #if defined(TARGET_SDL)
630 if (!Mix_Playing(channel))
633 #elif defined(TARGET_ALLEGRO)
635 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
636 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
638 /* sound sample has completed playing or was completely faded out */
639 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
642 #endif /* TARGET_ALLEGRO */
647 static boolean Mixer_AllocateChannel(int channel)
649 #if defined(TARGET_ALLEGRO)
650 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
651 if (mixer[channel].voice < 0)
658 static void Mixer_SetChannelProperties(int channel)
660 #if defined(TARGET_SDL)
661 Mix_Volume(channel, mixer[channel].volume);
662 Mix_SetPanning(channel,
663 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
664 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
665 #elif defined(TARGET_ALLEGRO)
666 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
667 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
671 static void Mixer_StartChannel(int channel)
673 #if defined(TARGET_SDL)
674 Mix_PlayChannel(channel, mixer[channel].data_ptr,
675 IS_LOOP(mixer[channel]) ? -1 : 0);
676 #elif defined(TARGET_ALLEGRO)
677 if (IS_LOOP(mixer[channel]))
678 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
680 voice_start(mixer[channel].voice);
684 static void Mixer_PlayChannel(int channel)
686 /* start with inactive channel in case something goes wrong */
687 mixer[channel].active = FALSE;
689 if (mixer[channel].type != MUS_TYPE_WAV)
692 if (!Mixer_AllocateChannel(channel))
695 Mixer_SetChannelProperties(channel);
696 Mixer_StartChannel(channel);
698 Mixer_ResetChannelExpiration(channel);
700 mixer[channel].playing_pos = 0;
701 mixer[channel].active = TRUE;
702 mixer_active_channels++;
705 static void Mixer_PlayMusicChannel()
707 Mixer_PlayChannel(audio.music_channel);
709 #if defined(TARGET_SDL)
710 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
712 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
713 this looks like a bug in the SDL_mixer library */
714 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
715 Mix_VolumeMusic(SOUND_MAX_VOLUME);
720 static void Mixer_StopChannel(int channel)
722 if (!mixer[channel].active)
725 #if defined(TARGET_SDL)
726 Mix_HaltChannel(channel);
727 #elif defined(TARGET_ALLEGRO)
728 voice_set_volume(mixer[channel].voice, 0);
729 deallocate_voice(mixer[channel].voice);
732 mixer[channel].active = FALSE;
733 mixer_active_channels--;
736 static void Mixer_StopMusicChannel()
738 Mixer_StopChannel(audio.music_channel);
740 #if defined(TARGET_SDL)
745 static void Mixer_FadeChannel(int channel)
747 if (!mixer[channel].active)
750 mixer[channel].state |= SND_CTRL_FADE;
752 #if defined(TARGET_SDL)
753 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
754 #elif defined(TARGET_ALLEGRO)
755 if (voice_check(mixer[channel].voice))
756 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
760 static void Mixer_FadeMusicChannel()
762 Mixer_FadeChannel(audio.music_channel);
764 #if defined(TARGET_SDL)
765 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
769 static void Mixer_UnFadeChannel(int channel)
771 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
774 mixer[channel].state &= ~SND_CTRL_FADE;
775 mixer[channel].volume = SOUND_MAX_VOLUME;
777 #if defined(TARGET_SDL)
778 Mix_ExpireChannel(channel, -1);
779 Mix_Volume(channel, mixer[channel].volume);
780 #elif defined(TARGET_ALLEGRO)
781 voice_stop_volumeramp(mixer[channel].voice);
782 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
783 mixer[channel].volume);
787 static void Mixer_InsertSound(SoundControl snd_ctrl)
793 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
797 printf("%d ACTIVE CHANNELS\n", mixer_active_channels);
800 if (IS_MUSIC(snd_ctrl))
801 snd_ctrl.nr = snd_ctrl.nr % num_music;
802 else if (snd_ctrl.nr >= num_sounds)
805 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
806 if (snd_info == NULL)
809 /* copy sound sample and format information */
810 snd_ctrl.type = snd_info->type;
811 snd_ctrl.format = snd_info->format;
812 snd_ctrl.data_ptr = snd_info->data_ptr;
813 snd_ctrl.data_len = snd_info->data_len;
815 /* play music samples on a dedicated music channel */
816 if (IS_MUSIC(snd_ctrl))
819 printf("PLAY MUSIC WITH VOLUME/STEREO %d/%d\n",
820 snd_ctrl.volume, snd_ctrl.stereo_position);
823 mixer[audio.music_channel] = snd_ctrl;
824 Mixer_PlayMusicChannel();
829 /* check if sound is already being played (and how often) */
830 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
831 if (mixer[i].active && mixer[i].nr == snd_ctrl.nr)
835 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
838 /* reset expiration delay for already playing loop sounds */
839 if (k > 0 && IS_LOOP(snd_ctrl))
841 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
843 if (mixer[i].active && mixer[i].nr == snd_ctrl.nr)
846 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
849 if (IS_FADING(mixer[i]))
850 Mixer_UnFadeChannel(i);
852 /* restore settings like volume and stereo position */
853 mixer[i].volume = snd_ctrl.volume;
854 mixer[i].stereo_position = snd_ctrl.stereo_position;
856 Mixer_SetChannelProperties(i);
857 Mixer_ResetChannelExpiration(i);
860 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
861 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
869 /* don't play sound more than n times simultaneously (with n == 2 for now) */
872 unsigned long playing_current = Counter();
873 int longest = 0, longest_nr = audio.first_sound_channel;
875 /* look for oldest equal sound */
876 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
878 int playing_time = playing_current - mixer[i].playing_starttime;
881 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
884 actual = 1000 * playing_time / mixer[i].data_len;
886 if (actual >= longest)
893 Mixer_StopChannel(longest_nr);
896 /* If all (non-music) channels are active, stop the channel that has
897 played its sound sample most completely (in percent of the sample
898 length). As we cannot currently get the actual playing position
899 of the channel's sound sample when compiling with the SDL mixer
900 library, we use the current playing time (in milliseconds) instead. */
902 if (mixer_active_channels ==
903 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
905 unsigned long playing_current = Counter();
906 int longest = 0, longest_nr = audio.first_sound_channel;
908 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
910 int playing_time = playing_current - mixer[i].playing_starttime;
911 int actual = 1000 * playing_time / mixer[i].data_len;
913 if (!IS_LOOP(mixer[i]) && actual > longest)
920 Mixer_StopChannel(longest_nr);
923 /* add the new sound to the mixer */
924 for(i=0; i<audio.num_channels; i++)
927 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
931 if (!mixer[i].active ||
932 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
934 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
935 (i != audio.music_channel && !mixer[i].active))
938 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
942 #if defined(AUDIO_UNIX_NATIVE)
943 if (snd_info->data_len == 0)
945 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
951 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
953 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
956 Mixer_StopChannel(i);
962 Mixer_PlayChannel(i);
969 static void HandleSoundRequest(SoundControl snd_ctrl)
973 #if defined(AUDIO_UNIX_NATIVE)
974 if (IS_PARENT_PROCESS(audio.mixer_pid))
976 SendSoundControlToMixerProcess(&snd_ctrl);
981 /* deactivate channels that have expired since the last request */
982 for (i=0; i<audio.num_channels; i++)
983 if (mixer[i].active && Mixer_ChannelExpired(i))
984 Mixer_StopChannel(i);
986 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
988 Mixer_StopMusicChannel();
989 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
990 Mixer_StopChannel(i);
992 #if defined(AUDIO_UNIX_NATIVE)
993 CloseAudioDevice(&audio.device_fd);
994 ReadReloadInfoFromPipe(&snd_ctrl);
997 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
998 ReloadCustomSounds();
1000 ReloadCustomMusic();
1002 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1004 if (IS_MUSIC(snd_ctrl))
1006 Mixer_FadeMusicChannel();
1010 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1011 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
1012 Mixer_FadeChannel(i);
1014 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1016 if (IS_MUSIC(snd_ctrl))
1018 Mixer_StopMusicChannel();
1022 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1023 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
1024 Mixer_StopChannel(i);
1026 #if defined(AUDIO_UNIX_NATIVE)
1027 if (!mixer_active_channels)
1028 CloseAudioDevice(&audio.device_fd);
1031 else if (snd_ctrl.active) /* add new sound to mixer */
1033 Mixer_InsertSound(snd_ctrl);
1037 void StartMixer(void)
1042 SDL_version compile_version;
1043 const SDL_version *link_version;
1044 MIX_VERSION(&compile_version);
1045 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1046 compile_version.major,
1047 compile_version.minor,
1048 compile_version.patch);
1049 link_version = Mix_Linked_Version();
1050 printf("running with SDL_mixer version: %d.%d.%d\n",
1051 link_version->major,
1052 link_version->minor,
1053 link_version->patch);
1056 if (!audio.sound_available)
1059 /* initialize stereo position conversion information */
1060 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1062 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1064 #if defined(AUDIO_UNIX_NATIVE)
1065 if (!ForkAudioProcess())
1066 audio.sound_available = FALSE;
1070 #if defined(AUDIO_UNIX_NATIVE)
1072 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1073 int sample_pos, int sample_size,
1076 void *sample_ptr = snd_ctrl->data_ptr;
1079 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1080 for (i=0; i<sample_size; i++)
1082 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1083 else /* AUDIO_FORMAT_S16 */
1084 for (i=0; i<sample_size; i++)
1086 ((short *)sample_ptr)[sample_pos + i];
1089 #if defined(AUDIO_STREAMING_DSP)
1090 static void Mixer_Main_DSP()
1092 static short premix_first_buffer[SND_BLOCKSIZE];
1093 static short premix_left_buffer[SND_BLOCKSIZE];
1094 static short premix_right_buffer[SND_BLOCKSIZE];
1095 static long premix_last_buffer[SND_BLOCKSIZE];
1096 static byte playing_buffer[SND_BLOCKSIZE];
1100 int max_sample_size;
1103 if (!mixer_active_channels)
1106 if (audio.device_fd < 0)
1108 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1111 InitAudioDevice(&afmt);
1114 stereo = afmt.stereo;
1115 fragment_size = afmt.fragment_size;
1116 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1117 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1119 /* first clear the last premixing buffer */
1120 memset(premix_last_buffer, 0,
1121 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1123 for(i=0; i<audio.num_channels; i++)
1130 if (!mixer[i].active)
1133 if (Mixer_ChannelExpired(i))
1135 Mixer_StopChannel(i);
1139 /* pointer, lenght and actual playing position of sound sample */
1140 sample_ptr = mixer[i].data_ptr;
1141 sample_len = mixer[i].data_len;
1142 sample_pos = mixer[i].playing_pos;
1143 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1144 mixer[i].playing_pos += sample_size;
1146 /* copy original sample to first mixing buffer */
1147 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1148 premix_first_buffer);
1150 /* are we about to restart a looping sound? */
1151 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1153 while (sample_size < max_sample_size)
1155 int restarted_sample_size =
1156 MIN(max_sample_size - sample_size, sample_len);
1158 if (mixer[i].format == AUDIO_FORMAT_U8)
1159 for (j=0; j<restarted_sample_size; j++)
1160 premix_first_buffer[sample_size + j] =
1161 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1163 for (j=0; j<restarted_sample_size; j++)
1164 premix_first_buffer[sample_size + j] =
1165 ((short *)sample_ptr)[j];
1167 mixer[i].playing_pos = restarted_sample_size;
1168 sample_size += restarted_sample_size;
1172 /* decrease volume if sound is fading out */
1173 if (IS_FADING(mixer[i]) &&
1174 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1175 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1177 /* adjust volume of actual sound sample */
1178 if (mixer[i].volume != SOUND_MAX_VOLUME)
1179 for(j=0; j<sample_size; j++)
1180 premix_first_buffer[j] =
1181 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1183 /* fill the last mixing buffer with stereo or mono sound */
1186 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1187 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1189 for(j=0; j<sample_size; j++)
1191 premix_left_buffer[j] =
1192 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1193 premix_right_buffer[j] =
1194 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1196 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1197 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1202 for(j=0; j<sample_size; j++)
1203 premix_last_buffer[j] += premix_first_buffer[j];
1206 /* delete completed sound entries from the mixer */
1207 if (mixer[i].playing_pos >= mixer[i].data_len)
1209 if (IS_LOOP(mixer[i]))
1210 mixer[i].playing_pos = 0;
1212 Mixer_StopChannel(i);
1214 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1215 Mixer_StopChannel(i);
1218 /* prepare final playing buffer according to system audio format */
1219 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1221 /* cut off at 17 bit value */
1222 if (premix_last_buffer[i] < -65535)
1223 premix_last_buffer[i] = -65535;
1224 else if (premix_last_buffer[i] > 65535)
1225 premix_last_buffer[i] = 65535;
1227 /* shift to 16 bit value */
1228 premix_last_buffer[i] >>= 1;
1230 if (afmt.format & AUDIO_FORMAT_U8)
1232 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1234 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1236 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1237 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1239 else /* big endian */
1241 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1242 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1246 /* finally play the sound fragment */
1247 write(audio.device_fd, playing_buffer, fragment_size);
1249 if (!mixer_active_channels)
1250 CloseAudioDevice(&audio.device_fd);
1253 #else /* !AUDIO_STREAMING_DSP */
1255 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1257 static short premix_first_buffer[SND_BLOCKSIZE];
1258 static byte playing_buffer[SND_BLOCKSIZE];
1259 int max_sample_size = SND_BLOCKSIZE;
1268 /* pointer, lenght and actual playing position of sound sample */
1269 sample_ptr = mixer[i].data_ptr;
1270 sample_len = mixer[i].data_len;
1271 sample_pos = mixer[i].playing_pos;
1272 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1273 mixer[i].playing_pos += sample_size;
1275 /* copy original sample to first mixing buffer */
1276 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1277 premix_first_buffer);
1279 /* adjust volume of actual sound sample */
1280 if (mixer[i].volume != SOUND_MAX_VOLUME)
1281 for(j=0; j<sample_size; j++)
1282 premix_first_buffer[j] =
1283 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1285 /* might be needed for u-law /dev/audio */
1287 for(j=0; j<sample_size; j++)
1289 linear_to_ulaw(premix_first_buffer[j]);
1292 /* delete completed sound entries from the mixer */
1293 if (mixer[i].playing_pos >= mixer[i].data_len)
1294 Mixer_StopChannel(i);
1296 for(i=0; i<sample_size; i++)
1297 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1299 /* finally play the sound fragment */
1300 write(audio.device_fd, playing_buffer, sample_size);
1304 #endif /* !AUDIO_STREAMING_DSP */
1308 SoundControl snd_ctrl;
1311 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1313 Mixer_InitChannels();
1315 #if defined(PLATFORM_HPUX)
1316 InitAudioDevice(&afmt);
1319 FD_ZERO(&mixer_fdset);
1320 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1322 while(1) /* wait for sound playing commands from client */
1324 struct timeval delay = { 0, 0 };
1326 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1327 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1328 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1331 ReadSoundControlFromMainProcess(&snd_ctrl);
1333 HandleSoundRequest(snd_ctrl);
1335 #if defined(AUDIO_STREAMING_DSP)
1337 while (mixer_active_channels &&
1338 select(audio.mixer_pipe[0] + 1,
1339 &mixer_fdset, NULL, NULL, &delay) < 1)
1341 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1346 #else /* !AUDIO_STREAMING_DSP */
1348 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1349 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1352 InitAudioDevice(&afmt);
1357 while (mixer_active_channels &&
1358 select(audio.mixer_pipe[0] + 1,
1359 &mixer_fdset, NULL, NULL, &delay) < 1)
1361 int wait_percent = 90; /* wait 90% of the real playing time */
1364 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1366 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1370 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1373 CloseAudioDevice(&audio.device_fd);
1375 Mixer_InitChannels(); /* remove all sounds from mixer */
1377 #endif /* !AUDIO_STREAMING_DSP */
1380 #endif /* AUDIO_UNIX_NATIVE */
1383 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1385 /* these two are stolen from "sox"... :) */
1388 ** This routine converts from linear to ulaw.
1390 ** Craig Reese: IDA/Supercomputing Research Center
1391 ** Joe Campbell: Department of Defense
1392 ** 29 September 1989
1395 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1396 ** 2) "A New Digital Technique for Implementation of Any
1397 ** Continuous PCM Companding Law," Villeret, Michel,
1398 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1399 ** 1973, pg. 11.12-11.17
1400 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1401 ** for Analog-to_Digital Conversion Techniques,"
1404 ** Input: Signed 16 bit linear sample
1405 ** Output: 8 bit ulaw sample
1408 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1409 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1412 static unsigned char linear_to_ulaw(int sample)
1414 static int exp_lut[256] =
1416 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1417 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1418 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1419 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1420 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1421 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1422 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1423 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1424 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1425 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1426 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1427 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1428 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1429 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1430 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1431 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1434 int sign, exponent, mantissa;
1435 unsigned char ulawbyte;
1437 /* Get the sample into sign-magnitude. */
1438 sign = (sample >> 8) & 0x80; /* set aside the sign */
1440 sample = -sample; /* get magnitude */
1442 sample = CLIP; /* clip the magnitude */
1444 /* Convert from 16 bit linear to ulaw. */
1445 sample = sample + BIAS;
1446 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1447 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1448 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1451 ulawbyte = 0x02; /* optional CCITT trap */
1458 ** This routine converts from ulaw to 16 bit linear.
1460 ** Craig Reese: IDA/Supercomputing Research Center
1461 ** 29 September 1989
1464 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1465 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1466 ** for Analog-to_Digital Conversion Techniques,"
1469 ** Input: 8 bit ulaw sample
1470 ** Output: signed 16 bit linear sample
1473 static int ulaw_to_linear(unsigned char ulawbyte)
1475 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1476 int sign, exponent, mantissa, sample;
1478 ulawbyte = ~ ulawbyte;
1479 sign = ( ulawbyte & 0x80 );
1480 exponent = ( ulawbyte >> 4 ) & 0x07;
1481 mantissa = ulawbyte & 0x0F;
1482 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1488 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1491 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1492 /* ========================================================================= */
1493 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1495 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1496 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1498 static SoundInfo *Load_WAV(char *filename)
1500 SoundInfo *snd_info;
1501 #if defined(AUDIO_UNIX_NATIVE)
1502 struct SoundHeader_WAV header;
1504 byte sound_header_buffer[WAV_HEADER_SIZE];
1507 char chunk_name[CHUNK_ID_LEN + 1];
1512 if (!audio.sound_available)
1516 printf("loading WAV file '%s'\n", filename);
1519 snd_info = checked_calloc(sizeof(SoundInfo));
1521 #if defined(TARGET_SDL)
1523 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1525 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1530 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1532 #elif defined(TARGET_ALLEGRO)
1534 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1536 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1541 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1543 #else /* AUDIO_UNIX_NATIVE */
1545 if ((file = fopen(filename, MODE_READ)) == NULL)
1547 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1552 /* read chunk id "RIFF" */
1553 getFileChunkLE(file, chunk_name, &chunk_size);
1554 if (strcmp(chunk_name, "RIFF") != 0)
1556 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1562 /* read "RIFF" type id "WAVE" */
1563 getFileChunkLE(file, chunk_name, NULL);
1564 if (strcmp(chunk_name, "WAVE") != 0)
1566 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1572 while (getFileChunkLE(file, chunk_name, &chunk_size))
1574 if (strcmp(chunk_name, "fmt ") == 0)
1576 if (chunk_size < WAV_HEADER_SIZE)
1578 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1584 header.compression_code = getFile16BitLE(file);
1585 header.num_channels = getFile16BitLE(file);
1586 header.sample_rate = getFile32BitLE(file);
1587 header.bytes_per_second = getFile32BitLE(file);
1588 header.block_align = getFile16BitLE(file);
1589 header.bits_per_sample = getFile16BitLE(file);
1591 if (chunk_size > WAV_HEADER_SIZE)
1592 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1594 if (header.compression_code != 1)
1596 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1597 filename, header.compression_code);
1603 if (header.num_channels != 1)
1605 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1606 filename, header.num_channels);
1612 if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1614 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1615 filename, header.bits_per_sample);
1621 /* warn, but accept wrong sample rate (may be only slightly different) */
1622 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1623 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1624 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1627 printf("WAV file: '%s'\n", filename);
1628 printf(" Compression code: %d'\n", header.compression_code);
1629 printf(" Number of channels: %d'\n", header.num_channels);
1630 printf(" Sample rate: %ld'\n", header.sample_rate);
1631 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1632 printf(" Block align: %d'\n", header.block_align);
1633 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1636 else if (strcmp(chunk_name, "data") == 0)
1638 snd_info->data_len = chunk_size;
1639 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1641 /* read sound data */
1642 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1645 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1647 free(snd_info->data_ptr);
1652 /* check for odd number of sample bytes (data chunk is word aligned) */
1653 if ((chunk_size % 2) == 1)
1654 ReadUnusedBytesFromFile(file, 1);
1656 else /* unknown chunk -- ignore */
1657 ReadUnusedBytesFromFile(file, chunk_size);
1662 if (snd_info->data_ptr == NULL)
1664 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1669 if (header.bits_per_sample == 8)
1670 snd_info->format = AUDIO_FORMAT_U8;
1671 else /* header.bits_per_sample == 16 */
1673 snd_info->format = AUDIO_FORMAT_S16;
1674 snd_info->data_len /= 2; /* correct number of samples */
1677 #endif /* AUDIO_UNIX_NATIVE */
1679 snd_info->type = SND_TYPE_WAV;
1680 snd_info->source_filename = getStringCopy(filename);
1685 static void deleteSoundEntry(SoundInfo **snd_info)
1689 char *filename = (*snd_info)->source_filename;
1692 printf("[decrementing reference counter of sound '%s']\n", filename);
1695 if (--(*snd_info)->num_references <= 0)
1698 printf("[deleting sound '%s']\n", filename);
1702 FreeSound(*snd_info);
1704 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1711 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1715 /* check if the old and the new sound file are the same */
1716 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1718 /* The old and new sound are the same (have the same filename and path).
1719 This usually means that this sound does not exist in this sound set
1720 and a fallback to the existing sound is done. */
1723 printf("[sound '%s' already exists (same list entry)]\n", filename);
1729 /* delete existing sound file entry */
1730 deleteSoundEntry(snd_info);
1732 /* check if the new sound file already exists in the list of sounds */
1733 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1736 printf("[sound '%s' already exists (other list entry)]\n", filename);
1739 *snd_info = (SoundInfo *)node->content;
1740 (*snd_info)->num_references++;
1742 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1744 (*snd_info)->num_references = 1;
1745 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1749 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1751 char *filename = getCustomSoundFilename(basename);
1754 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1757 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1759 deleteSoundEntry(snd_info);
1763 if (filename == NULL)
1765 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1769 replaceSoundEntry(snd_info, filename);
1772 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1775 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1777 sound_effect = sounds_list;
1778 num_sounds = num_list_entries;
1781 void LoadSoundToList(char *basename, int list_pos)
1783 if (Sound == NULL || list_pos >= num_sounds)
1787 printf("loading sound '%s' ... [%d]\n",
1788 basename, getNumNodes(SoundFileList));
1791 LoadCustomSound(&Sound[list_pos], basename);
1794 printf("loading sound '%s' done [%d]\n",
1795 basename, getNumNodes(SoundFileList));
1799 static MusicInfo *Load_MOD(char *filename)
1801 #if defined(TARGET_SDL)
1802 MusicInfo *mod_info;
1804 if (!audio.sound_available)
1807 mod_info = checked_calloc(sizeof(MusicInfo));
1809 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1811 Error(ERR_WARN, "cannot read music file '%s'", filename);
1816 mod_info->type = MUS_TYPE_MOD;
1817 mod_info->source_filename = getStringCopy(filename);
1825 void LoadCustomMusic(void)
1827 static boolean draw_init_text = TRUE; /* only draw at startup */
1828 char *music_directory = getCustomMusicDirectory();
1830 struct dirent *dir_entry;
1832 if (!audio.sound_available)
1835 if ((dir = opendir(music_directory)) == NULL)
1837 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1838 audio.music_available = FALSE;
1843 DrawInitText("Loading music:", 120, FC_GREEN);
1845 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1847 char *basename = dir_entry->d_name;
1848 char *filename = getPath2(music_directory, basename);
1849 MusicInfo *mus_info = NULL;
1852 DrawInitText(basename, 150, FC_YELLOW);
1854 if (FileIsSound(basename))
1855 mus_info = Load_WAV(filename);
1856 else if (FileIsMusic(basename))
1857 mus_info = Load_MOD(filename);
1864 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1865 Music[num_music -1] = mus_info;
1871 draw_init_text = FALSE;
1874 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1878 void PlayMusic(int nr)
1880 if (!audio.music_available)
1886 void PlaySound(int nr)
1888 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1891 void PlaySoundStereo(int nr, int stereo_position)
1893 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1896 void PlaySoundLoop(int nr)
1898 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1901 void PlaySoundMusic(int nr)
1903 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1906 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1908 SoundControl snd_ctrl;
1910 if (!audio.sound_available ||
1911 !audio.sound_enabled ||
1912 audio.sound_deactivated)
1915 if (volume < SOUND_MIN_VOLUME)
1916 volume = SOUND_MIN_VOLUME;
1917 else if (volume > SOUND_MAX_VOLUME)
1918 volume = SOUND_MAX_VOLUME;
1920 if (stereo_position < SOUND_MAX_LEFT)
1921 stereo_position = SOUND_MAX_LEFT;
1922 else if (stereo_position > SOUND_MAX_RIGHT)
1923 stereo_position = SOUND_MAX_RIGHT;
1925 snd_ctrl.active = TRUE;
1927 snd_ctrl.volume = volume;
1928 snd_ctrl.stereo_position = stereo_position;
1929 snd_ctrl.state = state;
1931 HandleSoundRequest(snd_ctrl);
1934 void FadeMusic(void)
1936 if (!audio.music_available)
1939 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1942 void FadeSound(int nr)
1944 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1950 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1953 void StopMusic(void)
1955 if (!audio.music_available)
1958 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1961 void StopSound(int nr)
1963 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1969 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1972 void StopSoundExt(int nr, int state)
1974 SoundControl snd_ctrl;
1976 if (!audio.sound_available)
1979 snd_ctrl.active = FALSE;
1981 snd_ctrl.state = state;
1983 HandleSoundRequest(snd_ctrl);
1986 ListNode *newListNode()
1988 return checked_calloc(sizeof(ListNode));
1991 void addNodeToList(ListNode **node_first, char *key, void *content)
1993 ListNode *node_new = newListNode();
1996 printf("LIST: adding node with key '%s'\n", key);
1999 node_new->key = getStringCopy(key);
2000 node_new->content = content;
2001 node_new->next = *node_first;
2002 *node_first = node_new;
2005 void deleteNodeFromList(ListNode **node_first, char *key,
2006 void (*destructor_function)(void *))
2008 if (node_first == NULL || *node_first == NULL)
2012 printf("[CHECKING LIST KEY '%s' == '%s']\n",
2013 (*node_first)->key, key);
2016 if (strcmp((*node_first)->key, key) == 0)
2019 printf("[DELETING LIST ENTRY]\n");
2022 free((*node_first)->key);
2023 if (destructor_function)
2024 destructor_function((*node_first)->content);
2025 *node_first = (*node_first)->next;
2028 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
2031 ListNode *getNodeFromKey(ListNode *node_first, char *key)
2033 if (node_first == NULL)
2036 if (strcmp(node_first->key, key) == 0)
2039 return getNodeFromKey(node_first->next, key);
2042 int getNumNodes(ListNode *node_first)
2044 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
2047 void dumpList(ListNode *node_first)
2049 ListNode *node = node_first;
2053 printf("['%s' (%d)]\n", node->key,
2054 ((SoundInfo *)node->content)->num_references);
2058 printf("[%d nodes]\n", getNumNodes(node_first));
2061 static void LoadSoundsInfo()
2063 char *filename = getCustomSoundConfigFilename();
2064 struct SetupFileList *setup_file_list;
2068 printf("GOT CUSTOM SOUND CONFIG FILE '%s'\n", filename);
2071 /* always start with reliable default values */
2072 for (i=0; i<num_sounds; i++)
2073 sound_effect[i].filename = NULL;
2075 if (filename == NULL)
2078 if ((setup_file_list = loadSetupFileList(filename)))
2080 for (i=0; i<num_sounds; i++)
2081 sound_effect[i].filename =
2082 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2084 freeSetupFileList(setup_file_list);
2087 for (i=0; i<num_sounds; i++)
2089 printf("'%s' ", sound_effect[i].text);
2090 if (sound_effect[i].filename)
2091 printf("-> '%s'\n", sound_effect[i].filename);
2093 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2099 static void ReloadCustomSounds()
2101 static boolean draw_init_text = TRUE; /* only draw at startup */
2105 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
2111 DrawInitText("Loading sounds:", 120, FC_GREEN);
2114 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2117 for(i=0; i<num_sounds; i++)
2120 DrawInitText(sound_effect[i].text, 150, FC_YELLOW);
2122 if (sound_effect[i].filename)
2123 LoadSoundToList(sound_effect[i].filename, i);
2125 LoadSoundToList(sound_effect[i].default_filename, i);
2128 draw_init_text = FALSE;
2131 printf("list size == %d\n", getNumNodes(SoundFileList));
2135 dumpList(SoundFileList);
2139 static void ReloadCustomMusic()
2142 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
2150 void InitReloadSounds(char *set_name)
2152 if (!audio.sound_available)
2155 #if defined(AUDIO_UNIX_NATIVE)
2156 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
2158 ReloadCustomSounds();
2162 void InitReloadMusic(char *set_name)
2164 if (!audio.music_available)
2167 #if defined(AUDIO_UNIX_NATIVE)
2168 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
2170 ReloadCustomMusic();
2174 void FreeSound(void *ptr)
2176 SoundInfo *sound = (SoundInfo *)ptr;
2181 if (sound->data_ptr)
2183 #if defined(TARGET_SDL)
2184 Mix_FreeChunk(sound->data_ptr);
2185 #elif defined(TARGET_ALLEGRO)
2186 destroy_sample(sound->data_ptr);
2187 #else /* AUDIO_UNIX_NATIVE */
2188 free(sound->data_ptr);
2192 if (sound->source_filename)
2193 free(sound->source_filename);
2198 void FreeMusic(MusicInfo *music)
2203 if (music->data_ptr)
2205 #if defined(TARGET_SDL)
2206 if (music->type == MUS_TYPE_MOD)
2207 Mix_FreeMusic(music->data_ptr);
2209 Mix_FreeChunk(music->data_ptr);
2210 #elif defined(TARGET_ALLEGRO)
2211 destroy_sample(music->data_ptr);
2212 #else /* AUDIO_UNIX_NATIVE */
2213 free(music->data_ptr);
2220 void FreeAllSounds()
2228 printf("%s: FREEING SOUNDS ...\n",
2229 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2232 for(i=0; i<num_sounds; i++)
2233 deleteSoundEntry(&Sound[i]);
2235 FreeSound(Sound[i]);
2239 printf("%s: FREEING SOUNDS -- DONE\n",
2240 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2256 for(i=0; i<num_music; i++)
2257 FreeMusic(Music[i]);
2265 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2266 /* ========================================================================= */