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)
74 struct SoundHeader_SUN
77 unsigned long hdr_size;
78 unsigned long data_size;
79 unsigned long encoding;
80 unsigned long sample_rate;
81 unsigned long channels;
84 struct SoundHeader_8SVX
87 unsigned long chunk_size;
92 #if defined(AUDIO_UNIX_NATIVE)
93 struct SoundHeader_WAV
95 unsigned short compression_code;
96 unsigned short num_channels;
97 unsigned long sample_rate;
98 unsigned long bytes_per_second;
99 unsigned short block_align;
100 unsigned short bits_per_sample;
104 struct AudioFormatInfo
106 boolean stereo; /* availability of stereo sound */
107 int format; /* size and endianess of sample data */
108 int sample_rate; /* sample frequency */
109 int fragment_size; /* audio device fragment size in bytes */
114 char *source_filename;
119 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
120 long data_len; /* number of samples, NOT number of bytes */
121 int num_channels; /* mono: 1 channel, stereo: 2 channels */
123 typedef struct SampleInfo SoundInfo;
124 typedef struct SampleInfo MusicInfo;
136 unsigned long playing_starttime;
137 unsigned long playing_pos;
141 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
142 long data_len; /* number of samples, NOT number of bytes */
143 int num_channels; /* mono: 1 channel, stereo: 2 channels */
145 #if defined(TARGET_ALLEGRO)
149 typedef struct SoundControl SoundControl;
151 static struct ArtworkListInfo *sound_info = NULL;
153 static SoundInfo **Sound = NULL;
155 static MusicInfo **Music = NULL;
157 static int num_sounds = 0;
159 static int num_music = 0;
160 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
163 /* ========================================================================= */
164 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
166 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
167 static int mixer_active_channels = 0;
169 #if defined(AUDIO_UNIX_NATIVE)
170 static struct AudioFormatInfo afmt;
172 static void Mixer_Main(void);
173 #if !defined(AUDIO_STREAMING_DSP)
174 static unsigned char linear_to_ulaw(int);
175 static int ulaw_to_linear(unsigned char);
179 static void ReloadCustomSounds();
180 static void ReloadCustomMusic();
181 static void FreeSound(void *);
183 static SoundInfo *getSoundInfoEntryFromSoundID(int);
186 /* ------------------------------------------------------------------------- */
187 /* functions for native (non-SDL) Unix audio/mixer support */
188 /* ------------------------------------------------------------------------- */
190 #if defined(AUDIO_UNIX_NATIVE)
192 static int OpenAudioDevice(char *audio_device_name)
196 /* check if desired audio device is accessible */
197 if (access(audio_device_name, W_OK) != 0)
200 /* try to open audio device in non-blocking mode */
201 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
202 return audio_device_fd;
204 /* re-open audio device in blocking mode */
205 close(audio_device_fd);
206 audio_device_fd = open(audio_device_name, O_WRONLY);
208 return audio_device_fd;
211 static void CloseAudioDevice(int *audio_device_fd)
213 if (*audio_device_fd == 0)
216 close(*audio_device_fd);
217 *audio_device_fd = -1;
220 static boolean TestAudioDevices(void)
222 static char *audio_device_name[] =
225 DEVICENAME_SOUND_DSP,
228 int audio_device_fd = -1;
231 /* look for available audio devices, starting with preferred ones */
232 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
233 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
236 if (audio_device_fd < 0)
238 Error(ERR_WARN, "cannot open audio device -- no sound");
242 close(audio_device_fd);
244 audio.device_name = audio_device_name[i];
249 static boolean ForkAudioProcess(void)
251 if (pipe(audio.mixer_pipe) < 0)
253 Error(ERR_WARN, "cannot create pipe -- no sounds");
257 if ((audio.mixer_pid = fork()) < 0)
259 Error(ERR_WARN, "cannot create sound server process -- no sounds");
263 if (audio.mixer_pid == 0) /* we are the child process */
264 audio.mixer_pid = getpid();
267 printf("PID: %d [%s]\n", getpid(),(IS_CHILD_PROCESS() ? "child" : "parent"));
271 if (IS_CHILD_PROCESS())
272 Mixer_Main(); /* this function never returns */
274 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
279 void UnixOpenAudio(void)
281 if (!TestAudioDevices())
284 audio.sound_available = TRUE;
285 audio.sound_enabled = TRUE;
287 #if defined(AUDIO_STREAMING_DSP)
288 audio.music_available = TRUE;
289 audio.loops_available = TRUE;
292 audio.num_channels = NUM_MIXER_CHANNELS;
293 audio.music_channel = MUSIC_CHANNEL;
294 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
297 void UnixCloseAudio(void)
300 close(audio.device_fd);
302 if (IS_PARENT_PROCESS() && HAS_CHILD_PROCESS())
303 kill(audio.mixer_pid, SIGTERM);
307 /* ------------------------------------------------------------------------- */
308 /* functions for platform specific audio device initialization */
309 /* ------------------------------------------------------------------------- */
311 #if defined(AUDIO_LINUX_IOCTL)
312 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
314 /* "ioctl()" expects pointer to 'int' value for stereo flag
315 (boolean is defined as 'char', which will not work here) */
316 unsigned int fragment_spec = 0;
317 int fragment_size_query = -1;
326 /* supported audio format in preferred order */
327 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
328 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
329 { AFMT_U8, AUDIO_FORMAT_U8 },
334 /* determine logarithm (log2) of the fragment size */
335 while ((1 << fragment_spec) < afmt->fragment_size)
338 /* use two fragments (play one fragment, prepare the other);
339 one fragment would result in interrupted audio output, more
340 than two fragments would raise audio output latency to much */
341 fragment_spec |= 0x00020000;
343 /* Example for fragment specification:
344 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
345 - (with stereo the effective buffer size will shrink to 256)
346 => fragment_size = 0x00020009 */
348 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
349 Error(ERR_EXIT_SOUND_SERVER,
350 "cannot set fragment size of audio device -- no sounds");
354 while (formats[i].format_result != -1)
356 unsigned int audio_format = formats[i].format_ioctl;
357 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
359 afmt->format = formats[i].format_result;
364 if (afmt->format == 0) /* no supported audio format found */
365 Error(ERR_EXIT_SOUND_SERVER,
366 "cannot set audio format of audio device -- no sounds");
368 /* try if we can use stereo sound */
370 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
371 afmt->stereo = FALSE;
373 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
374 Error(ERR_EXIT_SOUND_SERVER,
375 "cannot set sample rate of audio device -- no sounds");
377 /* get the real fragmentation size; this should return 512 */
378 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
379 Error(ERR_EXIT_SOUND_SERVER,
380 "cannot get fragment size of audio device -- no sounds");
381 if (fragment_size_query != afmt->fragment_size)
382 Error(ERR_EXIT_SOUND_SERVER,
383 "cannot set fragment size of audio device -- no sounds");
385 #endif /* AUDIO_LINUX_IOCTL */
387 #if defined(PLATFORM_NETBSD)
388 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
391 boolean stereo = TRUE;
393 AUDIO_INITINFO(&a_info);
394 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
395 a_info.play.precision = 8;
396 a_info.play.channels = 2;
397 a_info.play.sample_rate = afmt->sample_rate;
398 a_info.blocksize = afmt->fragment_size;
400 afmt->format = AUDIO_FORMAT_U8;
403 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
405 /* try to disable stereo */
406 a_info.play.channels = 1;
408 afmt->stereo = FALSE;
410 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
411 Error(ERR_EXIT_SOUND_SERVER,
412 "cannot set sample rate of audio device -- no sounds");
415 #endif /* PLATFORM_NETBSD */
417 #if defined(PLATFORM_HPUX)
418 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
420 struct audio_describe ainfo;
423 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
425 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
427 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
428 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
430 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
431 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
433 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
434 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
436 afmt->format = AUDIO_FORMAT_U8;
437 afmt->stereo = FALSE;
438 afmt->sample_rate = 8000;
442 #endif /* PLATFORM_HPUX */
444 static void InitAudioDevice(struct AudioFormatInfo *afmt)
447 afmt->format = AUDIO_FORMAT_UNKNOWN;
448 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
449 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
451 #if defined(AUDIO_LINUX_IOCTL)
452 InitAudioDevice_Linux(afmt);
453 #elif defined(PLATFORM_NETBSD)
454 InitAudioDevice_NetBSD(afmt);
455 #elif defined(PLATFORM_HPUX)
456 InitAudioDevice_HPUX(afmt);
458 /* generic /dev/audio stuff might be placed here */
463 /* ------------------------------------------------------------------------- */
464 /* functions for communication between main process and sound mixer process */
465 /* ------------------------------------------------------------------------- */
467 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
469 if (IS_CHILD_PROCESS())
472 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
474 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
475 audio.sound_available = audio.sound_enabled = FALSE;
480 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
482 if (IS_PARENT_PROCESS())
485 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
486 != sizeof(SoundControl))
487 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
490 static void WriteReloadInfoToPipe(char *set_identifier, int type)
492 SoundControl snd_ctrl;
493 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
494 artwork.mus_current);
495 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
496 unsigned long str_size2 = strlen(leveldir_current->sounds_path) + 1;
497 unsigned long str_size3 = strlen(leveldir_current->music_path) + 1;
498 unsigned long str_size4 = strlen(ti->basepath) + 1;
499 unsigned long str_size5 = strlen(ti->fullpath) + 1;
500 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
501 setup.override_level_sounds :
502 setup.override_level_music);
504 if (IS_CHILD_PROCESS())
507 if (leveldir_current == NULL) /* should never happen */
508 Error(ERR_EXIT, "leveldir_current == NULL");
510 memset(&snd_ctrl, 0, sizeof(SoundControl)); /* to make valgrind happy */
512 snd_ctrl.active = FALSE;
513 snd_ctrl.state = type;
514 snd_ctrl.data_len = strlen(set_identifier) + 1;
516 if (write(audio.mixer_pipe[1], &snd_ctrl,
517 sizeof(snd_ctrl)) < 0 ||
518 write(audio.mixer_pipe[1], set_identifier,
519 snd_ctrl.data_len) < 0 ||
520 write(audio.mixer_pipe[1], &override_level_artwork,
521 sizeof(boolean)) < 0 ||
522 write(audio.mixer_pipe[1], leveldir_current,
523 sizeof(TreeInfo)) < 0 ||
524 write(audio.mixer_pipe[1], ti,
525 sizeof(TreeInfo)) < 0 ||
526 write(audio.mixer_pipe[1], &str_size1,
527 sizeof(unsigned long)) < 0 ||
528 write(audio.mixer_pipe[1], &str_size2,
529 sizeof(unsigned long)) < 0 ||
530 write(audio.mixer_pipe[1], &str_size3,
531 sizeof(unsigned long)) < 0 ||
532 write(audio.mixer_pipe[1], &str_size4,
533 sizeof(unsigned long)) < 0 ||
534 write(audio.mixer_pipe[1], &str_size5,
535 sizeof(unsigned long)) < 0 ||
536 write(audio.mixer_pipe[1], leveldir_current->fullpath,
538 write(audio.mixer_pipe[1], leveldir_current->sounds_path,
540 write(audio.mixer_pipe[1], leveldir_current->music_path,
542 write(audio.mixer_pipe[1], ti->basepath,
544 write(audio.mixer_pipe[1], ti->fullpath,
547 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
548 audio.sound_available = audio.sound_enabled = FALSE;
553 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
555 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
556 &artwork.snd_current : &artwork.mus_current);
557 TreeInfo *ti = *ti_ptr;
558 unsigned long str_size1, str_size2, str_size3, str_size4, str_size5;
559 static char *set_identifier = NULL;
560 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
561 &setup.override_level_sounds :
562 &setup.override_level_music);
565 free(set_identifier);
567 set_identifier = checked_malloc(snd_ctrl->data_len);
569 if (leveldir_current == NULL)
570 leveldir_current = checked_calloc(sizeof(TreeInfo));
573 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
574 if (leveldir_current->fullpath != NULL)
575 free(leveldir_current->fullpath);
576 if (leveldir_current->sounds_path != NULL)
577 free(leveldir_current->sounds_path);
578 if (leveldir_current->music_path != NULL)
579 free(leveldir_current->music_path);
580 if (ti->basepath != NULL)
582 if (ti->fullpath != NULL)
585 if (read(audio.mixer_pipe[0], set_identifier,
586 snd_ctrl->data_len) != snd_ctrl->data_len ||
587 read(audio.mixer_pipe[0], override_level_artwork,
588 sizeof(boolean)) != sizeof(boolean) ||
589 read(audio.mixer_pipe[0], leveldir_current,
590 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
591 read(audio.mixer_pipe[0], ti,
592 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
593 read(audio.mixer_pipe[0], &str_size1,
594 sizeof(unsigned long)) != sizeof(unsigned long) ||
595 read(audio.mixer_pipe[0], &str_size2,
596 sizeof(unsigned long)) != sizeof(unsigned long) ||
597 read(audio.mixer_pipe[0], &str_size3,
598 sizeof(unsigned long)) != sizeof(unsigned long) ||
599 read(audio.mixer_pipe[0], &str_size4,
600 sizeof(unsigned long)) != sizeof(unsigned long) ||
601 read(audio.mixer_pipe[0], &str_size5,
602 sizeof(unsigned long)) != sizeof(unsigned long))
603 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
605 leveldir_current->fullpath = checked_calloc(str_size1);
606 leveldir_current->sounds_path = checked_calloc(str_size2);
607 leveldir_current->music_path = checked_calloc(str_size3);
608 ti->basepath = checked_calloc(str_size4);
609 ti->fullpath = checked_calloc(str_size5);
611 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
612 str_size1) != str_size1 ||
613 read(audio.mixer_pipe[0], leveldir_current->sounds_path,
614 str_size2) != str_size2 ||
615 read(audio.mixer_pipe[0], leveldir_current->music_path,
616 str_size3) != str_size3 ||
617 read(audio.mixer_pipe[0], ti->basepath,
618 str_size4) != str_size4 ||
619 read(audio.mixer_pipe[0], ti->fullpath,
620 str_size5) != str_size5)
621 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
623 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
624 artwork.snd_current_identifier = set_identifier;
626 artwork.mus_current_identifier = set_identifier;
629 #endif /* AUDIO_UNIX_NATIVE */
632 /* ------------------------------------------------------------------------- */
633 /* mixer functions */
634 /* ------------------------------------------------------------------------- */
636 void Mixer_InitChannels()
640 for(i=0; i<audio.num_channels; i++)
641 mixer[i].active = FALSE;
642 mixer_active_channels = 0;
645 static void Mixer_ResetChannelExpiration(int channel)
647 mixer[channel].playing_starttime = Counter();
649 #if defined(TARGET_SDL)
650 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
651 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
655 static boolean Mixer_ChannelExpired(int channel)
657 if (!mixer[channel].active)
660 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
661 DelayReached(&mixer[channel].playing_starttime,
662 SOUND_LOOP_EXPIRATION_TIME))
665 #if defined(TARGET_SDL)
667 if (!Mix_Playing(channel))
670 #elif defined(TARGET_ALLEGRO)
672 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
673 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
675 /* sound sample has completed playing or was completely faded out */
676 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
679 #endif /* TARGET_ALLEGRO */
684 static boolean Mixer_AllocateChannel(int channel)
686 #if defined(TARGET_ALLEGRO)
687 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
688 if (mixer[channel].voice < 0)
695 static void Mixer_SetChannelProperties(int channel)
697 #if defined(TARGET_SDL)
698 Mix_Volume(channel, mixer[channel].volume);
699 Mix_SetPanning(channel,
700 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
701 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
702 #elif defined(TARGET_ALLEGRO)
703 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
704 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
708 static void Mixer_StartChannel(int channel)
710 #if defined(TARGET_SDL)
711 Mix_PlayChannel(channel, mixer[channel].data_ptr,
712 IS_LOOP(mixer[channel]) ? -1 : 0);
713 #elif defined(TARGET_ALLEGRO)
714 if (IS_LOOP(mixer[channel]))
715 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
717 voice_start(mixer[channel].voice);
721 static void Mixer_PlayChannel(int channel)
723 /* start with inactive channel in case something goes wrong */
724 mixer[channel].active = FALSE;
726 if (mixer[channel].type != MUS_TYPE_WAV)
729 if (!Mixer_AllocateChannel(channel))
732 Mixer_SetChannelProperties(channel);
733 Mixer_StartChannel(channel);
735 Mixer_ResetChannelExpiration(channel);
737 mixer[channel].playing_pos = 0;
738 mixer[channel].active = TRUE;
739 mixer_active_channels++;
742 static void Mixer_PlayMusicChannel()
744 Mixer_PlayChannel(audio.music_channel);
746 #if defined(TARGET_SDL)
747 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
749 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
750 this looks like a bug in the SDL_mixer library */
751 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
752 Mix_VolumeMusic(SOUND_MAX_VOLUME);
757 static void Mixer_StopChannel(int channel)
759 if (!mixer[channel].active)
762 #if defined(TARGET_SDL)
763 Mix_HaltChannel(channel);
764 #elif defined(TARGET_ALLEGRO)
765 voice_set_volume(mixer[channel].voice, 0);
766 deallocate_voice(mixer[channel].voice);
769 mixer[channel].active = FALSE;
770 mixer_active_channels--;
773 static void Mixer_StopMusicChannel()
775 Mixer_StopChannel(audio.music_channel);
777 #if defined(TARGET_SDL)
782 static void Mixer_FadeChannel(int channel)
784 if (!mixer[channel].active)
787 mixer[channel].state |= SND_CTRL_FADE;
789 #if defined(TARGET_SDL)
790 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
791 #elif defined(TARGET_ALLEGRO)
792 if (voice_check(mixer[channel].voice))
793 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
797 static void Mixer_FadeMusicChannel()
799 Mixer_FadeChannel(audio.music_channel);
801 #if defined(TARGET_SDL)
802 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
806 static void Mixer_UnFadeChannel(int channel)
808 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
811 mixer[channel].state &= ~SND_CTRL_FADE;
812 mixer[channel].volume = SOUND_MAX_VOLUME;
814 #if defined(TARGET_SDL)
815 Mix_ExpireChannel(channel, -1);
816 Mix_Volume(channel, mixer[channel].volume);
817 #elif defined(TARGET_ALLEGRO)
818 voice_stop_volumeramp(mixer[channel].voice);
819 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
820 mixer[channel].volume);
824 static void Mixer_InsertSound(SoundControl snd_ctrl)
828 int num_sounds = getSoundListSize();
831 printf("NEW SOUND %d ARRIVED [%d] [%d ACTIVE CHANNELS]\n",
832 snd_ctrl.nr, num_sounds, mixer_active_channels);
835 if (IS_MUSIC(snd_ctrl))
840 snd_ctrl.nr = snd_ctrl.nr % num_music;
842 else if (snd_ctrl.nr >= num_sounds)
846 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
848 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] :
849 getSoundInfoEntryFromSoundID(snd_ctrl.nr));
852 if (snd_info == NULL)
855 /* copy sound sample and format information */
856 snd_ctrl.type = snd_info->type;
857 snd_ctrl.format = snd_info->format;
858 snd_ctrl.data_ptr = snd_info->data_ptr;
859 snd_ctrl.data_len = snd_info->data_len;
860 snd_ctrl.num_channels = snd_info->num_channels;
862 /* play music samples on a dedicated music channel */
863 if (IS_MUSIC(snd_ctrl))
865 Mixer_StopMusicChannel();
867 mixer[audio.music_channel] = snd_ctrl;
868 Mixer_PlayMusicChannel();
873 /* check if (and how often) this sound sample is already playing */
874 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
875 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
879 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
882 /* reset expiration delay for already playing loop sounds */
883 if (k > 0 && IS_LOOP(snd_ctrl))
885 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
887 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
890 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
893 if (IS_FADING(mixer[i]))
894 Mixer_UnFadeChannel(i);
896 /* restore settings like volume and stereo position */
897 mixer[i].volume = snd_ctrl.volume;
898 mixer[i].stereo_position = snd_ctrl.stereo_position;
900 Mixer_SetChannelProperties(i);
901 Mixer_ResetChannelExpiration(i);
904 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
905 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
914 printf("PLAYING NEW SOUND %d\n", snd_ctrl.nr);
917 /* don't play sound more than n times simultaneously (with n == 2 for now) */
920 unsigned long playing_current = Counter();
921 int longest = 0, longest_nr = audio.first_sound_channel;
923 /* look for oldest equal sound */
924 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
926 int playing_time = playing_current - mixer[i].playing_starttime;
929 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
932 actual = 1000 * playing_time / mixer[i].data_len;
934 if (actual >= longest)
941 Mixer_StopChannel(longest_nr);
944 /* If all (non-music) channels are active, stop the channel that has
945 played its sound sample most completely (in percent of the sample
946 length). As we cannot currently get the actual playing position
947 of the channel's sound sample when compiling with the SDL mixer
948 library, we use the current playing time (in milliseconds) instead. */
951 /* channel allocation sanity check -- should not be needed */
952 if (mixer_active_channels ==
953 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
955 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
957 if (!mixer[i].active)
959 Error(ERR_RETURN, "Mixer_InsertSound: Channel %d inactive", i);
960 Error(ERR_RETURN, "Mixer_InsertSound: This should never happen!");
962 mixer_active_channels--;
968 if (mixer_active_channels ==
969 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
971 unsigned long playing_current = Counter();
972 int longest = 0, longest_nr = audio.first_sound_channel;
976 /* print some debugging information about audio channel usage */
977 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
979 Error(ERR_RETURN, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
980 i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
985 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
987 int playing_time = playing_current - mixer[i].playing_starttime;
988 int actual = 1000 * playing_time / mixer[i].data_len;
990 if (!IS_LOOP(mixer[i]) && actual > longest)
997 Mixer_StopChannel(longest_nr);
1000 /* add the new sound to the mixer */
1001 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1004 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
1007 if (!mixer[i].active)
1010 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
1013 #if defined(AUDIO_UNIX_NATIVE)
1014 if (snd_info->data_len == 0)
1016 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
1020 mixer[i] = snd_ctrl;
1021 Mixer_PlayChannel(i);
1028 static void HandleSoundRequest(SoundControl snd_ctrl)
1032 #if defined(AUDIO_UNIX_NATIVE)
1033 if (IS_PARENT_PROCESS())
1035 SendSoundControlToMixerProcess(&snd_ctrl);
1040 /* deactivate channels that have expired since the last request */
1041 for (i=0; i<audio.num_channels; i++)
1042 if (mixer[i].active && Mixer_ChannelExpired(i))
1043 Mixer_StopChannel(i);
1045 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
1047 Mixer_StopMusicChannel();
1048 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1049 Mixer_StopChannel(i);
1051 #if defined(AUDIO_UNIX_NATIVE)
1052 CloseAudioDevice(&audio.device_fd);
1053 ReadReloadInfoFromPipe(&snd_ctrl);
1056 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1057 ReloadCustomSounds();
1059 ReloadCustomMusic();
1061 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1063 if (IS_MUSIC(snd_ctrl))
1065 Mixer_FadeMusicChannel();
1069 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1070 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1071 Mixer_FadeChannel(i);
1073 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1075 if (IS_MUSIC(snd_ctrl))
1077 Mixer_StopMusicChannel();
1081 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1082 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1083 Mixer_StopChannel(i);
1085 #if defined(AUDIO_UNIX_NATIVE)
1086 if (!mixer_active_channels)
1087 CloseAudioDevice(&audio.device_fd);
1090 else if (snd_ctrl.active) /* add new sound to mixer */
1092 Mixer_InsertSound(snd_ctrl);
1096 void StartMixer(void)
1101 SDL_version compile_version;
1102 const SDL_version *link_version;
1103 MIX_VERSION(&compile_version);
1104 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1105 compile_version.major,
1106 compile_version.minor,
1107 compile_version.patch);
1108 link_version = Mix_Linked_Version();
1109 printf("running with SDL_mixer version: %d.%d.%d\n",
1110 link_version->major,
1111 link_version->minor,
1112 link_version->patch);
1115 if (!audio.sound_available)
1118 /* initialize stereo position conversion information */
1119 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1121 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1123 #if defined(AUDIO_UNIX_NATIVE)
1124 if (!ForkAudioProcess())
1125 audio.sound_available = FALSE;
1129 #if defined(AUDIO_UNIX_NATIVE)
1131 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1132 int sample_pos, int sample_size,
1133 short *buffer_base_ptr, int buffer_pos,
1134 int num_output_channels)
1136 short *buffer_ptr = buffer_base_ptr + num_output_channels * buffer_pos;
1137 int num_channels = snd_ctrl->num_channels;
1138 int stepsize = num_channels;
1139 int output_stepsize = num_output_channels;
1142 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1144 byte *sample_ptr = (byte *)snd_ctrl->data_ptr + num_channels * sample_pos;
1146 for (i=0; i<num_output_channels; i++)
1148 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1150 for (j=0; j<sample_size; j++)
1151 buffer_ptr[output_stepsize * j + i] =
1152 ((short)(sample_ptr[stepsize * j + offset] ^ 0x80)) << 8;
1155 else /* AUDIO_FORMAT_S16 */
1157 short *sample_ptr= (short *)snd_ctrl->data_ptr + num_channels * sample_pos;
1159 for (i=0; i<num_output_channels; i++)
1161 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1163 for (j=0; j<sample_size; j++)
1164 buffer_ptr[output_stepsize * j + i] =
1165 sample_ptr[stepsize * j + offset];
1170 #if defined(AUDIO_STREAMING_DSP)
1171 static void Mixer_Main_DSP()
1173 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1174 static long premix_last_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1175 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1179 int max_sample_size;
1180 int num_output_channels;
1183 if (!mixer_active_channels)
1186 if (audio.device_fd < 0)
1188 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1191 InitAudioDevice(&afmt);
1194 stereo = afmt.stereo;
1195 fragment_size = afmt.fragment_size;
1196 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1197 num_output_channels = (stereo ? 2 : 1);
1198 max_sample_size = fragment_size / (num_output_channels * sample_bytes);
1200 /* first clear the last premixing buffer */
1201 memset(premix_last_buffer, 0,
1202 max_sample_size * num_output_channels * sizeof(long));
1204 for(i=0; i<audio.num_channels; i++)
1211 if (!mixer[i].active)
1214 if (Mixer_ChannelExpired(i))
1216 Mixer_StopChannel(i);
1220 /* pointer, lenght and actual playing position of sound sample */
1221 sample_ptr = mixer[i].data_ptr;
1222 sample_len = mixer[i].data_len;
1223 sample_pos = mixer[i].playing_pos;
1224 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1225 mixer[i].playing_pos += sample_size;
1227 /* copy original sample to first mixing buffer */
1228 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1229 premix_first_buffer, 0, num_output_channels);
1231 /* are we about to restart a looping sound? */
1232 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1234 while (sample_size < max_sample_size)
1236 int restarted_sample_size =
1237 MIN(max_sample_size - sample_size, sample_len);
1239 CopySampleToMixingBuffer(&mixer[i], 0, restarted_sample_size,
1240 premix_first_buffer, sample_size,
1241 num_output_channels);
1243 mixer[i].playing_pos = restarted_sample_size;
1244 sample_size += restarted_sample_size;
1248 /* decrease volume if sound is fading out */
1249 if (IS_FADING(mixer[i]) &&
1250 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1251 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1253 /* adjust volume of actual sound sample */
1254 if (mixer[i].volume != SOUND_MAX_VOLUME)
1255 for(j=0; j<sample_size * num_output_channels; j++)
1256 premix_first_buffer[j] =
1257 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1259 /* adjust left and right channel volume due to stereo sound position */
1262 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1263 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1265 for(j=0; j<sample_size; j++)
1267 premix_first_buffer[2 * j + 0] =
1268 left_volume * premix_first_buffer[2 * j + 0] / SOUND_MAX_LEFT2RIGHT;
1269 premix_first_buffer[2 * j + 1] =
1270 right_volume * premix_first_buffer[2 * j + 1] / SOUND_MAX_LEFT2RIGHT;
1274 /* fill the last mixing buffer with stereo or mono sound */
1275 for(j=0; j<sample_size * num_output_channels; j++)
1276 premix_last_buffer[j] += premix_first_buffer[j];
1278 /* delete completed sound entries from the mixer */
1279 if (mixer[i].playing_pos >= mixer[i].data_len)
1281 if (IS_LOOP(mixer[i]))
1282 mixer[i].playing_pos = 0;
1284 Mixer_StopChannel(i);
1286 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1287 Mixer_StopChannel(i);
1290 /* prepare final playing buffer according to system audio format */
1291 for(i=0; i<max_sample_size * num_output_channels; i++)
1293 /* cut off at 17 bit value */
1294 if (premix_last_buffer[i] < -65535)
1295 premix_last_buffer[i] = -65535;
1296 else if (premix_last_buffer[i] > 65535)
1297 premix_last_buffer[i] = 65535;
1299 /* shift to 16 bit value */
1300 premix_last_buffer[i] >>= 1;
1302 if (afmt.format & AUDIO_FORMAT_U8)
1304 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1306 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1308 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1309 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1311 else /* big endian */
1313 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1314 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1318 /* finally play the sound fragment */
1319 write(audio.device_fd, playing_buffer, fragment_size);
1321 if (!mixer_active_channels)
1322 CloseAudioDevice(&audio.device_fd);
1325 #else /* !AUDIO_STREAMING_DSP */
1327 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1329 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1330 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1331 int max_sample_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1332 int num_output_channels = 1;
1341 /* pointer, lenght and actual playing position of sound sample */
1342 sample_ptr = mixer[i].data_ptr;
1343 sample_len = mixer[i].data_len;
1344 sample_pos = mixer[i].playing_pos;
1345 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1346 mixer[i].playing_pos += sample_size;
1348 /* copy original sample to first mixing buffer */
1349 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1350 premix_first_buffer, 0, num_output_channels);
1352 /* adjust volume of actual sound sample */
1353 if (mixer[i].volume != SOUND_MAX_VOLUME)
1354 for(j=0; j<sample_size; j++)
1355 premix_first_buffer[j] =
1356 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1358 /* might be needed for u-law /dev/audio */
1360 for(j=0; j<sample_size; j++)
1362 linear_to_ulaw(premix_first_buffer[j]);
1365 /* delete completed sound entries from the mixer */
1366 if (mixer[i].playing_pos >= mixer[i].data_len)
1367 Mixer_StopChannel(i);
1369 for(i=0; i<sample_size; i++)
1370 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1372 /* finally play the sound fragment */
1373 write(audio.device_fd, playing_buffer, sample_size);
1377 #endif /* !AUDIO_STREAMING_DSP */
1381 SoundControl snd_ctrl;
1384 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1386 Mixer_InitChannels();
1388 #if defined(PLATFORM_HPUX)
1389 InitAudioDevice(&afmt);
1392 FD_ZERO(&mixer_fdset);
1393 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1395 while(1) /* wait for sound playing commands from client */
1397 struct timeval delay = { 0, 0 };
1399 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1400 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1401 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1404 ReadSoundControlFromMainProcess(&snd_ctrl);
1406 HandleSoundRequest(snd_ctrl);
1408 #if defined(AUDIO_STREAMING_DSP)
1410 while (mixer_active_channels &&
1411 select(audio.mixer_pipe[0] + 1,
1412 &mixer_fdset, NULL, NULL, &delay) < 1)
1414 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1419 #else /* !AUDIO_STREAMING_DSP */
1421 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1422 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1425 InitAudioDevice(&afmt);
1430 while (mixer_active_channels &&
1431 select(audio.mixer_pipe[0] + 1,
1432 &mixer_fdset, NULL, NULL, &delay) < 1)
1434 int wait_percent = 90; /* wait 90% of the real playing time */
1437 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1439 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1443 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1446 CloseAudioDevice(&audio.device_fd);
1448 Mixer_InitChannels(); /* remove all sounds from mixer */
1450 #endif /* !AUDIO_STREAMING_DSP */
1453 #endif /* AUDIO_UNIX_NATIVE */
1456 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1458 /* these two are stolen from "sox"... :) */
1461 ** This routine converts from linear to ulaw.
1463 ** Craig Reese: IDA/Supercomputing Research Center
1464 ** Joe Campbell: Department of Defense
1465 ** 29 September 1989
1468 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1469 ** 2) "A New Digital Technique for Implementation of Any
1470 ** Continuous PCM Companding Law," Villeret, Michel,
1471 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1472 ** 1973, pg. 11.12-11.17
1473 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1474 ** for Analog-to_Digital Conversion Techniques,"
1477 ** Input: Signed 16 bit linear sample
1478 ** Output: 8 bit ulaw sample
1481 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1482 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1485 static unsigned char linear_to_ulaw(int sample)
1487 static int exp_lut[256] =
1489 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1490 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1491 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1492 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1493 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1494 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1495 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1496 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1497 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1498 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1499 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1500 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1501 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1502 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1503 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1504 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1507 int sign, exponent, mantissa;
1508 unsigned char ulawbyte;
1510 /* Get the sample into sign-magnitude. */
1511 sign = (sample >> 8) & 0x80; /* set aside the sign */
1513 sample = -sample; /* get magnitude */
1515 sample = CLIP; /* clip the magnitude */
1517 /* Convert from 16 bit linear to ulaw. */
1518 sample = sample + BIAS;
1519 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1520 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1521 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1524 ulawbyte = 0x02; /* optional CCITT trap */
1531 ** This routine converts from ulaw to 16 bit linear.
1533 ** Craig Reese: IDA/Supercomputing Research Center
1534 ** 29 September 1989
1537 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1538 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1539 ** for Analog-to_Digital Conversion Techniques,"
1542 ** Input: 8 bit ulaw sample
1543 ** Output: signed 16 bit linear sample
1546 static int ulaw_to_linear(unsigned char ulawbyte)
1548 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1549 int sign, exponent, mantissa, sample;
1551 ulawbyte = ~ ulawbyte;
1552 sign = ( ulawbyte & 0x80 );
1553 exponent = ( ulawbyte >> 4 ) & 0x07;
1554 mantissa = ulawbyte & 0x0F;
1555 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1561 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1564 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1565 /* ========================================================================= */
1566 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1568 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1569 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1571 static void *Load_WAV(char *filename)
1573 SoundInfo *snd_info;
1574 #if defined(AUDIO_UNIX_NATIVE)
1575 struct SoundHeader_WAV header;
1577 byte sound_header_buffer[WAV_HEADER_SIZE];
1580 char chunk_name[CHUNK_ID_LEN + 1];
1586 if (!audio.sound_available)
1590 printf("loading WAV file '%s'\n", filename);
1593 snd_info = checked_calloc(sizeof(SoundInfo));
1595 #if defined(TARGET_SDL)
1597 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1599 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1604 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1606 #elif defined(TARGET_ALLEGRO)
1608 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1610 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1615 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1617 #else /* AUDIO_UNIX_NATIVE */
1619 if ((file = fopen(filename, MODE_READ)) == NULL)
1621 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1626 /* read chunk id "RIFF" */
1627 getFileChunkLE(file, chunk_name, &chunk_size);
1628 if (strcmp(chunk_name, "RIFF") != 0)
1630 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1636 /* read "RIFF" type id "WAVE" */
1637 getFileChunkLE(file, chunk_name, NULL);
1638 if (strcmp(chunk_name, "WAVE") != 0)
1640 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1646 while (getFileChunkLE(file, chunk_name, &chunk_size))
1648 if (strcmp(chunk_name, "fmt ") == 0)
1650 if (chunk_size < WAV_HEADER_SIZE)
1652 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1658 header.compression_code = getFile16BitLE(file);
1659 header.num_channels = getFile16BitLE(file);
1660 header.sample_rate = getFile32BitLE(file);
1661 header.bytes_per_second = getFile32BitLE(file);
1662 header.block_align = getFile16BitLE(file);
1663 header.bits_per_sample = getFile16BitLE(file);
1665 if (chunk_size > WAV_HEADER_SIZE)
1666 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1668 if (header.compression_code != 1)
1670 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1671 filename, header.compression_code);
1677 if (header.num_channels != 1 &&
1678 header.num_channels != 2)
1680 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1681 filename, header.num_channels);
1687 if (header.bits_per_sample != 8 &&
1688 header.bits_per_sample != 16)
1690 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1691 filename, header.bits_per_sample);
1697 /* warn, but accept wrong sample rate (may be only slightly different) */
1698 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1699 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1700 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1703 printf("WAV file: '%s'\n", filename);
1704 printf(" Compression code: %d'\n", header.compression_code);
1705 printf(" Number of channels: %d'\n", header.num_channels);
1706 printf(" Sample rate: %ld'\n", header.sample_rate);
1707 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1708 printf(" Block align: %d'\n", header.block_align);
1709 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1712 else if (strcmp(chunk_name, "data") == 0)
1714 data_byte_len = chunk_size;
1716 snd_info->data_len = data_byte_len;
1717 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1719 /* read sound data */
1720 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1723 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1725 free(snd_info->data_ptr);
1730 /* check for odd number of data bytes (data chunk is word aligned) */
1731 if ((data_byte_len % 2) == 1)
1732 ReadUnusedBytesFromFile(file, 1);
1734 else /* unknown chunk -- ignore */
1735 ReadUnusedBytesFromFile(file, chunk_size);
1740 if (snd_info->data_ptr == NULL)
1742 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1747 if (header.bits_per_sample == 8)
1748 snd_info->format = AUDIO_FORMAT_U8;
1749 else /* header.bits_per_sample == 16 */
1751 snd_info->format = AUDIO_FORMAT_S16;
1752 snd_info->data_len /= 2; /* correct number of samples */
1755 snd_info->num_channels = header.num_channels;
1756 if (header.num_channels == 2)
1757 snd_info->data_len /= 2; /* correct number of samples */
1760 if (header.num_channels == 1) /* convert mono sound to stereo */
1762 void *buffer_ptr = checked_malloc(data_byte_len * 2);
1763 void *sample_ptr = snd_info->data_ptr;
1764 int sample_size = snd_info->data_len;
1767 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1768 for (i=0; i<sample_size; i++)
1770 ((short)(((byte *)sample_ptr)[i] ^ 0x80)) << 8;
1771 else /* AUDIO_FORMAT_S16 */
1772 for (i=0; i<sample_size; i++)
1774 ((short *)sample_ptr)[i];
1778 #endif /* AUDIO_UNIX_NATIVE */
1780 snd_info->type = SND_TYPE_WAV;
1781 snd_info->source_filename = getStringCopy(filename);
1786 int getSoundListSize()
1788 return (sound_info->num_file_list_entries +
1789 sound_info->num_dynamic_file_list_entries);
1792 struct FileInfo *getSoundListEntry(int pos)
1794 int num_list_entries = sound_info->num_file_list_entries;
1795 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1797 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
1798 &sound_info->dynamic_file_list[list_pos]);
1801 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
1803 int num_list_entries = sound_info->num_file_list_entries;
1804 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1805 SoundInfo **snd_info =
1806 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
1807 sound_info->dynamic_artwork_list);
1809 return snd_info[list_pos];
1812 int getSoundListPropertyMappingSize()
1814 return sound_info->num_property_mapping_entries;
1817 struct PropertyMapping *getSoundListPropertyMapping()
1819 return sound_info->property_mapping;
1822 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
1823 struct ConfigInfo *config_suffix_list,
1824 char **base_prefixes, char **ext1_suffixes,
1825 char **ext2_suffixes, char **ext3_suffixes,
1826 char **ignore_tokens)
1830 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1831 sound_info->type = ARTWORK_TYPE_SOUNDS;
1833 /* ---------- initialize file list and suffix lists ---------- */
1835 sound_info->num_file_list_entries = num_file_list_entries;
1836 sound_info->num_dynamic_file_list_entries = 0;
1838 sound_info->file_list =
1839 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
1840 num_file_list_entries);
1841 sound_info->dynamic_file_list = NULL;
1843 sound_info->num_suffix_list_entries = 0;
1844 for (i=0; config_suffix_list[i].token != NULL; i++)
1845 sound_info->num_suffix_list_entries++;
1847 sound_info->suffix_list = config_suffix_list;
1849 /* ---------- initialize base prefix and suffixes lists ---------- */
1851 sound_info->num_base_prefixes = 0;
1852 for (i=0; base_prefixes[i] != NULL; i++)
1853 sound_info->num_base_prefixes++;
1855 sound_info->num_ext1_suffixes = 0;
1856 for (i=0; ext1_suffixes[i] != NULL; i++)
1857 sound_info->num_ext1_suffixes++;
1859 sound_info->num_ext2_suffixes = 0;
1860 for (i=0; ext2_suffixes[i] != NULL; i++)
1861 sound_info->num_ext2_suffixes++;
1863 sound_info->num_ext3_suffixes = 0;
1864 for (i=0; ext3_suffixes[i] != NULL; i++)
1865 sound_info->num_ext3_suffixes++;
1867 sound_info->num_ignore_tokens = 0;
1868 for (i=0; ignore_tokens[i] != NULL; i++)
1869 sound_info->num_ignore_tokens++;
1871 sound_info->base_prefixes = base_prefixes;
1872 sound_info->ext1_suffixes = ext1_suffixes;
1873 sound_info->ext2_suffixes = ext2_suffixes;
1874 sound_info->ext3_suffixes = ext3_suffixes;
1875 sound_info->ignore_tokens = ignore_tokens;
1877 sound_info->num_property_mapping_entries = 0;
1879 sound_info->property_mapping = NULL;
1881 /* ---------- initialize artwork reference and content lists ---------- */
1883 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
1885 sound_info->artwork_list =
1886 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
1887 sound_info->dynamic_artwork_list = NULL;
1889 sound_info->content_list = NULL;
1891 /* ---------- initialize artwork loading/freeing functions ---------- */
1893 sound_info->load_artwork = Load_WAV;
1894 sound_info->free_artwork = FreeSound;
1897 num_sounds = sound_info->num_file_list_entries;
1898 Sound = (SoundInfo **)sound_info->artwork_list;
1902 static MusicInfo *Load_MOD(char *filename)
1904 #if defined(TARGET_SDL)
1905 MusicInfo *mod_info;
1907 if (!audio.sound_available)
1910 mod_info = checked_calloc(sizeof(MusicInfo));
1912 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1914 Error(ERR_WARN, "cannot read music file '%s'", filename);
1919 mod_info->type = MUS_TYPE_MOD;
1920 mod_info->source_filename = getStringCopy(filename);
1928 void LoadCustomMusic(void)
1930 static boolean draw_init_text = TRUE; /* only draw at startup */
1931 static char *last_music_directory = NULL;
1932 char *music_directory = getCustomMusicDirectory();
1934 struct dirent *dir_entry;
1936 if (!audio.sound_available)
1939 if (last_music_directory != NULL &&
1940 strcmp(last_music_directory, music_directory) == 0)
1941 return; /* old and new music directory are the same */
1943 if (last_music_directory != NULL)
1944 free(last_music_directory);
1945 last_music_directory = getStringCopy(music_directory);
1949 if ((dir = opendir(music_directory)) == NULL)
1951 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1952 audio.music_available = FALSE;
1957 DrawInitText("Loading music:", 120, FC_GREEN);
1959 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1961 char *basename = dir_entry->d_name;
1962 char *filename = getPath2(music_directory, basename);
1963 MusicInfo *mus_info = NULL;
1966 printf("DEBUG: loading music '%s' ...\n", basename);
1970 DrawInitText(basename, 150, FC_YELLOW);
1972 if (FileIsSound(basename))
1973 mus_info = Load_WAV(filename);
1974 else if (FileIsMusic(basename))
1975 mus_info = Load_MOD(filename);
1982 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1983 Music[num_music - 1] = mus_info;
1989 draw_init_text = FALSE;
1992 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1996 void PlayMusic(int nr)
1998 if (!audio.music_available)
2004 void PlaySound(int nr)
2006 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
2009 void PlaySoundStereo(int nr, int stereo_position)
2011 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
2014 void PlaySoundLoop(int nr)
2016 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
2019 void PlaySoundMusic(int nr)
2021 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
2024 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
2026 SoundControl snd_ctrl;
2028 if (!audio.sound_available ||
2029 !audio.sound_enabled ||
2030 audio.sound_deactivated)
2033 if (volume < SOUND_MIN_VOLUME)
2034 volume = SOUND_MIN_VOLUME;
2035 else if (volume > SOUND_MAX_VOLUME)
2036 volume = SOUND_MAX_VOLUME;
2038 if (stereo_position < SOUND_MAX_LEFT)
2039 stereo_position = SOUND_MAX_LEFT;
2040 else if (stereo_position > SOUND_MAX_RIGHT)
2041 stereo_position = SOUND_MAX_RIGHT;
2043 memset(&snd_ctrl, 0, sizeof(SoundControl)); /* to make valgrind happy */
2045 snd_ctrl.active = TRUE;
2047 snd_ctrl.volume = volume;
2048 snd_ctrl.stereo_position = stereo_position;
2049 snd_ctrl.state = state;
2051 HandleSoundRequest(snd_ctrl);
2054 void FadeMusic(void)
2056 if (!audio.music_available)
2059 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2062 void FadeSound(int nr)
2064 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2070 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2073 void StopMusic(void)
2075 if (!audio.music_available)
2078 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2081 void StopSound(int nr)
2083 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2089 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2092 void StopSoundExt(int nr, int state)
2094 SoundControl snd_ctrl;
2096 if (!audio.sound_available)
2099 memset(&snd_ctrl, 0, sizeof(SoundControl)); /* to make valgrind happy */
2101 snd_ctrl.active = FALSE;
2103 snd_ctrl.state = state;
2105 HandleSoundRequest(snd_ctrl);
2108 static void ReloadCustomSounds()
2111 printf("DEBUG: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
2114 LoadArtworkConfig(sound_info);
2115 ReloadCustomArtworkList(sound_info);
2118 num_sounds = getSoundListSize();
2122 static void ReloadCustomMusic()
2125 printf("DEBUG: reloading music '%s' ...\n", artwork.mus_current_identifier);
2131 void InitReloadCustomSounds(char *set_identifier)
2133 if (!audio.sound_available)
2136 #if defined(AUDIO_UNIX_NATIVE)
2137 LoadArtworkConfig(sound_info); /* also load config on sound client */
2138 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2140 ReloadCustomSounds();
2144 void InitReloadCustomMusic(char *set_identifier)
2146 if (!audio.music_available)
2149 #if defined(AUDIO_UNIX_NATIVE)
2150 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2152 ReloadCustomMusic();
2156 void FreeSound(void *ptr)
2158 SoundInfo *sound = (SoundInfo *)ptr;
2163 if (sound->data_ptr)
2165 #if defined(TARGET_SDL)
2166 Mix_FreeChunk(sound->data_ptr);
2167 #elif defined(TARGET_ALLEGRO)
2168 destroy_sample(sound->data_ptr);
2169 #else /* AUDIO_UNIX_NATIVE */
2170 free(sound->data_ptr);
2174 if (sound->source_filename)
2175 free(sound->source_filename);
2180 void FreeMusic(MusicInfo *music)
2185 if (music->data_ptr)
2187 #if defined(TARGET_SDL)
2188 if (music->type == MUS_TYPE_MOD)
2189 Mix_FreeMusic(music->data_ptr);
2191 Mix_FreeChunk(music->data_ptr);
2192 #elif defined(TARGET_ALLEGRO)
2193 destroy_sample(music->data_ptr);
2194 #else /* AUDIO_UNIX_NATIVE */
2195 free(music->data_ptr);
2202 void FreeAllSounds()
2204 FreeCustomArtworkLists(sound_info);
2214 for(i=0; i<num_music; i++)
2215 FreeMusic(Music[i]);
2223 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2224 /* ========================================================================= */