1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
31 struct ListNode *next;
33 typedef struct ListNode ListNode;
35 static ListNode *newListNode(void);
36 static void addNodeToList(ListNode **, char *, void *);
37 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
38 static ListNode *getNodeFromKey(ListNode *, char *);
39 static int getNumNodes(ListNode *);
42 static struct SoundEffectInfo *sound_effect;
43 static ListNode *SoundFileList = NULL;
44 static SoundInfo **Sound = NULL;
45 static MusicInfo **Music = NULL;
46 static int num_sounds = 0, num_music = 0;
49 /* ========================================================================= */
50 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
52 static struct AudioFormatInfo afmt;
53 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
54 static int mixer_active_channels = 0;
56 /* forward declaration of internal functions */
57 static void Mixer_Main(void);
58 static void Mixer_InsertNewSound(struct SoundControl);
59 static void InitAudioDevice(struct AudioFormatInfo *);
61 #if defined(PLATFORM_UNIX)
62 #if !defined(AUDIO_STREAMING_DSP)
63 static unsigned char linear_to_ulaw(int);
64 static int ulaw_to_linear(unsigned char);
66 #elif defined(PLATFORM_MSDOS)
67 static void Mixer_InsertNewSound(struct SoundControl);
68 static void Mixer_StopSound(struct SoundControl);
69 static void Mixer_StopAllSounds();
72 static void ReloadCustomSounds();
73 static void ReloadCustomMusic();
74 static void FreeSound(void *);
76 #if defined(PLATFORM_UNIX)
77 static int OpenAudioDevice(char *audio_device_name)
81 /* check if desired audio device is accessible */
82 if (access(audio_device_name, W_OK) != 0)
85 /* try to open audio device in non-blocking mode */
86 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
87 return audio_device_fd;
89 /* re-open audio device in blocking mode */
90 close(audio_device_fd);
91 audio_device_fd = open(audio_device_name, O_WRONLY);
93 return audio_device_fd;
96 static void CloseAudioDevice(int *audio_device_fd)
98 if (*audio_device_fd == 0)
101 close(*audio_device_fd);
102 *audio_device_fd = -1;
105 static boolean TestAudioDevices(void)
107 static char *audio_device_name[] =
112 int audio_device_fd = -1;
115 /* look for available audio devices, starting with preferred ones */
116 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
117 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
120 if (audio_device_fd < 0)
122 Error(ERR_WARN, "cannot open audio device -- no sound");
126 close(audio_device_fd);
128 audio.device_name = audio_device_name[i];
133 #if !defined(TARGET_SDL)
134 static boolean ForkAudioProcess(void)
136 if (pipe(audio.mixer_pipe) < 0)
138 Error(ERR_WARN, "cannot create pipe -- no sounds");
142 if ((audio.mixer_pid = fork()) < 0)
144 Error(ERR_WARN, "cannot create sound server process -- no sounds");
148 if (audio.mixer_pid == 0) /* we are child process */
155 else /* we are parent */
156 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
162 void UnixOpenAudio(void)
164 if (!TestAudioDevices())
167 audio.sound_available = TRUE;
168 audio.sound_enabled = TRUE;
170 #if defined(AUDIO_STREAMING_DSP)
171 audio.music_available = TRUE;
172 audio.loops_available = TRUE;
175 audio.num_channels = NUM_MIXER_CHANNELS;
176 audio.music_channel = MUSIC_CHANNEL;
177 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
180 void UnixCloseAudio(void)
183 close(audio.device_fd);
185 if (audio.mixer_pid > 0) /* we are parent process */
186 kill(audio.mixer_pid, SIGTERM);
189 static void WriteReloadInfoToPipe(char *set_name, int type)
191 struct SoundControl snd_ctrl;
192 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
193 artwork.mus_current);
194 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
195 unsigned long str_size2 = strlen(ti->basepath) + 1;
196 unsigned long str_size3 = strlen(ti->fullpath) + 1;
198 if (audio.mixer_pid == 0) /* we are child process */
201 if (leveldir_current == NULL) /* should never happen */
202 Error(ERR_EXIT, "leveldir_current == NULL");
204 snd_ctrl.active = FALSE;
205 snd_ctrl.state = type;
206 snd_ctrl.data_len = strlen(set_name) + 1;
208 if (write(audio.mixer_pipe[1], &snd_ctrl,
209 sizeof(snd_ctrl)) < 0 ||
210 write(audio.mixer_pipe[1], set_name,
211 snd_ctrl.data_len) < 0 ||
212 write(audio.mixer_pipe[1], leveldir_current,
213 sizeof(TreeInfo)) < 0 ||
214 write(audio.mixer_pipe[1], ti,
215 sizeof(TreeInfo)) < 0 ||
216 write(audio.mixer_pipe[1], &str_size1,
217 sizeof(unsigned long)) < 0 ||
218 write(audio.mixer_pipe[1], &str_size2,
219 sizeof(unsigned long)) < 0 ||
220 write(audio.mixer_pipe[1], &str_size3,
221 sizeof(unsigned long)) < 0 ||
222 write(audio.mixer_pipe[1], leveldir_current->fullpath,
224 write(audio.mixer_pipe[1], ti->basepath,
226 write(audio.mixer_pipe[1], ti->fullpath,
229 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
230 audio.sound_available = audio.sound_enabled = FALSE;
235 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
237 TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
238 &artwork.snd_current : &artwork.mus_current);
239 TreeInfo *ti = *ti_ptr;
240 unsigned long str_size1, str_size2, str_size3;
241 static char *set_name = NULL;
246 set_name = checked_malloc(snd_ctrl.data_len);
248 if (leveldir_current == NULL)
249 leveldir_current = checked_calloc(sizeof(TreeInfo));
251 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
252 if (leveldir_current->fullpath != NULL)
253 free(leveldir_current->fullpath);
254 if (ti->basepath != NULL)
256 if (ti->fullpath != NULL)
259 if (read(audio.mixer_pipe[0], set_name,
260 snd_ctrl.data_len) != snd_ctrl.data_len ||
261 read(audio.mixer_pipe[0], leveldir_current,
262 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
263 read(audio.mixer_pipe[0], ti,
264 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
265 read(audio.mixer_pipe[0], &str_size1,
266 sizeof(unsigned long)) != sizeof(unsigned long) ||
267 read(audio.mixer_pipe[0], &str_size2,
268 sizeof(unsigned long)) != sizeof(unsigned long) ||
269 read(audio.mixer_pipe[0], &str_size3,
270 sizeof(unsigned long)) != sizeof(unsigned long))
271 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
273 leveldir_current->fullpath = checked_calloc(str_size1);
274 ti->basepath = checked_calloc(str_size2);
275 ti->fullpath = checked_calloc(str_size3);
277 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
278 str_size1) != str_size1 ||
279 read(audio.mixer_pipe[0], ti->basepath,
280 str_size2) != str_size2 ||
281 read(audio.mixer_pipe[0], ti->fullpath,
282 str_size3) != str_size3)
283 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
285 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
286 artwork.sounds_set_current = set_name;
288 artwork.music_set_current = set_name;
290 #endif /* PLATFORM_UNIX */
292 void Mixer_InitChannels()
296 for(i=0; i<audio.num_channels; i++)
297 mixer[i].active = FALSE;
298 mixer_active_channels = 0;
301 static void Mixer_FadeSound(int channel)
303 mixer[channel].state |= SND_CTRL_FADE;
306 static void Mixer_RemoveSound(int channel)
308 if (!mixer_active_channels || !mixer[channel].active)
312 printf("REMOVING MIXER SOUND %d\n", channel);
315 mixer[channel].active = FALSE;
316 mixer_active_channels--;
319 static void Mixer_InsertSound(struct SoundControl snd_ctrl)
325 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
328 if (IS_MUSIC(snd_ctrl))
329 snd_ctrl.nr = snd_ctrl.nr % num_music;
330 else if (snd_ctrl.nr >= num_sounds)
333 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
334 if (snd_info == NULL)
337 printf("sound/music %d undefined\n", snd_ctrl.nr);
343 printf("-> %d\n", mixer_active_channels);
346 if (mixer_active_channels == audio.num_channels)
348 for (i=0; i<audio.num_channels; i++)
350 if (mixer[i].data_ptr == NULL)
353 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
356 Mixer_RemoveSound(i);
361 /* if mixer is full, remove oldest sound */
362 if (mixer_active_channels == audio.num_channels)
364 int longest = 0, longest_nr = audio.first_sound_channel;
366 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
368 #if !defined(PLATFORM_MSDOS)
369 int actual = 100 * mixer[i].playingpos / mixer[i].data_len;
371 int actual = mixer[i].playingpos;
374 if (!IS_LOOP(mixer[i]) && actual > longest)
380 #if defined(PLATFORM_MSDOS)
381 voice_set_volume(mixer[longest_nr].voice, 0);
382 deallocate_voice(mixer[longest_nr].voice);
384 Mixer_RemoveSound(longest_nr);
387 /* check if sound is already being played (and how often) */
388 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
389 if (mixer[i].nr == snd_ctrl.nr)
392 /* restart loop sounds only if they are just fading out */
393 if (k >= 1 && IS_LOOP(snd_ctrl))
395 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
397 if (mixer[i].nr == snd_ctrl.nr && IS_FADING(mixer[i]))
399 mixer[i].state &= ~SND_CTRL_FADE;
400 mixer[i].volume = PSND_MAX_VOLUME;
401 #if defined(PLATFORM_MSDOS)
402 mixer[i].state |= SND_CTRL_LOOP;
403 voice_stop_volumeramp(mixer[i].voice);
404 voice_ramp_volume(mixer[i].voice, mixer[i].volume, 1000);
412 /* don't play sound more than n times simultaneously (with n == 2 for now) */
415 int longest = 0, longest_nr = audio.first_sound_channel;
417 /* look for oldest equal sound */
418 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
422 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
425 #if !defined(PLATFORM_MSDOS)
426 actual = 100 * mixer[i].playingpos / mixer[i].data_len;
428 actual = mixer[i].playingpos;
430 if (actual >= longest)
437 #if defined(PLATFORM_MSDOS)
438 voice_set_volume(mixer[longest_nr].voice, 0);
439 deallocate_voice(mixer[longest_nr].voice);
441 Mixer_RemoveSound(longest_nr);
444 /* add new sound to mixer */
445 for(i=0; i<audio.num_channels; i++)
448 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
452 if (!mixer[i].active ||
453 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
455 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
456 (i != audio.music_channel && !mixer[i].active))
458 snd_ctrl.data_ptr = snd_info->data_ptr;
459 snd_ctrl.data_len = snd_info->data_len;
460 snd_ctrl.format = snd_info->format;
462 snd_ctrl.playingpos = 0;
463 snd_ctrl.playingtime = 0;
466 if (snd_info->data_len == 0)
468 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
473 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
475 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
478 Mixer_RemoveSound(i);
484 mixer_active_channels++;
487 printf("NEW SOUND %d ADDED TO MIXER\n", snd_ctrl.nr);
490 #if defined(PLATFORM_MSDOS)
491 mixer[i].voice = allocate_voice((SAMPLE *)mixer[i].data_ptr);
494 voice_set_playmode(mixer[i].voice, PLAYMODE_LOOP);
496 voice_set_volume(mixer[i].voice, snd_ctrl.volume);
497 voice_set_pan(mixer[i].voice, snd_ctrl.stereo);
498 voice_start(mixer[i].voice);
505 static void HandleSoundRequest(struct SoundControl snd_ctrl)
509 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
511 ReadReloadInfoFromPipe(snd_ctrl);
512 Mixer_InitChannels();
513 CloseAudioDevice(&audio.device_fd);
515 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
516 ReloadCustomSounds();
520 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
522 if (!mixer_active_channels)
525 if (IS_MUSIC(snd_ctrl))
527 mixer[audio.music_channel].state |= SND_CTRL_FADE;
531 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
532 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
533 mixer[i].state |= SND_CTRL_FADE;
535 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
537 if (!mixer_active_channels)
540 if (IS_MUSIC(snd_ctrl))
542 Mixer_RemoveSound(audio.music_channel);
546 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
547 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
548 Mixer_RemoveSound(i);
550 if (!mixer_active_channels)
551 CloseAudioDevice(&audio.device_fd);
553 else if (snd_ctrl.active) /* add new sound to mixer */
555 Mixer_InsertNewSound(snd_ctrl);
559 void StartMixer(void)
561 if (!audio.sound_available)
564 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
565 if (!ForkAudioProcess())
566 audio.sound_available = FALSE;
570 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
572 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
573 int sample_pos, int sample_size,
576 void *sample_ptr = snd_ctrl->data_ptr;
579 if (snd_ctrl->format == AUDIO_FORMAT_U8)
580 for (i=0; i<sample_size; i++)
582 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
583 else /* AUDIO_FORMAT_S16 */
584 for (i=0; i<sample_size; i++)
586 ((short *)sample_ptr)[sample_pos + i];
589 #if defined(AUDIO_STREAMING_DSP)
590 static void Mixer_Main_DSP()
592 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
593 static boolean stereo_volume_calculated = FALSE;
594 static short premix_first_buffer[SND_BLOCKSIZE];
595 static short premix_left_buffer[SND_BLOCKSIZE];
596 static short premix_right_buffer[SND_BLOCKSIZE];
597 static long premix_last_buffer[SND_BLOCKSIZE];
598 static byte playing_buffer[SND_BLOCKSIZE];
605 if (!stereo_volume_calculated)
607 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
609 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
611 stereo_volume_calculated = TRUE;
614 if (!mixer_active_channels)
617 if (audio.device_fd < 0)
619 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
622 InitAudioDevice(&afmt);
625 stereo = afmt.stereo;
626 fragment_size = afmt.fragment_size;
627 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
628 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
630 /* first clear the last premixing buffer */
631 memset(premix_last_buffer, 0,
632 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
634 for(i=0; i<audio.num_channels; i++)
641 if (!mixer[i].active)
644 /* pointer, lenght and actual playing position of sound sample */
645 sample_ptr = mixer[i].data_ptr;
646 sample_len = mixer[i].data_len;
647 sample_pos = mixer[i].playingpos;
648 sample_size = MIN(max_sample_size, sample_len - sample_pos);
649 mixer[i].playingpos += sample_size;
651 /* copy original sample to first mixing buffer */
652 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
653 premix_first_buffer);
655 /* are we about to restart a looping sound? */
656 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
658 while (sample_size < max_sample_size)
660 int restarted_sample_size =
661 MIN(max_sample_size - sample_size, sample_len);
663 if (mixer[i].format == AUDIO_FORMAT_U8)
664 for (j=0; j<restarted_sample_size; j++)
665 premix_first_buffer[sample_size + j] =
666 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
668 for (j=0; j<restarted_sample_size; j++)
669 premix_first_buffer[sample_size + j] =
670 ((short *)sample_ptr)[j];
672 mixer[i].playingpos = restarted_sample_size;
673 sample_size += restarted_sample_size;
677 /* decrease volume if sound is fading out */
678 if (IS_FADING(mixer[i]) &&
679 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
680 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
682 /* adjust volume of actual sound sample */
683 if (mixer[i].volume != PSND_MAX_VOLUME)
684 for(j=0; j<sample_size; j++)
685 premix_first_buffer[j] =
686 (mixer[i].volume * (long)premix_first_buffer[j])
687 >> PSND_MAX_VOLUME_BITS;
689 /* fill the last mixing buffer with stereo or mono sound */
692 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
693 int left_volume = stereo_volume[middle_pos + mixer[i].stereo];
694 int right_volume= stereo_volume[middle_pos - mixer[i].stereo];
696 for(j=0; j<sample_size; j++)
698 premix_left_buffer[j] =
699 (left_volume * premix_first_buffer[j])
700 >> PSND_MAX_LEFT2RIGHT_BITS;
701 premix_right_buffer[j] =
702 (right_volume * premix_first_buffer[j])
703 >> PSND_MAX_LEFT2RIGHT_BITS;
705 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
706 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
711 for(j=0; j<sample_size; j++)
712 premix_last_buffer[j] += premix_first_buffer[j];
715 /* delete completed sound entries from the mixer */
716 if (mixer[i].playingpos >= mixer[i].data_len)
718 if (IS_LOOP(mixer[i]))
719 mixer[i].playingpos = 0;
721 Mixer_RemoveSound(i);
723 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
724 Mixer_RemoveSound(i);
727 /* prepare final playing buffer according to system audio format */
728 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
730 /* cut off at 17 bit value */
731 if (premix_last_buffer[i] < -65535)
732 premix_last_buffer[i] = -65535;
733 else if (premix_last_buffer[i] > 65535)
734 premix_last_buffer[i] = 65535;
736 /* shift to 16 bit value */
737 premix_last_buffer[i] >>= 1;
739 if (afmt.format & AUDIO_FORMAT_U8)
741 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
743 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
745 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
746 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
748 else /* big endian */
750 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
751 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
755 /* finally play the sound fragment */
756 write(audio.device_fd, playing_buffer, fragment_size);
758 if (!mixer_active_channels)
759 CloseAudioDevice(&audio.device_fd);
762 #else /* !AUDIO_STREAMING_DSP */
764 static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
766 static short premix_first_buffer[SND_BLOCKSIZE];
767 static byte playing_buffer[SND_BLOCKSIZE];
768 int max_sample_size = SND_BLOCKSIZE;
777 /* pointer, lenght and actual playing position of sound sample */
778 sample_ptr = mixer[i].data_ptr;
779 sample_len = mixer[i].data_len;
780 sample_pos = mixer[i].playingpos;
781 sample_size = MIN(max_sample_size, sample_len - sample_pos);
782 mixer[i].playingpos += sample_size;
784 /* copy original sample to first mixing buffer */
785 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
786 premix_first_buffer);
788 /* adjust volume of actual sound sample */
789 if (mixer[i].volume != PSND_MAX_VOLUME)
790 for(j=0; j<sample_size; j++)
791 premix_first_buffer[j] =
792 (mixer[i].volume * (long)premix_first_buffer[j])
793 >> PSND_MAX_VOLUME_BITS;
795 /* might be needed for u-law /dev/audio */
797 for(j=0; j<sample_size; j++)
799 linear_to_ulaw(premix_first_buffer[j]);
802 /* delete completed sound entries from the mixer */
803 if (mixer[i].playingpos >= mixer[i].data_len)
804 Mixer_RemoveSound(i);
806 for(i=0; i<sample_size; i++)
807 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
809 /* finally play the sound fragment */
810 write(audio.device_fd, playing_buffer, sample_size);
814 #endif /* !AUDIO_STREAMING_DSP */
818 struct SoundControl snd_ctrl;
821 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
823 Mixer_InitChannels();
825 #if defined(PLATFORM_HPUX)
826 InitAudioDevice(&afmt);
829 FD_ZERO(&mixer_fdset);
830 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
832 while(1) /* wait for sound playing commands from client */
834 struct timeval delay = { 0, 0 };
836 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
837 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
838 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
840 if (read(audio.mixer_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
842 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
844 HandleSoundRequest(snd_ctrl);
846 #if defined(AUDIO_STREAMING_DSP)
848 while (mixer_active_channels &&
849 select(audio.mixer_pipe[0] + 1,
850 &mixer_fdset, NULL, NULL, &delay) < 1)
852 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
857 #else /* !AUDIO_STREAMING_DSP */
859 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
860 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
863 InitAudioDevice(&afmt);
868 while (mixer_active_channels &&
869 select(audio.mixer_pipe[0] + 1,
870 &mixer_fdset, NULL, NULL, &delay) < 1)
872 int wait_percent = 90; /* wait 90% of the real playing time */
875 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
877 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
881 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
884 CloseAudioDevice(&audio.device_fd);
886 Mixer_InitChannels(); /* remove all sounds from mixer */
888 #endif /* !AUDIO_STREAMING_DSP */
891 #endif /* PLATFORM_UNIX */
893 #if defined(PLATFORM_MSDOS)
894 static void sound_handler(struct SoundControl snd_ctrl)
898 if (snd_ctrl.fade_sound)
900 if (!mixer_active_channels)
903 for (i=0; i<audio.num_channels; i++)
904 if ((snd_ctrl.stop_all_sounds ||
905 (i != audio.music_channel && mixer[i].nr == snd_ctrl.nr) ||
906 (i == audio.music_channel && snd_ctrl.music)) &&
907 !mixer[i].fade_sound)
909 mixer[i].fade_sound = TRUE;
910 if (voice_check(mixer[i].voice))
911 voice_ramp_volume(mixer[i].voice, 1000, 0);
912 mixer[i].state &= ~SND_CTRL_IS_LOOP;
915 else if (snd_ctrl.stop_all_sounds)
917 if (!mixer_active_channels)
919 Mixer_StopAllSounds();
921 else if (snd_ctrl.stop_sound)
923 if (!mixer_active_channels)
925 Mixer_StopSound(snd_ctrl);
928 for (i=0; i<audio.num_channels; i++)
930 if (!mixer[i].active || mixer[i].loop)
933 mixer[i].playingpos = voice_get_position(mixer[i].voice);
934 mixer[i].volume = voice_get_volume(mixer[i].voice);
935 if (mixer[i].playingpos == -1 || !mixer[i].volume)
937 deallocate_voice(mixer[i].voice);
938 Mixer_RemoveSound(i);
943 Mixer_InsertNewSound(snd_ctrl);
945 #endif /* PLATFORM_MSDOS */
948 #if defined(TARGET_SDL)
949 static void sound_handler_SDL(struct SoundControl snd_ctrl)
951 /* copy sound_handler() here ... */
953 #endif /* TARGET_SDL */
956 #if !defined(PLATFORM_WIN32)
957 static void Mixer_InsertNewSound(struct SoundControl snd_ctrl)
959 Mixer_InsertSound(snd_ctrl);
961 #endif /* !PLATFORM_WIN32 */
964 void Mixer_FadeSound(int nr)
968 if (!mixer_active_channels)
971 for(i=0;i<audio.num_channels;i++)
972 if (snd_ctrl.stop_all_sounds || mixer[i].nr == snd_ctrl.nr)
973 mixer[i].fade_sound = TRUE;
977 #if !defined(PLATFORM_WIN32)
978 #if defined(PLATFORM_MSDOS)
979 static void Mixer_StopSound(struct SoundControl snd_ctrl)
981 int nr = snd_ctrl.nr;
984 if (!mixer_active_channels)
987 for(i=0; i<audio.num_channels; i++)
989 if ((i == audio.music_channel && snd_ctrl.music) ||
990 (i != audio.music_channel && mixer[i].nr == nr))
992 #if defined(PLATFORM_MSDOS)
993 voice_set_volume(mixer[i].voice, 0);
994 deallocate_voice(mixer[i].voice);
996 Mixer_RemoveSound(i);
1000 #if !defined(PLATFORM_MSDOS)
1001 if (!mixer_active_channels)
1002 close(audio.device_fd);
1006 static void Mixer_StopAllSounds()
1010 for(i=0; i<audio.num_channels; i++)
1012 #if defined(PLATFORM_MSDOS)
1013 voice_set_volume(mixer[i].voice, 0);
1014 deallocate_voice(mixer[i].voice);
1016 Mixer_RemoveSound(i);
1018 mixer_active_channels = 0;
1020 #if !defined(PLATFORM_MSDOS)
1021 close(audio.device_fd);
1024 #endif /* PLATFORM_MSDOS */
1025 #endif /* !PLATFORM_WIN32 */
1028 /* ------------------------------------------------------------------------- */
1029 /* platform dependant audio initialization code */
1030 /* ------------------------------------------------------------------------- */
1032 #if defined(AUDIO_LINUX_IOCTL)
1033 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1035 /* "ioctl()" expects pointer to 'int' value for stereo flag
1036 (boolean is defined as 'char', which will not work here) */
1037 unsigned int fragment_spec = 0;
1038 int fragment_size_query;
1047 /* supported audio format in preferred order */
1048 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1049 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1050 { AFMT_U8, AUDIO_FORMAT_U8 },
1055 /* determine logarithm (log2) of the fragment size */
1056 while ((1 << fragment_spec) < afmt->fragment_size)
1059 /* use two fragments (play one fragment, prepare the other);
1060 one fragment would result in interrupted audio output, more
1061 than two fragments would raise audio output latency to much */
1062 fragment_spec |= 0x00020000;
1064 /* Example for fragment specification:
1065 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1066 - (with stereo the effective buffer size will shrink to 256)
1067 => fragment_size = 0x00020009 */
1069 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1070 Error(ERR_EXIT_SOUND_SERVER,
1071 "cannot set fragment size of /dev/dsp -- no sounds");
1075 while (formats[i].format_result != -1)
1077 unsigned int audio_format = formats[i].format_ioctl;
1078 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1080 afmt->format = formats[i].format_result;
1085 if (afmt->format == 0) /* no supported audio format found */
1086 Error(ERR_EXIT_SOUND_SERVER,
1087 "cannot set audio format of /dev/dsp -- no sounds");
1089 /* try if we can use stereo sound */
1090 afmt->stereo = TRUE;
1091 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1092 afmt->stereo = FALSE;
1094 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1095 Error(ERR_EXIT_SOUND_SERVER,
1096 "cannot set sample rate of /dev/dsp -- no sounds");
1098 /* get the real fragmentation size; this should return 512 */
1099 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1100 Error(ERR_EXIT_SOUND_SERVER,
1101 "cannot get fragment size of /dev/dsp -- no sounds");
1102 if (fragment_size_query != afmt->fragment_size)
1103 Error(ERR_EXIT_SOUND_SERVER,
1104 "cannot set fragment size of /dev/dsp -- no sounds");
1106 #endif /* AUDIO_LINUX_IOCTL */
1108 #if defined(PLATFORM_NETBSD)
1109 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1111 audio_info_t a_info;
1112 boolean stereo = TRUE;
1114 AUDIO_INITINFO(&a_info);
1115 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1116 a_info.play.precision = 8;
1117 a_info.play.channels = 2;
1118 a_info.play.sample_rate = sample_rate;
1119 a_info.blocksize = fragment_size;
1121 afmt->format = AUDIO_FORMAT_U8;
1122 afmt->stereo = TRUE;
1124 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1126 /* try to disable stereo */
1127 a_info.play.channels = 1;
1129 afmt->stereo = FALSE;
1131 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1132 Error(ERR_EXIT_SOUND_SERVER,
1133 "cannot set sample rate of /dev/audio -- no sounds");
1136 #endif /* PLATFORM_NETBSD */
1138 #if defined(PLATFORM_HPUX)
1139 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1141 struct audio_describe ainfo;
1144 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1145 if (audio_ctl == -1)
1146 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1148 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1149 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1151 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1152 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1154 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1155 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1157 afmt->format = AUDIO_FORMAT_U8;
1158 afmt->stereo = FALSE;
1159 afmt->sample_rate = 8000;
1163 #endif /* PLATFORM_HPUX */
1165 #if defined(PLATFORM_UNIX)
1166 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1168 afmt->stereo = TRUE;
1169 afmt->format = AUDIO_FORMAT_UNKNOWN;
1170 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
1171 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1173 #if defined(AUDIO_LINUX_IOCTL)
1174 InitAudioDevice_Linux(afmt);
1175 #elif defined(PLATFORM_NETBSD)
1176 InitAudioDevice_NetBSD(afmt);
1177 #elif defined(PLATFORM_HPUX)
1178 InitAudioDevice_HPUX(afmt);
1180 /* generic /dev/audio stuff might be placed here */
1183 #endif /* PLATFORM_UNIX */
1185 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1187 /* these two are stolen from "sox"... :) */
1190 ** This routine converts from linear to ulaw.
1192 ** Craig Reese: IDA/Supercomputing Research Center
1193 ** Joe Campbell: Department of Defense
1194 ** 29 September 1989
1197 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1198 ** 2) "A New Digital Technique for Implementation of Any
1199 ** Continuous PCM Companding Law," Villeret, Michel,
1200 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1201 ** 1973, pg. 11.12-11.17
1202 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1203 ** for Analog-to_Digital Conversion Techniques,"
1206 ** Input: Signed 16 bit linear sample
1207 ** Output: 8 bit ulaw sample
1210 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1211 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1214 static unsigned char linear_to_ulaw(int sample)
1216 static int exp_lut[256] =
1218 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1219 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1220 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1221 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1222 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1223 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1224 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1225 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1226 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1227 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1228 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1229 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1230 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1231 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1232 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1233 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1236 int sign, exponent, mantissa;
1237 unsigned char ulawbyte;
1239 /* Get the sample into sign-magnitude. */
1240 sign = (sample >> 8) & 0x80; /* set aside the sign */
1242 sample = -sample; /* get magnitude */
1244 sample = CLIP; /* clip the magnitude */
1246 /* Convert from 16 bit linear to ulaw. */
1247 sample = sample + BIAS;
1248 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1249 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1250 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1253 ulawbyte = 0x02; /* optional CCITT trap */
1260 ** This routine converts from ulaw to 16 bit linear.
1262 ** Craig Reese: IDA/Supercomputing Research Center
1263 ** 29 September 1989
1266 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1267 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1268 ** for Analog-to_Digital Conversion Techniques,"
1271 ** Input: 8 bit ulaw sample
1272 ** Output: signed 16 bit linear sample
1275 static int ulaw_to_linear(unsigned char ulawbyte)
1277 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1278 int sign, exponent, mantissa, sample;
1280 ulawbyte = ~ ulawbyte;
1281 sign = ( ulawbyte & 0x80 );
1282 exponent = ( ulawbyte >> 4 ) & 0x07;
1283 mantissa = ulawbyte & 0x0F;
1284 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1290 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1293 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1294 /* ========================================================================= */
1295 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1297 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1298 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1300 static SoundInfo *Load_WAV(char *filename)
1302 SoundInfo *snd_info;
1303 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1304 byte sound_header_buffer[WAV_HEADER_SIZE];
1305 char chunk_name[CHUNK_ID_LEN + 1];
1311 if (!audio.sound_available)
1315 printf("loading WAV file '%s'\n", filename);
1318 snd_info = checked_calloc(sizeof(SoundInfo));
1320 #if defined(TARGET_SDL)
1322 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1324 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1329 #elif defined(TARGET_ALLEGRO)
1331 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1333 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1338 #else /* PLATFORM_UNIX */
1340 if ((file = fopen(filename, MODE_READ)) == NULL)
1342 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1347 /* read chunk id "RIFF" */
1348 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1349 if (strcmp(chunk_name, "RIFF") != 0)
1351 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1357 /* read "RIFF" type id "WAVE" */
1358 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1359 if (strcmp(chunk_name, "WAVE") != 0)
1361 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1367 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1369 if (strcmp(chunk_name, "fmt ") == 0)
1371 /* read header information */
1372 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1373 sound_header_buffer[i] = fgetc(file);
1375 if (chunk_size > WAV_HEADER_SIZE)
1376 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1378 else if (strcmp(chunk_name, "data") == 0)
1380 snd_info->data_len = chunk_size;
1381 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1383 /* read sound data */
1384 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1387 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1389 free(snd_info->data_ptr);
1394 /* check for odd number of sample bytes (data chunk is word aligned) */
1395 if ((chunk_size % 2) == 1)
1396 ReadUnusedBytesFromFile(file, 1);
1398 else /* unknown chunk -- ignore */
1399 ReadUnusedBytesFromFile(file, chunk_size);
1404 if (snd_info->data_ptr == NULL)
1406 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1411 snd_info->format = AUDIO_FORMAT_U8;
1413 #endif /* PLATFORM_UNIX */
1415 snd_info->type = SND_TYPE_WAV;
1416 snd_info->source_filename = getStringCopy(filename);
1421 static void deleteSoundEntry(SoundInfo **snd_info)
1425 char *filename = (*snd_info)->source_filename;
1428 printf("[decrementing reference counter of sound '%s']\n", filename);
1431 if (--(*snd_info)->num_references <= 0)
1434 printf("[deleting sound '%s']\n", filename);
1438 FreeSound(*snd_info);
1440 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1447 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1451 /* check if the old and the new sound file are the same */
1452 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1454 /* The old and new sound are the same (have the same filename and path).
1455 This usually means that this sound does not exist in this sound set
1456 and a fallback to the existing sound is done. */
1459 printf("[sound '%s' already exists (same list entry)]\n", filename);
1465 /* delete existing sound file entry */
1466 deleteSoundEntry(snd_info);
1468 /* check if the new sound file already exists in the list of sounds */
1469 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1472 printf("[sound '%s' already exists (other list entry)]\n", filename);
1475 *snd_info = (SoundInfo *)node->content;
1476 (*snd_info)->num_references++;
1478 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1480 (*snd_info)->num_references = 1;
1481 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1485 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1487 char *filename = getCustomSoundFilename(basename);
1489 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1491 deleteSoundEntry(snd_info);
1495 if (filename == NULL)
1497 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1501 replaceSoundEntry(snd_info, filename);
1504 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1507 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1509 sound_effect = sounds_list;
1510 num_sounds = num_list_entries;
1513 void LoadSoundToList(char *basename, int list_pos)
1515 if (Sound == NULL || list_pos >= num_sounds)
1519 printf("loading sound '%s' ... [%d]\n",
1520 basename, getNumNodes(SoundFileList));
1523 LoadCustomSound(&Sound[list_pos], basename);
1526 printf("loading sound '%s' done [%d]\n",
1527 basename, getNumNodes(SoundFileList));
1531 static MusicInfo *Load_MOD(char *filename)
1533 #if defined(TARGET_SDL)
1534 MusicInfo *mod_info;
1536 if (!audio.sound_available)
1539 mod_info = checked_calloc(sizeof(MusicInfo));
1541 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1543 Error(ERR_WARN, "cannot read music file '%s'", filename);
1548 mod_info->type = MUS_TYPE_MOD;
1549 mod_info->source_filename = getStringCopy(filename);
1557 void LoadCustomMusic(void)
1559 char *music_directory = getCustomMusicDirectory();
1561 struct dirent *dir_entry;
1563 if (!audio.sound_available)
1566 if ((dir = opendir(music_directory)) == NULL)
1568 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1569 audio.music_available = FALSE;
1573 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1575 char *basename = dir_entry->d_name;
1576 char *filename = getPath2(music_directory, basename);
1577 MusicInfo *mus_info = NULL;
1579 if (FileIsSound(basename))
1580 mus_info = Load_WAV(filename);
1581 else if (FileIsMusic(basename))
1582 mus_info = Load_MOD(filename);
1589 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1590 Music[num_music -1] = mus_info;
1597 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1601 void PlayMusic(int nr)
1603 if (!audio.music_available)
1606 #if defined(TARGET_SDL)
1608 nr = nr % num_music;
1610 if (Music[nr]->type == MUS_TYPE_MOD)
1612 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1613 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1615 else /* play WAV music loop */
1617 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1618 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1628 void PlaySound(int nr)
1630 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1633 void PlaySoundStereo(int nr, int stereo)
1635 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1638 void PlaySoundLoop(int nr)
1640 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1643 void PlaySoundMusic(int nr)
1645 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1648 void PlaySoundExt(int nr, int volume, int stereo, int state)
1650 struct SoundControl snd_ctrl;
1652 if (!audio.sound_available ||
1653 !audio.sound_enabled ||
1654 audio.sound_deactivated)
1657 if (volume < PSND_MIN_VOLUME)
1658 volume = PSND_MIN_VOLUME;
1659 else if (volume > PSND_MAX_VOLUME)
1660 volume = PSND_MAX_VOLUME;
1662 if (stereo < PSND_MAX_LEFT)
1663 stereo = PSND_MAX_LEFT;
1664 else if (stereo > PSND_MAX_RIGHT)
1665 stereo = PSND_MAX_RIGHT;
1667 snd_ctrl.active = TRUE;
1669 snd_ctrl.volume = volume;
1670 snd_ctrl.stereo = stereo;
1671 snd_ctrl.state = state;
1673 #if defined(TARGET_SDL)
1676 Mix_Volume(-1, SOUND_MAX_VOLUME);
1677 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1679 #elif defined(PLATFORM_UNIX)
1680 if (audio.mixer_pid == 0) /* we are child process */
1683 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1685 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1686 audio.sound_available = audio.sound_enabled = FALSE;
1689 #elif defined(PLATFORM_MSDOS)
1690 sound_handler(snd_ctrl);
1694 void FadeMusic(void)
1696 if (!audio.sound_available)
1699 #if defined(TARGET_SDL)
1700 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1701 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1703 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1707 void FadeSound(int nr)
1709 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1715 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1718 void StopMusic(void)
1720 #if defined(TARGET_SDL)
1721 if (!audio.sound_available)
1725 Mix_HaltChannel(audio.music_channel);
1727 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1731 void StopSound(int nr)
1733 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1739 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1742 void StopSoundExt(int nr, int state)
1744 struct SoundControl snd_ctrl;
1746 if (!audio.sound_available)
1749 snd_ctrl.active = FALSE;
1751 snd_ctrl.state = state;
1753 #if defined(TARGET_SDL)
1755 if (state & SND_CTRL_FADE)
1760 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
1763 for (i=0; i<audio.channels; i++)
1764 if (i != audio.music_channel || snd_ctrl.music)
1765 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1766 if (state & SND_CTRL_MUSIC)
1767 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1773 for (i=0; i<audio.channels; i++)
1774 if (i != audio.music_channel || snd_ctrl.music)
1776 if (state & SND_CTRL_MUSIC)
1780 #elif !defined(PLATFORM_MSDOS)
1782 if (audio.mixer_pid == 0) /* we are child process */
1785 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1787 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1788 audio.sound_available = audio.sound_enabled = FALSE;
1791 #else /* PLATFORM_MSDOS */
1792 sound_handler(snd_ctrl);
1796 ListNode *newListNode()
1798 return checked_calloc(sizeof(ListNode));
1801 void addNodeToList(ListNode **node_first, char *key, void *content)
1803 ListNode *node_new = newListNode();
1806 printf("LIST: adding node with key '%s'\n", key);
1809 node_new->key = getStringCopy(key);
1810 node_new->content = content;
1811 node_new->next = *node_first;
1812 *node_first = node_new;
1815 void deleteNodeFromList(ListNode **node_first, char *key,
1816 void (*destructor_function)(void *))
1818 if (node_first == NULL || *node_first == NULL)
1822 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1823 (*node_first)->key, key);
1826 if (strcmp((*node_first)->key, key) == 0)
1829 printf("[DELETING LIST ENTRY]\n");
1832 free((*node_first)->key);
1833 if (destructor_function)
1834 destructor_function((*node_first)->content);
1835 *node_first = (*node_first)->next;
1838 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1841 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1843 if (node_first == NULL)
1846 if (strcmp(node_first->key, key) == 0)
1849 return getNodeFromKey(node_first->next, key);
1852 int getNumNodes(ListNode *node_first)
1854 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1857 void dumpList(ListNode *node_first)
1859 ListNode *node = node_first;
1863 printf("['%s' (%d)]\n", node->key,
1864 ((SoundInfo *)node->content)->num_references);
1868 printf("[%d nodes]\n", getNumNodes(node_first));
1871 static void LoadSoundsInfo()
1873 char *filename = getCustomSoundConfigFilename();
1874 struct SetupFileList *setup_file_list;
1877 /* always start with reliable default values */
1878 for (i=0; i<num_sounds; i++)
1879 sound_effect[i].filename = NULL;
1881 if (filename == NULL)
1884 if ((setup_file_list = loadSetupFileList(filename)))
1886 for (i=0; i<num_sounds; i++)
1887 sound_effect[i].filename =
1888 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1890 freeSetupFileList(setup_file_list);
1893 for (i=0; i<num_sounds; i++)
1895 printf("'%s' ", sound_effect[i].text);
1896 if (sound_effect[i].filename)
1897 printf("-> '%s'\n", sound_effect[i].filename);
1899 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1905 static void ReloadCustomSounds()
1910 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1916 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1919 for(i=0; i<num_sounds; i++)
1921 if (sound_effect[i].filename)
1922 LoadSoundToList(sound_effect[i].filename, i);
1924 LoadSoundToList(sound_effect[i].default_filename, i);
1928 printf("list size == %d\n", getNumNodes(SoundFileList));
1932 dumpList(SoundFileList);
1936 static void ReloadCustomMusic()
1939 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1947 void InitReloadSounds(char *set_name)
1949 if (!audio.sound_available)
1952 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1953 ReloadCustomSounds();
1954 #elif defined(PLATFORM_UNIX)
1955 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
1959 void InitReloadMusic(char *set_name)
1961 if (!audio.music_available)
1964 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1965 ReloadCustomMusic();
1966 #elif defined(PLATFORM_UNIX)
1967 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
1971 void FreeSound(void *ptr)
1973 SoundInfo *sound = (SoundInfo *)ptr;
1978 if (sound->data_ptr)
1980 #if defined(TARGET_SDL)
1981 Mix_FreeChunk(sound->data_ptr);
1982 #elif defined(TARGET_ALLEGRO)
1983 destroy_sample(sound->data_ptr);
1984 #else /* PLATFORM_UNIX */
1985 free(sound->data_ptr);
1989 if (sound->source_filename)
1990 free(sound->source_filename);
1995 void FreeMusic(MusicInfo *music)
2000 if (music->data_ptr)
2002 #if defined(TARGET_SDL)
2003 if (music->type == MUS_TYPE_MOD)
2004 Mix_FreeMusic(music->data_ptr);
2006 Mix_FreeChunk(music->data_ptr);
2007 #elif defined(TARGET_ALLEGRO)
2008 destroy_sample(music->data_ptr);
2009 #else /* PLATFORM_UNIX */
2010 free(music->data_ptr);
2017 void FreeAllSounds()
2024 printf("%s: FREEING SOUNDS ...\n",
2025 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
2027 for(i=0; i<num_sounds; i++)
2028 deleteSoundEntry(&Sound[i]);
2030 FreeSound(Sound[i]);
2033 printf("%s: FREEING SOUNDS -- DONE\n",
2034 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
2049 for(i=0; i<num_music; i++)
2050 FreeMusic(Music[i]);
2058 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2059 /* ========================================================================= */