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;
159 struct ListNode *next;
161 typedef struct ListNode ListNode;
163 static ListNode *newListNode(void);
164 static void addNodeToList(ListNode **, char *, void *);
165 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
166 static ListNode *getNodeFromKey(ListNode *, char *);
167 static int getNumNodes(ListNode *);
170 static struct SoundEffectInfo *sound_effect;
171 static ListNode *SoundFileList = NULL;
172 static SoundInfo **Sound = NULL;
173 static MusicInfo **Music = NULL;
174 static int num_sounds = 0, num_music = 0;
175 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
178 /* ========================================================================= */
179 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
181 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
182 static int mixer_active_channels = 0;
184 #if defined(AUDIO_UNIX_NATIVE)
185 static struct AudioFormatInfo afmt;
187 static void Mixer_Main(void);
188 #if !defined(AUDIO_STREAMING_DSP)
189 static unsigned char linear_to_ulaw(int);
190 static int ulaw_to_linear(unsigned char);
194 static void ReloadCustomSounds();
195 static void ReloadCustomMusic();
196 static void FreeSound(void *);
199 /* ------------------------------------------------------------------------- */
200 /* functions for native (non-SDL) Unix audio/mixer support */
201 /* ------------------------------------------------------------------------- */
203 #if defined(AUDIO_UNIX_NATIVE)
205 static int OpenAudioDevice(char *audio_device_name)
209 /* check if desired audio device is accessible */
210 if (access(audio_device_name, W_OK) != 0)
213 /* try to open audio device in non-blocking mode */
214 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
215 return audio_device_fd;
217 /* re-open audio device in blocking mode */
218 close(audio_device_fd);
219 audio_device_fd = open(audio_device_name, O_WRONLY);
221 return audio_device_fd;
224 static void CloseAudioDevice(int *audio_device_fd)
226 if (*audio_device_fd == 0)
229 close(*audio_device_fd);
230 *audio_device_fd = -1;
233 static boolean TestAudioDevices(void)
235 static char *audio_device_name[] =
238 DEVICENAME_SOUND_DSP,
241 int audio_device_fd = -1;
244 /* look for available audio devices, starting with preferred ones */
245 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
246 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
249 if (audio_device_fd < 0)
251 Error(ERR_WARN, "cannot open audio device -- no sound");
255 close(audio_device_fd);
257 audio.device_name = audio_device_name[i];
262 static boolean ForkAudioProcess(void)
264 if (pipe(audio.mixer_pipe) < 0)
266 Error(ERR_WARN, "cannot create pipe -- no sounds");
270 if ((audio.mixer_pid = fork()) < 0)
272 Error(ERR_WARN, "cannot create sound server process -- no sounds");
277 printf("PID: %d [%s]\n", getpid(),
278 (IS_CHILD_PROCESS(audio.mixer_pid) ? "child" : "parent"));
282 if (IS_CHILD_PROCESS(audio.mixer_pid))
283 Mixer_Main(); /* this function never returns */
285 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
290 void UnixOpenAudio(void)
292 if (!TestAudioDevices())
295 audio.sound_available = TRUE;
296 audio.sound_enabled = TRUE;
298 #if defined(AUDIO_STREAMING_DSP)
299 audio.music_available = TRUE;
300 audio.loops_available = TRUE;
303 audio.num_channels = NUM_MIXER_CHANNELS;
304 audio.music_channel = MUSIC_CHANNEL;
305 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
308 void UnixCloseAudio(void)
311 close(audio.device_fd);
313 if (IS_PARENT_PROCESS(audio.mixer_pid))
314 kill(audio.mixer_pid, SIGTERM);
318 /* ------------------------------------------------------------------------- */
319 /* functions for platform specific audio device initialization */
320 /* ------------------------------------------------------------------------- */
322 #if defined(AUDIO_LINUX_IOCTL)
323 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
325 /* "ioctl()" expects pointer to 'int' value for stereo flag
326 (boolean is defined as 'char', which will not work here) */
327 unsigned int fragment_spec = 0;
328 int fragment_size_query;
337 /* supported audio format in preferred order */
338 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
339 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
340 { AFMT_U8, AUDIO_FORMAT_U8 },
345 /* determine logarithm (log2) of the fragment size */
346 while ((1 << fragment_spec) < afmt->fragment_size)
349 /* use two fragments (play one fragment, prepare the other);
350 one fragment would result in interrupted audio output, more
351 than two fragments would raise audio output latency to much */
352 fragment_spec |= 0x00020000;
354 /* Example for fragment specification:
355 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
356 - (with stereo the effective buffer size will shrink to 256)
357 => fragment_size = 0x00020009 */
359 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
360 Error(ERR_EXIT_SOUND_SERVER,
361 "cannot set fragment size of audio device -- no sounds");
365 while (formats[i].format_result != -1)
367 unsigned int audio_format = formats[i].format_ioctl;
368 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
370 afmt->format = formats[i].format_result;
375 if (afmt->format == 0) /* no supported audio format found */
376 Error(ERR_EXIT_SOUND_SERVER,
377 "cannot set audio format of audio device -- no sounds");
379 /* try if we can use stereo sound */
381 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
382 afmt->stereo = FALSE;
384 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
385 Error(ERR_EXIT_SOUND_SERVER,
386 "cannot set sample rate of audio device -- no sounds");
388 /* get the real fragmentation size; this should return 512 */
389 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
390 Error(ERR_EXIT_SOUND_SERVER,
391 "cannot get fragment size of audio device -- no sounds");
392 if (fragment_size_query != afmt->fragment_size)
393 Error(ERR_EXIT_SOUND_SERVER,
394 "cannot set fragment size of audio device -- no sounds");
396 #endif /* AUDIO_LINUX_IOCTL */
398 #if defined(PLATFORM_NETBSD)
399 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
402 boolean stereo = TRUE;
404 AUDIO_INITINFO(&a_info);
405 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
406 a_info.play.precision = 8;
407 a_info.play.channels = 2;
408 a_info.play.sample_rate = afmt->sample_rate;
409 a_info.blocksize = afmt->fragment_size;
411 afmt->format = AUDIO_FORMAT_U8;
414 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
416 /* try to disable stereo */
417 a_info.play.channels = 1;
419 afmt->stereo = FALSE;
421 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
422 Error(ERR_EXIT_SOUND_SERVER,
423 "cannot set sample rate of audio device -- no sounds");
426 #endif /* PLATFORM_NETBSD */
428 #if defined(PLATFORM_HPUX)
429 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
431 struct audio_describe ainfo;
434 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
436 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
438 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
439 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
441 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
442 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
444 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
445 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
447 afmt->format = AUDIO_FORMAT_U8;
448 afmt->stereo = FALSE;
449 afmt->sample_rate = 8000;
453 #endif /* PLATFORM_HPUX */
455 static void InitAudioDevice(struct AudioFormatInfo *afmt)
458 afmt->format = AUDIO_FORMAT_UNKNOWN;
459 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
460 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
462 #if defined(AUDIO_LINUX_IOCTL)
463 InitAudioDevice_Linux(afmt);
464 #elif defined(PLATFORM_NETBSD)
465 InitAudioDevice_NetBSD(afmt);
466 #elif defined(PLATFORM_HPUX)
467 InitAudioDevice_HPUX(afmt);
469 /* generic /dev/audio stuff might be placed here */
474 /* ------------------------------------------------------------------------- */
475 /* functions for communication between main process and sound mixer process */
476 /* ------------------------------------------------------------------------- */
478 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
480 if (IS_CHILD_PROCESS(audio.mixer_pid))
483 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
485 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
486 audio.sound_available = audio.sound_enabled = FALSE;
491 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
493 if (IS_PARENT_PROCESS(audio.mixer_pid))
496 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
497 != sizeof(SoundControl))
498 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
501 static void WriteReloadInfoToPipe(char *set_identifier, int type)
503 SoundControl snd_ctrl;
504 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
505 artwork.mus_current);
506 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
507 unsigned long str_size2 = strlen(leveldir_current->sounds_path) + 1;
508 unsigned long str_size3 = strlen(leveldir_current->music_path) + 1;
509 unsigned long str_size4 = strlen(ti->basepath) + 1;
510 unsigned long str_size5 = strlen(ti->fullpath) + 1;
511 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
512 setup.override_level_sounds :
513 setup.override_level_music);
515 if (IS_CHILD_PROCESS(audio.mixer_pid))
518 if (leveldir_current == NULL) /* should never happen */
519 Error(ERR_EXIT, "leveldir_current == NULL");
521 snd_ctrl.active = FALSE;
522 snd_ctrl.state = type;
523 snd_ctrl.data_len = strlen(set_identifier) + 1;
525 if (write(audio.mixer_pipe[1], &snd_ctrl,
526 sizeof(snd_ctrl)) < 0 ||
527 write(audio.mixer_pipe[1], set_identifier,
528 snd_ctrl.data_len) < 0 ||
529 write(audio.mixer_pipe[1], &override_level_artwork,
530 sizeof(boolean)) < 0 ||
531 write(audio.mixer_pipe[1], leveldir_current,
532 sizeof(TreeInfo)) < 0 ||
533 write(audio.mixer_pipe[1], ti,
534 sizeof(TreeInfo)) < 0 ||
535 write(audio.mixer_pipe[1], &str_size1,
536 sizeof(unsigned long)) < 0 ||
537 write(audio.mixer_pipe[1], &str_size2,
538 sizeof(unsigned long)) < 0 ||
539 write(audio.mixer_pipe[1], &str_size3,
540 sizeof(unsigned long)) < 0 ||
541 write(audio.mixer_pipe[1], &str_size4,
542 sizeof(unsigned long)) < 0 ||
543 write(audio.mixer_pipe[1], &str_size5,
544 sizeof(unsigned long)) < 0 ||
545 write(audio.mixer_pipe[1], leveldir_current->fullpath,
547 write(audio.mixer_pipe[1], leveldir_current->sounds_path,
549 write(audio.mixer_pipe[1], leveldir_current->music_path,
551 write(audio.mixer_pipe[1], ti->basepath,
553 write(audio.mixer_pipe[1], ti->fullpath,
556 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
557 audio.sound_available = audio.sound_enabled = FALSE;
562 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
564 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
565 &artwork.snd_current : &artwork.mus_current);
566 TreeInfo *ti = *ti_ptr;
567 unsigned long str_size1, str_size2, str_size3, str_size4, str_size5;
568 static char *set_identifier = NULL;
569 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
570 &setup.override_level_sounds :
571 &setup.override_level_music);
574 free(set_identifier);
576 set_identifier = checked_malloc(snd_ctrl->data_len);
578 if (leveldir_current == NULL)
579 leveldir_current = checked_calloc(sizeof(TreeInfo));
582 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
583 if (leveldir_current->fullpath != NULL)
584 free(leveldir_current->fullpath);
585 if (leveldir_current->sounds_path != NULL)
586 free(leveldir_current->sounds_path);
587 if (leveldir_current->music_path != NULL)
588 free(leveldir_current->music_path);
589 if (ti->basepath != NULL)
591 if (ti->fullpath != NULL)
594 if (read(audio.mixer_pipe[0], set_identifier,
595 snd_ctrl->data_len) != snd_ctrl->data_len ||
596 read(audio.mixer_pipe[0], override_level_artwork,
597 sizeof(boolean)) != sizeof(boolean) ||
598 read(audio.mixer_pipe[0], leveldir_current,
599 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
600 read(audio.mixer_pipe[0], ti,
601 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
602 read(audio.mixer_pipe[0], &str_size1,
603 sizeof(unsigned long)) != sizeof(unsigned long) ||
604 read(audio.mixer_pipe[0], &str_size2,
605 sizeof(unsigned long)) != sizeof(unsigned long) ||
606 read(audio.mixer_pipe[0], &str_size3,
607 sizeof(unsigned long)) != sizeof(unsigned long) ||
608 read(audio.mixer_pipe[0], &str_size4,
609 sizeof(unsigned long)) != sizeof(unsigned long) ||
610 read(audio.mixer_pipe[0], &str_size5,
611 sizeof(unsigned long)) != sizeof(unsigned long))
612 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
614 leveldir_current->fullpath = checked_calloc(str_size1);
615 leveldir_current->sounds_path = checked_calloc(str_size2);
616 leveldir_current->music_path = checked_calloc(str_size3);
617 ti->basepath = checked_calloc(str_size4);
618 ti->fullpath = checked_calloc(str_size5);
620 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
621 str_size1) != str_size1 ||
622 read(audio.mixer_pipe[0], leveldir_current->sounds_path,
623 str_size2) != str_size2 ||
624 read(audio.mixer_pipe[0], leveldir_current->music_path,
625 str_size3) != str_size3 ||
626 read(audio.mixer_pipe[0], ti->basepath,
627 str_size4) != str_size4 ||
628 read(audio.mixer_pipe[0], ti->fullpath,
629 str_size5) != str_size5)
630 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
632 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
633 artwork.snd_current_identifier = set_identifier;
635 artwork.mus_current_identifier = set_identifier;
638 #endif /* AUDIO_UNIX_NATIVE */
641 /* ------------------------------------------------------------------------- */
642 /* mixer functions */
643 /* ------------------------------------------------------------------------- */
645 void Mixer_InitChannels()
649 for(i=0; i<audio.num_channels; i++)
650 mixer[i].active = FALSE;
651 mixer_active_channels = 0;
654 static void Mixer_ResetChannelExpiration(int channel)
656 mixer[channel].playing_starttime = Counter();
658 #if defined(TARGET_SDL)
659 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
660 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
664 static boolean Mixer_ChannelExpired(int channel)
666 if (!mixer[channel].active)
669 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
670 DelayReached(&mixer[channel].playing_starttime,
671 SOUND_LOOP_EXPIRATION_TIME))
674 #if defined(TARGET_SDL)
676 if (!Mix_Playing(channel))
679 #elif defined(TARGET_ALLEGRO)
681 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
682 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
684 /* sound sample has completed playing or was completely faded out */
685 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
688 #endif /* TARGET_ALLEGRO */
693 static boolean Mixer_AllocateChannel(int channel)
695 #if defined(TARGET_ALLEGRO)
696 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
697 if (mixer[channel].voice < 0)
704 static void Mixer_SetChannelProperties(int channel)
706 #if defined(TARGET_SDL)
707 Mix_Volume(channel, mixer[channel].volume);
708 Mix_SetPanning(channel,
709 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
710 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
711 #elif defined(TARGET_ALLEGRO)
712 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
713 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
717 static void Mixer_StartChannel(int channel)
719 #if defined(TARGET_SDL)
720 Mix_PlayChannel(channel, mixer[channel].data_ptr,
721 IS_LOOP(mixer[channel]) ? -1 : 0);
722 #elif defined(TARGET_ALLEGRO)
723 if (IS_LOOP(mixer[channel]))
724 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
726 voice_start(mixer[channel].voice);
730 static void Mixer_PlayChannel(int channel)
732 /* start with inactive channel in case something goes wrong */
733 mixer[channel].active = FALSE;
735 if (mixer[channel].type != MUS_TYPE_WAV)
738 if (!Mixer_AllocateChannel(channel))
741 Mixer_SetChannelProperties(channel);
742 Mixer_StartChannel(channel);
744 Mixer_ResetChannelExpiration(channel);
746 mixer[channel].playing_pos = 0;
747 mixer[channel].active = TRUE;
748 mixer_active_channels++;
751 static void Mixer_PlayMusicChannel()
753 Mixer_PlayChannel(audio.music_channel);
755 #if defined(TARGET_SDL)
756 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
758 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
759 this looks like a bug in the SDL_mixer library */
760 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
761 Mix_VolumeMusic(SOUND_MAX_VOLUME);
766 static void Mixer_StopChannel(int channel)
768 if (!mixer[channel].active)
771 #if defined(TARGET_SDL)
772 Mix_HaltChannel(channel);
773 #elif defined(TARGET_ALLEGRO)
774 voice_set_volume(mixer[channel].voice, 0);
775 deallocate_voice(mixer[channel].voice);
778 mixer[channel].active = FALSE;
779 mixer_active_channels--;
782 static void Mixer_StopMusicChannel()
784 Mixer_StopChannel(audio.music_channel);
786 #if defined(TARGET_SDL)
791 static void Mixer_FadeChannel(int channel)
793 if (!mixer[channel].active)
796 mixer[channel].state |= SND_CTRL_FADE;
798 #if defined(TARGET_SDL)
799 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
800 #elif defined(TARGET_ALLEGRO)
801 if (voice_check(mixer[channel].voice))
802 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
806 static void Mixer_FadeMusicChannel()
808 Mixer_FadeChannel(audio.music_channel);
810 #if defined(TARGET_SDL)
811 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
815 static void Mixer_UnFadeChannel(int channel)
817 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
820 mixer[channel].state &= ~SND_CTRL_FADE;
821 mixer[channel].volume = SOUND_MAX_VOLUME;
823 #if defined(TARGET_SDL)
824 Mix_ExpireChannel(channel, -1);
825 Mix_Volume(channel, mixer[channel].volume);
826 #elif defined(TARGET_ALLEGRO)
827 voice_stop_volumeramp(mixer[channel].voice);
828 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
829 mixer[channel].volume);
833 static void Mixer_InsertSound(SoundControl snd_ctrl)
839 printf("NEW SOUND %d ARRIVED [%d] [%d ACTIVE CHANNELS]\n",
840 snd_ctrl.nr, num_sounds, mixer_active_channels);
843 if (IS_MUSIC(snd_ctrl))
848 snd_ctrl.nr = snd_ctrl.nr % num_music;
850 else if (snd_ctrl.nr >= num_sounds)
853 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
854 if (snd_info == NULL)
857 /* copy sound sample and format information */
858 snd_ctrl.type = snd_info->type;
859 snd_ctrl.format = snd_info->format;
860 snd_ctrl.data_ptr = snd_info->data_ptr;
861 snd_ctrl.data_len = snd_info->data_len;
863 /* play music samples on a dedicated music channel */
864 if (IS_MUSIC(snd_ctrl))
866 Mixer_StopMusicChannel();
868 mixer[audio.music_channel] = snd_ctrl;
869 Mixer_PlayMusicChannel();
874 /* check if (and how often) this sound sample is already playing */
875 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
876 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
880 printf("SOUND %d [CURRENTLY PLAYING %d TIMES]\n", snd_ctrl.nr, k);
883 /* reset expiration delay for already playing loop sounds */
884 if (k > 0 && IS_LOOP(snd_ctrl))
886 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
888 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
891 printf("RESETTING EXPIRATION FOR SOUND %d\n", snd_ctrl.nr);
894 if (IS_FADING(mixer[i]))
895 Mixer_UnFadeChannel(i);
897 /* restore settings like volume and stereo position */
898 mixer[i].volume = snd_ctrl.volume;
899 mixer[i].stereo_position = snd_ctrl.stereo_position;
901 Mixer_SetChannelProperties(i);
902 Mixer_ResetChannelExpiration(i);
905 printf("RESETTING VOLUME/STEREO FOR SOUND %d TO %d/%d\n",
906 snd_ctrl.nr, snd_ctrl.volume, snd_ctrl.stereo_position);
915 printf("PLAYING NEW SOUND %d\n", snd_ctrl.nr);
918 /* don't play sound more than n times simultaneously (with n == 2 for now) */
921 unsigned long playing_current = Counter();
922 int longest = 0, longest_nr = audio.first_sound_channel;
924 /* look for oldest equal sound */
925 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
927 int playing_time = playing_current - mixer[i].playing_starttime;
930 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
933 actual = 1000 * playing_time / mixer[i].data_len;
935 if (actual >= longest)
942 Mixer_StopChannel(longest_nr);
945 /* If all (non-music) channels are active, stop the channel that has
946 played its sound sample most completely (in percent of the sample
947 length). As we cannot currently get the actual playing position
948 of the channel's sound sample when compiling with the SDL mixer
949 library, we use the current playing time (in milliseconds) instead. */
952 /* channel allocation sanity check -- should not be needed */
953 if (mixer_active_channels ==
954 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
956 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
958 if (!mixer[i].active)
960 Error(ERR_RETURN, "Mixer_InsertSound: Channel %d inactive", i);
961 Error(ERR_RETURN, "Mixer_InsertSound: This should never happen!");
963 mixer_active_channels--;
969 if (mixer_active_channels ==
970 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
972 unsigned long playing_current = Counter();
973 int longest = 0, longest_nr = audio.first_sound_channel;
975 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
977 Error(ERR_RETURN, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
978 i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
981 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
983 int playing_time = playing_current - mixer[i].playing_starttime;
984 int actual = 1000 * playing_time / mixer[i].data_len;
986 if (!IS_LOOP(mixer[i]) && actual > longest)
993 Mixer_StopChannel(longest_nr);
996 /* add the new sound to the mixer */
997 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1000 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
1003 if (!mixer[i].active)
1006 printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
1009 #if defined(AUDIO_UNIX_NATIVE)
1010 if (snd_info->data_len == 0)
1012 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
1016 mixer[i] = snd_ctrl;
1017 Mixer_PlayChannel(i);
1024 static void HandleSoundRequest(SoundControl snd_ctrl)
1028 #if defined(AUDIO_UNIX_NATIVE)
1029 if (IS_PARENT_PROCESS(audio.mixer_pid))
1031 SendSoundControlToMixerProcess(&snd_ctrl);
1036 /* deactivate channels that have expired since the last request */
1037 for (i=0; i<audio.num_channels; i++)
1038 if (mixer[i].active && Mixer_ChannelExpired(i))
1039 Mixer_StopChannel(i);
1041 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
1043 Mixer_StopMusicChannel();
1044 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1045 Mixer_StopChannel(i);
1047 #if defined(AUDIO_UNIX_NATIVE)
1048 CloseAudioDevice(&audio.device_fd);
1049 ReadReloadInfoFromPipe(&snd_ctrl);
1052 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1053 ReloadCustomSounds();
1055 ReloadCustomMusic();
1057 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1059 if (IS_MUSIC(snd_ctrl))
1061 Mixer_FadeMusicChannel();
1065 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1066 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1067 Mixer_FadeChannel(i);
1069 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1071 if (IS_MUSIC(snd_ctrl))
1073 Mixer_StopMusicChannel();
1077 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1078 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1079 Mixer_StopChannel(i);
1081 #if defined(AUDIO_UNIX_NATIVE)
1082 if (!mixer_active_channels)
1083 CloseAudioDevice(&audio.device_fd);
1086 else if (snd_ctrl.active) /* add new sound to mixer */
1088 Mixer_InsertSound(snd_ctrl);
1092 void StartMixer(void)
1097 SDL_version compile_version;
1098 const SDL_version *link_version;
1099 MIX_VERSION(&compile_version);
1100 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1101 compile_version.major,
1102 compile_version.minor,
1103 compile_version.patch);
1104 link_version = Mix_Linked_Version();
1105 printf("running with SDL_mixer version: %d.%d.%d\n",
1106 link_version->major,
1107 link_version->minor,
1108 link_version->patch);
1111 if (!audio.sound_available)
1114 /* initialize stereo position conversion information */
1115 for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1117 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1119 #if defined(AUDIO_UNIX_NATIVE)
1120 if (!ForkAudioProcess())
1121 audio.sound_available = FALSE;
1125 #if defined(AUDIO_UNIX_NATIVE)
1127 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1128 int sample_pos, int sample_size,
1131 void *sample_ptr = snd_ctrl->data_ptr;
1134 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1135 for (i=0; i<sample_size; i++)
1137 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1138 else /* AUDIO_FORMAT_S16 */
1139 for (i=0; i<sample_size; i++)
1141 ((short *)sample_ptr)[sample_pos + i];
1144 #if defined(AUDIO_STREAMING_DSP)
1145 static void Mixer_Main_DSP()
1147 static short premix_first_buffer[SND_BLOCKSIZE];
1148 static short premix_left_buffer[SND_BLOCKSIZE];
1149 static short premix_right_buffer[SND_BLOCKSIZE];
1150 static long premix_last_buffer[SND_BLOCKSIZE];
1151 static byte playing_buffer[SND_BLOCKSIZE];
1155 int max_sample_size;
1158 if (!mixer_active_channels)
1161 if (audio.device_fd < 0)
1163 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1166 InitAudioDevice(&afmt);
1169 stereo = afmt.stereo;
1170 fragment_size = afmt.fragment_size;
1171 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1172 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1174 /* first clear the last premixing buffer */
1175 memset(premix_last_buffer, 0,
1176 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1178 for(i=0; i<audio.num_channels; i++)
1185 if (!mixer[i].active)
1188 if (Mixer_ChannelExpired(i))
1190 Mixer_StopChannel(i);
1194 /* pointer, lenght and actual playing position of sound sample */
1195 sample_ptr = mixer[i].data_ptr;
1196 sample_len = mixer[i].data_len;
1197 sample_pos = mixer[i].playing_pos;
1198 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1199 mixer[i].playing_pos += sample_size;
1201 /* copy original sample to first mixing buffer */
1202 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1203 premix_first_buffer);
1205 /* are we about to restart a looping sound? */
1206 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1208 while (sample_size < max_sample_size)
1210 int restarted_sample_size =
1211 MIN(max_sample_size - sample_size, sample_len);
1213 if (mixer[i].format == AUDIO_FORMAT_U8)
1214 for (j=0; j<restarted_sample_size; j++)
1215 premix_first_buffer[sample_size + j] =
1216 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1218 for (j=0; j<restarted_sample_size; j++)
1219 premix_first_buffer[sample_size + j] =
1220 ((short *)sample_ptr)[j];
1222 mixer[i].playing_pos = restarted_sample_size;
1223 sample_size += restarted_sample_size;
1227 /* decrease volume if sound is fading out */
1228 if (IS_FADING(mixer[i]) &&
1229 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1230 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1232 /* adjust volume of actual sound sample */
1233 if (mixer[i].volume != SOUND_MAX_VOLUME)
1234 for(j=0; j<sample_size; j++)
1235 premix_first_buffer[j] =
1236 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1238 /* fill the last mixing buffer with stereo or mono sound */
1241 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1242 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1244 for(j=0; j<sample_size; j++)
1246 premix_left_buffer[j] =
1247 left_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1248 premix_right_buffer[j] =
1249 right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1251 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1252 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1257 for(j=0; j<sample_size; j++)
1258 premix_last_buffer[j] += premix_first_buffer[j];
1261 /* delete completed sound entries from the mixer */
1262 if (mixer[i].playing_pos >= mixer[i].data_len)
1264 if (IS_LOOP(mixer[i]))
1265 mixer[i].playing_pos = 0;
1267 Mixer_StopChannel(i);
1269 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1270 Mixer_StopChannel(i);
1273 /* prepare final playing buffer according to system audio format */
1274 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1276 /* cut off at 17 bit value */
1277 if (premix_last_buffer[i] < -65535)
1278 premix_last_buffer[i] = -65535;
1279 else if (premix_last_buffer[i] > 65535)
1280 premix_last_buffer[i] = 65535;
1282 /* shift to 16 bit value */
1283 premix_last_buffer[i] >>= 1;
1285 if (afmt.format & AUDIO_FORMAT_U8)
1287 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1289 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1291 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1292 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1294 else /* big endian */
1296 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1297 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1301 /* finally play the sound fragment */
1302 write(audio.device_fd, playing_buffer, fragment_size);
1304 if (!mixer_active_channels)
1305 CloseAudioDevice(&audio.device_fd);
1308 #else /* !AUDIO_STREAMING_DSP */
1310 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1312 static short premix_first_buffer[SND_BLOCKSIZE];
1313 static byte playing_buffer[SND_BLOCKSIZE];
1314 int max_sample_size = SND_BLOCKSIZE;
1323 /* pointer, lenght and actual playing position of sound sample */
1324 sample_ptr = mixer[i].data_ptr;
1325 sample_len = mixer[i].data_len;
1326 sample_pos = mixer[i].playing_pos;
1327 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1328 mixer[i].playing_pos += sample_size;
1330 /* copy original sample to first mixing buffer */
1331 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1332 premix_first_buffer);
1334 /* adjust volume of actual sound sample */
1335 if (mixer[i].volume != SOUND_MAX_VOLUME)
1336 for(j=0; j<sample_size; j++)
1337 premix_first_buffer[j] =
1338 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1340 /* might be needed for u-law /dev/audio */
1342 for(j=0; j<sample_size; j++)
1344 linear_to_ulaw(premix_first_buffer[j]);
1347 /* delete completed sound entries from the mixer */
1348 if (mixer[i].playing_pos >= mixer[i].data_len)
1349 Mixer_StopChannel(i);
1351 for(i=0; i<sample_size; i++)
1352 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1354 /* finally play the sound fragment */
1355 write(audio.device_fd, playing_buffer, sample_size);
1359 #endif /* !AUDIO_STREAMING_DSP */
1363 SoundControl snd_ctrl;
1366 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1368 Mixer_InitChannels();
1370 #if defined(PLATFORM_HPUX)
1371 InitAudioDevice(&afmt);
1374 FD_ZERO(&mixer_fdset);
1375 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1377 while(1) /* wait for sound playing commands from client */
1379 struct timeval delay = { 0, 0 };
1381 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1382 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1383 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1386 ReadSoundControlFromMainProcess(&snd_ctrl);
1388 HandleSoundRequest(snd_ctrl);
1390 #if defined(AUDIO_STREAMING_DSP)
1392 while (mixer_active_channels &&
1393 select(audio.mixer_pipe[0] + 1,
1394 &mixer_fdset, NULL, NULL, &delay) < 1)
1396 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1401 #else /* !AUDIO_STREAMING_DSP */
1403 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1404 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1407 InitAudioDevice(&afmt);
1412 while (mixer_active_channels &&
1413 select(audio.mixer_pipe[0] + 1,
1414 &mixer_fdset, NULL, NULL, &delay) < 1)
1416 int wait_percent = 90; /* wait 90% of the real playing time */
1419 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1421 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1425 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1428 CloseAudioDevice(&audio.device_fd);
1430 Mixer_InitChannels(); /* remove all sounds from mixer */
1432 #endif /* !AUDIO_STREAMING_DSP */
1435 #endif /* AUDIO_UNIX_NATIVE */
1438 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1440 /* these two are stolen from "sox"... :) */
1443 ** This routine converts from linear to ulaw.
1445 ** Craig Reese: IDA/Supercomputing Research Center
1446 ** Joe Campbell: Department of Defense
1447 ** 29 September 1989
1450 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1451 ** 2) "A New Digital Technique for Implementation of Any
1452 ** Continuous PCM Companding Law," Villeret, Michel,
1453 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1454 ** 1973, pg. 11.12-11.17
1455 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1456 ** for Analog-to_Digital Conversion Techniques,"
1459 ** Input: Signed 16 bit linear sample
1460 ** Output: 8 bit ulaw sample
1463 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1464 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1467 static unsigned char linear_to_ulaw(int sample)
1469 static int exp_lut[256] =
1471 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1472 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1473 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1474 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1475 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1476 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1477 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1478 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1479 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1480 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1481 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1482 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1483 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1484 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1485 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1486 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1489 int sign, exponent, mantissa;
1490 unsigned char ulawbyte;
1492 /* Get the sample into sign-magnitude. */
1493 sign = (sample >> 8) & 0x80; /* set aside the sign */
1495 sample = -sample; /* get magnitude */
1497 sample = CLIP; /* clip the magnitude */
1499 /* Convert from 16 bit linear to ulaw. */
1500 sample = sample + BIAS;
1501 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1502 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1503 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1506 ulawbyte = 0x02; /* optional CCITT trap */
1513 ** This routine converts from ulaw to 16 bit linear.
1515 ** Craig Reese: IDA/Supercomputing Research Center
1516 ** 29 September 1989
1519 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1520 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1521 ** for Analog-to_Digital Conversion Techniques,"
1524 ** Input: 8 bit ulaw sample
1525 ** Output: signed 16 bit linear sample
1528 static int ulaw_to_linear(unsigned char ulawbyte)
1530 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1531 int sign, exponent, mantissa, sample;
1533 ulawbyte = ~ ulawbyte;
1534 sign = ( ulawbyte & 0x80 );
1535 exponent = ( ulawbyte >> 4 ) & 0x07;
1536 mantissa = ulawbyte & 0x0F;
1537 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1543 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1546 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1547 /* ========================================================================= */
1548 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1550 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1551 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1553 static SoundInfo *Load_WAV(char *filename)
1555 SoundInfo *snd_info;
1556 #if defined(AUDIO_UNIX_NATIVE)
1557 struct SoundHeader_WAV header;
1559 byte sound_header_buffer[WAV_HEADER_SIZE];
1562 char chunk_name[CHUNK_ID_LEN + 1];
1567 if (!audio.sound_available)
1571 printf("loading WAV file '%s'\n", filename);
1574 snd_info = checked_calloc(sizeof(SoundInfo));
1576 #if defined(TARGET_SDL)
1578 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1580 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1585 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1587 #elif defined(TARGET_ALLEGRO)
1589 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1591 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1596 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1598 #else /* AUDIO_UNIX_NATIVE */
1600 if ((file = fopen(filename, MODE_READ)) == NULL)
1602 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1607 /* read chunk id "RIFF" */
1608 getFileChunkLE(file, chunk_name, &chunk_size);
1609 if (strcmp(chunk_name, "RIFF") != 0)
1611 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1617 /* read "RIFF" type id "WAVE" */
1618 getFileChunkLE(file, chunk_name, NULL);
1619 if (strcmp(chunk_name, "WAVE") != 0)
1621 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1627 while (getFileChunkLE(file, chunk_name, &chunk_size))
1629 if (strcmp(chunk_name, "fmt ") == 0)
1631 if (chunk_size < WAV_HEADER_SIZE)
1633 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1639 header.compression_code = getFile16BitLE(file);
1640 header.num_channels = getFile16BitLE(file);
1641 header.sample_rate = getFile32BitLE(file);
1642 header.bytes_per_second = getFile32BitLE(file);
1643 header.block_align = getFile16BitLE(file);
1644 header.bits_per_sample = getFile16BitLE(file);
1646 if (chunk_size > WAV_HEADER_SIZE)
1647 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1649 if (header.compression_code != 1)
1651 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1652 filename, header.compression_code);
1658 if (header.num_channels != 1)
1660 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1661 filename, header.num_channels);
1667 if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1669 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1670 filename, header.bits_per_sample);
1676 /* warn, but accept wrong sample rate (may be only slightly different) */
1677 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1678 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1679 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1682 printf("WAV file: '%s'\n", filename);
1683 printf(" Compression code: %d'\n", header.compression_code);
1684 printf(" Number of channels: %d'\n", header.num_channels);
1685 printf(" Sample rate: %ld'\n", header.sample_rate);
1686 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1687 printf(" Block align: %d'\n", header.block_align);
1688 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1691 else if (strcmp(chunk_name, "data") == 0)
1693 snd_info->data_len = chunk_size;
1694 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1696 /* read sound data */
1697 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1700 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1702 free(snd_info->data_ptr);
1707 /* check for odd number of sample bytes (data chunk is word aligned) */
1708 if ((chunk_size % 2) == 1)
1709 ReadUnusedBytesFromFile(file, 1);
1711 else /* unknown chunk -- ignore */
1712 ReadUnusedBytesFromFile(file, chunk_size);
1717 if (snd_info->data_ptr == NULL)
1719 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1724 if (header.bits_per_sample == 8)
1725 snd_info->format = AUDIO_FORMAT_U8;
1726 else /* header.bits_per_sample == 16 */
1728 snd_info->format = AUDIO_FORMAT_S16;
1729 snd_info->data_len /= 2; /* correct number of samples */
1732 #endif /* AUDIO_UNIX_NATIVE */
1734 snd_info->type = SND_TYPE_WAV;
1735 snd_info->source_filename = getStringCopy(filename);
1740 static void deleteSoundEntry(SoundInfo **snd_info)
1744 char *filename = (*snd_info)->source_filename;
1747 printf("[decrementing reference counter of sound '%s']\n", filename);
1750 if (--(*snd_info)->num_references <= 0)
1753 printf("[deleting sound '%s']\n", filename);
1757 FreeSound(*snd_info);
1759 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1766 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1770 /* check if the old and the new sound file are the same */
1771 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1773 /* The old and new sound are the same (have the same filename and path).
1774 This usually means that this sound does not exist in this sound set
1775 and a fallback to the existing sound is done. */
1778 printf("[sound '%s' already exists (same list entry)]\n", filename);
1784 /* delete existing sound file entry */
1785 deleteSoundEntry(snd_info);
1787 /* check if the new sound file already exists in the list of sounds */
1788 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1791 printf("[sound '%s' already exists (other list entry)]\n", filename);
1794 *snd_info = (SoundInfo *)node->content;
1795 (*snd_info)->num_references++;
1797 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1799 (*snd_info)->num_references = 1;
1800 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1804 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1806 char *filename = getCustomSoundFilename(basename);
1809 printf("GOT CUSTOM SOUND FILE '%s'\n", filename);
1812 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1814 deleteSoundEntry(snd_info);
1818 if (filename == NULL)
1820 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1824 replaceSoundEntry(snd_info, filename);
1827 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1830 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1832 sound_effect = sounds_list;
1833 num_sounds = num_list_entries;
1836 void LoadSoundToList(char *basename, int list_pos)
1838 if (Sound == NULL || list_pos >= num_sounds)
1842 printf("loading sound '%s' ... [%d]\n",
1843 basename, getNumNodes(SoundFileList));
1846 LoadCustomSound(&Sound[list_pos], basename);
1849 printf("loading sound '%s' done [%d]\n",
1850 basename, getNumNodes(SoundFileList));
1854 static MusicInfo *Load_MOD(char *filename)
1856 #if defined(TARGET_SDL)
1857 MusicInfo *mod_info;
1859 if (!audio.sound_available)
1862 mod_info = checked_calloc(sizeof(MusicInfo));
1864 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1866 Error(ERR_WARN, "cannot read music file '%s'", filename);
1871 mod_info->type = MUS_TYPE_MOD;
1872 mod_info->source_filename = getStringCopy(filename);
1880 void LoadCustomMusic(void)
1882 static boolean draw_init_text = TRUE; /* only draw at startup */
1883 static char *last_music_directory = NULL;
1884 char *music_directory = getCustomMusicDirectory();
1886 struct dirent *dir_entry;
1888 if (!audio.sound_available)
1891 if (last_music_directory != NULL &&
1892 strcmp(last_music_directory, music_directory) == 0)
1893 return; /* old and new music directory are the same */
1895 if (last_music_directory != NULL)
1896 free(last_music_directory);
1897 last_music_directory = getStringCopy(music_directory);
1901 if ((dir = opendir(music_directory)) == NULL)
1903 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1904 audio.music_available = FALSE;
1909 DrawInitText("Loading music:", 120, FC_GREEN);
1911 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1913 char *basename = dir_entry->d_name;
1914 char *filename = getPath2(music_directory, basename);
1915 MusicInfo *mus_info = NULL;
1918 printf("DEBUG: loading music '%s' ...\n", basename);
1922 DrawInitText(basename, 150, FC_YELLOW);
1924 if (FileIsSound(basename))
1925 mus_info = Load_WAV(filename);
1926 else if (FileIsMusic(basename))
1927 mus_info = Load_MOD(filename);
1934 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1935 Music[num_music -1] = mus_info;
1941 draw_init_text = FALSE;
1944 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1948 void PlayMusic(int nr)
1950 if (!audio.music_available)
1956 void PlaySound(int nr)
1958 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1961 void PlaySoundStereo(int nr, int stereo_position)
1963 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1966 void PlaySoundLoop(int nr)
1968 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1971 void PlaySoundMusic(int nr)
1973 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1976 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1978 SoundControl snd_ctrl;
1980 if (!audio.sound_available ||
1981 !audio.sound_enabled ||
1982 audio.sound_deactivated)
1985 if (volume < SOUND_MIN_VOLUME)
1986 volume = SOUND_MIN_VOLUME;
1987 else if (volume > SOUND_MAX_VOLUME)
1988 volume = SOUND_MAX_VOLUME;
1990 if (stereo_position < SOUND_MAX_LEFT)
1991 stereo_position = SOUND_MAX_LEFT;
1992 else if (stereo_position > SOUND_MAX_RIGHT)
1993 stereo_position = SOUND_MAX_RIGHT;
1995 snd_ctrl.active = TRUE;
1997 snd_ctrl.volume = volume;
1998 snd_ctrl.stereo_position = stereo_position;
1999 snd_ctrl.state = state;
2001 HandleSoundRequest(snd_ctrl);
2004 void FadeMusic(void)
2006 if (!audio.music_available)
2009 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2012 void FadeSound(int nr)
2014 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2020 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2023 void StopMusic(void)
2025 if (!audio.music_available)
2028 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2031 void StopSound(int nr)
2033 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2039 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2042 void StopSoundExt(int nr, int state)
2044 SoundControl snd_ctrl;
2046 if (!audio.sound_available)
2049 snd_ctrl.active = FALSE;
2051 snd_ctrl.state = state;
2053 HandleSoundRequest(snd_ctrl);
2056 ListNode *newListNode()
2058 return checked_calloc(sizeof(ListNode));
2061 void addNodeToList(ListNode **node_first, char *key, void *content)
2063 ListNode *node_new = newListNode();
2066 printf("LIST: adding node with key '%s'\n", key);
2069 node_new->key = getStringCopy(key);
2070 node_new->content = content;
2071 node_new->next = *node_first;
2072 *node_first = node_new;
2075 void deleteNodeFromList(ListNode **node_first, char *key,
2076 void (*destructor_function)(void *))
2078 if (node_first == NULL || *node_first == NULL)
2082 printf("[CHECKING LIST KEY '%s' == '%s']\n",
2083 (*node_first)->key, key);
2086 if (strcmp((*node_first)->key, key) == 0)
2089 printf("[DELETING LIST ENTRY]\n");
2092 free((*node_first)->key);
2093 if (destructor_function)
2094 destructor_function((*node_first)->content);
2095 *node_first = (*node_first)->next;
2098 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
2101 ListNode *getNodeFromKey(ListNode *node_first, char *key)
2103 if (node_first == NULL)
2106 if (strcmp(node_first->key, key) == 0)
2109 return getNodeFromKey(node_first->next, key);
2112 int getNumNodes(ListNode *node_first)
2114 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
2117 void dumpList(ListNode *node_first)
2119 ListNode *node = node_first;
2123 printf("['%s' (%d)]\n", node->key,
2124 ((SoundInfo *)node->content)->num_references);
2128 printf("[%d nodes]\n", getNumNodes(node_first));
2131 static void LoadSoundsInfo()
2133 char *filename = getCustomSoundConfigFilename();
2134 struct SetupFileList *setup_file_list;
2138 printf("GOT CUSTOM SOUND CONFIG FILE '%s'\n", filename);
2141 /* always start with reliable default values */
2142 for (i=0; i<num_sounds; i++)
2143 sound_effect[i].filename = NULL;
2145 if (filename == NULL)
2148 if ((setup_file_list = loadSetupFileList(filename)))
2150 for (i=0; i<num_sounds; i++)
2151 sound_effect[i].filename =
2152 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
2154 freeSetupFileList(setup_file_list);
2157 for (i=0; i<num_sounds; i++)
2159 printf("'%s' ", sound_effect[i].text);
2160 if (sound_effect[i].filename)
2161 printf("-> '%s'\n", sound_effect[i].filename);
2163 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
2169 static void ReloadCustomSounds()
2171 static boolean draw_init_text = TRUE; /* only draw at startup */
2175 printf("DEBUG: reloading sounds '%s' ...\n",artwork.snd_current_identifier);
2181 DrawInitText("Loading sounds:", 120, FC_GREEN);
2184 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
2187 for(i=0; i<num_sounds; i++)
2190 DrawInitText(sound_effect[i].text, 150, FC_YELLOW);
2192 if (sound_effect[i].filename)
2193 LoadSoundToList(sound_effect[i].filename, i);
2195 LoadSoundToList(sound_effect[i].default_filename, i);
2198 draw_init_text = FALSE;
2201 printf("list size == %d\n", getNumNodes(SoundFileList));
2205 dumpList(SoundFileList);
2209 static void ReloadCustomMusic()
2212 printf("DEBUG: reloading music '%s' ...\n", artwork.mus_current_identifier);
2216 /* this is done directly in LoadCustomMusic() now */
2223 void InitReloadSounds(char *set_identifier)
2225 if (!audio.sound_available)
2228 #if defined(AUDIO_UNIX_NATIVE)
2229 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2231 ReloadCustomSounds();
2235 void InitReloadMusic(char *set_identifier)
2237 if (!audio.music_available)
2240 #if defined(AUDIO_UNIX_NATIVE)
2241 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2243 ReloadCustomMusic();
2247 void FreeSound(void *ptr)
2249 SoundInfo *sound = (SoundInfo *)ptr;
2254 if (sound->data_ptr)
2256 #if defined(TARGET_SDL)
2257 Mix_FreeChunk(sound->data_ptr);
2258 #elif defined(TARGET_ALLEGRO)
2259 destroy_sample(sound->data_ptr);
2260 #else /* AUDIO_UNIX_NATIVE */
2261 free(sound->data_ptr);
2265 if (sound->source_filename)
2266 free(sound->source_filename);
2271 void FreeMusic(MusicInfo *music)
2276 if (music->data_ptr)
2278 #if defined(TARGET_SDL)
2279 if (music->type == MUS_TYPE_MOD)
2280 Mix_FreeMusic(music->data_ptr);
2282 Mix_FreeChunk(music->data_ptr);
2283 #elif defined(TARGET_ALLEGRO)
2284 destroy_sample(music->data_ptr);
2285 #else /* AUDIO_UNIX_NATIVE */
2286 free(music->data_ptr);
2293 void FreeAllSounds()
2301 printf("%s: FREEING SOUNDS ...\n",
2302 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2305 for(i=0; i<num_sounds; i++)
2306 deleteSoundEntry(&Sound[i]);
2308 FreeSound(Sound[i]);
2312 printf("%s: FREEING SOUNDS -- DONE\n",
2313 IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
2329 for(i=0; i<num_music; i++)
2330 FreeMusic(Music[i]);
2338 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2339 /* ========================================================================= */