1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include <sys/types.h>
25 #if defined(PLATFORM_LINUX)
26 #include <sys/ioctl.h>
27 #include <linux/soundcard.h>
28 #elif defined(PLATFORM_FREEBSD)
29 #include <machine/soundcard.h>
30 #elif defined(PLATFORM_NETBSD)
31 #include <sys/ioctl.h>
32 #include <sys/audioio.h>
33 #elif defined(PLATFORM_HPUX)
34 #include <sys/audio.h>
44 /* expiration time (in milliseconds) for sound loops */
45 #define SOUND_LOOP_EXPIRATION_TIME 200
47 /* one second fading interval == 1000 ticks (milliseconds) */
48 #define SOUND_FADING_INTERVAL 1000
50 #if defined(AUDIO_STREAMING_DSP)
51 #define SOUND_FADING_VOLUME_STEP (SOUND_MAX_VOLUME / 40)
52 #define SOUND_FADING_VOLUME_THRESHOLD (SOUND_FADING_VOLUME_STEP * 2)
55 #if !defined(PLATFORM_HPUX)
56 #define SND_BLOCKSIZE 4096
58 #define SND_BLOCKSIZE 32768
61 #define SND_TYPE_NONE 0
62 #define SND_TYPE_WAV 1
64 #define MUS_TYPE_NONE 0
65 #define MUS_TYPE_WAV 1
66 #define MUS_TYPE_MOD 2
68 #define DEVICENAME_DSP "/dev/dsp"
69 #define DEVICENAME_SOUND_DSP "/dev/sound/dsp"
70 #define DEVICENAME_AUDIO "/dev/audio"
71 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
73 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
74 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
76 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
77 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
80 struct SoundHeader_SUN
83 unsigned long hdr_size;
84 unsigned long data_size;
85 unsigned long encoding;
86 unsigned long sample_rate;
87 unsigned long channels;
90 struct SoundHeader_8SVX
93 unsigned long chunk_size;
98 #if defined(AUDIO_UNIX_NATIVE)
99 struct SoundHeader_WAV
101 unsigned short compression_code;
102 unsigned short num_channels;
103 unsigned long sample_rate;
104 unsigned long bytes_per_second;
105 unsigned short block_align;
106 unsigned short bits_per_sample;
110 struct AudioFormatInfo
112 boolean stereo; /* availability of stereo sound */
113 int format; /* size and endianess of sample data */
114 int sample_rate; /* sample frequency */
115 int fragment_size; /* audio device fragment size in bytes */
120 char *source_filename;
125 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
126 long data_len; /* number of samples, NOT number of bytes */
128 typedef struct SampleInfo SoundInfo;
129 typedef struct SampleInfo MusicInfo;
141 unsigned long playing_starttime;
142 unsigned long playing_pos;
146 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
147 long data_len; /* number of samples, NOT number of bytes */
149 #if defined(TARGET_ALLEGRO)
153 typedef struct SoundControl SoundControl;
159 struct ListNode *next;
161 typedef struct ListNode ListNode;
163 static ListNode *newListNode(void);
164 static void addNodeToList(ListNode **, char *, void *);
165 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
166 static ListNode *getNodeFromKey(ListNode *, char *);
167 static int getNumNodes(ListNode *);
170 static struct SoundEffectInfo *sound_effect;
171 static ListNode *SoundFileList = NULL;
172 static SoundInfo **Sound = NULL;
173 static MusicInfo **Music = NULL;
174 static int num_sounds = 0, num_music = 0;
175 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
178 /* ========================================================================= */
179 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
181 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
182 static int mixer_active_channels = 0;
184 #if defined(AUDIO_UNIX_NATIVE)
185 static struct AudioFormatInfo afmt;
187 static void Mixer_Main(void);
188 #if !defined(AUDIO_STREAMING_DSP)
189 static unsigned char linear_to_ulaw(int);
190 static int ulaw_to_linear(unsigned char);
194 static void ReloadCustomSounds();
195 static void ReloadCustomMusic();
196 static void FreeSound(void *);
199 /* ------------------------------------------------------------------------- */
200 /* functions for native (non-SDL) Unix audio/mixer support */
201 /* ------------------------------------------------------------------------- */
203 #if defined(AUDIO_UNIX_NATIVE)
205 static int OpenAudioDevice(char *audio_device_name)
209 /* check if desired audio device is accessible */
210 if (access(audio_device_name, W_OK) != 0)
213 /* try to open audio device in non-blocking mode */
214 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
215 return audio_device_fd;
217 /* re-open audio device in blocking mode */
218 close(audio_device_fd);
219 audio_device_fd = open(audio_device_name, O_WRONLY);
221 return audio_device_fd;
224 static void CloseAudioDevice(int *audio_device_fd)
226 if (*audio_device_fd == 0)
229 close(*audio_device_fd);
230 *audio_device_fd = -1;
233 static boolean TestAudioDevices(void)
235 static char *audio_device_name[] =
238 DEVICENAME_SOUND_DSP,
241 int audio_device_fd = -1;
244 /* look for available audio devices, starting with preferred ones */
245 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
246 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
249 if (audio_device_fd < 0)
251 Error(ERR_WARN, "cannot open audio device -- no sound");
255 close(audio_device_fd);
257 audio.device_name = audio_device_name[i];
262 static boolean ForkAudioProcess(void)
264 if (pipe(audio.mixer_pipe) < 0)
266 Error(ERR_WARN, "cannot create pipe -- no sounds");
270 if ((audio.mixer_pid = fork()) < 0)
272 Error(ERR_WARN, "cannot create sound server process -- no sounds");
276 if (IS_CHILD_PROCESS(audio.mixer_pid))
277 Mixer_Main(); /* this function never returns */
279 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
284 void UnixOpenAudio(void)
286 if (!TestAudioDevices())
289 audio.sound_available = TRUE;
290 audio.sound_enabled = TRUE;
292 #if defined(AUDIO_STREAMING_DSP)
293 audio.music_available = TRUE;
294 audio.loops_available = TRUE;
297 audio.num_channels = NUM_MIXER_CHANNELS;
298 audio.music_channel = MUSIC_CHANNEL;
299 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
302 void UnixCloseAudio(void)
305 close(audio.device_fd);
307 if (IS_PARENT_PROCESS(audio.mixer_pid))
308 kill(audio.mixer_pid, SIGTERM);
312 /* ------------------------------------------------------------------------- */
313 /* functions for platform specific audio device initialization */
314 /* ------------------------------------------------------------------------- */
316 #if defined(AUDIO_LINUX_IOCTL)
317 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
319 /* "ioctl()" expects pointer to 'int' value for stereo flag
320 (boolean is defined as 'char', which will not work here) */
321 unsigned int fragment_spec = 0;
322 int fragment_size_query;
331 /* supported audio format in preferred order */
332 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
333 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
334 { AFMT_U8, AUDIO_FORMAT_U8 },
339 /* determine logarithm (log2) of the fragment size */
340 while ((1 << fragment_spec) < afmt->fragment_size)
343 /* use two fragments (play one fragment, prepare the other);
344 one fragment would result in interrupted audio output, more
345 than two fragments would raise audio output latency to much */
346 fragment_spec |= 0x00020000;
348 /* Example for fragment specification:
349 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
350 - (with stereo the effective buffer size will shrink to 256)
351 => fragment_size = 0x00020009 */
353 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
354 Error(ERR_EXIT_SOUND_SERVER,
355 "cannot set fragment size of audio device -- no sounds");
359 while (formats[i].format_result != -1)
361 unsigned int audio_format = formats[i].format_ioctl;
362 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
364 afmt->format = formats[i].format_result;
369 if (afmt->format == 0) /* no supported audio format found */
370 Error(ERR_EXIT_SOUND_SERVER,
371 "cannot set audio format of audio device -- no sounds");
373 /* try if we can use stereo sound */
375 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
376 afmt->stereo = FALSE;
378 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
379 Error(ERR_EXIT_SOUND_SERVER,
380 "cannot set sample rate of audio device -- no sounds");
382 /* get the real fragmentation size; this should return 512 */
383 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
384 Error(ERR_EXIT_SOUND_SERVER,
385 "cannot get fragment size of audio device -- no sounds");
386 if (fragment_size_query != afmt->fragment_size)
387 Error(ERR_EXIT_SOUND_SERVER,
388 "cannot set fragment size of audio device -- no sounds");
390 #endif /* AUDIO_LINUX_IOCTL */
392 #if defined(PLATFORM_NETBSD)
393 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
396 boolean stereo = TRUE;
398 AUDIO_INITINFO(&a_info);
399 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
400 a_info.play.precision = 8;
401 a_info.play.channels = 2;
402 a_info.play.sample_rate = afmt->sample_rate;
403 a_info.blocksize = afmt->fragment_size;
405 afmt->format = AUDIO_FORMAT_U8;
408 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
410 /* try to disable stereo */
411 a_info.play.channels = 1;
413 afmt->stereo = FALSE;
415 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
416 Error(ERR_EXIT_SOUND_SERVER,
417 "cannot set sample rate of audio device -- no sounds");
420 #endif /* PLATFORM_NETBSD */
422 #if defined(PLATFORM_HPUX)
423 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
425 struct audio_describe ainfo;
428 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
430 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
432 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
433 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
435 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
436 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
438 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
439 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
441 afmt->format = AUDIO_FORMAT_U8;
442 afmt->stereo = FALSE;
443 afmt->sample_rate = 8000;
447 #endif /* PLATFORM_HPUX */
449 static void InitAudioDevice(struct AudioFormatInfo *afmt)
452 afmt->format = AUDIO_FORMAT_UNKNOWN;
453 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
454 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
456 #if defined(AUDIO_LINUX_IOCTL)
457 InitAudioDevice_Linux(afmt);
458 #elif defined(PLATFORM_NETBSD)
459 InitAudioDevice_NetBSD(afmt);
460 #elif defined(PLATFORM_HPUX)
461 InitAudioDevice_HPUX(afmt);
463 /* generic /dev/audio stuff might be placed here */
468 /* ------------------------------------------------------------------------- */
469 /* functions for communication between main process and sound mixer process */
470 /* ------------------------------------------------------------------------- */
472 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
474 if (IS_CHILD_PROCESS(audio.mixer_pid))
477 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
479 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
480 audio.sound_available = audio.sound_enabled = FALSE;
485 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
487 if (IS_PARENT_PROCESS(audio.mixer_pid))
490 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
491 != sizeof(SoundControl))
492 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
495 static void WriteReloadInfoToPipe(char *set_name, int type)
497 SoundControl snd_ctrl;
498 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
499 artwork.mus_current);
500 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
501 unsigned long str_size2 = strlen(ti->basepath) + 1;
502 unsigned long str_size3 = strlen(ti->fullpath) + 1;
503 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
504 setup.override_level_sounds :
505 setup.override_level_music);
507 if (IS_CHILD_PROCESS(audio.mixer_pid))
510 if (leveldir_current == NULL) /* should never happen */
511 Error(ERR_EXIT, "leveldir_current == NULL");
513 snd_ctrl.active = FALSE;
514 snd_ctrl.state = type;
515 snd_ctrl.data_len = strlen(set_name) + 1;
517 if (write(audio.mixer_pipe[1], &snd_ctrl,
518 sizeof(snd_ctrl)) < 0 ||
519 write(audio.mixer_pipe[1], set_name,
520 snd_ctrl.data_len) < 0 ||
521 write(audio.mixer_pipe[1], &override_level_artwork,
522 sizeof(boolean)) < 0 ||
523 write(audio.mixer_pipe[1], leveldir_current,
524 sizeof(TreeInfo)) < 0 ||
525 write(audio.mixer_pipe[1], ti,
526 sizeof(TreeInfo)) < 0 ||
527 write(audio.mixer_pipe[1], &str_size1,
528 sizeof(unsigned long)) < 0 ||
529 write(audio.mixer_pipe[1], &str_size2,
530 sizeof(unsigned long)) < 0 ||
531 write(audio.mixer_pipe[1], &str_size3,
532 sizeof(unsigned long)) < 0 ||
533 write(audio.mixer_pipe[1], leveldir_current->fullpath,
535 write(audio.mixer_pipe[1], ti->basepath,
537 write(audio.mixer_pipe[1], ti->fullpath,
540 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
541 audio.sound_available = audio.sound_enabled = FALSE;
546 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
548 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
549 &artwork.snd_current : &artwork.mus_current);
550 TreeInfo *ti = *ti_ptr;
551 unsigned long str_size1, str_size2, str_size3;
552 static char *set_name = NULL;
553 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
554 &setup.override_level_sounds :
555 &setup.override_level_music);
560 set_name = checked_malloc(snd_ctrl->data_len);
562 if (leveldir_current == NULL)
563 leveldir_current = checked_calloc(sizeof(TreeInfo));
565 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
566 if (leveldir_current->fullpath != NULL)
567 free(leveldir_current->fullpath);
568 if (ti->basepath != NULL)
570 if (ti->fullpath != NULL)
573 if (read(audio.mixer_pipe[0], set_name,
574 snd_ctrl->data_len) != snd_ctrl->data_len ||
575 read(audio.mixer_pipe[0], override_level_artwork,
576 sizeof(boolean)) != sizeof(boolean) ||
577 read(audio.mixer_pipe[0], leveldir_current,
578 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
579 read(audio.mixer_pipe[0], ti,
580 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
581 read(audio.mixer_pipe[0], &str_size1,
582 sizeof(unsigned long)) != sizeof(unsigned long) ||
583 read(audio.mixer_pipe[0], &str_size2,
584 sizeof(unsigned long)) != sizeof(unsigned long) ||
585 read(audio.mixer_pipe[0], &str_size3,
586 sizeof(unsigned long)) != sizeof(unsigned long))
587 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
589 leveldir_current->fullpath = checked_calloc(str_size1);
590 ti->basepath = checked_calloc(str_size2);
591 ti->fullpath = checked_calloc(str_size3);
593 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
594 str_size1) != str_size1 ||
595 read(audio.mixer_pipe[0], ti->basepath,
596 str_size2) != str_size2 ||
597 read(audio.mixer_pipe[0], ti->fullpath,
598 str_size3) != str_size3)
599 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
601 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
602 artwork.sounds_set_current_name = set_name;
604 artwork.music_set_current_name = set_name;
607 #endif /* AUDIO_UNIX_NATIVE */
610 /* ------------------------------------------------------------------------- */
611 /* mixer functions */
612 /* ------------------------------------------------------------------------- */
614 void Mixer_InitChannels()
618 for(i=0; i<audio.num_channels; i++)
619 mixer[i].active = FALSE;
620 mixer_active_channels = 0;
623 static void Mixer_ResetChannelExpiration(int channel)
625 mixer[channel].playing_starttime = Counter();
627 #if defined(TARGET_SDL)
628 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
629 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
633 static boolean Mixer_ChannelExpired(int channel)
635 if (!mixer[channel].active)
638 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
639 DelayReached(&mixer[channel].playing_starttime,
640 SOUND_LOOP_EXPIRATION_TIME))
643 #if defined(TARGET_SDL)
645 if (!Mix_Playing(channel))
648 #elif defined(TARGET_ALLEGRO)
650 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
651 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
653 /* sound sample has completed playing or was completely faded out */
654 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
657 #endif /* TARGET_ALLEGRO */
662 static boolean Mixer_AllocateChannel(int channel)
664 #if defined(TARGET_ALLEGRO)
665 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
666 if (mixer[channel].voice < 0)
673 static void Mixer_SetChannelProperties(int channel)
675 #if defined(TARGET_SDL)
676 Mix_Volume(channel, mixer[channel].volume);
677 Mix_SetPanning(channel,
678 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
679 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
680 #elif defined(TARGET_ALLEGRO)
681 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
682 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
686 static void Mixer_StartChannel(int channel)
688 #if defined(TARGET_SDL)
689 Mix_PlayChannel(channel, mixer[channel].data_ptr,
690 IS_LOOP(mixer[channel]) ? -1 : 0);
691 #elif defined(TARGET_ALLEGRO)
692 if (IS_LOOP(mixer[channel]))
693 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
695 voice_start(mixer[channel].voice);
699 static void Mixer_PlayChannel(int channel)
701 /* start with inactive channel in case something goes wrong */
702 mixer[channel].active = FALSE;
704 if (mixer[channel].type != MUS_TYPE_WAV)
707 if (!Mixer_AllocateChannel(channel))
710 Mixer_SetChannelProperties(channel);
711 Mixer_StartChannel(channel);
713 Mixer_ResetChannelExpiration(channel);
715 mixer[channel].playing_pos = 0;
716 mixer[channel].active = TRUE;
717 mixer_active_channels++;
720 static void Mixer_PlayMusicChannel()
722 Mixer_PlayChannel(audio.music_channel);
724 #if defined(TARGET_SDL)
725 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
727 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
728 this looks like a bug in the SDL_mixer library */
729 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
730 Mix_VolumeMusic(SOUND_MAX_VOLUME);
735 static void Mixer_StopChannel(int channel)
737 if (!mixer[channel].active)
740 #if defined(TARGET_SDL)
741 Mix_HaltChannel(channel);
742 #elif defined(TARGET_ALLEGRO)
743 voice_set_volume(mixer[channel].voice, 0);
744 deallocate_voice(mixer[channel].voice);
747 mixer[channel].active = FALSE;
748 mixer_active_channels--;
751 static void Mixer_StopMusicChannel()
753 Mixer_StopChannel(audio.music_channel);
755 #if defined(TARGET_SDL)
760 static void Mixer_FadeChannel(int channel)
762 if (!mixer[channel].active)
765 mixer[channel].state |= SND_CTRL_FADE;
767 #if defined(TARGET_SDL)
768 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
769 #elif defined(TARGET_ALLEGRO)
770 if (voice_check(mixer[channel].voice))
771 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
775 static void Mixer_FadeMusicChannel()
777 Mixer_FadeChannel(audio.music_channel);
779 #if defined(TARGET_SDL)
780 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
784 static void Mixer_UnFadeChannel(int channel)
786 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
789 mixer[channel].state &= ~SND_CTRL_FADE;
790 mixer[channel].volume = SOUND_MAX_VOLUME;
792 #if defined(TARGET_SDL)
793 Mix_ExpireChannel(channel, -1);
794 Mix_Volume(channel, mixer[channel].volume);
795 #elif defined(TARGET_ALLEGRO)
796 voice_stop_volumeramp(mixer[channel].voice);
797 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
798 mixer[channel].volume);
802 static void Mixer_InsertSound(SoundControl snd_ctrl)
808 printf("NEW SOUND %d ARRIVED [%d] [%d ACTIVE CHANNELS]\n",
809 snd_ctrl.nr, num_sounds, mixer_active_channels);
812 if (IS_MUSIC(snd_ctrl))
817 snd_ctrl.nr = snd_ctrl.nr % num_music;
819 else if (snd_ctrl.nr >= num_sounds)
822 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
823 if (snd_info == NULL)
826 /* copy sound sample and format information */
827 snd_ctrl.type = snd_info->type;
828 snd_ctrl.format = snd_info->format;
829 snd_ctrl.data_ptr = snd_info->data_ptr;
830 snd_ctrl.data_len = snd_info->data_len;
832 /* play music samples on a dedicated music channel */
833 if (IS_MUSIC(snd_ctrl))
835 Mixer_StopMusicChannel();
837 mixer[audio.music_channel] = snd_ctrl;
838 Mixer_PlayMusicChannel();
843 /* check if (and how often) this sound sample is already playing */
844 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
845 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
849 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
852 /* reset expiration delay for already playing loop sounds */
853 if (k > 0 && IS_LOOP(snd_ctrl))
855 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
857 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
860 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
863 if (IS_FADING(mixer[i]))
864 Mixer_UnFadeChannel(i);
866 /* restore settings like volume and stereo position */
867 mixer[i].volume = snd_ctrl.volume;
868 mixer[i].stereo_position = snd_ctrl.stereo_position;
870 Mixer_SetChannelProperties(i);
871 Mixer_ResetChannelExpiration(i);
874 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
875 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
884 printf("PLAYING NEW SOUND %d\n", snd_ctrl.nr);
887 /* don't play sound more than n times simultaneously (with n == 2 for now) */
890 unsigned long playing_current = Counter();
891 int longest = 0, longest_nr = audio.first_sound_channel;
893 /* look for oldest equal sound */
894 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
896 int playing_time = playing_current - mixer[i].playing_starttime;
899 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
902 actual = 1000 * playing_time / mixer[i].data_len;
904 if (actual >= longest)
911 Mixer_StopChannel(longest_nr);
914 /* If all (non-music) channels are active, stop the channel that has
915 played its sound sample most completely (in percent of the sample
916 length). As we cannot currently get the actual playing position
917 of the channel's sound sample when compiling with the SDL mixer
918 library, we use the current playing time (in milliseconds) instead. */
921 /* channel allocation sanity check -- should not be needed */
922 if (mixer_active_channels ==
923 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
925 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
927 if (!mixer[i].active)
929 Error(ERR_RETURN, "Mixer_InsertSound: Channel %d inactive", i);
930 Error(ERR_RETURN, "Mixer_InsertSound: This should never happen!");
932 mixer_active_channels--;
938 if (mixer_active_channels ==
939 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
941 unsigned long playing_current = Counter();
942 int longest = 0, longest_nr = audio.first_sound_channel;
944 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
946 Error(ERR_RETURN, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
947 i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
950 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
952 int playing_time = playing_current - mixer[i].playing_starttime;
953 int actual = 1000 * playing_time / mixer[i].data_len;
955 if (!IS_LOOP(mixer[i]) && actual > longest)
962 Mixer_StopChannel(longest_nr);
965 /* add the new sound to the mixer */
966 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
969 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
972 if (!mixer[i].active)
975 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
978 #if defined(AUDIO_UNIX_NATIVE)
979 if (snd_info->data_len == 0)
981 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
986 Mixer_PlayChannel(i);
993 static void HandleSoundRequest(SoundControl snd_ctrl)
997 #if defined(AUDIO_UNIX_NATIVE)
998 if (IS_PARENT_PROCESS(audio.mixer_pid))
1000 SendSoundControlToMixerProcess(&snd_ctrl);
1005 /* deactivate channels that have expired since the last request */
1006 for (i=0; i<audio.num_channels; i++)
1007 if (mixer[i].active && Mixer_ChannelExpired(i))
1008 Mixer_StopChannel(i);
1010 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
1012 Mixer_StopMusicChannel();
1013 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1014 Mixer_StopChannel(i);
1016 #if defined(AUDIO_UNIX_NATIVE)
1017 CloseAudioDevice(&audio.device_fd);
1018 ReadReloadInfoFromPipe(&snd_ctrl);
1021 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1022 ReloadCustomSounds();
1024 ReloadCustomMusic();
1026 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1028 if (IS_MUSIC(snd_ctrl))
1030 Mixer_FadeMusicChannel();
1034 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1035 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1036 Mixer_FadeChannel(i);
1038 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1040 if (IS_MUSIC(snd_ctrl))
1042 Mixer_StopMusicChannel();
1046 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1047 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1048 Mixer_StopChannel(i);
1050 #if defined(AUDIO_UNIX_NATIVE)
1051 if (!mixer_active_channels)
1052 CloseAudioDevice(&audio.device_fd);
1055 else if (snd_ctrl.active) /* add new sound to mixer */
1057 Mixer_InsertSound(snd_ctrl);
1061 void StartMixer(void)
1066 SDL_version compile_version;
1067 const SDL_version *link_version;
1068 MIX_VERSION(&compile_version);
1069 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1070 compile_version.major,
1071 compile_version.minor,
1072 compile_version.patch);
1073 link_version = Mix_Linked_Version();
1074 printf("running with SDL_mixer version: %d.%d.%d\n",
1075 link_version->major,
1076 link_version->minor,
1077 link_version->patch);
1080 if (!audio.sound_available)
1083 /* initialize stereo position conversion information */
1084 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1086 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1088 #if defined(AUDIO_UNIX_NATIVE)
1089 if (!ForkAudioProcess())
1090 audio.sound_available = FALSE;
1094 #if defined(AUDIO_UNIX_NATIVE)
1096 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1097 int sample_pos, int sample_size,
1100 void *sample_ptr = snd_ctrl->data_ptr;
1103 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1104 for (i=0; i<sample_size; i++)
1106 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1107 else /* AUDIO_FORMAT_S16 */
1108 for (i=0; i<sample_size; i++)
1110 ((short *)sample_ptr)[sample_pos + i];
1113 #if defined(AUDIO_STREAMING_DSP)
1114 static void Mixer_Main_DSP()
1116 static short premix_first_buffer[SND_BLOCKSIZE];
1117 static short premix_left_buffer[SND_BLOCKSIZE];
1118 static short premix_right_buffer[SND_BLOCKSIZE];
1119 static long premix_last_buffer[SND_BLOCKSIZE];
1120 static byte playing_buffer[SND_BLOCKSIZE];
1124 int max_sample_size;
1127 if (!mixer_active_channels)
1130 if (audio.device_fd < 0)
1132 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1135 InitAudioDevice(&afmt);
1138 stereo = afmt.stereo;
1139 fragment_size = afmt.fragment_size;
1140 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1141 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1143 /* first clear the last premixing buffer */
1144 memset(premix_last_buffer, 0,
1145 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1147 for(i=0; i<audio.num_channels; i++)
1154 if (!mixer[i].active)
1157 if (Mixer_ChannelExpired(i))
1159 Mixer_StopChannel(i);
1163 /* pointer, lenght and actual playing position of sound sample */
1164 sample_ptr = mixer[i].data_ptr;
1165 sample_len = mixer[i].data_len;
1166 sample_pos = mixer[i].playing_pos;
1167 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1168 mixer[i].playing_pos += sample_size;
1170 /* copy original sample to first mixing buffer */
1171 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1172 premix_first_buffer);
1174 /* are we about to restart a looping sound? */
1175 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1177 while (sample_size < max_sample_size)
1179 int restarted_sample_size =
1180 MIN(max_sample_size - sample_size, sample_len);
1182 if (mixer[i].format == AUDIO_FORMAT_U8)
1183 for (j=0; j<restarted_sample_size; j++)
1184 premix_first_buffer[sample_size + j] =
1185 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1187 for (j=0; j<restarted_sample_size; j++)
1188 premix_first_buffer[sample_size + j] =
1189 ((short *)sample_ptr)[j];
1191 mixer[i].playing_pos = restarted_sample_size;
1192 sample_size += restarted_sample_size;
1196 /* decrease volume if sound is fading out */
1197 if (IS_FADING(mixer[i]) &&
1198 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1199 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1201 /* adjust volume of actual sound sample */
1202 if (mixer[i].volume != SOUND_MAX_VOLUME)
1203 for(j=0; j<sample_size; j++)
1204 premix_first_buffer[j] =
1205 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1207 /* fill the last mixing buffer with stereo or mono sound */
1210 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1211 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1213 for(j=0; j<sample_size; j++)
1215 premix_left_buffer[j] =
1216 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1217 premix_right_buffer[j] =
1218 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1220 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1221 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1226 for(j=0; j<sample_size; j++)
1227 premix_last_buffer[j] += premix_first_buffer[j];
1230 /* delete completed sound entries from the mixer */
1231 if (mixer[i].playing_pos >= mixer[i].data_len)
1233 if (IS_LOOP(mixer[i]))
1234 mixer[i].playing_pos = 0;
1236 Mixer_StopChannel(i);
1238 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1239 Mixer_StopChannel(i);
1242 /* prepare final playing buffer according to system audio format */
1243 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1245 /* cut off at 17 bit value */
1246 if (premix_last_buffer[i] < -65535)
1247 premix_last_buffer[i] = -65535;
1248 else if (premix_last_buffer[i] > 65535)
1249 premix_last_buffer[i] = 65535;
1251 /* shift to 16 bit value */
1252 premix_last_buffer[i] >>= 1;
1254 if (afmt.format & AUDIO_FORMAT_U8)
1256 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1258 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1260 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1261 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1263 else /* big endian */
1265 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1266 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1270 /* finally play the sound fragment */
1271 write(audio.device_fd, playing_buffer, fragment_size);
1273 if (!mixer_active_channels)
1274 CloseAudioDevice(&audio.device_fd);
1277 #else /* !AUDIO_STREAMING_DSP */
1279 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1281 static short premix_first_buffer[SND_BLOCKSIZE];
1282 static byte playing_buffer[SND_BLOCKSIZE];
1283 int max_sample_size = SND_BLOCKSIZE;
1292 /* pointer, lenght and actual playing position of sound sample */
1293 sample_ptr = mixer[i].data_ptr;
1294 sample_len = mixer[i].data_len;
1295 sample_pos = mixer[i].playing_pos;
1296 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1297 mixer[i].playing_pos += sample_size;
1299 /* copy original sample to first mixing buffer */
1300 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1301 premix_first_buffer);
1303 /* adjust volume of actual sound sample */
1304 if (mixer[i].volume != SOUND_MAX_VOLUME)
1305 for(j=0; j<sample_size; j++)
1306 premix_first_buffer[j] =
1307 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1309 /* might be needed for u-law /dev/audio */
1311 for(j=0; j<sample_size; j++)
1313 linear_to_ulaw(premix_first_buffer[j]);
1316 /* delete completed sound entries from the mixer */
1317 if (mixer[i].playing_pos >= mixer[i].data_len)
1318 Mixer_StopChannel(i);
1320 for(i=0; i<sample_size; i++)
1321 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1323 /* finally play the sound fragment */
1324 write(audio.device_fd, playing_buffer, sample_size);
1328 #endif /* !AUDIO_STREAMING_DSP */
1332 SoundControl snd_ctrl;
1335 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1337 Mixer_InitChannels();
1339 #if defined(PLATFORM_HPUX)
1340 InitAudioDevice(&afmt);
1343 FD_ZERO(&mixer_fdset);
1344 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1346 while(1) /* wait for sound playing commands from client */
1348 struct timeval delay = { 0, 0 };
1350 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1351 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1352 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1355 ReadSoundControlFromMainProcess(&snd_ctrl);
1357 HandleSoundRequest(snd_ctrl);
1359 #if defined(AUDIO_STREAMING_DSP)
1361 while (mixer_active_channels &&
1362 select(audio.mixer_pipe[0] + 1,
1363 &mixer_fdset, NULL, NULL, &delay) < 1)
1365 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1370 #else /* !AUDIO_STREAMING_DSP */
1372 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1373 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1376 InitAudioDevice(&afmt);
1381 while (mixer_active_channels &&
1382 select(audio.mixer_pipe[0] + 1,
1383 &mixer_fdset, NULL, NULL, &delay) < 1)
1385 int wait_percent = 90; /* wait 90% of the real playing time */
1388 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1390 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1394 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1397 CloseAudioDevice(&audio.device_fd);
1399 Mixer_InitChannels(); /* remove all sounds from mixer */
1401 #endif /* !AUDIO_STREAMING_DSP */
1404 #endif /* AUDIO_UNIX_NATIVE */
1407 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1409 /* these two are stolen from "sox"... :) */
1412 ** This routine converts from linear to ulaw.
1414 ** Craig Reese: IDA/Supercomputing Research Center
1415 ** Joe Campbell: Department of Defense
1416 ** 29 September 1989
1419 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1420 ** 2) "A New Digital Technique for Implementation of Any
1421 ** Continuous PCM Companding Law," Villeret, Michel,
1422 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1423 ** 1973, pg. 11.12-11.17
1424 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1425 ** for Analog-to_Digital Conversion Techniques,"
1428 ** Input: Signed 16 bit linear sample
1429 ** Output: 8 bit ulaw sample
1432 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1433 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1436 static unsigned char linear_to_ulaw(int sample)
1438 static int exp_lut[256] =
1440 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1441 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1442 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1443 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1444 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1445 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1446 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1447 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1448 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1449 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1450 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1451 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1452 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1453 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1454 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1455 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1458 int sign, exponent, mantissa;
1459 unsigned char ulawbyte;
1461 /* Get the sample into sign-magnitude. */
1462 sign = (sample >> 8) & 0x80; /* set aside the sign */
1464 sample = -sample; /* get magnitude */
1466 sample = CLIP; /* clip the magnitude */
1468 /* Convert from 16 bit linear to ulaw. */
1469 sample = sample + BIAS;
1470 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1471 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1472 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1475 ulawbyte = 0x02; /* optional CCITT trap */
1482 ** This routine converts from ulaw to 16 bit linear.
1484 ** Craig Reese: IDA/Supercomputing Research Center
1485 ** 29 September 1989
1488 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1489 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1490 ** for Analog-to_Digital Conversion Techniques,"
1493 ** Input: 8 bit ulaw sample
1494 ** Output: signed 16 bit linear sample
1497 static int ulaw_to_linear(unsigned char ulawbyte)
1499 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1500 int sign, exponent, mantissa, sample;
1502 ulawbyte = ~ ulawbyte;
1503 sign = ( ulawbyte & 0x80 );
1504 exponent = ( ulawbyte >> 4 ) & 0x07;
1505 mantissa = ulawbyte & 0x0F;
1506 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1512 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1515 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1516 /* ========================================================================= */
1517 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1519 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1520 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1522 static SoundInfo *Load_WAV(char *filename)
1524 SoundInfo *snd_info;
1525 #if defined(AUDIO_UNIX_NATIVE)
1526 struct SoundHeader_WAV header;
1528 byte sound_header_buffer[WAV_HEADER_SIZE];
1531 char chunk_name[CHUNK_ID_LEN + 1];
1536 if (!audio.sound_available)
1540 printf("loading WAV file '%s'\n", filename);
1543 snd_info = checked_calloc(sizeof(SoundInfo));
1545 #if defined(TARGET_SDL)
1547 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1549 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1554 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1556 #elif defined(TARGET_ALLEGRO)
1558 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1560 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1565 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1567 #else /* AUDIO_UNIX_NATIVE */
1569 if ((file = fopen(filename, MODE_READ)) == NULL)
1571 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1576 /* read chunk id "RIFF" */
1577 getFileChunkLE(file, chunk_name, &chunk_size);
1578 if (strcmp(chunk_name, "RIFF") != 0)
1580 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1586 /* read "RIFF" type id "WAVE" */
1587 getFileChunkLE(file, chunk_name, NULL);
1588 if (strcmp(chunk_name, "WAVE") != 0)
1590 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1596 while (getFileChunkLE(file, chunk_name, &chunk_size))
1598 if (strcmp(chunk_name, "fmt ") == 0)
1600 if (chunk_size < WAV_HEADER_SIZE)
1602 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1608 header.compression_code = getFile16BitLE(file);
1609 header.num_channels = getFile16BitLE(file);
1610 header.sample_rate = getFile32BitLE(file);
1611 header.bytes_per_second = getFile32BitLE(file);
1612 header.block_align = getFile16BitLE(file);
1613 header.bits_per_sample = getFile16BitLE(file);
1615 if (chunk_size > WAV_HEADER_SIZE)
1616 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1618 if (header.compression_code != 1)
1620 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1621 filename, header.compression_code);
1627 if (header.num_channels != 1)
1629 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1630 filename, header.num_channels);
1636 if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1638 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1639 filename, header.bits_per_sample);
1645 /* warn, but accept wrong sample rate (may be only slightly different) */
1646 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1647 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1648 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1651 printf("WAV file: '%s'\n", filename);
1652 printf(" Compression code: %d'\n", header.compression_code);
1653 printf(" Number of channels: %d'\n", header.num_channels);
1654 printf(" Sample rate: %ld'\n", header.sample_rate);
1655 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1656 printf(" Block align: %d'\n", header.block_align);
1657 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1660 else if (strcmp(chunk_name, "data") == 0)
1662 snd_info->data_len = chunk_size;
1663 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1665 /* read sound data */
1666 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1669 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1671 free(snd_info->data_ptr);
1676 /* check for odd number of sample bytes (data chunk is word aligned) */
1677 if ((chunk_size % 2) == 1)
1678 ReadUnusedBytesFromFile(file, 1);
1680 else /* unknown chunk -- ignore */
1681 ReadUnusedBytesFromFile(file, chunk_size);
1686 if (snd_info->data_ptr == NULL)
1688 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1693 if (header.bits_per_sample == 8)
1694 snd_info->format = AUDIO_FORMAT_U8;
1695 else /* header.bits_per_sample == 16 */
1697 snd_info->format = AUDIO_FORMAT_S16;
1698 snd_info->data_len /= 2; /* correct number of samples */
1701 #endif /* AUDIO_UNIX_NATIVE */
1703 snd_info->type = SND_TYPE_WAV;
1704 snd_info->source_filename = getStringCopy(filename);
1709 static void deleteSoundEntry(SoundInfo **snd_info)
1713 char *filename = (*snd_info)->source_filename;
1716 printf("[decrementing reference counter of sound '%s']\n", filename);
1719 if (--(*snd_info)->num_references <= 0)
1722 printf("[deleting sound '%s']\n", filename);
1726 FreeSound(*snd_info);
1728 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1735 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1739 /* check if the old and the new sound file are the same */
1740 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1742 /* The old and new sound are the same (have the same filename and path).
1743 This usually means that this sound does not exist in this sound set
1744 and a fallback to the existing sound is done. */
1747 printf("[sound '%s' already exists (same list entry)]\n", filename);
1753 /* delete existing sound file entry */
1754 deleteSoundEntry(snd_info);
1756 /* check if the new sound file already exists in the list of sounds */
1757 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1760 printf("[sound '%s' already exists (other list entry)]\n", filename);
1763 *snd_info = (SoundInfo *)node->content;
1764 (*snd_info)->num_references++;
1766 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1768 (*snd_info)->num_references = 1;
1769 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1773 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1775 char *filename = getCustomSoundFilename(basename);
1778 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1781 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1783 deleteSoundEntry(snd_info);
1787 if (filename == NULL)
1789 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1793 replaceSoundEntry(snd_info, filename);
1796 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1799 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1801 sound_effect = sounds_list;
1802 num_sounds = num_list_entries;
1805 void LoadSoundToList(char *basename, int list_pos)
1807 if (Sound == NULL || list_pos >= num_sounds)
1811 printf("loading sound '%s' ... [%d]\n",
1812 basename, getNumNodes(SoundFileList));
1815 LoadCustomSound(&Sound[list_pos], basename);
1818 printf("loading sound '%s' done [%d]\n",
1819 basename, getNumNodes(SoundFileList));
1823 static MusicInfo *Load_MOD(char *filename)
1825 #if defined(TARGET_SDL)
1826 MusicInfo *mod_info;
1828 if (!audio.sound_available)
1831 mod_info = checked_calloc(sizeof(MusicInfo));
1833 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1835 Error(ERR_WARN, "cannot read music file '%s'", filename);
1840 mod_info->type = MUS_TYPE_MOD;
1841 mod_info->source_filename = getStringCopy(filename);
1849 void LoadCustomMusic(void)
1851 static boolean draw_init_text = TRUE; /* only draw at startup */
1852 static char *last_music_directory = NULL;
1853 char *music_directory = getCustomMusicDirectory();
1855 struct dirent *dir_entry;
1857 if (!audio.sound_available)
1860 if (last_music_directory != NULL &&
1861 strcmp(last_music_directory, music_directory) == 0)
1862 return; /* old and new music directory are the same */
1864 last_music_directory = music_directory;
1868 if ((dir = opendir(music_directory)) == NULL)
1870 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1871 audio.music_available = FALSE;
1876 DrawInitText("Loading music:", 120, FC_GREEN);
1878 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1880 char *basename = dir_entry->d_name;
1881 char *filename = getPath2(music_directory, basename);
1882 MusicInfo *mus_info = NULL;
1885 DrawInitText(basename, 150, FC_YELLOW);
1887 if (FileIsSound(basename))
1888 mus_info = Load_WAV(filename);
1889 else if (FileIsMusic(basename))
1890 mus_info = Load_MOD(filename);
1897 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1898 Music[num_music -1] = mus_info;
1904 draw_init_text = FALSE;
1907 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1911 void PlayMusic(int nr)
1913 if (!audio.music_available)
1919 void PlaySound(int nr)
1921 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1924 void PlaySoundStereo(int nr, int stereo_position)
1926 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1929 void PlaySoundLoop(int nr)
1931 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1934 void PlaySoundMusic(int nr)
1936 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1939 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1941 SoundControl snd_ctrl;
1943 if (!audio.sound_available ||
1944 !audio.sound_enabled ||
1945 audio.sound_deactivated)
1948 if (volume < SOUND_MIN_VOLUME)
1949 volume = SOUND_MIN_VOLUME;
1950 else if (volume > SOUND_MAX_VOLUME)
1951 volume = SOUND_MAX_VOLUME;
1953 if (stereo_position < SOUND_MAX_LEFT)
1954 stereo_position = SOUND_MAX_LEFT;
1955 else if (stereo_position > SOUND_MAX_RIGHT)
1956 stereo_position = SOUND_MAX_RIGHT;
1958 snd_ctrl.active = TRUE;
1960 snd_ctrl.volume = volume;
1961 snd_ctrl.stereo_position = stereo_position;
1962 snd_ctrl.state = state;
1964 HandleSoundRequest(snd_ctrl);
1967 void FadeMusic(void)
1969 if (!audio.music_available)
1972 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1975 void FadeSound(int nr)
1977 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1983 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1986 void StopMusic(void)
1988 if (!audio.music_available)
1991 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1994 void StopSound(int nr)
1996 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2002 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2005 void StopSoundExt(int nr, int state)
2007 SoundControl snd_ctrl;
2009 if (!audio.sound_available)
2012 snd_ctrl.active = FALSE;
2014 snd_ctrl.state = state;
2016 HandleSoundRequest(snd_ctrl);
2019 ListNode *newListNode()
2021 return checked_calloc(sizeof(ListNode));
2024 void addNodeToList(ListNode **node_first, char *key, void *content)
2026 ListNode *node_new = newListNode();
2029 printf("LIST: adding node with key '%s'\n", key);
2032 node_new->key = getStringCopy(key);
2033 node_new->content = content;
2034 node_new->next = *node_first;
2035 *node_first = node_new;
2038 void deleteNodeFromList(ListNode **node_first, char *key,
2039 void (*destructor_function)(void *))
2041 if (node_first == NULL || *node_first == NULL)
2045 printf("[CHECKING LIST KEY '%s' == '%s']\n",
2046 (*node_first)->key, key);
2049 if (strcmp((*node_first)->key, key) == 0)
2052 printf("[DELETING LIST ENTRY]\n");
2055 free((*node_first)->key);
2056 if (destructor_function)
2057 destructor_function((*node_first)->content);
2058 *node_first = (*node_first)->next;
2061 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
2064 ListNode *getNodeFromKey(ListNode *node_first, char *key)
2066 if (node_first == NULL)
2069 if (strcmp(node_first->key, key) == 0)
2072 return getNodeFromKey(node_first->next, key);
2075 int getNumNodes(ListNode *node_first)
2077 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
2080 void dumpList(ListNode *node_first)
2082 ListNode *node = node_first;
2086 printf("['%s' (%d)]\n", node->key,
2087 ((SoundInfo *)node->content)->num_references);
2091 printf("[%d nodes]\n", getNumNodes(node_first));
2094 static void LoadSoundsInfo()
2096 char *filename = getCustomSoundConfigFilename();
2097 struct SetupFileList *setup_file_list;
2101 printf("GOT CUSTOM SOUND CONFIG FILE '%s'\n", filename);
2104 /* always start with reliable default values */
2105 for (i=0; i<num_sounds; i++)
2106 sound_effect[i].filename = NULL;
2108 if (filename == NULL)
2111 if ((setup_file_list = loadSetupFileList(filename)))
2113 for (i=0; i<num_sounds; i++)
2114 sound_effect[i].filename =
2115 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2117 freeSetupFileList(setup_file_list);
2120 for (i=0; i<num_sounds; i++)
2122 printf("'%s' ", sound_effect[i].text);
2123 if (sound_effect[i].filename)
2124 printf("-> '%s'\n", sound_effect[i].filename);
2126 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2132 static void ReloadCustomSounds()
2134 static boolean draw_init_text = TRUE; /* only draw at startup */
2138 printf("DEBUG: reloading sounds '%s' ...\n",artwork.sounds_set_current_name);
2144 DrawInitText("Loading sounds:", 120, FC_GREEN);
2147 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2150 for(i=0; i<num_sounds; i++)
2153 DrawInitText(sound_effect[i].text, 150, FC_YELLOW);
2155 if (sound_effect[i].filename)
2156 LoadSoundToList(sound_effect[i].filename, i);
2158 LoadSoundToList(sound_effect[i].default_filename, i);
2161 draw_init_text = FALSE;
2164 printf("list size == %d\n", getNumNodes(SoundFileList));
2168 dumpList(SoundFileList);
2172 static void ReloadCustomMusic()
2175 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current_name);
2179 /* this is done directly in LoadCustomMusic() now */
2186 void InitReloadSounds(char *set_name)
2188 if (!audio.sound_available)
2191 #if defined(AUDIO_UNIX_NATIVE)
2192 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
2194 ReloadCustomSounds();
2198 void InitReloadMusic(char *set_name)
2200 if (!audio.music_available)
2203 #if defined(AUDIO_UNIX_NATIVE)
2204 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
2206 ReloadCustomMusic();
2210 void FreeSound(void *ptr)
2212 SoundInfo *sound = (SoundInfo *)ptr;
2217 if (sound->data_ptr)
2219 #if defined(TARGET_SDL)
2220 Mix_FreeChunk(sound->data_ptr);
2221 #elif defined(TARGET_ALLEGRO)
2222 destroy_sample(sound->data_ptr);
2223 #else /* AUDIO_UNIX_NATIVE */
2224 free(sound->data_ptr);
2228 if (sound->source_filename)
2229 free(sound->source_filename);
2234 void FreeMusic(MusicInfo *music)
2239 if (music->data_ptr)
2241 #if defined(TARGET_SDL)
2242 if (music->type == MUS_TYPE_MOD)
2243 Mix_FreeMusic(music->data_ptr);
2245 Mix_FreeChunk(music->data_ptr);
2246 #elif defined(TARGET_ALLEGRO)
2247 destroy_sample(music->data_ptr);
2248 #else /* AUDIO_UNIX_NATIVE */
2249 free(music->data_ptr);
2256 void FreeAllSounds()
2264 printf("%s: FREEING SOUNDS ...\n",
2265 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2268 for(i=0; i<num_sounds; i++)
2269 deleteSoundEntry(&Sound[i]);
2271 FreeSound(Sound[i]);
2275 printf("%s: FREEING SOUNDS -- DONE\n",
2276 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2292 for(i=0; i<num_music; i++)
2293 FreeMusic(Music[i]);
2301 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2302 /* ========================================================================= */