1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 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 gfx.override_level_sounds :
478 gfx.override_level_music);
480 if (IS_CHILD_PROCESS())
483 if (leveldir_current == NULL) /* should never happen */
484 Error(ERR_EXIT, "leveldir_current == NULL");
486 clear_mem(&snd_ctrl, 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 &gfx.override_level_sounds :
538 &gfx.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_INFO, "Mixer_InsertSound: Channel %d inactive", i);
917 Error(ERR_INFO, "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_INFO, "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 clear_mem(premix_last_buffer,
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 clear_mem(&header, sizeof(struct SoundHeader_WAV)); /* to make gcc happy */
1564 if ((file = fopen(filename, MODE_READ)) == NULL)
1566 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1571 /* read chunk id "RIFF" */
1572 getFileChunkLE(file, chunk_name, &chunk_size);
1573 if (!strEqual(chunk_name, "RIFF"))
1575 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1581 /* read "RIFF" type id "WAVE" */
1582 getFileChunkLE(file, chunk_name, NULL);
1583 if (!strEqual(chunk_name, "WAVE"))
1585 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1591 while (getFileChunkLE(file, chunk_name, &chunk_size))
1593 if (strEqual(chunk_name, "fmt "))
1595 if (chunk_size < WAV_HEADER_SIZE)
1597 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1603 header.compression_code = getFile16BitLE(file);
1604 header.num_channels = getFile16BitLE(file);
1605 header.sample_rate = getFile32BitLE(file);
1606 header.bytes_per_second = getFile32BitLE(file);
1607 header.block_align = getFile16BitLE(file);
1608 header.bits_per_sample = getFile16BitLE(file);
1610 if (chunk_size > WAV_HEADER_SIZE)
1611 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1613 if (header.compression_code != 1)
1615 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1616 filename, header.compression_code);
1622 if (header.num_channels != 1 &&
1623 header.num_channels != 2)
1625 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1626 filename, header.num_channels);
1632 if (header.bits_per_sample != 8 &&
1633 header.bits_per_sample != 16)
1635 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1636 filename, header.bits_per_sample);
1642 /* warn, but accept wrong sample rate (may be only slightly different) */
1643 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1644 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1645 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1648 printf("WAV file: '%s'\n", filename);
1649 printf(" Compression code: %d'\n", header.compression_code);
1650 printf(" Number of channels: %d'\n", header.num_channels);
1651 printf(" Sample rate: %ld'\n", header.sample_rate);
1652 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1653 printf(" Block align: %d'\n", header.block_align);
1654 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1657 else if (strEqual(chunk_name, "data"))
1659 data_byte_len = chunk_size;
1661 snd_info->data_len = data_byte_len;
1662 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1664 /* read sound data */
1665 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1668 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1670 free(snd_info->data_ptr);
1675 /* check for odd number of data bytes (data chunk is word aligned) */
1676 if ((data_byte_len % 2) == 1)
1677 ReadUnusedBytesFromFile(file, 1);
1679 else /* unknown chunk -- ignore */
1680 ReadUnusedBytesFromFile(file, chunk_size);
1685 if (snd_info->data_ptr == NULL)
1687 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1692 if (header.bits_per_sample == 8)
1693 snd_info->format = AUDIO_FORMAT_U8;
1694 else /* header.bits_per_sample == 16 */
1696 snd_info->format = AUDIO_FORMAT_S16;
1697 snd_info->data_len /= 2; /* correct number of samples */
1700 snd_info->num_channels = header.num_channels;
1701 if (header.num_channels == 2)
1702 snd_info->data_len /= 2; /* correct number of samples */
1705 if (header.num_channels == 1) /* convert mono sound to stereo */
1707 void *buffer_ptr = checked_malloc(data_byte_len * 2);
1708 void *sample_ptr = snd_info->data_ptr;
1709 int sample_size = snd_info->data_len;
1712 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1713 for (i = 0; i < sample_size; i++)
1715 ((short)(((byte *)sample_ptr)[i] ^ 0x80)) << 8;
1716 else /* AUDIO_FORMAT_S16 */
1717 for (i = 0; i < sample_size; i++)
1719 ((short *)sample_ptr)[i];
1723 #endif /* AUDIO_UNIX_NATIVE */
1725 snd_info->type = SND_TYPE_WAV;
1726 snd_info->source_filename = getStringCopy(filename);
1731 static void *Load_MOD(char *filename)
1733 #if defined(TARGET_SDL)
1734 MusicInfo *mod_info;
1736 if (!audio.sound_available)
1739 mod_info = checked_calloc(sizeof(MusicInfo));
1741 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1743 Error(ERR_WARN, "cannot read music file '%s'", filename);
1748 mod_info->type = MUS_TYPE_MOD;
1749 mod_info->source_filename = getStringCopy(filename);
1757 static void *Load_WAV_or_MOD(char *filename)
1759 if (FileIsSound(filename))
1760 return Load_WAV(filename);
1761 else if (FileIsMusic(filename))
1762 return Load_MOD(filename);
1767 void LoadCustomMusic_NoConf(void)
1769 static boolean draw_init_text = TRUE; /* only draw at startup */
1770 static char *last_music_directory = NULL;
1771 char *music_directory = getCustomMusicDirectory();
1773 struct dirent *dir_entry;
1774 int num_music = getMusicListSize();
1776 if (!audio.sound_available)
1779 if (last_music_directory != NULL &&
1780 strEqual(last_music_directory, music_directory))
1781 return; /* old and new music directory are the same */
1783 if (last_music_directory != NULL)
1784 free(last_music_directory);
1785 last_music_directory = getStringCopy(music_directory);
1787 FreeAllMusic_NoConf();
1789 if ((dir = opendir(music_directory)) == NULL)
1791 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1792 audio.music_available = FALSE;
1797 DrawInitText("Loading music", 120, FC_GREEN);
1799 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1801 char *basename = dir_entry->d_name;
1802 char *filename = NULL;
1803 MusicInfo *mus_info = NULL;
1804 boolean music_already_used = FALSE;
1807 /* skip all music files that are configured in music config file */
1808 for (i = 0; i < num_music; i++)
1810 struct FileInfo *music = getMusicListEntry(i);
1812 if (strEqual(basename, music->filename))
1814 music_already_used = TRUE;
1819 if (music_already_used)
1823 DrawInitText(basename, 150, FC_YELLOW);
1825 filename = getPath2(music_directory, basename);
1827 if (FileIsMusic(basename))
1828 mus_info = Load_WAV_or_MOD(filename);
1835 Music_NoConf = checked_realloc(Music_NoConf,
1836 num_music_noconf * sizeof(MusicInfo *));
1837 Music_NoConf[num_music_noconf - 1] = mus_info;
1843 draw_init_text = FALSE;
1846 int getSoundListSize()
1848 return (sound_info->num_file_list_entries +
1849 sound_info->num_dynamic_file_list_entries);
1852 int getMusicListSize()
1854 return (music_info->num_file_list_entries +
1855 music_info->num_dynamic_file_list_entries);
1858 struct FileInfo *getSoundListEntry(int pos)
1860 int num_list_entries = sound_info->num_file_list_entries;
1861 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1863 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
1864 &sound_info->dynamic_file_list[list_pos]);
1867 struct FileInfo *getMusicListEntry(int pos)
1869 int num_list_entries = music_info->num_file_list_entries;
1870 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1872 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
1873 &music_info->dynamic_file_list[list_pos]);
1876 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
1878 int num_list_entries = sound_info->num_file_list_entries;
1879 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1880 SoundInfo **snd_info =
1881 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
1882 sound_info->dynamic_artwork_list);
1884 return snd_info[list_pos];
1887 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
1889 int num_list_entries = music_info->num_file_list_entries;
1890 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1891 MusicInfo **mus_info =
1892 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
1893 music_info->dynamic_artwork_list);
1895 return mus_info[list_pos];
1898 int getSoundListPropertyMappingSize()
1900 return sound_info->num_property_mapping_entries;
1903 int getMusicListPropertyMappingSize()
1905 return music_info->num_property_mapping_entries;
1908 struct PropertyMapping *getSoundListPropertyMapping()
1910 return sound_info->property_mapping;
1913 struct PropertyMapping *getMusicListPropertyMapping()
1915 return music_info->property_mapping;
1918 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
1919 struct ConfigTypeInfo *config_suffix_list,
1920 char **base_prefixes, char **ext1_suffixes,
1921 char **ext2_suffixes, char **ext3_suffixes,
1922 char **ignore_tokens)
1926 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1927 sound_info->type = ARTWORK_TYPE_SOUNDS;
1929 /* ---------- initialize file list and suffix lists ---------- */
1931 sound_info->num_file_list_entries = num_file_list_entries;
1932 sound_info->num_dynamic_file_list_entries = 0;
1934 sound_info->file_list =
1935 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
1936 num_file_list_entries);
1937 sound_info->dynamic_file_list = NULL;
1939 sound_info->num_suffix_list_entries = 0;
1940 for (i = 0; config_suffix_list[i].token != NULL; i++)
1941 sound_info->num_suffix_list_entries++;
1943 sound_info->suffix_list = config_suffix_list;
1945 /* ---------- initialize base prefix and suffixes lists ---------- */
1947 sound_info->num_base_prefixes = 0;
1948 for (i = 0; base_prefixes[i] != NULL; i++)
1949 sound_info->num_base_prefixes++;
1951 sound_info->num_ext1_suffixes = 0;
1952 for (i = 0; ext1_suffixes[i] != NULL; i++)
1953 sound_info->num_ext1_suffixes++;
1955 sound_info->num_ext2_suffixes = 0;
1956 for (i = 0; ext2_suffixes[i] != NULL; i++)
1957 sound_info->num_ext2_suffixes++;
1959 sound_info->num_ext3_suffixes = 0;
1960 for (i = 0; ext3_suffixes[i] != NULL; i++)
1961 sound_info->num_ext3_suffixes++;
1963 sound_info->num_ignore_tokens = 0;
1964 for (i = 0; ignore_tokens[i] != NULL; i++)
1965 sound_info->num_ignore_tokens++;
1967 sound_info->base_prefixes = base_prefixes;
1968 sound_info->ext1_suffixes = ext1_suffixes;
1969 sound_info->ext2_suffixes = ext2_suffixes;
1970 sound_info->ext3_suffixes = ext3_suffixes;
1971 sound_info->ignore_tokens = ignore_tokens;
1973 sound_info->num_property_mapping_entries = 0;
1975 sound_info->property_mapping = NULL;
1977 /* ---------- initialize artwork reference and content lists ---------- */
1979 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
1981 sound_info->artwork_list =
1982 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
1983 sound_info->dynamic_artwork_list = NULL;
1985 sound_info->content_list = NULL;
1987 /* ---------- initialize artwork loading/freeing functions ---------- */
1989 sound_info->load_artwork = Load_WAV;
1990 sound_info->free_artwork = FreeSound;
1993 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
1994 struct ConfigTypeInfo *config_suffix_list,
1995 char **base_prefixes, char **ext1_suffixes,
1996 char **ext2_suffixes, char **ext3_suffixes,
1997 char **ignore_tokens)
2001 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
2002 music_info->type = ARTWORK_TYPE_MUSIC;
2004 /* ---------- initialize file list and suffix lists ---------- */
2006 music_info->num_file_list_entries = num_file_list_entries;
2007 music_info->num_dynamic_file_list_entries = 0;
2009 music_info->file_list =
2010 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
2011 num_file_list_entries);
2012 music_info->dynamic_file_list = NULL;
2014 music_info->num_suffix_list_entries = 0;
2015 for (i = 0; config_suffix_list[i].token != NULL; i++)
2016 music_info->num_suffix_list_entries++;
2018 music_info->suffix_list = config_suffix_list;
2020 /* ---------- initialize base prefix and suffixes lists ---------- */
2022 music_info->num_base_prefixes = 0;
2023 for (i = 0; base_prefixes[i] != NULL; i++)
2024 music_info->num_base_prefixes++;
2026 music_info->num_ext1_suffixes = 0;
2027 for (i = 0; ext1_suffixes[i] != NULL; i++)
2028 music_info->num_ext1_suffixes++;
2030 music_info->num_ext2_suffixes = 0;
2031 for (i = 0; ext2_suffixes[i] != NULL; i++)
2032 music_info->num_ext2_suffixes++;
2034 music_info->num_ext3_suffixes = 0;
2035 for (i = 0; ext3_suffixes[i] != NULL; i++)
2036 music_info->num_ext3_suffixes++;
2038 music_info->num_ignore_tokens = 0;
2039 for (i = 0; ignore_tokens[i] != NULL; i++)
2040 music_info->num_ignore_tokens++;
2042 music_info->base_prefixes = base_prefixes;
2043 music_info->ext1_suffixes = ext1_suffixes;
2044 music_info->ext2_suffixes = ext2_suffixes;
2045 music_info->ext3_suffixes = ext3_suffixes;
2046 music_info->ignore_tokens = ignore_tokens;
2048 music_info->num_property_mapping_entries = 0;
2050 music_info->property_mapping = NULL;
2052 /* ---------- initialize artwork reference and content lists ---------- */
2054 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
2056 music_info->artwork_list =
2057 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
2058 music_info->dynamic_artwork_list = NULL;
2060 music_info->content_list = NULL;
2062 /* ---------- initialize artwork loading/freeing functions ---------- */
2064 music_info->load_artwork = Load_WAV_or_MOD;
2065 music_info->free_artwork = FreeMusic;
2068 void PlayMusic(int nr)
2070 if (!audio.music_available)
2076 void PlaySound(int nr)
2078 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
2081 void PlaySoundStereo(int nr, int stereo_position)
2083 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
2086 void PlaySoundLoop(int nr)
2088 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
2091 void PlaySoundMusic(int nr)
2093 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
2096 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
2098 SoundControl snd_ctrl;
2100 if (!audio.sound_available ||
2101 !audio.sound_enabled ||
2102 audio.sound_deactivated)
2105 if (volume < SOUND_MIN_VOLUME)
2106 volume = SOUND_MIN_VOLUME;
2107 else if (volume > SOUND_MAX_VOLUME)
2108 volume = SOUND_MAX_VOLUME;
2110 if (stereo_position < SOUND_MAX_LEFT)
2111 stereo_position = SOUND_MAX_LEFT;
2112 else if (stereo_position > SOUND_MAX_RIGHT)
2113 stereo_position = SOUND_MAX_RIGHT;
2115 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
2117 snd_ctrl.active = TRUE;
2119 snd_ctrl.volume = volume;
2120 snd_ctrl.stereo_position = stereo_position;
2121 snd_ctrl.state = state;
2123 HandleSoundRequest(snd_ctrl);
2126 void FadeMusic(void)
2128 if (!audio.music_available)
2131 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2134 void FadeSound(int nr)
2136 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2141 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2144 void FadeSoundsAndMusic()
2150 void StopMusic(void)
2152 if (!audio.music_available)
2155 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2158 void StopSound(int nr)
2160 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2166 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2169 void StopSoundExt(int nr, int state)
2171 SoundControl snd_ctrl;
2173 if (!audio.sound_available)
2176 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
2178 snd_ctrl.active = FALSE;
2180 snd_ctrl.state = state;
2182 HandleSoundRequest(snd_ctrl);
2185 static void ReloadCustomSounds()
2188 printf("::: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
2191 LoadArtworkConfig(sound_info);
2192 ReloadCustomArtworkList(sound_info);
2195 static void ReloadCustomMusic()
2198 printf("::: reloading music '%s' ...\n", artwork.mus_current_identifier);
2201 LoadArtworkConfig(music_info);
2202 ReloadCustomArtworkList(music_info);
2204 /* load all music files from directory not defined in "musicinfo.conf" */
2205 LoadCustomMusic_NoConf();
2208 void InitReloadCustomSounds(char *set_identifier)
2210 if (!audio.sound_available)
2213 #if defined(AUDIO_UNIX_NATIVE)
2214 LoadArtworkConfig(sound_info); /* also load config on sound client */
2215 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2217 ReloadCustomSounds();
2221 void InitReloadCustomMusic(char *set_identifier)
2223 if (!audio.music_available)
2226 #if defined(AUDIO_UNIX_NATIVE)
2227 LoadArtworkConfig(music_info); /* also load config on sound client */
2228 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2230 ReloadCustomMusic();
2234 void FreeSound(void *ptr)
2236 SoundInfo *sound = (SoundInfo *)ptr;
2241 if (sound->data_ptr)
2243 #if defined(TARGET_SDL)
2244 Mix_FreeChunk(sound->data_ptr);
2245 #elif defined(TARGET_ALLEGRO)
2246 destroy_sample(sound->data_ptr);
2247 #else /* AUDIO_UNIX_NATIVE */
2248 free(sound->data_ptr);
2252 checked_free(sound->source_filename);
2257 void FreeMusic(void *ptr)
2259 MusicInfo *music = (MusicInfo *)ptr;
2264 if (music->data_ptr)
2266 #if defined(TARGET_SDL)
2267 if (music->type == MUS_TYPE_MOD)
2268 Mix_FreeMusic(music->data_ptr);
2270 Mix_FreeChunk(music->data_ptr);
2271 #elif defined(TARGET_ALLEGRO)
2272 destroy_sample(music->data_ptr);
2273 #else /* AUDIO_UNIX_NATIVE */
2274 free(music->data_ptr);
2281 static void FreeAllMusic_NoConf()
2285 if (Music_NoConf == NULL)
2288 for (i = 0; i < num_music_noconf; i++)
2289 FreeMusic(Music_NoConf[i]);
2293 Music_NoConf = NULL;
2294 num_music_noconf = 0;
2297 void FreeAllSounds()
2299 FreeCustomArtworkLists(sound_info);
2304 FreeCustomArtworkLists(music_info);
2305 FreeAllMusic_NoConf();
2308 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2309 /* ========================================================================= */