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 #define SND_TYPE_NONE 0
56 #define SND_TYPE_WAV 1
58 #define MUS_TYPE_NONE 0
59 #define MUS_TYPE_WAV 1
60 #define MUS_TYPE_MOD 2
62 #define DEVICENAME_DSP "/dev/dsp"
63 #define DEVICENAME_SOUND_DSP "/dev/sound/dsp"
64 #define DEVICENAME_AUDIO "/dev/audio"
65 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
67 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
68 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
70 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
71 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
73 #if defined(AUDIO_UNIX_NATIVE)
74 struct SoundHeader_WAV
76 unsigned short compression_code;
77 unsigned short num_channels;
78 unsigned long sample_rate;
79 unsigned long bytes_per_second;
80 unsigned short block_align;
81 unsigned short bits_per_sample;
85 struct AudioFormatInfo
87 boolean stereo; /* availability of stereo sound */
88 int format; /* size and endianess of sample data */
89 int sample_rate; /* sample frequency */
90 int fragment_size; /* audio device fragment size in bytes */
95 char *source_filename;
100 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
101 long data_len; /* number of samples, NOT number of bytes */
102 int num_channels; /* mono: 1 channel, stereo: 2 channels */
104 typedef struct SampleInfo SoundInfo;
105 typedef struct SampleInfo MusicInfo;
117 unsigned long playing_starttime;
118 unsigned long playing_pos;
122 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
123 long data_len; /* number of samples, NOT number of bytes */
124 int num_channels; /* mono: 1 channel, stereo: 2 channels */
126 #if defined(TARGET_ALLEGRO)
130 typedef struct SoundControl SoundControl;
132 static struct ArtworkListInfo *sound_info = NULL;
133 static struct ArtworkListInfo *music_info = NULL;
135 static MusicInfo **Music_NoConf = NULL;
137 static int num_music_noconf = 0;
138 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
141 /* ========================================================================= */
142 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
144 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
145 static int mixer_active_channels = 0;
147 #if defined(AUDIO_UNIX_NATIVE)
148 static struct AudioFormatInfo afmt;
150 static void Mixer_Main(void);
151 #if !defined(AUDIO_STREAMING_DSP)
152 static unsigned char linear_to_ulaw(int);
153 static int ulaw_to_linear(unsigned char);
157 static void ReloadCustomSounds();
158 static void ReloadCustomMusic();
159 static void FreeSound(void *);
160 static void FreeMusic(void *);
161 static void FreeAllMusic_NoConf();
163 static SoundInfo *getSoundInfoEntryFromSoundID(int);
164 static MusicInfo *getMusicInfoEntryFromMusicID(int);
167 /* ------------------------------------------------------------------------- */
168 /* functions for native (non-SDL) Unix audio/mixer support */
169 /* ------------------------------------------------------------------------- */
171 #if defined(AUDIO_UNIX_NATIVE)
173 static int OpenAudioDevice(char *audio_device_name)
177 /* check if desired audio device is accessible */
178 if (access(audio_device_name, W_OK) != 0)
181 /* try to open audio device in non-blocking mode */
182 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
183 return audio_device_fd;
185 /* re-open audio device in blocking mode */
186 close(audio_device_fd);
187 audio_device_fd = open(audio_device_name, O_WRONLY);
189 return audio_device_fd;
192 static void CloseAudioDevice(int *audio_device_fd)
194 if (*audio_device_fd == 0)
197 close(*audio_device_fd);
198 *audio_device_fd = -1;
201 static boolean TestAudioDevices(void)
203 static char *audio_device_name[] =
206 DEVICENAME_SOUND_DSP,
209 int audio_device_fd = -1;
212 /* look for available audio devices, starting with preferred ones */
213 for (i = 0; i < sizeof(audio_device_name)/sizeof(char *); i++)
214 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
217 if (audio_device_fd < 0)
219 Error(ERR_WARN, "cannot open audio device -- no sound");
223 close(audio_device_fd);
225 audio.device_name = audio_device_name[i];
230 static boolean ForkAudioProcess(void)
232 if (pipe(audio.mixer_pipe) < 0)
234 Error(ERR_WARN, "cannot create pipe -- no sounds");
238 if ((audio.mixer_pid = fork()) < 0)
240 Error(ERR_WARN, "cannot create sound server process -- no sounds");
244 if (audio.mixer_pid == 0) /* we are the child process */
245 audio.mixer_pid = getpid();
247 if (IS_CHILD_PROCESS())
248 Mixer_Main(); /* this function never returns */
250 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
255 void UnixOpenAudio(void)
257 if (!TestAudioDevices())
260 audio.sound_available = TRUE;
261 audio.sound_enabled = TRUE;
263 #if defined(AUDIO_STREAMING_DSP)
264 audio.music_available = TRUE;
265 audio.loops_available = TRUE;
268 audio.num_channels = NUM_MIXER_CHANNELS;
269 audio.music_channel = MUSIC_CHANNEL;
270 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
273 void UnixCloseAudio(void)
276 close(audio.device_fd);
278 if (IS_PARENT_PROCESS() && HAS_CHILD_PROCESS())
279 kill(audio.mixer_pid, SIGTERM);
283 /* ------------------------------------------------------------------------- */
284 /* functions for platform specific audio device initialization */
285 /* ------------------------------------------------------------------------- */
287 #if defined(AUDIO_LINUX_IOCTL)
288 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
290 /* "ioctl()" expects pointer to 'int' value for stereo flag
291 (boolean is defined as 'char', which will not work here) */
292 unsigned int fragment_spec = 0;
293 int fragment_size_query = -1;
302 /* supported audio format in preferred order */
303 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
304 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
305 { AFMT_U8, AUDIO_FORMAT_U8 },
310 /* determine logarithm (log2) of the fragment size */
311 while ((1 << fragment_spec) < afmt->fragment_size)
314 /* use two fragments (play one fragment, prepare the other);
315 one fragment would result in interrupted audio output, more
316 than two fragments would raise audio output latency to much */
317 fragment_spec |= 0x00020000;
319 /* Example for fragment specification:
320 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
321 - (with stereo the effective buffer size will shrink to 256)
322 => fragment_size = 0x00020009 */
324 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
325 Error(ERR_EXIT_SOUND_SERVER,
326 "cannot set fragment size of audio device -- no sounds");
330 while (formats[i].format_result != -1)
332 unsigned int audio_format = formats[i].format_ioctl;
333 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
335 afmt->format = formats[i].format_result;
340 if (afmt->format == 0) /* no supported audio format found */
341 Error(ERR_EXIT_SOUND_SERVER,
342 "cannot set audio format of audio device -- no sounds");
344 /* try if we can use stereo sound */
346 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
347 afmt->stereo = FALSE;
349 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
350 Error(ERR_EXIT_SOUND_SERVER,
351 "cannot set sample rate of audio device -- no sounds");
353 /* get the real fragmentation size; this should return 512 */
354 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
355 Error(ERR_EXIT_SOUND_SERVER,
356 "cannot get fragment size of audio device -- no sounds");
357 if (fragment_size_query != afmt->fragment_size)
358 Error(ERR_EXIT_SOUND_SERVER,
359 "cannot set fragment size of audio device -- no sounds");
361 #endif /* AUDIO_LINUX_IOCTL */
363 #if defined(PLATFORM_NETBSD)
364 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
367 boolean stereo = TRUE;
369 AUDIO_INITINFO(&a_info);
370 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
371 a_info.play.precision = 8;
372 a_info.play.channels = 2;
373 a_info.play.sample_rate = afmt->sample_rate;
374 a_info.blocksize = afmt->fragment_size;
376 afmt->format = AUDIO_FORMAT_U8;
379 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
381 /* try to disable stereo */
382 a_info.play.channels = 1;
384 afmt->stereo = FALSE;
386 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
387 Error(ERR_EXIT_SOUND_SERVER,
388 "cannot set sample rate of audio device -- no sounds");
391 #endif /* PLATFORM_NETBSD */
393 #if defined(PLATFORM_HPUX)
394 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
396 struct audio_describe ainfo;
399 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
401 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
403 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
404 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
406 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
407 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
409 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
410 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
412 afmt->format = AUDIO_FORMAT_U8;
413 afmt->stereo = FALSE;
414 afmt->sample_rate = 8000;
418 #endif /* PLATFORM_HPUX */
420 static void InitAudioDevice(struct AudioFormatInfo *afmt)
423 afmt->format = AUDIO_FORMAT_UNKNOWN;
424 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
425 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
427 #if defined(AUDIO_LINUX_IOCTL)
428 InitAudioDevice_Linux(afmt);
429 #elif defined(PLATFORM_NETBSD)
430 InitAudioDevice_NetBSD(afmt);
431 #elif defined(PLATFORM_HPUX)
432 InitAudioDevice_HPUX(afmt);
434 /* generic /dev/audio stuff might be placed here */
439 /* ------------------------------------------------------------------------- */
440 /* functions for communication between main process and sound mixer process */
441 /* ------------------------------------------------------------------------- */
443 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
445 if (IS_CHILD_PROCESS())
448 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
450 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
451 audio.sound_available = audio.sound_enabled = FALSE;
456 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
458 if (IS_PARENT_PROCESS())
461 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
462 != sizeof(SoundControl))
463 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
466 static void WriteReloadInfoToPipe(char *set_identifier, int type)
468 SoundControl snd_ctrl;
469 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
470 artwork.mus_current);
471 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
472 unsigned long str_size2 = strlen(leveldir_current->sounds_path) + 1;
473 unsigned long str_size3 = strlen(leveldir_current->music_path) + 1;
474 unsigned long str_size4 = strlen(ti->basepath) + 1;
475 unsigned long str_size5 = strlen(ti->fullpath) + 1;
476 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
477 setup.override_level_sounds :
478 setup.override_level_music);
480 if (IS_CHILD_PROCESS())
483 if (leveldir_current == NULL) /* should never happen */
484 Error(ERR_EXIT, "leveldir_current == NULL");
486 memset(&snd_ctrl, 0, sizeof(SoundControl)); /* to make valgrind happy */
488 snd_ctrl.active = FALSE;
489 snd_ctrl.state = type;
490 snd_ctrl.data_len = strlen(set_identifier) + 1;
492 if (write(audio.mixer_pipe[1], &snd_ctrl,
493 sizeof(snd_ctrl)) < 0 ||
494 write(audio.mixer_pipe[1], set_identifier,
495 snd_ctrl.data_len) < 0 ||
496 write(audio.mixer_pipe[1], &override_level_artwork,
497 sizeof(boolean)) < 0 ||
498 write(audio.mixer_pipe[1], leveldir_current,
499 sizeof(TreeInfo)) < 0 ||
500 write(audio.mixer_pipe[1], ti,
501 sizeof(TreeInfo)) < 0 ||
502 write(audio.mixer_pipe[1], &str_size1,
503 sizeof(unsigned long)) < 0 ||
504 write(audio.mixer_pipe[1], &str_size2,
505 sizeof(unsigned long)) < 0 ||
506 write(audio.mixer_pipe[1], &str_size3,
507 sizeof(unsigned long)) < 0 ||
508 write(audio.mixer_pipe[1], &str_size4,
509 sizeof(unsigned long)) < 0 ||
510 write(audio.mixer_pipe[1], &str_size5,
511 sizeof(unsigned long)) < 0 ||
512 write(audio.mixer_pipe[1], leveldir_current->fullpath,
514 write(audio.mixer_pipe[1], leveldir_current->sounds_path,
516 write(audio.mixer_pipe[1], leveldir_current->music_path,
518 write(audio.mixer_pipe[1], ti->basepath,
520 write(audio.mixer_pipe[1], ti->fullpath,
523 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
524 audio.sound_available = audio.sound_enabled = FALSE;
529 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
531 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
532 &artwork.snd_current : &artwork.mus_current);
533 TreeInfo *ti = *ti_ptr;
534 unsigned long str_size1, str_size2, str_size3, str_size4, str_size5;
535 static char *set_identifier = NULL;
536 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
537 &setup.override_level_sounds :
538 &setup.override_level_music);
540 checked_free(set_identifier);
542 set_identifier = checked_malloc(snd_ctrl->data_len);
544 if (leveldir_current == NULL)
545 leveldir_current = checked_calloc(sizeof(TreeInfo));
548 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
550 checked_free(leveldir_current->fullpath);
551 checked_free(leveldir_current->sounds_path);
552 checked_free(leveldir_current->music_path);
553 checked_free(ti->basepath);
554 checked_free(ti->fullpath);
556 if (read(audio.mixer_pipe[0], set_identifier,
557 snd_ctrl->data_len) != snd_ctrl->data_len ||
558 read(audio.mixer_pipe[0], override_level_artwork,
559 sizeof(boolean)) != sizeof(boolean) ||
560 read(audio.mixer_pipe[0], leveldir_current,
561 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
562 read(audio.mixer_pipe[0], ti,
563 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
564 read(audio.mixer_pipe[0], &str_size1,
565 sizeof(unsigned long)) != sizeof(unsigned long) ||
566 read(audio.mixer_pipe[0], &str_size2,
567 sizeof(unsigned long)) != sizeof(unsigned long) ||
568 read(audio.mixer_pipe[0], &str_size3,
569 sizeof(unsigned long)) != sizeof(unsigned long) ||
570 read(audio.mixer_pipe[0], &str_size4,
571 sizeof(unsigned long)) != sizeof(unsigned long) ||
572 read(audio.mixer_pipe[0], &str_size5,
573 sizeof(unsigned long)) != sizeof(unsigned long))
574 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
576 leveldir_current->fullpath = checked_calloc(str_size1);
577 leveldir_current->sounds_path = checked_calloc(str_size2);
578 leveldir_current->music_path = checked_calloc(str_size3);
579 ti->basepath = checked_calloc(str_size4);
580 ti->fullpath = checked_calloc(str_size5);
582 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
583 str_size1) != str_size1 ||
584 read(audio.mixer_pipe[0], leveldir_current->sounds_path,
585 str_size2) != str_size2 ||
586 read(audio.mixer_pipe[0], leveldir_current->music_path,
587 str_size3) != str_size3 ||
588 read(audio.mixer_pipe[0], ti->basepath,
589 str_size4) != str_size4 ||
590 read(audio.mixer_pipe[0], ti->fullpath,
591 str_size5) != str_size5)
592 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
594 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
595 artwork.snd_current_identifier = set_identifier;
597 artwork.mus_current_identifier = set_identifier;
600 #endif /* AUDIO_UNIX_NATIVE */
603 /* ------------------------------------------------------------------------- */
604 /* mixer functions */
605 /* ------------------------------------------------------------------------- */
607 void Mixer_InitChannels()
611 for (i = 0; i < audio.num_channels; i++)
612 mixer[i].active = FALSE;
613 mixer_active_channels = 0;
616 static void Mixer_ResetChannelExpiration(int channel)
618 mixer[channel].playing_starttime = Counter();
620 #if defined(TARGET_SDL)
621 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
622 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
626 static boolean Mixer_ChannelExpired(int channel)
628 if (!mixer[channel].active)
631 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
632 DelayReached(&mixer[channel].playing_starttime,
633 SOUND_LOOP_EXPIRATION_TIME))
636 #if defined(TARGET_SDL)
638 if (!Mix_Playing(channel))
641 #elif defined(TARGET_ALLEGRO)
643 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
644 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
646 /* sound sample has completed playing or was completely faded out */
647 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
650 #endif /* TARGET_ALLEGRO */
655 static boolean Mixer_AllocateChannel(int channel)
657 #if defined(TARGET_ALLEGRO)
658 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
659 if (mixer[channel].voice < 0)
666 static void Mixer_SetChannelProperties(int channel)
668 #if defined(TARGET_SDL)
669 Mix_Volume(channel, mixer[channel].volume);
670 Mix_SetPanning(channel,
671 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
672 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
673 #elif defined(TARGET_ALLEGRO)
674 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
675 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
679 static void Mixer_StartChannel(int channel)
681 #if defined(TARGET_SDL)
682 Mix_PlayChannel(channel, mixer[channel].data_ptr,
683 IS_LOOP(mixer[channel]) ? -1 : 0);
684 #elif defined(TARGET_ALLEGRO)
685 if (IS_LOOP(mixer[channel]))
686 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
688 voice_start(mixer[channel].voice);
692 static void Mixer_PlayChannel(int channel)
694 /* start with inactive channel in case something goes wrong */
695 mixer[channel].active = FALSE;
697 if (mixer[channel].type != MUS_TYPE_WAV)
700 if (!Mixer_AllocateChannel(channel))
703 Mixer_SetChannelProperties(channel);
704 Mixer_StartChannel(channel);
706 Mixer_ResetChannelExpiration(channel);
708 mixer[channel].playing_pos = 0;
709 mixer[channel].active = TRUE;
710 mixer_active_channels++;
713 static void Mixer_PlayMusicChannel()
715 Mixer_PlayChannel(audio.music_channel);
717 #if defined(TARGET_SDL)
718 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
720 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
721 this looks like a bug in the SDL_mixer library */
722 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
723 Mix_VolumeMusic(SOUND_MAX_VOLUME);
728 static void Mixer_StopChannel(int channel)
730 if (!mixer[channel].active)
733 #if defined(TARGET_SDL)
734 Mix_HaltChannel(channel);
735 #elif defined(TARGET_ALLEGRO)
736 voice_set_volume(mixer[channel].voice, 0);
737 deallocate_voice(mixer[channel].voice);
740 mixer[channel].active = FALSE;
741 mixer_active_channels--;
744 static void Mixer_StopMusicChannel()
746 Mixer_StopChannel(audio.music_channel);
748 #if defined(TARGET_SDL)
753 static void Mixer_FadeChannel(int channel)
755 if (!mixer[channel].active)
758 mixer[channel].state |= SND_CTRL_FADE;
760 #if defined(TARGET_SDL)
761 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
762 #elif defined(TARGET_ALLEGRO)
763 if (voice_check(mixer[channel].voice))
764 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
768 static void Mixer_FadeMusicChannel()
770 Mixer_FadeChannel(audio.music_channel);
772 #if defined(TARGET_SDL)
773 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
777 static void Mixer_UnFadeChannel(int channel)
779 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
782 mixer[channel].state &= ~SND_CTRL_FADE;
783 mixer[channel].volume = SOUND_MAX_VOLUME;
785 #if defined(TARGET_SDL)
786 Mix_ExpireChannel(channel, -1);
787 Mix_Volume(channel, mixer[channel].volume);
788 #elif defined(TARGET_ALLEGRO)
789 voice_stop_volumeramp(mixer[channel].voice);
790 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
791 mixer[channel].volume);
795 static void Mixer_InsertSound(SoundControl snd_ctrl)
799 int num_sounds = getSoundListSize();
800 int num_music = getMusicListSize();
802 if (IS_MUSIC(snd_ctrl))
804 if (snd_ctrl.nr >= num_music) /* invalid music */
807 if (snd_ctrl.nr < 0) /* undefined music */
809 if (num_music_noconf == 0) /* no fallback music available */
812 snd_ctrl.nr = UNMAP_NOCONF_MUSIC(snd_ctrl.nr) % num_music_noconf;
813 snd_info = Music_NoConf[snd_ctrl.nr];
816 snd_info = getMusicInfoEntryFromMusicID(snd_ctrl.nr);
820 if (snd_ctrl.nr < 0 || snd_ctrl.nr >= num_sounds)
823 snd_info = getSoundInfoEntryFromSoundID(snd_ctrl.nr);
826 if (snd_info == NULL)
829 /* copy sound sample and format information */
830 snd_ctrl.type = snd_info->type;
831 snd_ctrl.format = snd_info->format;
832 snd_ctrl.data_ptr = snd_info->data_ptr;
833 snd_ctrl.data_len = snd_info->data_len;
834 snd_ctrl.num_channels = snd_info->num_channels;
836 /* play music samples on a dedicated music channel */
837 if (IS_MUSIC(snd_ctrl))
839 Mixer_StopMusicChannel();
841 mixer[audio.music_channel] = snd_ctrl;
842 Mixer_PlayMusicChannel();
847 /* check if (and how often) this sound sample is already playing */
848 for (k = 0, i = audio.first_sound_channel; i < audio.num_channels; i++)
849 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
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))
859 if (IS_FADING(mixer[i]))
860 Mixer_UnFadeChannel(i);
862 /* restore settings like volume and stereo position */
863 mixer[i].volume = snd_ctrl.volume;
864 mixer[i].stereo_position = snd_ctrl.stereo_position;
866 Mixer_SetChannelProperties(i);
867 Mixer_ResetChannelExpiration(i);
874 /* don't play sound more than n times simultaneously (with n == 2 for now) */
877 unsigned long playing_current = Counter();
878 int longest = 0, longest_nr = audio.first_sound_channel;
880 /* look for oldest equal sound */
881 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
883 int playing_time = playing_current - mixer[i].playing_starttime;
886 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
889 actual = 1000 * playing_time / mixer[i].data_len;
891 if (actual >= longest)
898 Mixer_StopChannel(longest_nr);
901 /* If all (non-music) channels are active, stop the channel that has
902 played its sound sample most completely (in percent of the sample
903 length). As we cannot currently get the actual playing position
904 of the channel's sound sample when compiling with the SDL mixer
905 library, we use the current playing time (in milliseconds) instead. */
908 /* channel allocation sanity check -- should not be needed */
909 if (mixer_active_channels ==
910 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
912 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
914 if (!mixer[i].active)
916 Error(ERR_RETURN, "Mixer_InsertSound: Channel %d inactive", i);
917 Error(ERR_RETURN, "Mixer_InsertSound: This should never happen!");
919 mixer_active_channels--;
925 if (mixer_active_channels ==
926 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
928 unsigned long playing_current = Counter();
929 int longest = 0, longest_nr = audio.first_sound_channel;
933 /* print some debugging information about audio channel usage */
934 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
936 Error(ERR_RETURN, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
937 i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
942 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
944 int playing_time = playing_current - mixer[i].playing_starttime;
945 int actual = 1000 * playing_time / mixer[i].data_len;
947 if (!IS_LOOP(mixer[i]) && actual > longest)
954 Mixer_StopChannel(longest_nr);
957 /* add the new sound to the mixer */
958 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
960 if (!mixer[i].active)
962 #if defined(AUDIO_UNIX_NATIVE)
963 if (snd_info->data_len == 0)
965 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
970 Mixer_PlayChannel(i);
977 static void HandleSoundRequest(SoundControl snd_ctrl)
981 #if defined(AUDIO_UNIX_NATIVE)
982 if (IS_PARENT_PROCESS())
984 SendSoundControlToMixerProcess(&snd_ctrl);
989 /* deactivate channels that have expired since the last request */
990 for (i = 0; i < audio.num_channels; i++)
991 if (mixer[i].active && Mixer_ChannelExpired(i))
992 Mixer_StopChannel(i);
994 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
996 Mixer_StopMusicChannel();
997 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
998 Mixer_StopChannel(i);
1000 #if defined(AUDIO_UNIX_NATIVE)
1001 CloseAudioDevice(&audio.device_fd);
1002 ReadReloadInfoFromPipe(&snd_ctrl);
1005 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1006 ReloadCustomSounds();
1008 ReloadCustomMusic();
1010 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1012 if (IS_MUSIC(snd_ctrl))
1014 Mixer_FadeMusicChannel();
1018 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
1019 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1020 Mixer_FadeChannel(i);
1022 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1024 if (IS_MUSIC(snd_ctrl))
1026 Mixer_StopMusicChannel();
1030 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
1031 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1032 Mixer_StopChannel(i);
1034 #if defined(AUDIO_UNIX_NATIVE)
1035 if (!mixer_active_channels)
1036 CloseAudioDevice(&audio.device_fd);
1039 else if (snd_ctrl.active) /* add new sound to mixer */
1041 Mixer_InsertSound(snd_ctrl);
1045 void StartMixer(void)
1050 SDL_version compile_version;
1051 const SDL_version *link_version;
1052 MIX_VERSION(&compile_version);
1053 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1054 compile_version.major,
1055 compile_version.minor,
1056 compile_version.patch);
1057 link_version = Mix_Linked_Version();
1058 printf("running with SDL_mixer version: %d.%d.%d\n",
1059 link_version->major,
1060 link_version->minor,
1061 link_version->patch);
1064 if (!audio.sound_available)
1067 /* initialize stereo position conversion information */
1068 for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
1070 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1072 #if defined(AUDIO_UNIX_NATIVE)
1073 if (!ForkAudioProcess())
1074 audio.sound_available = FALSE;
1078 #if defined(AUDIO_UNIX_NATIVE)
1080 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1081 int sample_pos, int sample_size,
1082 short *buffer_base_ptr, int buffer_pos,
1083 int num_output_channels)
1085 short *buffer_ptr = buffer_base_ptr + num_output_channels * buffer_pos;
1086 int num_channels = snd_ctrl->num_channels;
1087 int stepsize = num_channels;
1088 int output_stepsize = num_output_channels;
1091 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1093 byte *sample_ptr = (byte *)snd_ctrl->data_ptr + num_channels * sample_pos;
1095 for (i = 0; i < num_output_channels; i++)
1097 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1099 for (j = 0; j < sample_size; j++)
1100 buffer_ptr[output_stepsize * j + i] =
1101 ((short)(sample_ptr[stepsize * j + offset] ^ 0x80)) << 8;
1104 else /* AUDIO_FORMAT_S16 */
1106 short *sample_ptr= (short *)snd_ctrl->data_ptr + num_channels * sample_pos;
1108 for (i = 0; i < num_output_channels; i++)
1110 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1112 for (j = 0; j < sample_size; j++)
1113 buffer_ptr[output_stepsize * j + i] =
1114 sample_ptr[stepsize * j + offset];
1119 #if defined(AUDIO_STREAMING_DSP)
1120 static void Mixer_Main_DSP()
1122 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1123 static long premix_last_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1124 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1128 int max_sample_size;
1129 int num_output_channels;
1132 if (!mixer_active_channels)
1135 if (audio.device_fd < 0)
1137 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1140 InitAudioDevice(&afmt);
1143 stereo = afmt.stereo;
1144 fragment_size = afmt.fragment_size;
1145 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1146 num_output_channels = (stereo ? 2 : 1);
1147 max_sample_size = fragment_size / (num_output_channels * sample_bytes);
1149 /* first clear the last premixing buffer */
1150 memset(premix_last_buffer, 0,
1151 max_sample_size * num_output_channels * sizeof(long));
1153 for (i = 0; i < audio.num_channels; i++)
1160 if (!mixer[i].active)
1163 if (Mixer_ChannelExpired(i))
1165 Mixer_StopChannel(i);
1169 /* pointer, lenght and actual playing position of sound sample */
1170 sample_ptr = mixer[i].data_ptr;
1171 sample_len = mixer[i].data_len;
1172 sample_pos = mixer[i].playing_pos;
1173 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1174 mixer[i].playing_pos += sample_size;
1176 /* copy original sample to first mixing buffer */
1177 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1178 premix_first_buffer, 0, num_output_channels);
1180 /* are we about to restart a looping sound? */
1181 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1183 while (sample_size < max_sample_size)
1185 int restarted_sample_size =
1186 MIN(max_sample_size - sample_size, sample_len);
1188 CopySampleToMixingBuffer(&mixer[i], 0, restarted_sample_size,
1189 premix_first_buffer, sample_size,
1190 num_output_channels);
1192 mixer[i].playing_pos = restarted_sample_size;
1193 sample_size += restarted_sample_size;
1197 /* decrease volume if sound is fading out */
1198 if (IS_FADING(mixer[i]) &&
1199 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1200 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1202 /* adjust volume of actual sound sample */
1203 if (mixer[i].volume != SOUND_MAX_VOLUME)
1204 for (j = 0; j < sample_size * num_output_channels; j++)
1205 premix_first_buffer[j] =
1206 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1208 /* adjust left and right channel volume due to stereo sound position */
1211 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1212 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1214 for (j = 0; j < sample_size; j++)
1216 premix_first_buffer[2 * j + 0] =
1217 left_volume * premix_first_buffer[2 * j + 0] / SOUND_MAX_LEFT2RIGHT;
1218 premix_first_buffer[2 * j + 1] =
1219 right_volume * premix_first_buffer[2 * j + 1] / SOUND_MAX_LEFT2RIGHT;
1223 /* fill the last mixing buffer with stereo or mono sound */
1224 for (j = 0; j < sample_size * num_output_channels; j++)
1225 premix_last_buffer[j] += premix_first_buffer[j];
1227 /* delete completed sound entries from the mixer */
1228 if (mixer[i].playing_pos >= mixer[i].data_len)
1230 if (IS_LOOP(mixer[i]))
1231 mixer[i].playing_pos = 0;
1233 Mixer_StopChannel(i);
1235 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1236 Mixer_StopChannel(i);
1239 /* prepare final playing buffer according to system audio format */
1240 for (i = 0; i < max_sample_size * num_output_channels; i++)
1242 /* cut off at 17 bit value */
1243 if (premix_last_buffer[i] < -65535)
1244 premix_last_buffer[i] = -65535;
1245 else if (premix_last_buffer[i] > 65535)
1246 premix_last_buffer[i] = 65535;
1248 /* shift to 16 bit value */
1249 premix_last_buffer[i] >>= 1;
1251 if (afmt.format & AUDIO_FORMAT_U8)
1253 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1255 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1257 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1258 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1260 else /* big endian */
1262 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1263 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1267 /* finally play the sound fragment */
1268 write(audio.device_fd, playing_buffer, fragment_size);
1270 if (!mixer_active_channels)
1271 CloseAudioDevice(&audio.device_fd);
1274 #else /* !AUDIO_STREAMING_DSP */
1276 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1278 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1279 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1280 int max_sample_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1281 int num_output_channels = 1;
1290 /* pointer, lenght and actual playing position of sound sample */
1291 sample_ptr = mixer[i].data_ptr;
1292 sample_len = mixer[i].data_len;
1293 sample_pos = mixer[i].playing_pos;
1294 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1295 mixer[i].playing_pos += sample_size;
1297 /* copy original sample to first mixing buffer */
1298 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1299 premix_first_buffer, 0, num_output_channels);
1301 /* adjust volume of actual sound sample */
1302 if (mixer[i].volume != SOUND_MAX_VOLUME)
1303 for (j = 0; j < sample_size; j++)
1304 premix_first_buffer[j] =
1305 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1307 /* might be needed for u-law /dev/audio */
1308 for (j = 0; j < sample_size; j++)
1310 linear_to_ulaw(premix_first_buffer[j]);
1312 /* delete completed sound entries from the mixer */
1313 if (mixer[i].playing_pos >= mixer[i].data_len)
1314 Mixer_StopChannel(i);
1316 for (i = 0; i < sample_size; i++)
1317 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1319 /* finally play the sound fragment */
1320 write(audio.device_fd, playing_buffer, sample_size);
1324 #endif /* !AUDIO_STREAMING_DSP */
1328 SoundControl snd_ctrl;
1331 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1333 Mixer_InitChannels();
1335 #if defined(PLATFORM_HPUX)
1336 InitAudioDevice(&afmt);
1339 FD_ZERO(&mixer_fdset);
1340 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1342 while (1) /* wait for sound playing commands from client */
1344 struct timeval delay = { 0, 0 };
1346 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1347 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1348 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1351 ReadSoundControlFromMainProcess(&snd_ctrl);
1353 HandleSoundRequest(snd_ctrl);
1355 #if defined(AUDIO_STREAMING_DSP)
1357 while (mixer_active_channels &&
1358 select(audio.mixer_pipe[0] + 1,
1359 &mixer_fdset, NULL, NULL, &delay) < 1)
1361 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1366 #else /* !AUDIO_STREAMING_DSP */
1368 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1369 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1372 InitAudioDevice(&afmt);
1377 while (mixer_active_channels &&
1378 select(audio.mixer_pipe[0] + 1,
1379 &mixer_fdset, NULL, NULL, &delay) < 1)
1381 int wait_percent = 90; /* wait 90% of the real playing time */
1384 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1386 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1390 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1393 CloseAudioDevice(&audio.device_fd);
1395 Mixer_InitChannels(); /* remove all sounds from mixer */
1397 #endif /* !AUDIO_STREAMING_DSP */
1400 #endif /* AUDIO_UNIX_NATIVE */
1403 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1405 /* these two are stolen from "sox"... :) */
1408 ** This routine converts from linear to ulaw.
1410 ** Craig Reese: IDA/Supercomputing Research Center
1411 ** Joe Campbell: Department of Defense
1412 ** 29 September 1989
1415 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1416 ** 2) "A New Digital Technique for Implementation of Any
1417 ** Continuous PCM Companding Law," Villeret, Michel,
1418 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1419 ** 1973, pg. 11.12-11.17
1420 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1421 ** for Analog-to_Digital Conversion Techniques,"
1424 ** Input: Signed 16 bit linear sample
1425 ** Output: 8 bit ulaw sample
1428 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1429 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1432 static unsigned char linear_to_ulaw(int sample)
1434 static int exp_lut[256] =
1436 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1437 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1438 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1439 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1440 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1441 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1442 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1443 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1444 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1445 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1446 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1447 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
1454 int sign, exponent, mantissa;
1455 unsigned char ulawbyte;
1457 /* Get the sample into sign-magnitude. */
1458 sign = (sample >> 8) & 0x80; /* set aside the sign */
1460 sample = -sample; /* get magnitude */
1462 sample = CLIP; /* clip the magnitude */
1464 /* Convert from 16 bit linear to ulaw. */
1465 sample = sample + BIAS;
1466 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1467 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1468 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1471 ulawbyte = 0x02; /* optional CCITT trap */
1478 ** This routine converts from ulaw to 16 bit linear.
1480 ** Craig Reese: IDA/Supercomputing Research Center
1481 ** 29 September 1989
1484 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1485 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1486 ** for Analog-to_Digital Conversion Techniques,"
1489 ** Input: 8 bit ulaw sample
1490 ** Output: signed 16 bit linear sample
1493 static int ulaw_to_linear(unsigned char ulawbyte)
1495 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1496 int sign, exponent, mantissa, sample;
1498 ulawbyte = ~ ulawbyte;
1499 sign = ( ulawbyte & 0x80 );
1500 exponent = ( ulawbyte >> 4 ) & 0x07;
1501 mantissa = ulawbyte & 0x0F;
1502 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1508 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1511 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1512 /* ========================================================================= */
1513 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1515 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1516 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1518 static void *Load_WAV(char *filename)
1520 SoundInfo *snd_info;
1521 #if defined(AUDIO_UNIX_NATIVE)
1522 struct SoundHeader_WAV header;
1524 byte sound_header_buffer[WAV_HEADER_SIZE];
1527 char chunk_name[CHUNK_ID_LEN + 1];
1533 if (!audio.sound_available)
1536 snd_info = checked_calloc(sizeof(SoundInfo));
1538 #if defined(TARGET_SDL)
1540 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1542 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1547 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1549 #elif defined(TARGET_ALLEGRO)
1551 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1553 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1558 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1560 #else /* AUDIO_UNIX_NATIVE */
1562 if ((file = fopen(filename, MODE_READ)) == NULL)
1564 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1569 /* read chunk id "RIFF" */
1570 getFileChunkLE(file, chunk_name, &chunk_size);
1571 if (strcmp(chunk_name, "RIFF") != 0)
1573 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1579 /* read "RIFF" type id "WAVE" */
1580 getFileChunkLE(file, chunk_name, NULL);
1581 if (strcmp(chunk_name, "WAVE") != 0)
1583 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1589 while (getFileChunkLE(file, chunk_name, &chunk_size))
1591 if (strcmp(chunk_name, "fmt ") == 0)
1593 if (chunk_size < WAV_HEADER_SIZE)
1595 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1601 header.compression_code = getFile16BitLE(file);
1602 header.num_channels = getFile16BitLE(file);
1603 header.sample_rate = getFile32BitLE(file);
1604 header.bytes_per_second = getFile32BitLE(file);
1605 header.block_align = getFile16BitLE(file);
1606 header.bits_per_sample = getFile16BitLE(file);
1608 if (chunk_size > WAV_HEADER_SIZE)
1609 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1611 if (header.compression_code != 1)
1613 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1614 filename, header.compression_code);
1620 if (header.num_channels != 1 &&
1621 header.num_channels != 2)
1623 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1624 filename, header.num_channels);
1630 if (header.bits_per_sample != 8 &&
1631 header.bits_per_sample != 16)
1633 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1634 filename, header.bits_per_sample);
1640 /* warn, but accept wrong sample rate (may be only slightly different) */
1641 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1642 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1643 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1646 printf("WAV file: '%s'\n", filename);
1647 printf(" Compression code: %d'\n", header.compression_code);
1648 printf(" Number of channels: %d'\n", header.num_channels);
1649 printf(" Sample rate: %ld'\n", header.sample_rate);
1650 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1651 printf(" Block align: %d'\n", header.block_align);
1652 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1655 else if (strcmp(chunk_name, "data") == 0)
1657 data_byte_len = chunk_size;
1659 snd_info->data_len = data_byte_len;
1660 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1662 /* read sound data */
1663 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1666 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1668 free(snd_info->data_ptr);
1673 /* check for odd number of data bytes (data chunk is word aligned) */
1674 if ((data_byte_len % 2) == 1)
1675 ReadUnusedBytesFromFile(file, 1);
1677 else /* unknown chunk -- ignore */
1678 ReadUnusedBytesFromFile(file, chunk_size);
1683 if (snd_info->data_ptr == NULL)
1685 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1690 if (header.bits_per_sample == 8)
1691 snd_info->format = AUDIO_FORMAT_U8;
1692 else /* header.bits_per_sample == 16 */
1694 snd_info->format = AUDIO_FORMAT_S16;
1695 snd_info->data_len /= 2; /* correct number of samples */
1698 snd_info->num_channels = header.num_channels;
1699 if (header.num_channels == 2)
1700 snd_info->data_len /= 2; /* correct number of samples */
1703 if (header.num_channels == 1) /* convert mono sound to stereo */
1705 void *buffer_ptr = checked_malloc(data_byte_len * 2);
1706 void *sample_ptr = snd_info->data_ptr;
1707 int sample_size = snd_info->data_len;
1710 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1711 for (i = 0; i < sample_size; i++)
1713 ((short)(((byte *)sample_ptr)[i] ^ 0x80)) << 8;
1714 else /* AUDIO_FORMAT_S16 */
1715 for (i = 0; i < sample_size; i++)
1717 ((short *)sample_ptr)[i];
1721 #endif /* AUDIO_UNIX_NATIVE */
1723 snd_info->type = SND_TYPE_WAV;
1724 snd_info->source_filename = getStringCopy(filename);
1729 static void *Load_MOD(char *filename)
1731 #if defined(TARGET_SDL)
1732 MusicInfo *mod_info;
1734 if (!audio.sound_available)
1737 mod_info = checked_calloc(sizeof(MusicInfo));
1739 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1741 Error(ERR_WARN, "cannot read music file '%s'", filename);
1746 mod_info->type = MUS_TYPE_MOD;
1747 mod_info->source_filename = getStringCopy(filename);
1755 static void *Load_WAV_or_MOD(char *filename)
1757 if (FileIsSound(filename))
1758 return Load_WAV(filename);
1759 else if (FileIsMusic(filename))
1760 return Load_MOD(filename);
1765 void LoadCustomMusic_NoConf(void)
1767 static boolean draw_init_text = TRUE; /* only draw at startup */
1768 static char *last_music_directory = NULL;
1769 char *music_directory = getCustomMusicDirectory();
1771 struct dirent *dir_entry;
1772 int num_music = getMusicListSize();
1774 if (!audio.sound_available)
1777 if (last_music_directory != NULL &&
1778 strcmp(last_music_directory, music_directory) == 0)
1779 return; /* old and new music directory are the same */
1781 if (last_music_directory != NULL)
1782 free(last_music_directory);
1783 last_music_directory = getStringCopy(music_directory);
1785 FreeAllMusic_NoConf();
1787 if ((dir = opendir(music_directory)) == NULL)
1789 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1790 audio.music_available = FALSE;
1795 DrawInitText("Loading music:", 120, FC_GREEN);
1797 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1799 char *basename = dir_entry->d_name;
1800 char *filename = NULL;
1801 MusicInfo *mus_info = NULL;
1802 boolean music_already_used = FALSE;
1805 /* skip all music files that are configured in music config file */
1806 for (i = 0; i < num_music; i++)
1808 struct FileInfo *music = getMusicListEntry(i);
1810 if (strcmp(basename, music->filename) == 0)
1812 music_already_used = TRUE;
1817 if (music_already_used)
1821 DrawInitText(basename, 150, FC_YELLOW);
1823 filename = getPath2(music_directory, basename);
1825 if (FileIsMusic(basename))
1826 mus_info = Load_WAV_or_MOD(filename);
1833 Music_NoConf = checked_realloc(Music_NoConf,
1834 num_music_noconf * sizeof(MusicInfo *));
1835 Music_NoConf[num_music_noconf - 1] = mus_info;
1841 draw_init_text = FALSE;
1844 int getSoundListSize()
1846 return (sound_info->num_file_list_entries +
1847 sound_info->num_dynamic_file_list_entries);
1850 int getMusicListSize()
1852 return (music_info->num_file_list_entries +
1853 music_info->num_dynamic_file_list_entries);
1856 struct FileInfo *getSoundListEntry(int pos)
1858 int num_list_entries = sound_info->num_file_list_entries;
1859 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1861 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
1862 &sound_info->dynamic_file_list[list_pos]);
1865 struct FileInfo *getMusicListEntry(int pos)
1867 int num_list_entries = music_info->num_file_list_entries;
1868 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1870 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
1871 &music_info->dynamic_file_list[list_pos]);
1874 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
1876 int num_list_entries = sound_info->num_file_list_entries;
1877 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1878 SoundInfo **snd_info =
1879 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
1880 sound_info->dynamic_artwork_list);
1882 return snd_info[list_pos];
1885 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
1887 int num_list_entries = music_info->num_file_list_entries;
1888 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1889 MusicInfo **mus_info =
1890 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
1891 music_info->dynamic_artwork_list);
1893 return mus_info[list_pos];
1896 int getSoundListPropertyMappingSize()
1898 return sound_info->num_property_mapping_entries;
1901 int getMusicListPropertyMappingSize()
1903 return music_info->num_property_mapping_entries;
1906 struct PropertyMapping *getSoundListPropertyMapping()
1908 return sound_info->property_mapping;
1911 struct PropertyMapping *getMusicListPropertyMapping()
1913 return music_info->property_mapping;
1916 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
1917 struct ConfigTypeInfo *config_suffix_list,
1918 char **base_prefixes, char **ext1_suffixes,
1919 char **ext2_suffixes, char **ext3_suffixes,
1920 char **ignore_tokens)
1924 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1925 sound_info->type = ARTWORK_TYPE_SOUNDS;
1927 /* ---------- initialize file list and suffix lists ---------- */
1929 sound_info->num_file_list_entries = num_file_list_entries;
1930 sound_info->num_dynamic_file_list_entries = 0;
1932 sound_info->file_list =
1933 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
1934 num_file_list_entries);
1935 sound_info->dynamic_file_list = NULL;
1937 sound_info->num_suffix_list_entries = 0;
1938 for (i = 0; config_suffix_list[i].token != NULL; i++)
1939 sound_info->num_suffix_list_entries++;
1941 sound_info->suffix_list = config_suffix_list;
1943 /* ---------- initialize base prefix and suffixes lists ---------- */
1945 sound_info->num_base_prefixes = 0;
1946 for (i = 0; base_prefixes[i] != NULL; i++)
1947 sound_info->num_base_prefixes++;
1949 sound_info->num_ext1_suffixes = 0;
1950 for (i = 0; ext1_suffixes[i] != NULL; i++)
1951 sound_info->num_ext1_suffixes++;
1953 sound_info->num_ext2_suffixes = 0;
1954 for (i = 0; ext2_suffixes[i] != NULL; i++)
1955 sound_info->num_ext2_suffixes++;
1957 sound_info->num_ext3_suffixes = 0;
1958 for (i = 0; ext3_suffixes[i] != NULL; i++)
1959 sound_info->num_ext3_suffixes++;
1961 sound_info->num_ignore_tokens = 0;
1962 for (i = 0; ignore_tokens[i] != NULL; i++)
1963 sound_info->num_ignore_tokens++;
1965 sound_info->base_prefixes = base_prefixes;
1966 sound_info->ext1_suffixes = ext1_suffixes;
1967 sound_info->ext2_suffixes = ext2_suffixes;
1968 sound_info->ext3_suffixes = ext3_suffixes;
1969 sound_info->ignore_tokens = ignore_tokens;
1971 sound_info->num_property_mapping_entries = 0;
1973 sound_info->property_mapping = NULL;
1975 /* ---------- initialize artwork reference and content lists ---------- */
1977 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
1979 sound_info->artwork_list =
1980 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
1981 sound_info->dynamic_artwork_list = NULL;
1983 sound_info->content_list = NULL;
1985 /* ---------- initialize artwork loading/freeing functions ---------- */
1987 sound_info->load_artwork = Load_WAV;
1988 sound_info->free_artwork = FreeSound;
1991 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
1992 struct ConfigTypeInfo *config_suffix_list,
1993 char **base_prefixes, char **ext1_suffixes,
1994 char **ext2_suffixes, char **ext3_suffixes,
1995 char **ignore_tokens)
1999 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
2000 music_info->type = ARTWORK_TYPE_MUSIC;
2002 /* ---------- initialize file list and suffix lists ---------- */
2004 music_info->num_file_list_entries = num_file_list_entries;
2005 music_info->num_dynamic_file_list_entries = 0;
2007 music_info->file_list =
2008 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
2009 num_file_list_entries);
2010 music_info->dynamic_file_list = NULL;
2012 music_info->num_suffix_list_entries = 0;
2013 for (i = 0; config_suffix_list[i].token != NULL; i++)
2014 music_info->num_suffix_list_entries++;
2016 music_info->suffix_list = config_suffix_list;
2018 /* ---------- initialize base prefix and suffixes lists ---------- */
2020 music_info->num_base_prefixes = 0;
2021 for (i = 0; base_prefixes[i] != NULL; i++)
2022 music_info->num_base_prefixes++;
2024 music_info->num_ext1_suffixes = 0;
2025 for (i = 0; ext1_suffixes[i] != NULL; i++)
2026 music_info->num_ext1_suffixes++;
2028 music_info->num_ext2_suffixes = 0;
2029 for (i = 0; ext2_suffixes[i] != NULL; i++)
2030 music_info->num_ext2_suffixes++;
2032 music_info->num_ext3_suffixes = 0;
2033 for (i = 0; ext3_suffixes[i] != NULL; i++)
2034 music_info->num_ext3_suffixes++;
2036 music_info->num_ignore_tokens = 0;
2037 for (i = 0; ignore_tokens[i] != NULL; i++)
2038 music_info->num_ignore_tokens++;
2040 music_info->base_prefixes = base_prefixes;
2041 music_info->ext1_suffixes = ext1_suffixes;
2042 music_info->ext2_suffixes = ext2_suffixes;
2043 music_info->ext3_suffixes = ext3_suffixes;
2044 music_info->ignore_tokens = ignore_tokens;
2046 music_info->num_property_mapping_entries = 0;
2048 music_info->property_mapping = NULL;
2050 /* ---------- initialize artwork reference and content lists ---------- */
2052 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
2054 music_info->artwork_list =
2055 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
2056 music_info->dynamic_artwork_list = NULL;
2058 music_info->content_list = NULL;
2060 /* ---------- initialize artwork loading/freeing functions ---------- */
2062 music_info->load_artwork = Load_WAV_or_MOD;
2063 music_info->free_artwork = FreeMusic;
2066 void PlayMusic(int nr)
2068 if (!audio.music_available)
2074 void PlaySound(int nr)
2076 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
2079 void PlaySoundStereo(int nr, int stereo_position)
2081 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
2084 void PlaySoundLoop(int nr)
2086 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
2089 void PlaySoundMusic(int nr)
2091 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
2094 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
2096 SoundControl snd_ctrl;
2098 if (!audio.sound_available ||
2099 !audio.sound_enabled ||
2100 audio.sound_deactivated)
2103 if (volume < SOUND_MIN_VOLUME)
2104 volume = SOUND_MIN_VOLUME;
2105 else if (volume > SOUND_MAX_VOLUME)
2106 volume = SOUND_MAX_VOLUME;
2108 if (stereo_position < SOUND_MAX_LEFT)
2109 stereo_position = SOUND_MAX_LEFT;
2110 else if (stereo_position > SOUND_MAX_RIGHT)
2111 stereo_position = SOUND_MAX_RIGHT;
2113 memset(&snd_ctrl, 0, sizeof(SoundControl)); /* to make valgrind happy */
2115 snd_ctrl.active = TRUE;
2117 snd_ctrl.volume = volume;
2118 snd_ctrl.stereo_position = stereo_position;
2119 snd_ctrl.state = state;
2121 HandleSoundRequest(snd_ctrl);
2124 void FadeMusic(void)
2126 if (!audio.music_available)
2129 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2132 void FadeSound(int nr)
2134 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2139 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2142 void FadeSoundsAndMusic()
2148 void StopMusic(void)
2150 if (!audio.music_available)
2153 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2156 void StopSound(int nr)
2158 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2164 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2167 void StopSoundExt(int nr, int state)
2169 SoundControl snd_ctrl;
2171 if (!audio.sound_available)
2174 memset(&snd_ctrl, 0, sizeof(SoundControl)); /* to make valgrind happy */
2176 snd_ctrl.active = FALSE;
2178 snd_ctrl.state = state;
2180 HandleSoundRequest(snd_ctrl);
2183 static void ReloadCustomSounds()
2186 printf("::: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
2189 LoadArtworkConfig(sound_info);
2190 ReloadCustomArtworkList(sound_info);
2193 static void ReloadCustomMusic()
2196 printf("::: reloading music '%s' ...\n", artwork.mus_current_identifier);
2199 LoadArtworkConfig(music_info);
2200 ReloadCustomArtworkList(music_info);
2202 /* load all music files from directory not defined in "musicinfo.conf" */
2203 LoadCustomMusic_NoConf();
2206 void InitReloadCustomSounds(char *set_identifier)
2208 if (!audio.sound_available)
2211 #if defined(AUDIO_UNIX_NATIVE)
2212 LoadArtworkConfig(sound_info); /* also load config on sound client */
2213 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2215 ReloadCustomSounds();
2219 void InitReloadCustomMusic(char *set_identifier)
2221 if (!audio.music_available)
2224 #if defined(AUDIO_UNIX_NATIVE)
2225 LoadArtworkConfig(music_info); /* also load config on sound client */
2226 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2228 ReloadCustomMusic();
2232 void FreeSound(void *ptr)
2234 SoundInfo *sound = (SoundInfo *)ptr;
2239 if (sound->data_ptr)
2241 #if defined(TARGET_SDL)
2242 Mix_FreeChunk(sound->data_ptr);
2243 #elif defined(TARGET_ALLEGRO)
2244 destroy_sample(sound->data_ptr);
2245 #else /* AUDIO_UNIX_NATIVE */
2246 free(sound->data_ptr);
2250 checked_free(sound->source_filename);
2255 void FreeMusic(void *ptr)
2257 MusicInfo *music = (MusicInfo *)ptr;
2262 if (music->data_ptr)
2264 #if defined(TARGET_SDL)
2265 if (music->type == MUS_TYPE_MOD)
2266 Mix_FreeMusic(music->data_ptr);
2268 Mix_FreeChunk(music->data_ptr);
2269 #elif defined(TARGET_ALLEGRO)
2270 destroy_sample(music->data_ptr);
2271 #else /* AUDIO_UNIX_NATIVE */
2272 free(music->data_ptr);
2279 static void FreeAllMusic_NoConf()
2283 if (Music_NoConf == NULL)
2286 for (i = 0; i < num_music_noconf; i++)
2287 FreeMusic(Music_NoConf[i]);
2291 Music_NoConf = NULL;
2292 num_music_noconf = 0;
2295 void FreeAllSounds()
2297 FreeCustomArtworkLists(sound_info);
2302 FreeCustomArtworkLists(music_info);
2303 FreeAllMusic_NoConf();
2306 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2307 /* ========================================================================= */