1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
12 #include <sys/types.h>
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 #define SND_TYPE_NONE 0
55 #define SND_TYPE_WAV 1
57 #define MUS_TYPE_NONE 0
58 #define MUS_TYPE_WAV 1
59 #define MUS_TYPE_MOD 2
61 #define DEVICENAME_DSP "/dev/dsp"
62 #define DEVICENAME_SOUND_DSP "/dev/sound/dsp"
63 #define DEVICENAME_AUDIO "/dev/audio"
64 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
66 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
67 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
69 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
70 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
72 #define SOUND_VOLUME_FROM_PERCENT(v,p) ((p) < 0 ? SOUND_MIN_VOLUME : \
76 #define SOUND_VOLUME_SIMPLE(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_simple)
77 #define SOUND_VOLUME_LOOPS(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_loops)
78 #define SOUND_VOLUME_MUSIC(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_music)
80 #define SETUP_SOUND_VOLUME(v,s) ((s) == SND_CTRL_PLAY_MUSIC ? \
81 SOUND_VOLUME_MUSIC(v) : \
82 (s) == SND_CTRL_PLAY_LOOP ? \
83 SOUND_VOLUME_LOOPS(v) : \
84 SOUND_VOLUME_SIMPLE(v))
87 #if defined(AUDIO_UNIX_NATIVE)
88 struct SoundHeader_WAV
90 unsigned short compression_code;
91 unsigned short num_channels;
92 unsigned int sample_rate;
93 unsigned int bytes_per_second;
94 unsigned short block_align;
95 unsigned short bits_per_sample;
99 struct AudioFormatInfo
101 boolean stereo; /* availability of stereo sound */
102 int format; /* size and endianess of sample data */
103 int sample_rate; /* sample frequency */
104 int fragment_size; /* audio device fragment size in bytes */
109 char *source_filename;
114 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
115 int data_len; /* number of samples, NOT number of bytes */
116 int num_channels; /* mono: 1 channel, stereo: 2 channels */
118 typedef struct SampleInfo SoundInfo;
119 typedef struct SampleInfo MusicInfo;
131 unsigned int playing_starttime;
132 unsigned int playing_pos;
136 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
137 int data_len; /* number of samples, NOT number of bytes */
138 int num_channels; /* mono: 1 channel, stereo: 2 channels */
140 typedef struct SoundControl SoundControl;
142 static struct ArtworkListInfo *sound_info = NULL;
143 static struct ArtworkListInfo *music_info = NULL;
145 static MusicInfo **Music_NoConf = NULL;
147 static int num_music_noconf = 0;
148 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
151 /* ========================================================================= */
152 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
154 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
155 static int mixer_active_channels = 0;
157 #if defined(AUDIO_UNIX_NATIVE)
158 static struct AudioFormatInfo afmt;
160 static void Mixer_Main(void);
161 #if !defined(AUDIO_STREAMING_DSP)
162 static unsigned char linear_to_ulaw(int);
163 static int ulaw_to_linear(unsigned char);
167 static void ReloadCustomSounds();
168 static void ReloadCustomMusic();
169 static void FreeSound(void *);
170 static void FreeMusic(void *);
171 static void FreeAllMusic_NoConf();
173 static SoundInfo *getSoundInfoEntryFromSoundID(int);
174 static MusicInfo *getMusicInfoEntryFromMusicID(int);
177 /* ------------------------------------------------------------------------- */
178 /* functions for native (non-SDL) Unix audio/mixer support */
179 /* ------------------------------------------------------------------------- */
181 #if defined(AUDIO_UNIX_NATIVE)
183 static int OpenAudioDevice(char *audio_device_name)
187 /* check if desired audio device is accessible */
188 if (access(audio_device_name, W_OK) != 0)
191 /* try to open audio device in non-blocking mode */
192 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
193 return audio_device_fd;
195 /* re-open audio device in blocking mode */
196 close(audio_device_fd);
197 audio_device_fd = open(audio_device_name, O_WRONLY);
199 return audio_device_fd;
202 static void CloseAudioDevice(int *audio_device_fd)
204 if (*audio_device_fd == 0)
207 close(*audio_device_fd);
208 *audio_device_fd = -1;
211 static boolean TestAudioDevices(void)
213 static char *audio_device_name[] =
216 DEVICENAME_SOUND_DSP,
219 int audio_device_fd = -1;
222 /* look for available audio devices, starting with preferred ones */
223 for (i = 0; i < sizeof(audio_device_name)/sizeof(char *); i++)
224 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
227 if (audio_device_fd < 0)
229 Error(ERR_WARN, "cannot open audio device -- no sound");
233 close(audio_device_fd);
235 audio.device_name = audio_device_name[i];
240 static boolean ForkAudioProcess(void)
242 if (pipe(audio.mixer_pipe) < 0)
244 Error(ERR_WARN, "cannot create pipe -- no sounds");
248 if ((audio.mixer_pid = fork()) < 0)
250 Error(ERR_WARN, "cannot create sound server process -- no sounds");
254 if (audio.mixer_pid == 0) /* we are the child process */
255 audio.mixer_pid = getpid();
257 if (IS_CHILD_PROCESS())
258 Mixer_Main(); /* this function never returns */
260 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
265 void UnixOpenAudio(void)
267 if (!TestAudioDevices())
270 audio.sound_available = TRUE;
271 audio.sound_enabled = TRUE;
273 #if defined(AUDIO_STREAMING_DSP)
274 audio.music_available = TRUE;
275 audio.loops_available = TRUE;
278 audio.num_channels = NUM_MIXER_CHANNELS;
279 audio.music_channel = MUSIC_CHANNEL;
280 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
283 void UnixCloseAudio(void)
286 close(audio.device_fd);
288 if (IS_PARENT_PROCESS() && HAS_CHILD_PROCESS())
289 kill(audio.mixer_pid, SIGTERM);
293 /* ------------------------------------------------------------------------- */
294 /* functions for platform specific audio device initialization */
295 /* ------------------------------------------------------------------------- */
297 #if defined(AUDIO_LINUX_IOCTL)
298 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
300 /* "ioctl()" expects pointer to 'int' value for stereo flag
301 (boolean is defined as 'char', which will not work here) */
302 unsigned int fragment_spec = 0;
303 int fragment_size_query = -1;
312 /* supported audio format in preferred order */
313 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
314 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
315 { AFMT_U8, AUDIO_FORMAT_U8 },
320 /* determine logarithm (log2) of the fragment size */
321 while ((1 << fragment_spec) < afmt->fragment_size)
324 /* use two fragments (play one fragment, prepare the other);
325 one fragment would result in interrupted audio output, more
326 than two fragments would raise audio output latency to much */
327 fragment_spec |= 0x00020000;
329 /* Example for fragment specification:
330 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
331 - (with stereo the effective buffer size will shrink to 256)
332 => fragment_size = 0x00020009 */
334 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
335 Error(ERR_EXIT_SOUND_SERVER,
336 "cannot set fragment size of audio device -- no sounds");
340 while (formats[i].format_result != -1)
342 unsigned int audio_format = formats[i].format_ioctl;
343 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
345 afmt->format = formats[i].format_result;
350 if (afmt->format == 0) /* no supported audio format found */
351 Error(ERR_EXIT_SOUND_SERVER,
352 "cannot set audio format of audio device -- no sounds");
354 /* try if we can use stereo sound */
356 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
357 afmt->stereo = FALSE;
359 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
360 Error(ERR_EXIT_SOUND_SERVER,
361 "cannot set sample rate of audio device -- no sounds");
363 /* get the real fragmentation size; this should return 512 */
364 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
365 Error(ERR_EXIT_SOUND_SERVER,
366 "cannot get fragment size of audio device -- no sounds");
367 if (fragment_size_query != afmt->fragment_size)
368 Error(ERR_EXIT_SOUND_SERVER,
369 "cannot set fragment size of audio device -- no sounds");
371 #endif /* AUDIO_LINUX_IOCTL */
373 #if defined(PLATFORM_NETBSD)
374 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
377 boolean stereo = TRUE;
379 AUDIO_INITINFO(&a_info);
380 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
381 a_info.play.precision = 8;
382 a_info.play.channels = 2;
383 a_info.play.sample_rate = afmt->sample_rate;
384 a_info.blocksize = afmt->fragment_size;
386 afmt->format = AUDIO_FORMAT_U8;
389 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
391 /* try to disable stereo */
392 a_info.play.channels = 1;
394 afmt->stereo = FALSE;
396 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
397 Error(ERR_EXIT_SOUND_SERVER,
398 "cannot set sample rate of audio device -- no sounds");
401 #endif /* PLATFORM_NETBSD */
403 #if defined(PLATFORM_HPUX)
404 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
406 struct audio_describe ainfo;
409 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
411 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
413 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
414 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
416 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
417 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
419 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
420 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
422 afmt->format = AUDIO_FORMAT_U8;
423 afmt->stereo = FALSE;
424 afmt->sample_rate = 8000;
428 #endif /* PLATFORM_HPUX */
430 static void InitAudioDevice(struct AudioFormatInfo *afmt)
433 afmt->format = AUDIO_FORMAT_UNKNOWN;
434 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
435 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
437 #if defined(AUDIO_LINUX_IOCTL)
438 InitAudioDevice_Linux(afmt);
439 #elif defined(PLATFORM_NETBSD)
440 InitAudioDevice_NetBSD(afmt);
441 #elif defined(PLATFORM_HPUX)
442 InitAudioDevice_HPUX(afmt);
444 /* generic /dev/audio stuff might be placed here */
449 /* ------------------------------------------------------------------------- */
450 /* functions for communication between main process and sound mixer process */
451 /* ------------------------------------------------------------------------- */
453 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
455 if (IS_CHILD_PROCESS())
458 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
460 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
461 audio.sound_available = audio.sound_enabled = FALSE;
466 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
468 if (IS_PARENT_PROCESS())
471 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
472 != sizeof(SoundControl))
473 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
476 static void WriteReloadInfoToPipe(char *set_identifier, int type)
478 SoundControl snd_ctrl;
479 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
480 artwork.mus_current);
481 unsigned int str_size1 = strlen(leveldir_current->fullpath) + 1;
482 unsigned int str_size2 = strlen(leveldir_current->sounds_path) + 1;
483 unsigned int str_size3 = strlen(leveldir_current->music_path) + 1;
484 unsigned int str_size4 = strlen(ti->basepath) + 1;
485 unsigned int str_size5 = strlen(ti->fullpath) + 1;
486 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
487 gfx.override_level_sounds :
488 gfx.override_level_music);
490 if (IS_CHILD_PROCESS())
493 if (leveldir_current == NULL) /* should never happen */
494 Error(ERR_EXIT, "leveldir_current == NULL");
496 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
498 snd_ctrl.active = FALSE;
499 snd_ctrl.state = type;
500 snd_ctrl.data_len = strlen(set_identifier) + 1;
502 if (write(audio.mixer_pipe[1], &snd_ctrl,
503 sizeof(snd_ctrl)) < 0 ||
504 write(audio.mixer_pipe[1], set_identifier,
505 snd_ctrl.data_len) < 0 ||
506 write(audio.mixer_pipe[1], &override_level_artwork,
507 sizeof(boolean)) < 0 ||
508 write(audio.mixer_pipe[1], leveldir_current,
509 sizeof(TreeInfo)) < 0 ||
510 write(audio.mixer_pipe[1], ti,
511 sizeof(TreeInfo)) < 0 ||
512 write(audio.mixer_pipe[1], &str_size1,
513 sizeof(unsigned int)) < 0 ||
514 write(audio.mixer_pipe[1], &str_size2,
515 sizeof(unsigned int)) < 0 ||
516 write(audio.mixer_pipe[1], &str_size3,
517 sizeof(unsigned int)) < 0 ||
518 write(audio.mixer_pipe[1], &str_size4,
519 sizeof(unsigned int)) < 0 ||
520 write(audio.mixer_pipe[1], &str_size5,
521 sizeof(unsigned int)) < 0 ||
522 write(audio.mixer_pipe[1], leveldir_current->fullpath,
524 write(audio.mixer_pipe[1], leveldir_current->sounds_path,
526 write(audio.mixer_pipe[1], leveldir_current->music_path,
528 write(audio.mixer_pipe[1], ti->basepath,
530 write(audio.mixer_pipe[1], ti->fullpath,
533 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
534 audio.sound_available = audio.sound_enabled = FALSE;
539 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
541 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
542 &artwork.snd_current : &artwork.mus_current);
543 TreeInfo *ti = *ti_ptr;
544 unsigned int str_size1, str_size2, str_size3, str_size4, str_size5;
545 static char *set_identifier = NULL;
546 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
547 &gfx.override_level_sounds :
548 &gfx.override_level_music);
550 checked_free(set_identifier);
552 set_identifier = checked_malloc(snd_ctrl->data_len);
554 if (leveldir_current == NULL)
555 leveldir_current = checked_calloc(sizeof(TreeInfo));
558 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
560 checked_free(leveldir_current->fullpath);
561 checked_free(leveldir_current->sounds_path);
562 checked_free(leveldir_current->music_path);
563 checked_free(ti->basepath);
564 checked_free(ti->fullpath);
566 if (read(audio.mixer_pipe[0], set_identifier,
567 snd_ctrl->data_len) != snd_ctrl->data_len ||
568 read(audio.mixer_pipe[0], override_level_artwork,
569 sizeof(boolean)) != sizeof(boolean) ||
570 read(audio.mixer_pipe[0], leveldir_current,
571 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
572 read(audio.mixer_pipe[0], ti,
573 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
574 read(audio.mixer_pipe[0], &str_size1,
575 sizeof(unsigned int)) != sizeof(unsigned int) ||
576 read(audio.mixer_pipe[0], &str_size2,
577 sizeof(unsigned int)) != sizeof(unsigned int) ||
578 read(audio.mixer_pipe[0], &str_size3,
579 sizeof(unsigned int)) != sizeof(unsigned int) ||
580 read(audio.mixer_pipe[0], &str_size4,
581 sizeof(unsigned int)) != sizeof(unsigned int) ||
582 read(audio.mixer_pipe[0], &str_size5,
583 sizeof(unsigned int)) != sizeof(unsigned int))
584 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
586 leveldir_current->fullpath = checked_calloc(str_size1);
587 leveldir_current->sounds_path = checked_calloc(str_size2);
588 leveldir_current->music_path = checked_calloc(str_size3);
589 ti->basepath = checked_calloc(str_size4);
590 ti->fullpath = checked_calloc(str_size5);
592 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
593 str_size1) != str_size1 ||
594 read(audio.mixer_pipe[0], leveldir_current->sounds_path,
595 str_size2) != str_size2 ||
596 read(audio.mixer_pipe[0], leveldir_current->music_path,
597 str_size3) != str_size3 ||
598 read(audio.mixer_pipe[0], ti->basepath,
599 str_size4) != str_size4 ||
600 read(audio.mixer_pipe[0], ti->fullpath,
601 str_size5) != str_size5)
602 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
604 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
605 artwork.snd_current_identifier = set_identifier;
607 artwork.mus_current_identifier = set_identifier;
610 #endif /* AUDIO_UNIX_NATIVE */
613 /* ------------------------------------------------------------------------- */
614 /* mixer functions */
615 /* ------------------------------------------------------------------------- */
617 void Mixer_InitChannels()
621 for (i = 0; i < audio.num_channels; i++)
622 mixer[i].active = FALSE;
623 mixer_active_channels = 0;
626 static void Mixer_ResetChannelExpiration(int channel)
628 mixer[channel].playing_starttime = Counter();
630 #if defined(TARGET_SDL)
631 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
632 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
636 static boolean Mixer_ChannelExpired(int channel)
638 if (!mixer[channel].active)
641 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
642 DelayReached(&mixer[channel].playing_starttime,
643 SOUND_LOOP_EXPIRATION_TIME))
646 #if defined(TARGET_SDL)
647 if (!Mix_Playing(channel))
654 static boolean Mixer_AllocateChannel(int channel)
659 static void Mixer_SetChannelProperties(int channel)
661 #if defined(TARGET_SDL)
662 Mix_Volume(channel, mixer[channel].volume);
663 Mix_SetPanning(channel,
664 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
665 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
669 static void Mixer_StartChannel(int channel)
671 #if defined(TARGET_SDL)
672 Mix_PlayChannel(channel, mixer[channel].data_ptr,
673 IS_LOOP(mixer[channel]) ? -1 : 0);
677 static void Mixer_PlayChannel(int channel)
679 /* start with inactive channel in case something goes wrong */
680 mixer[channel].active = FALSE;
682 if (mixer[channel].type != MUS_TYPE_WAV)
685 if (!Mixer_AllocateChannel(channel))
688 Mixer_SetChannelProperties(channel);
689 Mixer_StartChannel(channel);
691 Mixer_ResetChannelExpiration(channel);
693 mixer[channel].playing_pos = 0;
694 mixer[channel].active = TRUE;
695 mixer_active_channels++;
698 static void Mixer_PlayMusicChannel()
700 Mixer_PlayChannel(audio.music_channel);
702 #if defined(TARGET_SDL)
703 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
705 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
706 this looks like a bug in the SDL_mixer library */
707 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
708 Mix_VolumeMusic(mixer[audio.music_channel].volume);
713 static void Mixer_StopChannel(int channel)
715 if (!mixer[channel].active)
718 #if defined(TARGET_SDL)
719 Mix_HaltChannel(channel);
722 mixer[channel].active = FALSE;
723 mixer_active_channels--;
726 static void Mixer_StopMusicChannel()
728 Mixer_StopChannel(audio.music_channel);
730 #if defined(TARGET_SDL)
735 static void Mixer_FadeChannel(int channel)
737 if (!mixer[channel].active)
740 mixer[channel].state |= SND_CTRL_FADE;
742 #if defined(TARGET_SDL)
743 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
747 static void Mixer_FadeMusicChannel()
749 Mixer_FadeChannel(audio.music_channel);
751 #if defined(TARGET_SDL)
752 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
756 static void Mixer_UnFadeChannel(int channel)
758 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
761 mixer[channel].state &= ~SND_CTRL_FADE;
762 mixer[channel].volume = SOUND_MAX_VOLUME;
764 #if defined(TARGET_SDL)
765 Mix_ExpireChannel(channel, -1);
766 Mix_Volume(channel, mixer[channel].volume);
770 static void Mixer_InsertSound(SoundControl snd_ctrl)
774 int num_sounds = getSoundListSize();
775 int num_music = getMusicListSize();
777 if (IS_MUSIC(snd_ctrl))
779 if (snd_ctrl.nr >= num_music) /* invalid music */
782 if (snd_ctrl.nr < 0) /* undefined music */
784 if (num_music_noconf == 0) /* no fallback music available */
787 snd_ctrl.nr = UNMAP_NOCONF_MUSIC(snd_ctrl.nr) % num_music_noconf;
788 snd_info = Music_NoConf[snd_ctrl.nr];
791 snd_info = getMusicInfoEntryFromMusicID(snd_ctrl.nr);
795 if (snd_ctrl.nr < 0 || snd_ctrl.nr >= num_sounds)
798 snd_info = getSoundInfoEntryFromSoundID(snd_ctrl.nr);
801 if (snd_info == NULL)
804 /* copy sound sample and format information */
805 snd_ctrl.type = snd_info->type;
806 snd_ctrl.format = snd_info->format;
807 snd_ctrl.data_ptr = snd_info->data_ptr;
808 snd_ctrl.data_len = snd_info->data_len;
809 snd_ctrl.num_channels = snd_info->num_channels;
811 /* play music samples on a dedicated music channel */
812 if (IS_MUSIC(snd_ctrl))
814 Mixer_StopMusicChannel();
816 mixer[audio.music_channel] = snd_ctrl;
817 Mixer_PlayMusicChannel();
822 /* check if (and how often) this sound sample is already playing */
823 for (k = 0, i = audio.first_sound_channel; i < audio.num_channels; i++)
824 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
827 /* reset expiration delay for already playing loop sounds */
828 if (k > 0 && IS_LOOP(snd_ctrl))
830 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
832 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
834 if (IS_FADING(mixer[i]))
835 Mixer_UnFadeChannel(i);
837 /* restore settings like volume and stereo position */
838 mixer[i].volume = snd_ctrl.volume;
839 mixer[i].stereo_position = snd_ctrl.stereo_position;
841 Mixer_SetChannelProperties(i);
842 Mixer_ResetChannelExpiration(i);
849 /* don't play sound more than n times simultaneously (with n == 2 for now) */
852 unsigned int playing_current = Counter();
853 int longest = 0, longest_nr = audio.first_sound_channel;
855 /* look for oldest equal sound */
856 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
858 int playing_time = playing_current - mixer[i].playing_starttime;
861 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
864 actual = 1000 * playing_time / mixer[i].data_len;
866 if (actual >= longest)
873 Mixer_StopChannel(longest_nr);
876 /* If all (non-music) channels are active, stop the channel that has
877 played its sound sample most completely (in percent of the sample
878 length). As we cannot currently get the actual playing position
879 of the channel's sound sample when compiling with the SDL mixer
880 library, we use the current playing time (in milliseconds) instead. */
883 /* channel allocation sanity check -- should not be needed */
884 if (mixer_active_channels ==
885 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
887 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
889 if (!mixer[i].active)
891 Error(ERR_INFO, "Mixer_InsertSound: Channel %d inactive", i);
892 Error(ERR_INFO, "Mixer_InsertSound: This should never happen!");
894 mixer_active_channels--;
900 if (mixer_active_channels ==
901 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
903 unsigned int playing_current = Counter();
904 int longest = 0, longest_nr = audio.first_sound_channel;
908 /* print some debugging information about audio channel usage */
909 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
911 Error(ERR_INFO, "Mixer_InsertSound: %d [%d]: %d (%d)",
912 i, mixer[i].active, mixer[i].data_len, (int)mixer[i].data_ptr);
917 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
919 int playing_time = playing_current - mixer[i].playing_starttime;
920 int actual = 1000 * playing_time / mixer[i].data_len;
922 if (!IS_LOOP(mixer[i]) && actual > longest)
929 Mixer_StopChannel(longest_nr);
932 /* add the new sound to the mixer */
933 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
935 if (!mixer[i].active)
937 #if defined(AUDIO_UNIX_NATIVE)
938 if (snd_info->data_len == 0)
940 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
945 Mixer_PlayChannel(i);
952 static void HandleSoundRequest(SoundControl snd_ctrl)
956 #if defined(AUDIO_UNIX_NATIVE)
957 if (IS_PARENT_PROCESS())
959 SendSoundControlToMixerProcess(&snd_ctrl);
964 /* deactivate channels that have expired since the last request */
965 for (i = 0; i < audio.num_channels; i++)
966 if (mixer[i].active && Mixer_ChannelExpired(i))
967 Mixer_StopChannel(i);
969 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
971 Mixer_StopMusicChannel();
972 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
973 Mixer_StopChannel(i);
975 #if defined(AUDIO_UNIX_NATIVE)
976 CloseAudioDevice(&audio.device_fd);
977 ReadReloadInfoFromPipe(&snd_ctrl);
980 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
981 ReloadCustomSounds();
985 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
987 if (IS_MUSIC(snd_ctrl))
989 Mixer_FadeMusicChannel();
993 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
994 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
995 Mixer_FadeChannel(i);
997 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
999 if (IS_MUSIC(snd_ctrl))
1001 Mixer_StopMusicChannel();
1005 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
1006 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1007 Mixer_StopChannel(i);
1009 #if defined(AUDIO_UNIX_NATIVE)
1010 if (!mixer_active_channels)
1011 CloseAudioDevice(&audio.device_fd);
1014 else if (snd_ctrl.active) /* add new sound to mixer */
1016 Mixer_InsertSound(snd_ctrl);
1020 void StartMixer(void)
1025 SDL_version compile_version;
1026 const SDL_version *link_version;
1027 MIX_VERSION(&compile_version);
1028 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1029 compile_version.major,
1030 compile_version.minor,
1031 compile_version.patch);
1032 link_version = Mix_Linked_Version();
1033 printf("running with SDL_mixer version: %d.%d.%d\n",
1034 link_version->major,
1035 link_version->minor,
1036 link_version->patch);
1039 if (!audio.sound_available)
1042 /* initialize stereo position conversion information */
1043 for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
1045 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1047 #if defined(AUDIO_UNIX_NATIVE)
1048 if (!ForkAudioProcess())
1049 audio.sound_available = FALSE;
1053 #if defined(AUDIO_UNIX_NATIVE)
1055 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1056 int sample_pos, int sample_size,
1057 short *buffer_base_ptr, int buffer_pos,
1058 int num_output_channels)
1060 short *buffer_ptr = buffer_base_ptr + num_output_channels * buffer_pos;
1061 int num_channels = snd_ctrl->num_channels;
1062 int stepsize = num_channels;
1063 int output_stepsize = num_output_channels;
1066 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1068 byte *sample_ptr = (byte *)snd_ctrl->data_ptr + num_channels * sample_pos;
1070 for (i = 0; i < num_output_channels; i++)
1072 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1074 for (j = 0; j < sample_size; j++)
1075 buffer_ptr[output_stepsize * j + i] =
1076 ((short)(sample_ptr[stepsize * j + offset] ^ 0x80)) << 8;
1079 else /* AUDIO_FORMAT_S16 */
1081 short *sample_ptr= (short *)snd_ctrl->data_ptr + num_channels * sample_pos;
1083 for (i = 0; i < num_output_channels; i++)
1085 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1087 for (j = 0; j < sample_size; j++)
1088 buffer_ptr[output_stepsize * j + i] =
1089 sample_ptr[stepsize * j + offset];
1094 #if defined(AUDIO_STREAMING_DSP)
1095 static void Mixer_Main_DSP()
1097 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1098 static int premix_last_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1099 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1103 int max_sample_size;
1104 int num_output_channels;
1107 if (!mixer_active_channels)
1110 if (audio.device_fd < 0)
1112 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1115 InitAudioDevice(&afmt);
1118 stereo = afmt.stereo;
1119 fragment_size = afmt.fragment_size;
1120 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1121 num_output_channels = (stereo ? 2 : 1);
1122 max_sample_size = fragment_size / (num_output_channels * sample_bytes);
1124 /* first clear the last premixing buffer */
1125 clear_mem(premix_last_buffer,
1126 max_sample_size * num_output_channels * sizeof(int));
1128 for (i = 0; i < audio.num_channels; i++)
1130 // void *sample_ptr;
1135 if (!mixer[i].active)
1138 if (Mixer_ChannelExpired(i))
1140 Mixer_StopChannel(i);
1144 /* pointer, lenght and actual playing position of sound sample */
1145 // sample_ptr = mixer[i].data_ptr;
1146 sample_len = mixer[i].data_len;
1147 sample_pos = mixer[i].playing_pos;
1148 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1149 mixer[i].playing_pos += sample_size;
1151 /* copy original sample to first mixing buffer */
1152 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1153 premix_first_buffer, 0, num_output_channels);
1155 /* are we about to restart a looping sound? */
1156 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1158 while (sample_size < max_sample_size)
1160 int restarted_sample_size =
1161 MIN(max_sample_size - sample_size, sample_len);
1163 CopySampleToMixingBuffer(&mixer[i], 0, restarted_sample_size,
1164 premix_first_buffer, sample_size,
1165 num_output_channels);
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 * num_output_channels; j++)
1180 premix_first_buffer[j] =
1181 mixer[i].volume * (int)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1183 /* adjust left and right channel volume due to stereo sound position */
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_first_buffer[2 * j + 0] =
1192 left_volume * premix_first_buffer[2 * j + 0] / SOUND_MAX_LEFT2RIGHT;
1193 premix_first_buffer[2 * j + 1] =
1194 right_volume * premix_first_buffer[2 * j + 1] / SOUND_MAX_LEFT2RIGHT;
1198 /* fill the last mixing buffer with stereo or mono sound */
1199 for (j = 0; j < sample_size * num_output_channels; j++)
1200 premix_last_buffer[j] += premix_first_buffer[j];
1202 /* delete completed sound entries from the mixer */
1203 if (mixer[i].playing_pos >= mixer[i].data_len)
1205 if (IS_LOOP(mixer[i]))
1206 mixer[i].playing_pos = 0;
1208 Mixer_StopChannel(i);
1210 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1211 Mixer_StopChannel(i);
1214 /* prepare final playing buffer according to system audio format */
1215 for (i = 0; i < max_sample_size * num_output_channels; i++)
1217 /* cut off at 17 bit value */
1218 if (premix_last_buffer[i] < -65535)
1219 premix_last_buffer[i] = -65535;
1220 else if (premix_last_buffer[i] > 65535)
1221 premix_last_buffer[i] = 65535;
1223 /* shift to 16 bit value */
1224 premix_last_buffer[i] >>= 1;
1226 if (afmt.format & AUDIO_FORMAT_U8)
1228 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1230 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1232 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1233 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1235 else /* big endian */
1237 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1238 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1242 /* finally play the sound fragment */
1243 if (write(audio.device_fd, playing_buffer, fragment_size) == -1)
1244 Error(ERR_WARN, "write() failed; %s", strerror(errno));
1246 if (!mixer_active_channels)
1247 CloseAudioDevice(&audio.device_fd);
1250 #else /* !AUDIO_STREAMING_DSP */
1252 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1254 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1255 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1256 int max_sample_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1257 int num_output_channels = 1;
1266 /* pointer, lenght and actual playing position of sound sample */
1267 sample_ptr = mixer[i].data_ptr;
1268 sample_len = mixer[i].data_len;
1269 sample_pos = mixer[i].playing_pos;
1270 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1271 mixer[i].playing_pos += sample_size;
1273 /* copy original sample to first mixing buffer */
1274 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1275 premix_first_buffer, 0, num_output_channels);
1277 /* adjust volume of actual sound sample */
1278 if (mixer[i].volume != SOUND_MAX_VOLUME)
1279 for (j = 0; j < sample_size; j++)
1280 premix_first_buffer[j] =
1281 mixer[i].volume * (int)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1283 /* might be needed for u-law /dev/audio */
1284 for (j = 0; j < sample_size; j++)
1286 linear_to_ulaw(premix_first_buffer[j]);
1288 /* delete completed sound entries from the mixer */
1289 if (mixer[i].playing_pos >= mixer[i].data_len)
1290 Mixer_StopChannel(i);
1292 for (i = 0; i < sample_size; i++)
1293 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1295 /* finally play the sound fragment */
1296 write(audio.device_fd, playing_buffer, sample_size);
1300 #endif /* !AUDIO_STREAMING_DSP */
1304 SoundControl snd_ctrl;
1307 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1309 Mixer_InitChannels();
1311 #if defined(PLATFORM_HPUX)
1312 InitAudioDevice(&afmt);
1315 FD_ZERO(&mixer_fdset);
1316 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1318 while (1) /* wait for sound playing commands from client */
1320 struct timeval delay = { 0, 0 };
1322 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1323 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1324 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1327 ReadSoundControlFromMainProcess(&snd_ctrl);
1329 HandleSoundRequest(snd_ctrl);
1331 #if defined(AUDIO_STREAMING_DSP)
1333 while (mixer_active_channels &&
1334 select(audio.mixer_pipe[0] + 1,
1335 &mixer_fdset, NULL, NULL, &delay) < 1)
1337 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1342 #else /* !AUDIO_STREAMING_DSP */
1344 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1345 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1348 InitAudioDevice(&afmt);
1353 while (mixer_active_channels &&
1354 select(audio.mixer_pipe[0] + 1,
1355 &mixer_fdset, NULL, NULL, &delay) < 1)
1357 int wait_percent = 90; /* wait 90% of the real playing time */
1360 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1362 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1366 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1369 CloseAudioDevice(&audio.device_fd);
1371 Mixer_InitChannels(); /* remove all sounds from mixer */
1373 #endif /* !AUDIO_STREAMING_DSP */
1376 #endif /* AUDIO_UNIX_NATIVE */
1379 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1381 /* these two are stolen from "sox"... :) */
1384 ** This routine converts from linear to ulaw.
1386 ** Craig Reese: IDA/Supercomputing Research Center
1387 ** Joe Campbell: Department of Defense
1388 ** 29 September 1989
1391 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1392 ** 2) "A New Digital Technique for Implementation of Any
1393 ** Continuous PCM Companding Law," Villeret, Michel,
1394 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1395 ** 1973, pg. 11.12-11.17
1396 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1397 ** for Analog-to_Digital Conversion Techniques,"
1400 ** Input: Signed 16 bit linear sample
1401 ** Output: 8 bit ulaw sample
1404 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1405 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1408 static unsigned char linear_to_ulaw(int sample)
1410 static int exp_lut[256] =
1412 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1413 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1414 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1415 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1416 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1417 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1418 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1419 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1420 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1421 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1422 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1423 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
1430 int sign, exponent, mantissa;
1431 unsigned char ulawbyte;
1433 /* Get the sample into sign-magnitude. */
1434 sign = (sample >> 8) & 0x80; /* set aside the sign */
1436 sample = -sample; /* get magnitude */
1438 sample = CLIP; /* clip the magnitude */
1440 /* Convert from 16 bit linear to ulaw. */
1441 sample = sample + BIAS;
1442 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1443 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1444 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1447 ulawbyte = 0x02; /* optional CCITT trap */
1454 ** This routine converts from ulaw to 16 bit linear.
1456 ** Craig Reese: IDA/Supercomputing Research Center
1457 ** 29 September 1989
1460 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1461 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1462 ** for Analog-to_Digital Conversion Techniques,"
1465 ** Input: 8 bit ulaw sample
1466 ** Output: signed 16 bit linear sample
1469 static int ulaw_to_linear(unsigned char ulawbyte)
1471 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1472 int sign, exponent, mantissa, sample;
1474 ulawbyte = ~ ulawbyte;
1475 sign = ( ulawbyte & 0x80 );
1476 exponent = ( ulawbyte >> 4 ) & 0x07;
1477 mantissa = ulawbyte & 0x0F;
1478 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1484 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1487 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1488 /* ========================================================================= */
1489 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1491 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1492 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1494 static void *Load_WAV(char *filename)
1496 SoundInfo *snd_info;
1497 #if defined(AUDIO_UNIX_NATIVE)
1498 struct SoundHeader_WAV header;
1500 byte sound_header_buffer[WAV_HEADER_SIZE];
1503 char chunk_name[CHUNK_ID_LEN + 1];
1509 if (!audio.sound_available)
1512 snd_info = checked_calloc(sizeof(SoundInfo));
1514 #if defined(TARGET_SDL)
1516 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1518 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1523 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1525 #else /* AUDIO_UNIX_NATIVE */
1527 clear_mem(&header, sizeof(struct SoundHeader_WAV)); /* to make gcc happy */
1529 if ((file = fopen(filename, MODE_READ)) == NULL)
1531 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1536 /* read chunk id "RIFF" */
1537 getFileChunkLE(file, chunk_name, &chunk_size);
1538 if (!strEqual(chunk_name, "RIFF"))
1540 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1546 /* read "RIFF" type id "WAVE" */
1547 getFileChunkLE(file, chunk_name, NULL);
1548 if (!strEqual(chunk_name, "WAVE"))
1550 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1556 while (getFileChunkLE(file, chunk_name, &chunk_size))
1558 if (strEqual(chunk_name, "fmt "))
1560 if (chunk_size < WAV_HEADER_SIZE)
1562 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1568 header.compression_code = getFile16BitLE(file);
1569 header.num_channels = getFile16BitLE(file);
1570 header.sample_rate = getFile32BitLE(file);
1571 header.bytes_per_second = getFile32BitLE(file);
1572 header.block_align = getFile16BitLE(file);
1573 header.bits_per_sample = getFile16BitLE(file);
1575 if (chunk_size > WAV_HEADER_SIZE)
1576 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1578 if (header.compression_code != 1)
1580 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1581 filename, header.compression_code);
1587 if (header.num_channels != 1 &&
1588 header.num_channels != 2)
1590 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1591 filename, header.num_channels);
1597 if (header.bits_per_sample != 8 &&
1598 header.bits_per_sample != 16)
1600 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1601 filename, header.bits_per_sample);
1607 /* warn, but accept wrong sample rate (may be only slightly different) */
1608 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1609 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1610 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1613 printf("WAV file: '%s'\n", filename);
1614 printf(" Compression code: %d'\n", header.compression_code);
1615 printf(" Number of channels: %d'\n", header.num_channels);
1616 printf(" Sample rate: %d'\n", header.sample_rate);
1617 printf(" Average bytes per second: %d'\n", header.bytes_per_second);
1618 printf(" Block align: %d'\n", header.block_align);
1619 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1622 else if (strEqual(chunk_name, "data"))
1624 data_byte_len = chunk_size;
1626 snd_info->data_len = data_byte_len;
1627 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1629 /* read sound data */
1630 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1633 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1635 free(snd_info->data_ptr);
1640 /* check for odd number of data bytes (data chunk is word aligned) */
1641 if ((data_byte_len % 2) == 1)
1642 ReadUnusedBytesFromFile(file, 1);
1644 else /* unknown chunk -- ignore */
1645 ReadUnusedBytesFromFile(file, chunk_size);
1650 if (snd_info->data_ptr == NULL)
1652 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1657 if (header.bits_per_sample == 8)
1658 snd_info->format = AUDIO_FORMAT_U8;
1659 else /* header.bits_per_sample == 16 */
1661 snd_info->format = AUDIO_FORMAT_S16;
1662 snd_info->data_len /= 2; /* correct number of samples */
1665 snd_info->num_channels = header.num_channels;
1666 if (header.num_channels == 2)
1667 snd_info->data_len /= 2; /* correct number of samples */
1670 if (header.num_channels == 1) /* convert mono sound to stereo */
1672 void *buffer_ptr = checked_malloc(data_byte_len * 2);
1673 void *sample_ptr = snd_info->data_ptr;
1674 int sample_size = snd_info->data_len;
1677 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1678 for (i = 0; i < sample_size; i++)
1680 ((short)(((byte *)sample_ptr)[i] ^ 0x80)) << 8;
1681 else /* AUDIO_FORMAT_S16 */
1682 for (i = 0; i < sample_size; i++)
1684 ((short *)sample_ptr)[i];
1688 #endif /* AUDIO_UNIX_NATIVE */
1690 snd_info->type = SND_TYPE_WAV;
1691 snd_info->source_filename = getStringCopy(filename);
1696 static void *Load_MOD(char *filename)
1698 #if defined(TARGET_SDL)
1699 MusicInfo *mod_info;
1701 if (!audio.sound_available)
1704 mod_info = checked_calloc(sizeof(MusicInfo));
1706 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1708 Error(ERR_WARN, "cannot read music file '%s'", filename);
1713 mod_info->type = MUS_TYPE_MOD;
1714 mod_info->source_filename = getStringCopy(filename);
1722 static void *Load_WAV_or_MOD(char *filename)
1725 if (FileIsMusic(filename))
1726 return Load_MOD(filename);
1727 else if (FileIsSound(filename))
1728 return Load_WAV(filename);
1732 if (FileIsSound(filename))
1733 return Load_WAV(filename);
1734 else if (FileIsMusic(filename))
1735 return Load_MOD(filename);
1743 void LoadCustomMusic_NoConf(void)
1745 static boolean draw_init_text = TRUE; /* only draw at startup */
1746 static char *last_music_directory = NULL;
1747 char *music_directory = getCustomMusicDirectory();
1749 DirectoryEntry *dir_entry;
1750 int num_music = getMusicListSize();
1752 if (!audio.sound_available)
1755 if (last_music_directory != NULL &&
1756 strEqual(last_music_directory, music_directory))
1757 return; /* old and new music directory are the same */
1759 if (last_music_directory != NULL)
1760 free(last_music_directory);
1761 last_music_directory = getStringCopy(music_directory);
1763 FreeAllMusic_NoConf();
1765 if ((dir = openDirectory(music_directory)) == NULL)
1767 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1769 audio.music_available = FALSE;
1775 DrawInitText("Loading music", 120, FC_GREEN);
1777 while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */
1779 char *basename = dir_entry->basename;
1780 char *filename = NULL;
1781 MusicInfo *mus_info = NULL;
1782 boolean music_already_used = FALSE;
1785 /* skip all music files that are configured in music config file */
1786 for (i = 0; i < num_music; i++)
1788 struct FileInfo *music = getMusicListEntry(i);
1790 if (strEqual(basename, music->filename))
1792 music_already_used = TRUE;
1797 if (music_already_used)
1801 DrawInitText(basename, 150, FC_YELLOW);
1803 filename = getPath2(music_directory, basename);
1805 if (FileIsMusic(basename))
1806 mus_info = Load_WAV_or_MOD(filename);
1813 Music_NoConf = checked_realloc(Music_NoConf,
1814 num_music_noconf * sizeof(MusicInfo *));
1815 Music_NoConf[num_music_noconf - 1] = mus_info;
1819 closeDirectory(dir);
1821 draw_init_text = FALSE;
1826 void LoadCustomMusic_NoConf(void)
1828 static boolean draw_init_text = TRUE; /* only draw at startup */
1829 static char *last_music_directory = NULL;
1830 char *music_directory = getCustomMusicDirectory();
1832 struct dirent *dir_entry;
1833 int num_music = getMusicListSize();
1835 if (!audio.sound_available)
1838 if (last_music_directory != NULL &&
1839 strEqual(last_music_directory, music_directory))
1840 return; /* old and new music directory are the same */
1842 if (last_music_directory != NULL)
1843 free(last_music_directory);
1844 last_music_directory = getStringCopy(music_directory);
1846 FreeAllMusic_NoConf();
1848 if ((dir = opendir(music_directory)) == NULL)
1850 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1852 audio.music_available = FALSE;
1858 DrawInitText("Loading music", 120, FC_GREEN);
1860 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1862 char *basename = dir_entry->d_name;
1863 char *filename = NULL;
1864 MusicInfo *mus_info = NULL;
1865 boolean music_already_used = FALSE;
1868 /* skip all music files that are configured in music config file */
1869 for (i = 0; i < num_music; i++)
1871 struct FileInfo *music = getMusicListEntry(i);
1873 if (strEqual(basename, music->filename))
1875 music_already_used = TRUE;
1880 if (music_already_used)
1884 DrawInitText(basename, 150, FC_YELLOW);
1886 filename = getPath2(music_directory, basename);
1888 if (FileIsMusic(basename))
1889 mus_info = Load_WAV_or_MOD(filename);
1896 Music_NoConf = checked_realloc(Music_NoConf,
1897 num_music_noconf * sizeof(MusicInfo *));
1898 Music_NoConf[num_music_noconf - 1] = mus_info;
1904 draw_init_text = FALSE;
1909 int getSoundListSize()
1911 return (sound_info->num_file_list_entries +
1912 sound_info->num_dynamic_file_list_entries);
1915 int getMusicListSize()
1917 return (music_info->num_file_list_entries +
1918 music_info->num_dynamic_file_list_entries);
1921 struct FileInfo *getSoundListEntry(int pos)
1923 int num_list_entries = sound_info->num_file_list_entries;
1924 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1926 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
1927 &sound_info->dynamic_file_list[list_pos]);
1930 struct FileInfo *getMusicListEntry(int pos)
1932 int num_list_entries = music_info->num_file_list_entries;
1933 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1935 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
1936 &music_info->dynamic_file_list[list_pos]);
1939 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
1941 int num_list_entries = sound_info->num_file_list_entries;
1942 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1943 SoundInfo **snd_info =
1944 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
1945 sound_info->dynamic_artwork_list);
1947 return snd_info[list_pos];
1950 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
1952 int num_list_entries = music_info->num_file_list_entries;
1953 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1954 MusicInfo **mus_info =
1955 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
1956 music_info->dynamic_artwork_list);
1958 return mus_info[list_pos];
1961 int getSoundListPropertyMappingSize()
1963 return sound_info->num_property_mapping_entries;
1966 int getMusicListPropertyMappingSize()
1968 return music_info->num_property_mapping_entries;
1971 struct PropertyMapping *getSoundListPropertyMapping()
1973 return sound_info->property_mapping;
1976 struct PropertyMapping *getMusicListPropertyMapping()
1978 return music_info->property_mapping;
1981 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
1982 struct ConfigTypeInfo *config_suffix_list,
1983 char **base_prefixes, char **ext1_suffixes,
1984 char **ext2_suffixes, char **ext3_suffixes,
1985 char **ignore_tokens)
1989 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1990 sound_info->type = ARTWORK_TYPE_SOUNDS;
1992 /* ---------- initialize file list and suffix lists ---------- */
1994 sound_info->num_file_list_entries = num_file_list_entries;
1995 sound_info->num_dynamic_file_list_entries = 0;
1997 sound_info->file_list =
1998 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
1999 num_file_list_entries);
2000 sound_info->dynamic_file_list = NULL;
2002 sound_info->num_suffix_list_entries = 0;
2003 for (i = 0; config_suffix_list[i].token != NULL; i++)
2004 sound_info->num_suffix_list_entries++;
2006 sound_info->suffix_list = config_suffix_list;
2008 /* ---------- initialize base prefix and suffixes lists ---------- */
2010 sound_info->num_base_prefixes = 0;
2011 for (i = 0; base_prefixes[i] != NULL; i++)
2012 sound_info->num_base_prefixes++;
2014 sound_info->num_ext1_suffixes = 0;
2015 for (i = 0; ext1_suffixes[i] != NULL; i++)
2016 sound_info->num_ext1_suffixes++;
2018 sound_info->num_ext2_suffixes = 0;
2019 for (i = 0; ext2_suffixes[i] != NULL; i++)
2020 sound_info->num_ext2_suffixes++;
2022 sound_info->num_ext3_suffixes = 0;
2023 for (i = 0; ext3_suffixes[i] != NULL; i++)
2024 sound_info->num_ext3_suffixes++;
2026 sound_info->num_ignore_tokens = 0;
2027 for (i = 0; ignore_tokens[i] != NULL; i++)
2028 sound_info->num_ignore_tokens++;
2030 sound_info->base_prefixes = base_prefixes;
2031 sound_info->ext1_suffixes = ext1_suffixes;
2032 sound_info->ext2_suffixes = ext2_suffixes;
2033 sound_info->ext3_suffixes = ext3_suffixes;
2034 sound_info->ignore_tokens = ignore_tokens;
2036 sound_info->num_property_mapping_entries = 0;
2038 sound_info->property_mapping = NULL;
2040 /* ---------- initialize artwork reference and content lists ---------- */
2042 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
2044 sound_info->artwork_list =
2045 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
2046 sound_info->dynamic_artwork_list = NULL;
2048 sound_info->content_list = NULL;
2050 /* ---------- initialize artwork loading/freeing functions ---------- */
2052 sound_info->load_artwork = Load_WAV;
2053 sound_info->free_artwork = FreeSound;
2056 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
2057 struct ConfigTypeInfo *config_suffix_list,
2058 char **base_prefixes, char **ext1_suffixes,
2059 char **ext2_suffixes, char **ext3_suffixes,
2060 char **ignore_tokens)
2064 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
2065 music_info->type = ARTWORK_TYPE_MUSIC;
2067 /* ---------- initialize file list and suffix lists ---------- */
2069 music_info->num_file_list_entries = num_file_list_entries;
2070 music_info->num_dynamic_file_list_entries = 0;
2072 music_info->file_list =
2073 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
2074 num_file_list_entries);
2075 music_info->dynamic_file_list = NULL;
2077 music_info->num_suffix_list_entries = 0;
2078 for (i = 0; config_suffix_list[i].token != NULL; i++)
2079 music_info->num_suffix_list_entries++;
2081 music_info->suffix_list = config_suffix_list;
2083 /* ---------- initialize base prefix and suffixes lists ---------- */
2085 music_info->num_base_prefixes = 0;
2086 for (i = 0; base_prefixes[i] != NULL; i++)
2087 music_info->num_base_prefixes++;
2089 music_info->num_ext1_suffixes = 0;
2090 for (i = 0; ext1_suffixes[i] != NULL; i++)
2091 music_info->num_ext1_suffixes++;
2093 music_info->num_ext2_suffixes = 0;
2094 for (i = 0; ext2_suffixes[i] != NULL; i++)
2095 music_info->num_ext2_suffixes++;
2097 music_info->num_ext3_suffixes = 0;
2098 for (i = 0; ext3_suffixes[i] != NULL; i++)
2099 music_info->num_ext3_suffixes++;
2101 music_info->num_ignore_tokens = 0;
2102 for (i = 0; ignore_tokens[i] != NULL; i++)
2103 music_info->num_ignore_tokens++;
2105 music_info->base_prefixes = base_prefixes;
2106 music_info->ext1_suffixes = ext1_suffixes;
2107 music_info->ext2_suffixes = ext2_suffixes;
2108 music_info->ext3_suffixes = ext3_suffixes;
2109 music_info->ignore_tokens = ignore_tokens;
2111 music_info->num_property_mapping_entries = 0;
2113 music_info->property_mapping = NULL;
2115 /* ---------- initialize artwork reference and content lists ---------- */
2117 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
2119 music_info->artwork_list =
2120 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
2121 music_info->dynamic_artwork_list = NULL;
2123 music_info->content_list = NULL;
2125 /* ---------- initialize artwork loading/freeing functions ---------- */
2127 music_info->load_artwork = Load_WAV_or_MOD;
2128 music_info->free_artwork = FreeMusic;
2131 void PlayMusic(int nr)
2133 if (!audio.music_available)
2139 void PlaySound(int nr)
2141 if (!setup.sound_simple)
2144 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
2147 void PlaySoundStereo(int nr, int stereo_position)
2149 if (!setup.sound_simple)
2152 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
2155 void PlaySoundLoop(int nr)
2157 if (!setup.sound_loops)
2160 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
2163 void PlaySoundMusic(int nr)
2165 if (!setup.sound_music)
2168 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
2171 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
2173 SoundControl snd_ctrl;
2175 if (!audio.sound_available ||
2176 !audio.sound_enabled ||
2177 audio.sound_deactivated)
2180 volume = SETUP_SOUND_VOLUME(volume, state);
2182 if (volume < SOUND_MIN_VOLUME)
2183 volume = SOUND_MIN_VOLUME;
2184 else if (volume > SOUND_MAX_VOLUME)
2185 volume = SOUND_MAX_VOLUME;
2187 if (stereo_position < SOUND_MAX_LEFT)
2188 stereo_position = SOUND_MAX_LEFT;
2189 else if (stereo_position > SOUND_MAX_RIGHT)
2190 stereo_position = SOUND_MAX_RIGHT;
2192 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
2194 snd_ctrl.active = TRUE;
2196 snd_ctrl.volume = volume;
2197 snd_ctrl.stereo_position = stereo_position;
2198 snd_ctrl.state = state;
2200 HandleSoundRequest(snd_ctrl);
2203 void FadeMusic(void)
2205 if (!audio.music_available)
2208 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2211 void FadeSound(int nr)
2213 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2218 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2221 void FadeSoundsAndMusic()
2227 void StopMusic(void)
2229 if (!audio.music_available)
2232 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2235 void StopSound(int nr)
2237 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2243 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2246 void StopSoundExt(int nr, int state)
2248 SoundControl snd_ctrl;
2250 if (!audio.sound_available)
2253 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
2255 snd_ctrl.active = FALSE;
2257 snd_ctrl.state = state;
2259 HandleSoundRequest(snd_ctrl);
2262 static void ReloadCustomSounds()
2265 printf("::: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
2268 LoadArtworkConfig(sound_info);
2269 ReloadCustomArtworkList(sound_info);
2272 static void ReloadCustomMusic()
2275 printf("::: reloading music '%s' ...\n", artwork.mus_current_identifier);
2278 LoadArtworkConfig(music_info);
2279 ReloadCustomArtworkList(music_info);
2281 /* load all music files from directory not defined in "musicinfo.conf" */
2282 LoadCustomMusic_NoConf();
2285 void InitReloadCustomSounds(char *set_identifier)
2287 if (!audio.sound_available)
2290 #if defined(AUDIO_UNIX_NATIVE)
2291 LoadArtworkConfig(sound_info); /* also load config on sound client */
2292 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2294 ReloadCustomSounds();
2298 void InitReloadCustomMusic(char *set_identifier)
2300 if (!audio.music_available)
2303 #if defined(AUDIO_UNIX_NATIVE)
2304 LoadArtworkConfig(music_info); /* also load config on sound client */
2305 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2307 ReloadCustomMusic();
2311 void FreeSound(void *ptr)
2313 SoundInfo *sound = (SoundInfo *)ptr;
2318 if (sound->data_ptr)
2320 #if defined(TARGET_SDL)
2321 Mix_FreeChunk(sound->data_ptr);
2322 #else /* AUDIO_UNIX_NATIVE */
2323 free(sound->data_ptr);
2327 checked_free(sound->source_filename);
2332 void FreeMusic(void *ptr)
2334 MusicInfo *music = (MusicInfo *)ptr;
2339 if (music->data_ptr)
2341 #if defined(TARGET_SDL)
2342 if (music->type == MUS_TYPE_MOD)
2343 Mix_FreeMusic(music->data_ptr);
2345 Mix_FreeChunk(music->data_ptr);
2346 #else /* AUDIO_UNIX_NATIVE */
2347 free(music->data_ptr);
2354 static void FreeAllMusic_NoConf()
2358 if (Music_NoConf == NULL)
2361 for (i = 0; i < num_music_noconf; i++)
2362 FreeMusic(Music_NoConf[i]);
2366 Music_NoConf = NULL;
2367 num_music_noconf = 0;
2370 void FreeAllSounds()
2372 FreeCustomArtworkLists(sound_info);
2377 FreeCustomArtworkLists(music_info);
2378 FreeAllMusic_NoConf();
2381 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2382 /* ========================================================================= */