1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include <sys/types.h>
25 #if defined(PLATFORM_LINUX)
26 #include <sys/ioctl.h>
27 #include <linux/soundcard.h>
28 #elif defined(PLATFORM_FREEBSD)
29 #include <machine/soundcard.h>
30 #elif defined(PLATFORM_NETBSD)
31 #include <sys/ioctl.h>
32 #include <sys/audioio.h>
33 #elif defined(PLATFORM_HPUX)
34 #include <sys/audio.h>
44 /* expiration time (in milliseconds) for sound loops */
45 #define SOUND_LOOP_EXPIRATION_TIME 200
47 /* one second fading interval == 1000 ticks (milliseconds) */
48 #define SOUND_FADING_INTERVAL 1000
50 #if defined(AUDIO_STREAMING_DSP)
51 #define SOUND_FADING_VOLUME_STEP (SOUND_MAX_VOLUME / 40)
52 #define SOUND_FADING_VOLUME_THRESHOLD (SOUND_FADING_VOLUME_STEP * 2)
55 #if !defined(PLATFORM_HPUX)
56 #define SND_BLOCKSIZE 4096
58 #define SND_BLOCKSIZE 32768
61 #define SND_TYPE_NONE 0
62 #define SND_TYPE_WAV 1
64 #define MUS_TYPE_NONE 0
65 #define MUS_TYPE_WAV 1
66 #define MUS_TYPE_MOD 2
68 #define DEVICENAME_DSP "/dev/dsp"
69 #define DEVICENAME_SOUND_DSP "/dev/sound/dsp"
70 #define DEVICENAME_AUDIO "/dev/audio"
71 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
73 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
74 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
76 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
77 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
80 struct SoundHeader_SUN
83 unsigned long hdr_size;
84 unsigned long data_size;
85 unsigned long encoding;
86 unsigned long sample_rate;
87 unsigned long channels;
90 struct SoundHeader_8SVX
93 unsigned long chunk_size;
98 #if defined(AUDIO_UNIX_NATIVE)
99 struct SoundHeader_WAV
101 unsigned short compression_code;
102 unsigned short num_channels;
103 unsigned long sample_rate;
104 unsigned long bytes_per_second;
105 unsigned short block_align;
106 unsigned short bits_per_sample;
110 struct AudioFormatInfo
112 boolean stereo; /* availability of stereo sound */
113 int format; /* size and endianess of sample data */
114 int sample_rate; /* sample frequency */
115 int fragment_size; /* audio device fragment size in bytes */
120 char *source_filename;
125 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
126 long data_len; /* number of samples, NOT number of bytes */
128 typedef struct SampleInfo SoundInfo;
129 typedef struct SampleInfo MusicInfo;
141 unsigned long playing_starttime;
142 unsigned long playing_pos;
146 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
147 long data_len; /* number of samples, NOT number of bytes */
149 #if defined(TARGET_ALLEGRO)
153 typedef struct SoundControl SoundControl;
155 static struct ArtworkListInfo sound_info;
157 static struct ArtworkConfigInfo *sound_config = NULL;
158 static ListNode *SoundFileList = NULL;
159 static SoundInfo **Sound = NULL;
160 static MusicInfo **Music = NULL;
161 static int num_sounds = 0, num_music = 0;
162 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
165 /* ========================================================================= */
166 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
168 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
169 static int mixer_active_channels = 0;
171 #if defined(AUDIO_UNIX_NATIVE)
172 static struct AudioFormatInfo afmt;
174 static void Mixer_Main(void);
175 #if !defined(AUDIO_STREAMING_DSP)
176 static unsigned char linear_to_ulaw(int);
177 static int ulaw_to_linear(unsigned char);
181 static void ReloadCustomSounds();
182 static void ReloadCustomMusic();
183 static void FreeSound(void *);
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");
264 printf("PID: %d [%s]\n", getpid(),
265 (IS_CHILD_PROCESS(audio.mixer_pid) ? "child" : "parent"));
269 if (IS_CHILD_PROCESS(audio.mixer_pid))
270 Mixer_Main(); /* this function never returns */
272 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
277 void UnixOpenAudio(void)
279 if (!TestAudioDevices())
282 audio.sound_available = TRUE;
283 audio.sound_enabled = TRUE;
285 #if defined(AUDIO_STREAMING_DSP)
286 audio.music_available = TRUE;
287 audio.loops_available = TRUE;
290 audio.num_channels = NUM_MIXER_CHANNELS;
291 audio.music_channel = MUSIC_CHANNEL;
292 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
295 void UnixCloseAudio(void)
298 close(audio.device_fd);
300 if (IS_PARENT_PROCESS(audio.mixer_pid))
301 kill(audio.mixer_pid, SIGTERM);
305 /* ------------------------------------------------------------------------- */
306 /* functions for platform specific audio device initialization */
307 /* ------------------------------------------------------------------------- */
309 #if defined(AUDIO_LINUX_IOCTL)
310 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
312 /* "ioctl()" expects pointer to 'int' value for stereo flag
313 (boolean is defined as 'char', which will not work here) */
314 unsigned int fragment_spec = 0;
315 int fragment_size_query;
324 /* supported audio format in preferred order */
325 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
326 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
327 { AFMT_U8, AUDIO_FORMAT_U8 },
332 /* determine logarithm (log2) of the fragment size */
333 while ((1 << fragment_spec) < afmt->fragment_size)
336 /* use two fragments (play one fragment, prepare the other);
337 one fragment would result in interrupted audio output, more
338 than two fragments would raise audio output latency to much */
339 fragment_spec |= 0x00020000;
341 /* Example for fragment specification:
342 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
343 - (with stereo the effective buffer size will shrink to 256)
344 => fragment_size = 0x00020009 */
346 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
347 Error(ERR_EXIT_SOUND_SERVER,
348 "cannot set fragment size of audio device -- no sounds");
352 while (formats[i].format_result != -1)
354 unsigned int audio_format = formats[i].format_ioctl;
355 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
357 afmt->format = formats[i].format_result;
362 if (afmt->format == 0) /* no supported audio format found */
363 Error(ERR_EXIT_SOUND_SERVER,
364 "cannot set audio format of audio device -- no sounds");
366 /* try if we can use stereo sound */
368 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
369 afmt->stereo = FALSE;
371 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
372 Error(ERR_EXIT_SOUND_SERVER,
373 "cannot set sample rate of audio device -- no sounds");
375 /* get the real fragmentation size; this should return 512 */
376 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
377 Error(ERR_EXIT_SOUND_SERVER,
378 "cannot get fragment size of audio device -- no sounds");
379 if (fragment_size_query != afmt->fragment_size)
380 Error(ERR_EXIT_SOUND_SERVER,
381 "cannot set fragment size of audio device -- no sounds");
383 #endif /* AUDIO_LINUX_IOCTL */
385 #if defined(PLATFORM_NETBSD)
386 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
389 boolean stereo = TRUE;
391 AUDIO_INITINFO(&a_info);
392 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
393 a_info.play.precision = 8;
394 a_info.play.channels = 2;
395 a_info.play.sample_rate = afmt->sample_rate;
396 a_info.blocksize = afmt->fragment_size;
398 afmt->format = AUDIO_FORMAT_U8;
401 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
403 /* try to disable stereo */
404 a_info.play.channels = 1;
406 afmt->stereo = FALSE;
408 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
409 Error(ERR_EXIT_SOUND_SERVER,
410 "cannot set sample rate of audio device -- no sounds");
413 #endif /* PLATFORM_NETBSD */
415 #if defined(PLATFORM_HPUX)
416 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
418 struct audio_describe ainfo;
421 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
423 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
425 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
426 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
428 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
429 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
431 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
432 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
434 afmt->format = AUDIO_FORMAT_U8;
435 afmt->stereo = FALSE;
436 afmt->sample_rate = 8000;
440 #endif /* PLATFORM_HPUX */
442 static void InitAudioDevice(struct AudioFormatInfo *afmt)
445 afmt->format = AUDIO_FORMAT_UNKNOWN;
446 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
447 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
449 #if defined(AUDIO_LINUX_IOCTL)
450 InitAudioDevice_Linux(afmt);
451 #elif defined(PLATFORM_NETBSD)
452 InitAudioDevice_NetBSD(afmt);
453 #elif defined(PLATFORM_HPUX)
454 InitAudioDevice_HPUX(afmt);
456 /* generic /dev/audio stuff might be placed here */
461 /* ------------------------------------------------------------------------- */
462 /* functions for communication between main process and sound mixer process */
463 /* ------------------------------------------------------------------------- */
465 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
467 if (IS_CHILD_PROCESS(audio.mixer_pid))
470 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
472 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
473 audio.sound_available = audio.sound_enabled = FALSE;
478 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
480 if (IS_PARENT_PROCESS(audio.mixer_pid))
483 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
484 != sizeof(SoundControl))
485 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
488 static void WriteReloadInfoToPipe(char *set_identifier, int type)
490 SoundControl snd_ctrl;
491 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
492 artwork.mus_current);
493 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
494 unsigned long str_size2 = strlen(leveldir_current->sounds_path) + 1;
495 unsigned long str_size3 = strlen(leveldir_current->music_path) + 1;
496 unsigned long str_size4 = strlen(ti->basepath) + 1;
497 unsigned long str_size5 = strlen(ti->fullpath) + 1;
498 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
499 setup.override_level_sounds :
500 setup.override_level_music);
502 if (IS_CHILD_PROCESS(audio.mixer_pid))
505 if (leveldir_current == NULL) /* should never happen */
506 Error(ERR_EXIT, "leveldir_current == NULL");
508 snd_ctrl.active = FALSE;
509 snd_ctrl.state = type;
510 snd_ctrl.data_len = strlen(set_identifier) + 1;
512 if (write(audio.mixer_pipe[1], &snd_ctrl,
513 sizeof(snd_ctrl)) < 0 ||
514 write(audio.mixer_pipe[1], set_identifier,
515 snd_ctrl.data_len) < 0 ||
516 write(audio.mixer_pipe[1], &override_level_artwork,
517 sizeof(boolean)) < 0 ||
518 write(audio.mixer_pipe[1], leveldir_current,
519 sizeof(TreeInfo)) < 0 ||
520 write(audio.mixer_pipe[1], ti,
521 sizeof(TreeInfo)) < 0 ||
522 write(audio.mixer_pipe[1], &str_size1,
523 sizeof(unsigned long)) < 0 ||
524 write(audio.mixer_pipe[1], &str_size2,
525 sizeof(unsigned long)) < 0 ||
526 write(audio.mixer_pipe[1], &str_size3,
527 sizeof(unsigned long)) < 0 ||
528 write(audio.mixer_pipe[1], &str_size4,
529 sizeof(unsigned long)) < 0 ||
530 write(audio.mixer_pipe[1], &str_size5,
531 sizeof(unsigned long)) < 0 ||
532 write(audio.mixer_pipe[1], leveldir_current->fullpath,
534 write(audio.mixer_pipe[1], leveldir_current->sounds_path,
536 write(audio.mixer_pipe[1], leveldir_current->music_path,
538 write(audio.mixer_pipe[1], ti->basepath,
540 write(audio.mixer_pipe[1], ti->fullpath,
543 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
544 audio.sound_available = audio.sound_enabled = FALSE;
549 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
551 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
552 &artwork.snd_current : &artwork.mus_current);
553 TreeInfo *ti = *ti_ptr;
554 unsigned long str_size1, str_size2, str_size3, str_size4, str_size5;
555 static char *set_identifier = NULL;
556 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
557 &setup.override_level_sounds :
558 &setup.override_level_music);
561 free(set_identifier);
563 set_identifier = checked_malloc(snd_ctrl->data_len);
565 if (leveldir_current == NULL)
566 leveldir_current = checked_calloc(sizeof(TreeInfo));
569 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
570 if (leveldir_current->fullpath != NULL)
571 free(leveldir_current->fullpath);
572 if (leveldir_current->sounds_path != NULL)
573 free(leveldir_current->sounds_path);
574 if (leveldir_current->music_path != NULL)
575 free(leveldir_current->music_path);
576 if (ti->basepath != NULL)
578 if (ti->fullpath != NULL)
581 if (read(audio.mixer_pipe[0], set_identifier,
582 snd_ctrl->data_len) != snd_ctrl->data_len ||
583 read(audio.mixer_pipe[0], override_level_artwork,
584 sizeof(boolean)) != sizeof(boolean) ||
585 read(audio.mixer_pipe[0], leveldir_current,
586 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
587 read(audio.mixer_pipe[0], ti,
588 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
589 read(audio.mixer_pipe[0], &str_size1,
590 sizeof(unsigned long)) != sizeof(unsigned long) ||
591 read(audio.mixer_pipe[0], &str_size2,
592 sizeof(unsigned long)) != sizeof(unsigned long) ||
593 read(audio.mixer_pipe[0], &str_size3,
594 sizeof(unsigned long)) != sizeof(unsigned long) ||
595 read(audio.mixer_pipe[0], &str_size4,
596 sizeof(unsigned long)) != sizeof(unsigned long) ||
597 read(audio.mixer_pipe[0], &str_size5,
598 sizeof(unsigned long)) != sizeof(unsigned long))
599 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
601 leveldir_current->fullpath = checked_calloc(str_size1);
602 leveldir_current->sounds_path = checked_calloc(str_size2);
603 leveldir_current->music_path = checked_calloc(str_size3);
604 ti->basepath = checked_calloc(str_size4);
605 ti->fullpath = checked_calloc(str_size5);
607 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
608 str_size1) != str_size1 ||
609 read(audio.mixer_pipe[0], leveldir_current->sounds_path,
610 str_size2) != str_size2 ||
611 read(audio.mixer_pipe[0], leveldir_current->music_path,
612 str_size3) != str_size3 ||
613 read(audio.mixer_pipe[0], ti->basepath,
614 str_size4) != str_size4 ||
615 read(audio.mixer_pipe[0], ti->fullpath,
616 str_size5) != str_size5)
617 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
619 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
620 artwork.snd_current_identifier = set_identifier;
622 artwork.mus_current_identifier = set_identifier;
625 #endif /* AUDIO_UNIX_NATIVE */
628 /* ------------------------------------------------------------------------- */
629 /* mixer functions */
630 /* ------------------------------------------------------------------------- */
632 void Mixer_InitChannels()
636 for(i=0; i<audio.num_channels; i++)
637 mixer[i].active = FALSE;
638 mixer_active_channels = 0;
641 static void Mixer_ResetChannelExpiration(int channel)
643 mixer[channel].playing_starttime = Counter();
645 #if defined(TARGET_SDL)
646 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
647 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
651 static boolean Mixer_ChannelExpired(int channel)
653 if (!mixer[channel].active)
656 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
657 DelayReached(&mixer[channel].playing_starttime,
658 SOUND_LOOP_EXPIRATION_TIME))
661 #if defined(TARGET_SDL)
663 if (!Mix_Playing(channel))
666 #elif defined(TARGET_ALLEGRO)
668 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
669 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
671 /* sound sample has completed playing or was completely faded out */
672 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
675 #endif /* TARGET_ALLEGRO */
680 static boolean Mixer_AllocateChannel(int channel)
682 #if defined(TARGET_ALLEGRO)
683 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
684 if (mixer[channel].voice < 0)
691 static void Mixer_SetChannelProperties(int channel)
693 #if defined(TARGET_SDL)
694 Mix_Volume(channel, mixer[channel].volume);
695 Mix_SetPanning(channel,
696 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
697 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
698 #elif defined(TARGET_ALLEGRO)
699 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
700 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
704 static void Mixer_StartChannel(int channel)
706 #if defined(TARGET_SDL)
707 Mix_PlayChannel(channel, mixer[channel].data_ptr,
708 IS_LOOP(mixer[channel]) ? -1 : 0);
709 #elif defined(TARGET_ALLEGRO)
710 if (IS_LOOP(mixer[channel]))
711 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
713 voice_start(mixer[channel].voice);
717 static void Mixer_PlayChannel(int channel)
719 /* start with inactive channel in case something goes wrong */
720 mixer[channel].active = FALSE;
722 if (mixer[channel].type != MUS_TYPE_WAV)
725 if (!Mixer_AllocateChannel(channel))
728 Mixer_SetChannelProperties(channel);
729 Mixer_StartChannel(channel);
731 Mixer_ResetChannelExpiration(channel);
733 mixer[channel].playing_pos = 0;
734 mixer[channel].active = TRUE;
735 mixer_active_channels++;
738 static void Mixer_PlayMusicChannel()
740 Mixer_PlayChannel(audio.music_channel);
742 #if defined(TARGET_SDL)
743 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
745 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
746 this looks like a bug in the SDL_mixer library */
747 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
748 Mix_VolumeMusic(SOUND_MAX_VOLUME);
753 static void Mixer_StopChannel(int channel)
755 if (!mixer[channel].active)
758 #if defined(TARGET_SDL)
759 Mix_HaltChannel(channel);
760 #elif defined(TARGET_ALLEGRO)
761 voice_set_volume(mixer[channel].voice, 0);
762 deallocate_voice(mixer[channel].voice);
765 mixer[channel].active = FALSE;
766 mixer_active_channels--;
769 static void Mixer_StopMusicChannel()
771 Mixer_StopChannel(audio.music_channel);
773 #if defined(TARGET_SDL)
778 static void Mixer_FadeChannel(int channel)
780 if (!mixer[channel].active)
783 mixer[channel].state |= SND_CTRL_FADE;
785 #if defined(TARGET_SDL)
786 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
787 #elif defined(TARGET_ALLEGRO)
788 if (voice_check(mixer[channel].voice))
789 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
793 static void Mixer_FadeMusicChannel()
795 Mixer_FadeChannel(audio.music_channel);
797 #if defined(TARGET_SDL)
798 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
802 static void Mixer_UnFadeChannel(int channel)
804 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
807 mixer[channel].state &= ~SND_CTRL_FADE;
808 mixer[channel].volume = SOUND_MAX_VOLUME;
810 #if defined(TARGET_SDL)
811 Mix_ExpireChannel(channel, -1);
812 Mix_Volume(channel, mixer[channel].volume);
813 #elif defined(TARGET_ALLEGRO)
814 voice_stop_volumeramp(mixer[channel].voice);
815 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
816 mixer[channel].volume);
820 static void Mixer_InsertSound(SoundControl snd_ctrl)
826 printf("NEW SOUND %d ARRIVED [%d] [%d ACTIVE CHANNELS]\n",
827 snd_ctrl.nr, num_sounds, mixer_active_channels);
830 if (IS_MUSIC(snd_ctrl))
835 snd_ctrl.nr = snd_ctrl.nr % num_music;
837 else if (snd_ctrl.nr >= num_sounds)
840 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
841 if (snd_info == NULL)
844 /* copy sound sample and format information */
845 snd_ctrl.type = snd_info->type;
846 snd_ctrl.format = snd_info->format;
847 snd_ctrl.data_ptr = snd_info->data_ptr;
848 snd_ctrl.data_len = snd_info->data_len;
850 /* play music samples on a dedicated music channel */
851 if (IS_MUSIC(snd_ctrl))
853 Mixer_StopMusicChannel();
855 mixer[audio.music_channel] = snd_ctrl;
856 Mixer_PlayMusicChannel();
861 /* check if (and how often) this sound sample is already playing */
862 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
863 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
867 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
870 /* reset expiration delay for already playing loop sounds */
871 if (k > 0 && IS_LOOP(snd_ctrl))
873 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
875 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
878 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
881 if (IS_FADING(mixer[i]))
882 Mixer_UnFadeChannel(i);
884 /* restore settings like volume and stereo position */
885 mixer[i].volume = snd_ctrl.volume;
886 mixer[i].stereo_position = snd_ctrl.stereo_position;
888 Mixer_SetChannelProperties(i);
889 Mixer_ResetChannelExpiration(i);
892 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
893 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
902 printf("PLAYING NEW SOUND %d\n", snd_ctrl.nr);
905 /* don't play sound more than n times simultaneously (with n == 2 for now) */
908 unsigned long playing_current = Counter();
909 int longest = 0, longest_nr = audio.first_sound_channel;
911 /* look for oldest equal sound */
912 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
914 int playing_time = playing_current - mixer[i].playing_starttime;
917 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
920 actual = 1000 * playing_time / mixer[i].data_len;
922 if (actual >= longest)
929 Mixer_StopChannel(longest_nr);
932 /* If all (non-music) channels are active, stop the channel that has
933 played its sound sample most completely (in percent of the sample
934 length). As we cannot currently get the actual playing position
935 of the channel's sound sample when compiling with the SDL mixer
936 library, we use the current playing time (in milliseconds) instead. */
939 /* channel allocation sanity check -- should not be needed */
940 if (mixer_active_channels ==
941 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
943 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
945 if (!mixer[i].active)
947 Error(ERR_RETURN, "Mixer_InsertSound: Channel %d inactive", i);
948 Error(ERR_RETURN, "Mixer_InsertSound: This should never happen!");
950 mixer_active_channels--;
956 if (mixer_active_channels ==
957 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
959 unsigned long playing_current = Counter();
960 int longest = 0, longest_nr = audio.first_sound_channel;
962 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
964 Error(ERR_RETURN, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
965 i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
968 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
970 int playing_time = playing_current - mixer[i].playing_starttime;
971 int actual = 1000 * playing_time / mixer[i].data_len;
973 if (!IS_LOOP(mixer[i]) && actual > longest)
980 Mixer_StopChannel(longest_nr);
983 /* add the new sound to the mixer */
984 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
987 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
990 if (!mixer[i].active)
993 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
996 #if defined(AUDIO_UNIX_NATIVE)
997 if (snd_info->data_len == 0)
999 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
1003 mixer[i] = snd_ctrl;
1004 Mixer_PlayChannel(i);
1011 static void HandleSoundRequest(SoundControl snd_ctrl)
1015 #if defined(AUDIO_UNIX_NATIVE)
1016 if (IS_PARENT_PROCESS(audio.mixer_pid))
1018 SendSoundControlToMixerProcess(&snd_ctrl);
1023 /* deactivate channels that have expired since the last request */
1024 for (i=0; i<audio.num_channels; i++)
1025 if (mixer[i].active && Mixer_ChannelExpired(i))
1026 Mixer_StopChannel(i);
1028 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
1030 Mixer_StopMusicChannel();
1031 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1032 Mixer_StopChannel(i);
1034 #if defined(AUDIO_UNIX_NATIVE)
1035 CloseAudioDevice(&audio.device_fd);
1036 ReadReloadInfoFromPipe(&snd_ctrl);
1039 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1040 ReloadCustomSounds();
1042 ReloadCustomMusic();
1044 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1046 if (IS_MUSIC(snd_ctrl))
1048 Mixer_FadeMusicChannel();
1052 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1053 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1054 Mixer_FadeChannel(i);
1056 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1058 if (IS_MUSIC(snd_ctrl))
1060 Mixer_StopMusicChannel();
1064 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1065 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1066 Mixer_StopChannel(i);
1068 #if defined(AUDIO_UNIX_NATIVE)
1069 if (!mixer_active_channels)
1070 CloseAudioDevice(&audio.device_fd);
1073 else if (snd_ctrl.active) /* add new sound to mixer */
1075 Mixer_InsertSound(snd_ctrl);
1079 void StartMixer(void)
1084 SDL_version compile_version;
1085 const SDL_version *link_version;
1086 MIX_VERSION(&compile_version);
1087 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1088 compile_version.major,
1089 compile_version.minor,
1090 compile_version.patch);
1091 link_version = Mix_Linked_Version();
1092 printf("running with SDL_mixer version: %d.%d.%d\n",
1093 link_version->major,
1094 link_version->minor,
1095 link_version->patch);
1098 if (!audio.sound_available)
1101 /* initialize stereo position conversion information */
1102 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1104 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1106 #if defined(AUDIO_UNIX_NATIVE)
1107 if (!ForkAudioProcess())
1108 audio.sound_available = FALSE;
1112 #if defined(AUDIO_UNIX_NATIVE)
1114 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1115 int sample_pos, int sample_size,
1118 void *sample_ptr = snd_ctrl->data_ptr;
1121 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1122 for (i=0; i<sample_size; i++)
1124 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1125 else /* AUDIO_FORMAT_S16 */
1126 for (i=0; i<sample_size; i++)
1128 ((short *)sample_ptr)[sample_pos + i];
1131 #if defined(AUDIO_STREAMING_DSP)
1132 static void Mixer_Main_DSP()
1134 static short premix_first_buffer[SND_BLOCKSIZE];
1135 static short premix_left_buffer[SND_BLOCKSIZE];
1136 static short premix_right_buffer[SND_BLOCKSIZE];
1137 static long premix_last_buffer[SND_BLOCKSIZE];
1138 static byte playing_buffer[SND_BLOCKSIZE];
1142 int max_sample_size;
1145 if (!mixer_active_channels)
1148 if (audio.device_fd < 0)
1150 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1153 InitAudioDevice(&afmt);
1156 stereo = afmt.stereo;
1157 fragment_size = afmt.fragment_size;
1158 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1159 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1161 /* first clear the last premixing buffer */
1162 memset(premix_last_buffer, 0,
1163 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1165 for(i=0; i<audio.num_channels; i++)
1172 if (!mixer[i].active)
1175 if (Mixer_ChannelExpired(i))
1177 Mixer_StopChannel(i);
1181 /* pointer, lenght and actual playing position of sound sample */
1182 sample_ptr = mixer[i].data_ptr;
1183 sample_len = mixer[i].data_len;
1184 sample_pos = mixer[i].playing_pos;
1185 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1186 mixer[i].playing_pos += sample_size;
1188 /* copy original sample to first mixing buffer */
1189 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1190 premix_first_buffer);
1192 /* are we about to restart a looping sound? */
1193 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1195 while (sample_size < max_sample_size)
1197 int restarted_sample_size =
1198 MIN(max_sample_size - sample_size, sample_len);
1200 if (mixer[i].format == AUDIO_FORMAT_U8)
1201 for (j=0; j<restarted_sample_size; j++)
1202 premix_first_buffer[sample_size + j] =
1203 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1205 for (j=0; j<restarted_sample_size; j++)
1206 premix_first_buffer[sample_size + j] =
1207 ((short *)sample_ptr)[j];
1209 mixer[i].playing_pos = restarted_sample_size;
1210 sample_size += restarted_sample_size;
1214 /* decrease volume if sound is fading out */
1215 if (IS_FADING(mixer[i]) &&
1216 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1217 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1219 /* adjust volume of actual sound sample */
1220 if (mixer[i].volume != SOUND_MAX_VOLUME)
1221 for(j=0; j<sample_size; j++)
1222 premix_first_buffer[j] =
1223 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1225 /* fill the last mixing buffer with stereo or mono sound */
1228 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1229 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1231 for(j=0; j<sample_size; j++)
1233 premix_left_buffer[j] =
1234 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1235 premix_right_buffer[j] =
1236 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1238 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1239 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1244 for(j=0; j<sample_size; j++)
1245 premix_last_buffer[j] += premix_first_buffer[j];
1248 /* delete completed sound entries from the mixer */
1249 if (mixer[i].playing_pos >= mixer[i].data_len)
1251 if (IS_LOOP(mixer[i]))
1252 mixer[i].playing_pos = 0;
1254 Mixer_StopChannel(i);
1256 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1257 Mixer_StopChannel(i);
1260 /* prepare final playing buffer according to system audio format */
1261 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1263 /* cut off at 17 bit value */
1264 if (premix_last_buffer[i] < -65535)
1265 premix_last_buffer[i] = -65535;
1266 else if (premix_last_buffer[i] > 65535)
1267 premix_last_buffer[i] = 65535;
1269 /* shift to 16 bit value */
1270 premix_last_buffer[i] >>= 1;
1272 if (afmt.format & AUDIO_FORMAT_U8)
1274 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1276 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1278 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1279 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1281 else /* big endian */
1283 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1284 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1288 /* finally play the sound fragment */
1289 write(audio.device_fd, playing_buffer, fragment_size);
1291 if (!mixer_active_channels)
1292 CloseAudioDevice(&audio.device_fd);
1295 #else /* !AUDIO_STREAMING_DSP */
1297 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1299 static short premix_first_buffer[SND_BLOCKSIZE];
1300 static byte playing_buffer[SND_BLOCKSIZE];
1301 int max_sample_size = SND_BLOCKSIZE;
1310 /* pointer, lenght and actual playing position of sound sample */
1311 sample_ptr = mixer[i].data_ptr;
1312 sample_len = mixer[i].data_len;
1313 sample_pos = mixer[i].playing_pos;
1314 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1315 mixer[i].playing_pos += sample_size;
1317 /* copy original sample to first mixing buffer */
1318 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1319 premix_first_buffer);
1321 /* adjust volume of actual sound sample */
1322 if (mixer[i].volume != SOUND_MAX_VOLUME)
1323 for(j=0; j<sample_size; j++)
1324 premix_first_buffer[j] =
1325 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1327 /* might be needed for u-law /dev/audio */
1329 for(j=0; j<sample_size; j++)
1331 linear_to_ulaw(premix_first_buffer[j]);
1334 /* delete completed sound entries from the mixer */
1335 if (mixer[i].playing_pos >= mixer[i].data_len)
1336 Mixer_StopChannel(i);
1338 for(i=0; i<sample_size; i++)
1339 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1341 /* finally play the sound fragment */
1342 write(audio.device_fd, playing_buffer, sample_size);
1346 #endif /* !AUDIO_STREAMING_DSP */
1350 SoundControl snd_ctrl;
1353 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1355 Mixer_InitChannels();
1357 #if defined(PLATFORM_HPUX)
1358 InitAudioDevice(&afmt);
1361 FD_ZERO(&mixer_fdset);
1362 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1364 while(1) /* wait for sound playing commands from client */
1366 struct timeval delay = { 0, 0 };
1368 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1369 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1370 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1373 ReadSoundControlFromMainProcess(&snd_ctrl);
1375 HandleSoundRequest(snd_ctrl);
1377 #if defined(AUDIO_STREAMING_DSP)
1379 while (mixer_active_channels &&
1380 select(audio.mixer_pipe[0] + 1,
1381 &mixer_fdset, NULL, NULL, &delay) < 1)
1383 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1388 #else /* !AUDIO_STREAMING_DSP */
1390 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1391 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1394 InitAudioDevice(&afmt);
1399 while (mixer_active_channels &&
1400 select(audio.mixer_pipe[0] + 1,
1401 &mixer_fdset, NULL, NULL, &delay) < 1)
1403 int wait_percent = 90; /* wait 90% of the real playing time */
1406 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1408 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1412 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1415 CloseAudioDevice(&audio.device_fd);
1417 Mixer_InitChannels(); /* remove all sounds from mixer */
1419 #endif /* !AUDIO_STREAMING_DSP */
1422 #endif /* AUDIO_UNIX_NATIVE */
1425 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1427 /* these two are stolen from "sox"... :) */
1430 ** This routine converts from linear to ulaw.
1432 ** Craig Reese: IDA/Supercomputing Research Center
1433 ** Joe Campbell: Department of Defense
1434 ** 29 September 1989
1437 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1438 ** 2) "A New Digital Technique for Implementation of Any
1439 ** Continuous PCM Companding Law," Villeret, Michel,
1440 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1441 ** 1973, pg. 11.12-11.17
1442 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1443 ** for Analog-to_Digital Conversion Techniques,"
1446 ** Input: Signed 16 bit linear sample
1447 ** Output: 8 bit ulaw sample
1450 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1451 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1454 static unsigned char linear_to_ulaw(int sample)
1456 static int exp_lut[256] =
1458 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1459 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1460 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1461 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1462 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1463 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1464 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1465 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1466 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1467 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1468 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1469 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1470 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1471 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1472 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1473 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1476 int sign, exponent, mantissa;
1477 unsigned char ulawbyte;
1479 /* Get the sample into sign-magnitude. */
1480 sign = (sample >> 8) & 0x80; /* set aside the sign */
1482 sample = -sample; /* get magnitude */
1484 sample = CLIP; /* clip the magnitude */
1486 /* Convert from 16 bit linear to ulaw. */
1487 sample = sample + BIAS;
1488 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1489 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1490 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1493 ulawbyte = 0x02; /* optional CCITT trap */
1500 ** This routine converts from ulaw to 16 bit linear.
1502 ** Craig Reese: IDA/Supercomputing Research Center
1503 ** 29 September 1989
1506 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1507 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1508 ** for Analog-to_Digital Conversion Techniques,"
1511 ** Input: 8 bit ulaw sample
1512 ** Output: signed 16 bit linear sample
1515 static int ulaw_to_linear(unsigned char ulawbyte)
1517 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1518 int sign, exponent, mantissa, sample;
1520 ulawbyte = ~ ulawbyte;
1521 sign = ( ulawbyte & 0x80 );
1522 exponent = ( ulawbyte >> 4 ) & 0x07;
1523 mantissa = ulawbyte & 0x0F;
1524 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1530 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1533 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1534 /* ========================================================================= */
1535 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1537 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1538 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1540 static void *Load_WAV(char *filename)
1542 SoundInfo *snd_info;
1543 #if defined(AUDIO_UNIX_NATIVE)
1544 struct SoundHeader_WAV header;
1546 byte sound_header_buffer[WAV_HEADER_SIZE];
1549 char chunk_name[CHUNK_ID_LEN + 1];
1554 if (!audio.sound_available)
1558 printf("loading WAV file '%s'\n", filename);
1561 snd_info = checked_calloc(sizeof(SoundInfo));
1563 #if defined(TARGET_SDL)
1565 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1567 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1572 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1574 #elif defined(TARGET_ALLEGRO)
1576 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1578 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1583 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1585 #else /* AUDIO_UNIX_NATIVE */
1587 if ((file = fopen(filename, MODE_READ)) == NULL)
1589 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1594 /* read chunk id "RIFF" */
1595 getFileChunkLE(file, chunk_name, &chunk_size);
1596 if (strcmp(chunk_name, "RIFF") != 0)
1598 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1604 /* read "RIFF" type id "WAVE" */
1605 getFileChunkLE(file, chunk_name, NULL);
1606 if (strcmp(chunk_name, "WAVE") != 0)
1608 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1614 while (getFileChunkLE(file, chunk_name, &chunk_size))
1616 if (strcmp(chunk_name, "fmt ") == 0)
1618 if (chunk_size < WAV_HEADER_SIZE)
1620 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1626 header.compression_code = getFile16BitLE(file);
1627 header.num_channels = getFile16BitLE(file);
1628 header.sample_rate = getFile32BitLE(file);
1629 header.bytes_per_second = getFile32BitLE(file);
1630 header.block_align = getFile16BitLE(file);
1631 header.bits_per_sample = getFile16BitLE(file);
1633 if (chunk_size > WAV_HEADER_SIZE)
1634 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1636 if (header.compression_code != 1)
1638 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1639 filename, header.compression_code);
1645 if (header.num_channels != 1)
1647 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1648 filename, header.num_channels);
1654 if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1656 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1657 filename, header.bits_per_sample);
1663 /* warn, but accept wrong sample rate (may be only slightly different) */
1664 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1665 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1666 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1669 printf("WAV file: '%s'\n", filename);
1670 printf(" Compression code: %d'\n", header.compression_code);
1671 printf(" Number of channels: %d'\n", header.num_channels);
1672 printf(" Sample rate: %ld'\n", header.sample_rate);
1673 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1674 printf(" Block align: %d'\n", header.block_align);
1675 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1678 else if (strcmp(chunk_name, "data") == 0)
1680 snd_info->data_len = chunk_size;
1681 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1683 /* read sound data */
1684 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1687 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1689 free(snd_info->data_ptr);
1694 /* check for odd number of sample bytes (data chunk is word aligned) */
1695 if ((chunk_size % 2) == 1)
1696 ReadUnusedBytesFromFile(file, 1);
1698 else /* unknown chunk -- ignore */
1699 ReadUnusedBytesFromFile(file, chunk_size);
1704 if (snd_info->data_ptr == NULL)
1706 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1711 if (header.bits_per_sample == 8)
1712 snd_info->format = AUDIO_FORMAT_U8;
1713 else /* header.bits_per_sample == 16 */
1715 snd_info->format = AUDIO_FORMAT_S16;
1716 snd_info->data_len /= 2; /* correct number of samples */
1719 #endif /* AUDIO_UNIX_NATIVE */
1721 snd_info->type = SND_TYPE_WAV;
1722 snd_info->source_filename = getStringCopy(filename);
1727 static void deleteSoundEntry(SoundInfo **snd_info)
1731 char *filename = (*snd_info)->source_filename;
1734 printf("[decrementing reference counter of sound '%s']\n", filename);
1737 if (--(*snd_info)->num_references <= 0)
1740 printf("[deleting sound '%s']\n", filename);
1744 FreeSound(*snd_info);
1746 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1753 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1757 /* check if the old and the new sound file are the same */
1758 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1760 /* The old and new sound are the same (have the same filename and path).
1761 This usually means that this sound does not exist in this sound set
1762 and a fallback to the existing sound is done. */
1765 printf("[sound '%s' already exists (same list entry)]\n", filename);
1771 /* delete existing sound file entry */
1772 deleteSoundEntry(snd_info);
1774 /* check if the new sound file already exists in the list of sounds */
1775 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1778 printf("[sound '%s' already exists (other list entry)]\n", filename);
1781 *snd_info = (SoundInfo *)node->content;
1782 (*snd_info)->num_references++;
1784 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1786 (*snd_info)->num_references = 1;
1787 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1791 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1793 char *filename = getCustomSoundFilename(basename);
1796 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1799 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1801 deleteSoundEntry(snd_info);
1805 if (filename == NULL)
1807 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1811 replaceSoundEntry(snd_info, filename);
1814 void InitSoundList(struct ArtworkConfigInfo *config_list, int num_list_entries)
1817 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1819 sound_config = config_list;
1820 num_sounds = num_list_entries;
1822 sound_info.type = ARTWORK_TYPE_SOUNDS;
1823 sound_info.num_list_entries = num_list_entries;
1824 sound_info.config_list = config_list;
1825 sound_info.artwork_list = (struct ArtworkListNodeInfo **)Sound;
1826 sound_info.file_list = NULL;
1827 sound_info.load_artwork = Load_WAV;
1828 sound_info.free_artwork = FreeSound;
1831 void LoadSoundToList(char *basename, int list_pos)
1833 if (Sound == NULL || list_pos >= num_sounds)
1837 printf("loading sound '%s' ... [%d]\n",
1838 basename, getNumNodes(SoundFileList));
1841 LoadCustomSound(&Sound[list_pos], basename);
1844 printf("loading sound '%s' done [%d]\n",
1845 basename, getNumNodes(SoundFileList));
1849 static MusicInfo *Load_MOD(char *filename)
1851 #if defined(TARGET_SDL)
1852 MusicInfo *mod_info;
1854 if (!audio.sound_available)
1857 mod_info = checked_calloc(sizeof(MusicInfo));
1859 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1861 Error(ERR_WARN, "cannot read music file '%s'", filename);
1866 mod_info->type = MUS_TYPE_MOD;
1867 mod_info->source_filename = getStringCopy(filename);
1875 void LoadCustomMusic(void)
1877 static boolean draw_init_text = TRUE; /* only draw at startup */
1878 static char *last_music_directory = NULL;
1879 char *music_directory = getCustomMusicDirectory();
1881 struct dirent *dir_entry;
1883 if (!audio.sound_available)
1886 if (last_music_directory != NULL &&
1887 strcmp(last_music_directory, music_directory) == 0)
1888 return; /* old and new music directory are the same */
1890 if (last_music_directory != NULL)
1891 free(last_music_directory);
1892 last_music_directory = getStringCopy(music_directory);
1896 if ((dir = opendir(music_directory)) == NULL)
1898 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1899 audio.music_available = FALSE;
1904 DrawInitText("Loading music:", 120, FC_GREEN);
1906 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1908 char *basename = dir_entry->d_name;
1909 char *filename = getPath2(music_directory, basename);
1910 MusicInfo *mus_info = NULL;
1913 printf("DEBUG: loading music '%s' ...\n", basename);
1917 DrawInitText(basename, 150, FC_YELLOW);
1919 if (FileIsSound(basename))
1920 mus_info = Load_WAV(filename);
1921 else if (FileIsMusic(basename))
1922 mus_info = Load_MOD(filename);
1929 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1930 Music[num_music -1] = mus_info;
1936 draw_init_text = FALSE;
1939 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1943 void PlayMusic(int nr)
1945 if (!audio.music_available)
1951 void PlaySound(int nr)
1953 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1956 void PlaySoundStereo(int nr, int stereo_position)
1958 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1961 void PlaySoundLoop(int nr)
1963 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1966 void PlaySoundMusic(int nr)
1968 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1971 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1973 SoundControl snd_ctrl;
1975 if (!audio.sound_available ||
1976 !audio.sound_enabled ||
1977 audio.sound_deactivated)
1980 if (volume < SOUND_MIN_VOLUME)
1981 volume = SOUND_MIN_VOLUME;
1982 else if (volume > SOUND_MAX_VOLUME)
1983 volume = SOUND_MAX_VOLUME;
1985 if (stereo_position < SOUND_MAX_LEFT)
1986 stereo_position = SOUND_MAX_LEFT;
1987 else if (stereo_position > SOUND_MAX_RIGHT)
1988 stereo_position = SOUND_MAX_RIGHT;
1990 snd_ctrl.active = TRUE;
1992 snd_ctrl.volume = volume;
1993 snd_ctrl.stereo_position = stereo_position;
1994 snd_ctrl.state = state;
1996 HandleSoundRequest(snd_ctrl);
1999 void FadeMusic(void)
2001 if (!audio.music_available)
2004 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2007 void FadeSound(int nr)
2009 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2015 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2018 void StopMusic(void)
2020 if (!audio.music_available)
2023 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2026 void StopSound(int nr)
2028 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2034 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2037 void StopSoundExt(int nr, int state)
2039 SoundControl snd_ctrl;
2041 if (!audio.sound_available)
2044 snd_ctrl.active = FALSE;
2046 snd_ctrl.state = state;
2048 HandleSoundRequest(snd_ctrl);
2052 static void ReloadCustomSounds()
2054 ReloadCustomArtworkFiles(&sound_info);
2057 static void ReloadCustomSounds()
2059 static boolean draw_init_text = TRUE; /* only draw at startup */
2063 printf("DEBUG: reloading sounds '%s' ...\n",artwork.snd_current_identifier);
2066 LoadArtworkConfig(&sound_info);
2069 DrawInitText("Loading sounds:", 120, FC_GREEN);
2072 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2075 for(i=0; i<num_sounds; i++)
2078 DrawInitText(sound_config[i].token, 150, FC_YELLOW);
2080 if (sound_config[i].filename)
2081 LoadSoundToList(sound_config[i].filename, i);
2083 LoadSoundToList(sound_config[i].default_filename, i);
2086 draw_init_text = FALSE;
2089 printf("list size == %d\n", getNumNodes(SoundFileList));
2093 dumpList(SoundFileList);
2098 static void ReloadCustomMusic()
2101 printf("DEBUG: reloading music '%s' ...\n", artwork.mus_current_identifier);
2105 /* this is done directly in LoadCustomMusic() now */
2112 void InitReloadSounds(char *set_identifier)
2114 if (!audio.sound_available)
2117 #if defined(AUDIO_UNIX_NATIVE)
2118 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2120 ReloadCustomSounds();
2124 void InitReloadMusic(char *set_identifier)
2126 if (!audio.music_available)
2129 #if defined(AUDIO_UNIX_NATIVE)
2130 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2132 ReloadCustomMusic();
2136 void FreeSound(void *ptr)
2138 SoundInfo *sound = (SoundInfo *)ptr;
2143 if (sound->data_ptr)
2145 #if defined(TARGET_SDL)
2146 Mix_FreeChunk(sound->data_ptr);
2147 #elif defined(TARGET_ALLEGRO)
2148 destroy_sample(sound->data_ptr);
2149 #else /* AUDIO_UNIX_NATIVE */
2150 free(sound->data_ptr);
2154 if (sound->source_filename)
2155 free(sound->source_filename);
2160 void FreeMusic(MusicInfo *music)
2165 if (music->data_ptr)
2167 #if defined(TARGET_SDL)
2168 if (music->type == MUS_TYPE_MOD)
2169 Mix_FreeMusic(music->data_ptr);
2171 Mix_FreeChunk(music->data_ptr);
2172 #elif defined(TARGET_ALLEGRO)
2173 destroy_sample(music->data_ptr);
2174 #else /* AUDIO_UNIX_NATIVE */
2175 free(music->data_ptr);
2182 void FreeAllSounds()
2190 printf("%s: FREEING SOUNDS ...\n",
2191 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2194 for(i=0; i<num_sounds; i++)
2195 deleteSoundEntry(&Sound[i]);
2197 FreeSound(Sound[i]);
2201 printf("%s: FREEING SOUNDS -- DONE\n",
2202 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2218 for(i=0; i<num_music; i++)
2219 FreeMusic(Music[i]);
2227 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2228 /* ========================================================================= */