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_PlaySound(int channel)
303 #if defined(PLATFORM_MSDOS)
304 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
306 if (mixer[channel].voice < 0)
309 if (IS_LOOP(mixer[channel]))
310 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
312 voice_set_volume(mixer[channel].voice, snd_ctrl.volume);
313 voice_set_pan(mixer[channel].voice, snd_ctrl.stereo);
314 voice_start(mixer[channel].voice);
318 static void Mixer_StopSound(int channel)
320 #if defined(PLATFORM_MSDOS)
321 voice_set_volume(mixer[channel].voice, 0);
322 deallocate_voice(mixer[channel].voice);
326 static void Mixer_FadeSound(int channel)
328 mixer[channel].state |= SND_CTRL_FADE;
331 static void Mixer_RemoveSound(int channel)
333 if (!mixer_active_channels || !mixer[channel].active)
337 printf("REMOVING MIXER SOUND %d\n", channel);
340 Mixer_StopSound(channel);
342 mixer[channel].active = FALSE;
343 mixer_active_channels--;
346 static void Mixer_InsertSound(struct SoundControl snd_ctrl)
352 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
355 if (IS_MUSIC(snd_ctrl))
356 snd_ctrl.nr = snd_ctrl.nr % num_music;
357 else if (snd_ctrl.nr >= num_sounds)
360 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
361 if (snd_info == NULL)
364 printf("sound/music %d undefined\n", snd_ctrl.nr);
370 printf("-> %d\n", mixer_active_channels);
373 if (mixer_active_channels == audio.num_channels)
375 for (i=0; i<audio.num_channels; i++)
377 if (mixer[i].data_ptr == NULL)
380 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
383 Mixer_RemoveSound(i);
388 /* if mixer is full, remove oldest sound */
389 if (mixer_active_channels == audio.num_channels)
391 int longest = 0, longest_nr = audio.first_sound_channel;
393 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
395 #if !defined(PLATFORM_MSDOS)
396 int actual = 100 * mixer[i].playingpos / mixer[i].data_len;
398 int actual = mixer[i].playingpos;
401 if (!IS_LOOP(mixer[i]) && actual > longest)
408 Mixer_RemoveSound(longest_nr);
411 /* check if sound is already being played (and how often) */
412 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
413 if (mixer[i].nr == snd_ctrl.nr)
416 /* restart loop sounds only if they are just fading out */
417 if (k >= 1 && IS_LOOP(snd_ctrl))
419 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
421 if (mixer[i].nr == snd_ctrl.nr && IS_FADING(mixer[i]))
423 mixer[i].state &= ~SND_CTRL_FADE;
424 mixer[i].volume = PSND_MAX_VOLUME;
425 #if defined(PLATFORM_MSDOS)
426 mixer[i].state |= SND_CTRL_LOOP;
427 voice_stop_volumeramp(mixer[i].voice);
428 voice_ramp_volume(mixer[i].voice, mixer[i].volume, 1000);
436 /* don't play sound more than n times simultaneously (with n == 2 for now) */
439 int longest = 0, longest_nr = audio.first_sound_channel;
441 /* look for oldest equal sound */
442 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
446 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
449 #if !defined(PLATFORM_MSDOS)
450 actual = 100 * mixer[i].playingpos / mixer[i].data_len;
452 actual = mixer[i].playingpos;
454 if (actual >= longest)
461 Mixer_RemoveSound(longest_nr);
464 /* add new sound to mixer */
465 for(i=0; i<audio.num_channels; i++)
468 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
472 if (!mixer[i].active ||
473 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
475 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
476 (i != audio.music_channel && !mixer[i].active))
478 snd_ctrl.data_ptr = snd_info->data_ptr;
479 snd_ctrl.data_len = snd_info->data_len;
480 snd_ctrl.format = snd_info->format;
482 snd_ctrl.playingpos = 0;
483 snd_ctrl.playingtime = 0;
486 if (snd_info->data_len == 0)
488 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
493 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
495 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
498 Mixer_RemoveSound(i);
504 mixer_active_channels++;
507 printf("NEW SOUND %d ADDED TO MIXER\n", snd_ctrl.nr);
517 static void HandleSoundRequest(struct SoundControl snd_ctrl)
521 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
523 ReadReloadInfoFromPipe(snd_ctrl);
524 Mixer_InitChannels();
525 CloseAudioDevice(&audio.device_fd);
527 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
528 ReloadCustomSounds();
532 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
534 if (!mixer_active_channels)
537 if (IS_MUSIC(snd_ctrl))
539 mixer[audio.music_channel].state |= SND_CTRL_FADE;
543 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
544 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
545 mixer[i].state |= SND_CTRL_FADE;
547 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
549 if (!mixer_active_channels)
552 if (IS_MUSIC(snd_ctrl))
554 Mixer_RemoveSound(audio.music_channel);
558 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
559 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
560 Mixer_RemoveSound(i);
562 if (!mixer_active_channels)
563 CloseAudioDevice(&audio.device_fd);
565 else if (snd_ctrl.active) /* add new sound to mixer */
567 Mixer_InsertNewSound(snd_ctrl);
571 void StartMixer(void)
573 if (!audio.sound_available)
576 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
577 if (!ForkAudioProcess())
578 audio.sound_available = FALSE;
582 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
584 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
585 int sample_pos, int sample_size,
588 void *sample_ptr = snd_ctrl->data_ptr;
591 if (snd_ctrl->format == AUDIO_FORMAT_U8)
592 for (i=0; i<sample_size; i++)
594 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
595 else /* AUDIO_FORMAT_S16 */
596 for (i=0; i<sample_size; i++)
598 ((short *)sample_ptr)[sample_pos + i];
601 #if defined(AUDIO_STREAMING_DSP)
602 static void Mixer_Main_DSP()
604 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
605 static boolean stereo_volume_calculated = FALSE;
606 static short premix_first_buffer[SND_BLOCKSIZE];
607 static short premix_left_buffer[SND_BLOCKSIZE];
608 static short premix_right_buffer[SND_BLOCKSIZE];
609 static long premix_last_buffer[SND_BLOCKSIZE];
610 static byte playing_buffer[SND_BLOCKSIZE];
617 if (!stereo_volume_calculated)
619 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
621 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
623 stereo_volume_calculated = TRUE;
626 if (!mixer_active_channels)
629 if (audio.device_fd < 0)
631 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
634 InitAudioDevice(&afmt);
637 stereo = afmt.stereo;
638 fragment_size = afmt.fragment_size;
639 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
640 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
642 /* first clear the last premixing buffer */
643 memset(premix_last_buffer, 0,
644 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
646 for(i=0; i<audio.num_channels; i++)
653 if (!mixer[i].active)
656 /* pointer, lenght and actual playing position of sound sample */
657 sample_ptr = mixer[i].data_ptr;
658 sample_len = mixer[i].data_len;
659 sample_pos = mixer[i].playingpos;
660 sample_size = MIN(max_sample_size, sample_len - sample_pos);
661 mixer[i].playingpos += sample_size;
663 /* copy original sample to first mixing buffer */
664 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
665 premix_first_buffer);
667 /* are we about to restart a looping sound? */
668 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
670 while (sample_size < max_sample_size)
672 int restarted_sample_size =
673 MIN(max_sample_size - sample_size, sample_len);
675 if (mixer[i].format == AUDIO_FORMAT_U8)
676 for (j=0; j<restarted_sample_size; j++)
677 premix_first_buffer[sample_size + j] =
678 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
680 for (j=0; j<restarted_sample_size; j++)
681 premix_first_buffer[sample_size + j] =
682 ((short *)sample_ptr)[j];
684 mixer[i].playingpos = restarted_sample_size;
685 sample_size += restarted_sample_size;
689 /* decrease volume if sound is fading out */
690 if (IS_FADING(mixer[i]) &&
691 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
692 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
694 /* adjust volume of actual sound sample */
695 if (mixer[i].volume != PSND_MAX_VOLUME)
696 for(j=0; j<sample_size; j++)
697 premix_first_buffer[j] =
698 (mixer[i].volume * (long)premix_first_buffer[j])
699 >> PSND_MAX_VOLUME_BITS;
701 /* fill the last mixing buffer with stereo or mono sound */
704 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
705 int left_volume = stereo_volume[middle_pos + mixer[i].stereo];
706 int right_volume= stereo_volume[middle_pos - mixer[i].stereo];
708 for(j=0; j<sample_size; j++)
710 premix_left_buffer[j] =
711 (left_volume * premix_first_buffer[j])
712 >> PSND_MAX_LEFT2RIGHT_BITS;
713 premix_right_buffer[j] =
714 (right_volume * premix_first_buffer[j])
715 >> PSND_MAX_LEFT2RIGHT_BITS;
717 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
718 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
723 for(j=0; j<sample_size; j++)
724 premix_last_buffer[j] += premix_first_buffer[j];
727 /* delete completed sound entries from the mixer */
728 if (mixer[i].playingpos >= mixer[i].data_len)
730 if (IS_LOOP(mixer[i]))
731 mixer[i].playingpos = 0;
733 Mixer_RemoveSound(i);
735 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
736 Mixer_RemoveSound(i);
739 /* prepare final playing buffer according to system audio format */
740 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
742 /* cut off at 17 bit value */
743 if (premix_last_buffer[i] < -65535)
744 premix_last_buffer[i] = -65535;
745 else if (premix_last_buffer[i] > 65535)
746 premix_last_buffer[i] = 65535;
748 /* shift to 16 bit value */
749 premix_last_buffer[i] >>= 1;
751 if (afmt.format & AUDIO_FORMAT_U8)
753 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
755 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
757 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
758 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
760 else /* big endian */
762 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
763 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
767 /* finally play the sound fragment */
768 write(audio.device_fd, playing_buffer, fragment_size);
770 if (!mixer_active_channels)
771 CloseAudioDevice(&audio.device_fd);
774 #else /* !AUDIO_STREAMING_DSP */
776 static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
778 static short premix_first_buffer[SND_BLOCKSIZE];
779 static byte playing_buffer[SND_BLOCKSIZE];
780 int max_sample_size = SND_BLOCKSIZE;
789 /* pointer, lenght and actual playing position of sound sample */
790 sample_ptr = mixer[i].data_ptr;
791 sample_len = mixer[i].data_len;
792 sample_pos = mixer[i].playingpos;
793 sample_size = MIN(max_sample_size, sample_len - sample_pos);
794 mixer[i].playingpos += sample_size;
796 /* copy original sample to first mixing buffer */
797 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
798 premix_first_buffer);
800 /* adjust volume of actual sound sample */
801 if (mixer[i].volume != PSND_MAX_VOLUME)
802 for(j=0; j<sample_size; j++)
803 premix_first_buffer[j] =
804 (mixer[i].volume * (long)premix_first_buffer[j])
805 >> PSND_MAX_VOLUME_BITS;
807 /* might be needed for u-law /dev/audio */
809 for(j=0; j<sample_size; j++)
811 linear_to_ulaw(premix_first_buffer[j]);
814 /* delete completed sound entries from the mixer */
815 if (mixer[i].playingpos >= mixer[i].data_len)
816 Mixer_RemoveSound(i);
818 for(i=0; i<sample_size; i++)
819 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
821 /* finally play the sound fragment */
822 write(audio.device_fd, playing_buffer, sample_size);
826 #endif /* !AUDIO_STREAMING_DSP */
830 struct SoundControl snd_ctrl;
833 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
835 Mixer_InitChannels();
837 #if defined(PLATFORM_HPUX)
838 InitAudioDevice(&afmt);
841 FD_ZERO(&mixer_fdset);
842 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
844 while(1) /* wait for sound playing commands from client */
846 struct timeval delay = { 0, 0 };
848 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
849 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
850 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
852 if (read(audio.mixer_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
854 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
856 HandleSoundRequest(snd_ctrl);
858 #if defined(AUDIO_STREAMING_DSP)
860 while (mixer_active_channels &&
861 select(audio.mixer_pipe[0] + 1,
862 &mixer_fdset, NULL, NULL, &delay) < 1)
864 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
869 #else /* !AUDIO_STREAMING_DSP */
871 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
872 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
875 InitAudioDevice(&afmt);
880 while (mixer_active_channels &&
881 select(audio.mixer_pipe[0] + 1,
882 &mixer_fdset, NULL, NULL, &delay) < 1)
884 int wait_percent = 90; /* wait 90% of the real playing time */
887 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
889 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
893 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
896 CloseAudioDevice(&audio.device_fd);
898 Mixer_InitChannels(); /* remove all sounds from mixer */
900 #endif /* !AUDIO_STREAMING_DSP */
903 #endif /* PLATFORM_UNIX */
905 #if defined(PLATFORM_MSDOS)
906 static void sound_handler(struct SoundControl snd_ctrl)
910 if (snd_ctrl.fade_sound)
912 if (!mixer_active_channels)
915 for (i=0; i<audio.num_channels; i++)
916 if ((snd_ctrl.stop_all_sounds ||
917 (i != audio.music_channel && mixer[i].nr == snd_ctrl.nr) ||
918 (i == audio.music_channel && snd_ctrl.music)) &&
919 !mixer[i].fade_sound)
921 mixer[i].fade_sound = TRUE;
922 if (voice_check(mixer[i].voice))
923 voice_ramp_volume(mixer[i].voice, 1000, 0);
924 mixer[i].state &= ~SND_CTRL_IS_LOOP;
927 else if (snd_ctrl.stop_all_sounds)
929 if (!mixer_active_channels)
931 Mixer_StopAllSounds();
933 else if (snd_ctrl.stop_sound)
935 if (!mixer_active_channels)
937 Mixer_StopSound(snd_ctrl);
940 for (i=0; i<audio.num_channels; i++)
942 if (!mixer[i].active || mixer[i].loop)
945 mixer[i].playingpos = voice_get_position(mixer[i].voice);
946 mixer[i].volume = voice_get_volume(mixer[i].voice);
947 if (mixer[i].playingpos == -1 || !mixer[i].volume)
949 deallocate_voice(mixer[i].voice);
950 Mixer_RemoveSound(i);
955 Mixer_InsertNewSound(snd_ctrl);
957 #endif /* PLATFORM_MSDOS */
960 #if defined(TARGET_SDL)
961 static void sound_handler_SDL(struct SoundControl snd_ctrl)
963 /* copy sound_handler() here ... */
965 #endif /* TARGET_SDL */
968 #if !defined(PLATFORM_WIN32)
969 static void Mixer_InsertNewSound(struct SoundControl snd_ctrl)
971 Mixer_InsertSound(snd_ctrl);
973 #endif /* !PLATFORM_WIN32 */
976 void Mixer_FadeSound(int nr)
980 if (!mixer_active_channels)
983 for(i=0;i<audio.num_channels;i++)
984 if (snd_ctrl.stop_all_sounds || mixer[i].nr == snd_ctrl.nr)
985 mixer[i].fade_sound = TRUE;
989 #if !defined(PLATFORM_WIN32)
990 #if defined(PLATFORM_MSDOS)
991 static void Mixer_StopSound(struct SoundControl snd_ctrl)
993 int nr = snd_ctrl.nr;
996 if (!mixer_active_channels)
999 for(i=0; i<audio.num_channels; i++)
1001 if ((i == audio.music_channel && snd_ctrl.music) ||
1002 (i != audio.music_channel && mixer[i].nr == nr))
1004 #if defined(PLATFORM_MSDOS)
1005 voice_set_volume(mixer[i].voice, 0);
1006 deallocate_voice(mixer[i].voice);
1008 Mixer_RemoveSound(i);
1012 #if !defined(PLATFORM_MSDOS)
1013 if (!mixer_active_channels)
1014 close(audio.device_fd);
1018 static void Mixer_StopAllSounds()
1022 for(i=0; i<audio.num_channels; i++)
1024 #if defined(PLATFORM_MSDOS)
1025 voice_set_volume(mixer[i].voice, 0);
1026 deallocate_voice(mixer[i].voice);
1028 Mixer_RemoveSound(i);
1030 mixer_active_channels = 0;
1032 #if !defined(PLATFORM_MSDOS)
1033 close(audio.device_fd);
1036 #endif /* PLATFORM_MSDOS */
1037 #endif /* !PLATFORM_WIN32 */
1040 /* ------------------------------------------------------------------------- */
1041 /* platform dependant audio initialization code */
1042 /* ------------------------------------------------------------------------- */
1044 #if defined(AUDIO_LINUX_IOCTL)
1045 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1047 /* "ioctl()" expects pointer to 'int' value for stereo flag
1048 (boolean is defined as 'char', which will not work here) */
1049 unsigned int fragment_spec = 0;
1050 int fragment_size_query;
1059 /* supported audio format in preferred order */
1060 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1061 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1062 { AFMT_U8, AUDIO_FORMAT_U8 },
1067 /* determine logarithm (log2) of the fragment size */
1068 while ((1 << fragment_spec) < afmt->fragment_size)
1071 /* use two fragments (play one fragment, prepare the other);
1072 one fragment would result in interrupted audio output, more
1073 than two fragments would raise audio output latency to much */
1074 fragment_spec |= 0x00020000;
1076 /* Example for fragment specification:
1077 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1078 - (with stereo the effective buffer size will shrink to 256)
1079 => fragment_size = 0x00020009 */
1081 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1082 Error(ERR_EXIT_SOUND_SERVER,
1083 "cannot set fragment size of /dev/dsp -- no sounds");
1087 while (formats[i].format_result != -1)
1089 unsigned int audio_format = formats[i].format_ioctl;
1090 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1092 afmt->format = formats[i].format_result;
1097 if (afmt->format == 0) /* no supported audio format found */
1098 Error(ERR_EXIT_SOUND_SERVER,
1099 "cannot set audio format of /dev/dsp -- no sounds");
1101 /* try if we can use stereo sound */
1102 afmt->stereo = TRUE;
1103 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1104 afmt->stereo = FALSE;
1106 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1107 Error(ERR_EXIT_SOUND_SERVER,
1108 "cannot set sample rate of /dev/dsp -- no sounds");
1110 /* get the real fragmentation size; this should return 512 */
1111 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1112 Error(ERR_EXIT_SOUND_SERVER,
1113 "cannot get fragment size of /dev/dsp -- no sounds");
1114 if (fragment_size_query != afmt->fragment_size)
1115 Error(ERR_EXIT_SOUND_SERVER,
1116 "cannot set fragment size of /dev/dsp -- no sounds");
1118 #endif /* AUDIO_LINUX_IOCTL */
1120 #if defined(PLATFORM_NETBSD)
1121 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1123 audio_info_t a_info;
1124 boolean stereo = TRUE;
1126 AUDIO_INITINFO(&a_info);
1127 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1128 a_info.play.precision = 8;
1129 a_info.play.channels = 2;
1130 a_info.play.sample_rate = sample_rate;
1131 a_info.blocksize = fragment_size;
1133 afmt->format = AUDIO_FORMAT_U8;
1134 afmt->stereo = TRUE;
1136 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1138 /* try to disable stereo */
1139 a_info.play.channels = 1;
1141 afmt->stereo = FALSE;
1143 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1144 Error(ERR_EXIT_SOUND_SERVER,
1145 "cannot set sample rate of /dev/audio -- no sounds");
1148 #endif /* PLATFORM_NETBSD */
1150 #if defined(PLATFORM_HPUX)
1151 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1153 struct audio_describe ainfo;
1156 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1157 if (audio_ctl == -1)
1158 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1160 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1161 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1163 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1164 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1166 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1167 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1169 afmt->format = AUDIO_FORMAT_U8;
1170 afmt->stereo = FALSE;
1171 afmt->sample_rate = 8000;
1175 #endif /* PLATFORM_HPUX */
1177 #if defined(PLATFORM_UNIX)
1178 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1180 afmt->stereo = TRUE;
1181 afmt->format = AUDIO_FORMAT_UNKNOWN;
1182 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
1183 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1185 #if defined(AUDIO_LINUX_IOCTL)
1186 InitAudioDevice_Linux(afmt);
1187 #elif defined(PLATFORM_NETBSD)
1188 InitAudioDevice_NetBSD(afmt);
1189 #elif defined(PLATFORM_HPUX)
1190 InitAudioDevice_HPUX(afmt);
1192 /* generic /dev/audio stuff might be placed here */
1195 #endif /* PLATFORM_UNIX */
1197 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1199 /* these two are stolen from "sox"... :) */
1202 ** This routine converts from linear to ulaw.
1204 ** Craig Reese: IDA/Supercomputing Research Center
1205 ** Joe Campbell: Department of Defense
1206 ** 29 September 1989
1209 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1210 ** 2) "A New Digital Technique for Implementation of Any
1211 ** Continuous PCM Companding Law," Villeret, Michel,
1212 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1213 ** 1973, pg. 11.12-11.17
1214 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1215 ** for Analog-to_Digital Conversion Techniques,"
1218 ** Input: Signed 16 bit linear sample
1219 ** Output: 8 bit ulaw sample
1222 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1223 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1226 static unsigned char linear_to_ulaw(int sample)
1228 static int exp_lut[256] =
1230 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1231 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1232 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1233 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1234 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1235 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1236 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1237 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1238 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1239 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1240 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1241 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1242 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1243 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1244 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1245 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1248 int sign, exponent, mantissa;
1249 unsigned char ulawbyte;
1251 /* Get the sample into sign-magnitude. */
1252 sign = (sample >> 8) & 0x80; /* set aside the sign */
1254 sample = -sample; /* get magnitude */
1256 sample = CLIP; /* clip the magnitude */
1258 /* Convert from 16 bit linear to ulaw. */
1259 sample = sample + BIAS;
1260 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1261 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1262 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1265 ulawbyte = 0x02; /* optional CCITT trap */
1272 ** This routine converts from ulaw to 16 bit linear.
1274 ** Craig Reese: IDA/Supercomputing Research Center
1275 ** 29 September 1989
1278 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1279 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1280 ** for Analog-to_Digital Conversion Techniques,"
1283 ** Input: 8 bit ulaw sample
1284 ** Output: signed 16 bit linear sample
1287 static int ulaw_to_linear(unsigned char ulawbyte)
1289 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1290 int sign, exponent, mantissa, sample;
1292 ulawbyte = ~ ulawbyte;
1293 sign = ( ulawbyte & 0x80 );
1294 exponent = ( ulawbyte >> 4 ) & 0x07;
1295 mantissa = ulawbyte & 0x0F;
1296 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1302 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1305 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1306 /* ========================================================================= */
1307 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1309 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1310 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1312 static SoundInfo *Load_WAV(char *filename)
1314 SoundInfo *snd_info;
1315 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1316 byte sound_header_buffer[WAV_HEADER_SIZE];
1317 char chunk_name[CHUNK_ID_LEN + 1];
1323 if (!audio.sound_available)
1327 printf("loading WAV file '%s'\n", filename);
1330 snd_info = checked_calloc(sizeof(SoundInfo));
1332 #if defined(TARGET_SDL)
1334 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1336 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1341 #elif defined(TARGET_ALLEGRO)
1343 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1345 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1350 #else /* PLATFORM_UNIX */
1352 if ((file = fopen(filename, MODE_READ)) == NULL)
1354 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1359 /* read chunk id "RIFF" */
1360 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1361 if (strcmp(chunk_name, "RIFF") != 0)
1363 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1369 /* read "RIFF" type id "WAVE" */
1370 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1371 if (strcmp(chunk_name, "WAVE") != 0)
1373 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1379 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1381 if (strcmp(chunk_name, "fmt ") == 0)
1383 /* read header information */
1384 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1385 sound_header_buffer[i] = fgetc(file);
1387 if (chunk_size > WAV_HEADER_SIZE)
1388 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1390 else if (strcmp(chunk_name, "data") == 0)
1392 snd_info->data_len = chunk_size;
1393 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1395 /* read sound data */
1396 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1399 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1401 free(snd_info->data_ptr);
1406 /* check for odd number of sample bytes (data chunk is word aligned) */
1407 if ((chunk_size % 2) == 1)
1408 ReadUnusedBytesFromFile(file, 1);
1410 else /* unknown chunk -- ignore */
1411 ReadUnusedBytesFromFile(file, chunk_size);
1416 if (snd_info->data_ptr == NULL)
1418 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1423 snd_info->format = AUDIO_FORMAT_U8;
1425 #endif /* PLATFORM_UNIX */
1427 snd_info->type = SND_TYPE_WAV;
1428 snd_info->source_filename = getStringCopy(filename);
1433 static void deleteSoundEntry(SoundInfo **snd_info)
1437 char *filename = (*snd_info)->source_filename;
1440 printf("[decrementing reference counter of sound '%s']\n", filename);
1443 if (--(*snd_info)->num_references <= 0)
1446 printf("[deleting sound '%s']\n", filename);
1450 FreeSound(*snd_info);
1452 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1459 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1463 /* check if the old and the new sound file are the same */
1464 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1466 /* The old and new sound are the same (have the same filename and path).
1467 This usually means that this sound does not exist in this sound set
1468 and a fallback to the existing sound is done. */
1471 printf("[sound '%s' already exists (same list entry)]\n", filename);
1477 /* delete existing sound file entry */
1478 deleteSoundEntry(snd_info);
1480 /* check if the new sound file already exists in the list of sounds */
1481 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1484 printf("[sound '%s' already exists (other list entry)]\n", filename);
1487 *snd_info = (SoundInfo *)node->content;
1488 (*snd_info)->num_references++;
1490 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1492 (*snd_info)->num_references = 1;
1493 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1497 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1499 char *filename = getCustomSoundFilename(basename);
1501 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1503 deleteSoundEntry(snd_info);
1507 if (filename == NULL)
1509 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1513 replaceSoundEntry(snd_info, filename);
1516 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1519 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1521 sound_effect = sounds_list;
1522 num_sounds = num_list_entries;
1525 void LoadSoundToList(char *basename, int list_pos)
1527 if (Sound == NULL || list_pos >= num_sounds)
1531 printf("loading sound '%s' ... [%d]\n",
1532 basename, getNumNodes(SoundFileList));
1535 LoadCustomSound(&Sound[list_pos], basename);
1538 printf("loading sound '%s' done [%d]\n",
1539 basename, getNumNodes(SoundFileList));
1543 static MusicInfo *Load_MOD(char *filename)
1545 #if defined(TARGET_SDL)
1546 MusicInfo *mod_info;
1548 if (!audio.sound_available)
1551 mod_info = checked_calloc(sizeof(MusicInfo));
1553 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1555 Error(ERR_WARN, "cannot read music file '%s'", filename);
1560 mod_info->type = MUS_TYPE_MOD;
1561 mod_info->source_filename = getStringCopy(filename);
1569 void LoadCustomMusic(void)
1571 char *music_directory = getCustomMusicDirectory();
1573 struct dirent *dir_entry;
1575 if (!audio.sound_available)
1578 if ((dir = opendir(music_directory)) == NULL)
1580 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1581 audio.music_available = FALSE;
1585 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1587 char *basename = dir_entry->d_name;
1588 char *filename = getPath2(music_directory, basename);
1589 MusicInfo *mus_info = NULL;
1591 if (FileIsSound(basename))
1592 mus_info = Load_WAV(filename);
1593 else if (FileIsMusic(basename))
1594 mus_info = Load_MOD(filename);
1601 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1602 Music[num_music -1] = mus_info;
1609 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1613 void PlayMusic(int nr)
1615 if (!audio.music_available)
1618 #if defined(TARGET_SDL)
1620 nr = nr % num_music;
1622 if (Music[nr]->type == MUS_TYPE_MOD)
1624 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1625 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1627 else /* play WAV music loop */
1629 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1630 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1640 void PlaySound(int nr)
1642 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1645 void PlaySoundStereo(int nr, int stereo)
1647 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1650 void PlaySoundLoop(int nr)
1652 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1655 void PlaySoundMusic(int nr)
1657 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1660 void PlaySoundExt(int nr, int volume, int stereo, int state)
1662 struct SoundControl snd_ctrl;
1664 if (!audio.sound_available ||
1665 !audio.sound_enabled ||
1666 audio.sound_deactivated)
1669 if (volume < PSND_MIN_VOLUME)
1670 volume = PSND_MIN_VOLUME;
1671 else if (volume > PSND_MAX_VOLUME)
1672 volume = PSND_MAX_VOLUME;
1674 if (stereo < PSND_MAX_LEFT)
1675 stereo = PSND_MAX_LEFT;
1676 else if (stereo > PSND_MAX_RIGHT)
1677 stereo = PSND_MAX_RIGHT;
1679 snd_ctrl.active = TRUE;
1681 snd_ctrl.volume = volume;
1682 snd_ctrl.stereo = stereo;
1683 snd_ctrl.state = state;
1685 #if defined(TARGET_SDL)
1688 Mix_Volume(-1, SOUND_MAX_VOLUME);
1689 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1691 #elif defined(PLATFORM_UNIX)
1692 if (audio.mixer_pid == 0) /* we are child process */
1695 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1697 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1698 audio.sound_available = audio.sound_enabled = FALSE;
1701 #elif defined(PLATFORM_MSDOS)
1702 sound_handler(snd_ctrl);
1706 void FadeMusic(void)
1708 if (!audio.sound_available)
1711 #if defined(TARGET_SDL)
1712 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1713 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1715 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1719 void FadeSound(int nr)
1721 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1727 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1730 void StopMusic(void)
1732 #if defined(TARGET_SDL)
1733 if (!audio.sound_available)
1737 Mix_HaltChannel(audio.music_channel);
1739 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1743 void StopSound(int nr)
1745 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1751 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1754 void StopSoundExt(int nr, int state)
1756 struct SoundControl snd_ctrl;
1758 if (!audio.sound_available)
1761 snd_ctrl.active = FALSE;
1763 snd_ctrl.state = state;
1765 #if defined(TARGET_SDL)
1767 if (state & SND_CTRL_FADE)
1772 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
1775 for (i=0; i<audio.channels; i++)
1776 if (i != audio.music_channel || snd_ctrl.music)
1777 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1778 if (state & SND_CTRL_MUSIC)
1779 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1785 for (i=0; i<audio.channels; i++)
1786 if (i != audio.music_channel || snd_ctrl.music)
1788 if (state & SND_CTRL_MUSIC)
1792 #elif !defined(PLATFORM_MSDOS)
1794 if (audio.mixer_pid == 0) /* we are child process */
1797 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1799 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1800 audio.sound_available = audio.sound_enabled = FALSE;
1803 #else /* PLATFORM_MSDOS */
1804 sound_handler(snd_ctrl);
1808 ListNode *newListNode()
1810 return checked_calloc(sizeof(ListNode));
1813 void addNodeToList(ListNode **node_first, char *key, void *content)
1815 ListNode *node_new = newListNode();
1818 printf("LIST: adding node with key '%s'\n", key);
1821 node_new->key = getStringCopy(key);
1822 node_new->content = content;
1823 node_new->next = *node_first;
1824 *node_first = node_new;
1827 void deleteNodeFromList(ListNode **node_first, char *key,
1828 void (*destructor_function)(void *))
1830 if (node_first == NULL || *node_first == NULL)
1834 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1835 (*node_first)->key, key);
1838 if (strcmp((*node_first)->key, key) == 0)
1841 printf("[DELETING LIST ENTRY]\n");
1844 free((*node_first)->key);
1845 if (destructor_function)
1846 destructor_function((*node_first)->content);
1847 *node_first = (*node_first)->next;
1850 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1853 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1855 if (node_first == NULL)
1858 if (strcmp(node_first->key, key) == 0)
1861 return getNodeFromKey(node_first->next, key);
1864 int getNumNodes(ListNode *node_first)
1866 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1869 void dumpList(ListNode *node_first)
1871 ListNode *node = node_first;
1875 printf("['%s' (%d)]\n", node->key,
1876 ((SoundInfo *)node->content)->num_references);
1880 printf("[%d nodes]\n", getNumNodes(node_first));
1883 static void LoadSoundsInfo()
1885 char *filename = getCustomSoundConfigFilename();
1886 struct SetupFileList *setup_file_list;
1889 /* always start with reliable default values */
1890 for (i=0; i<num_sounds; i++)
1891 sound_effect[i].filename = NULL;
1893 if (filename == NULL)
1896 if ((setup_file_list = loadSetupFileList(filename)))
1898 for (i=0; i<num_sounds; i++)
1899 sound_effect[i].filename =
1900 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1902 freeSetupFileList(setup_file_list);
1905 for (i=0; i<num_sounds; i++)
1907 printf("'%s' ", sound_effect[i].text);
1908 if (sound_effect[i].filename)
1909 printf("-> '%s'\n", sound_effect[i].filename);
1911 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1917 static void ReloadCustomSounds()
1922 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1928 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1931 for(i=0; i<num_sounds; i++)
1933 if (sound_effect[i].filename)
1934 LoadSoundToList(sound_effect[i].filename, i);
1936 LoadSoundToList(sound_effect[i].default_filename, i);
1940 printf("list size == %d\n", getNumNodes(SoundFileList));
1944 dumpList(SoundFileList);
1948 static void ReloadCustomMusic()
1951 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1959 void InitReloadSounds(char *set_name)
1961 if (!audio.sound_available)
1964 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1965 ReloadCustomSounds();
1966 #elif defined(PLATFORM_UNIX)
1967 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
1971 void InitReloadMusic(char *set_name)
1973 if (!audio.music_available)
1976 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1977 ReloadCustomMusic();
1978 #elif defined(PLATFORM_UNIX)
1979 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
1983 void FreeSound(void *ptr)
1985 SoundInfo *sound = (SoundInfo *)ptr;
1990 if (sound->data_ptr)
1992 #if defined(TARGET_SDL)
1993 Mix_FreeChunk(sound->data_ptr);
1994 #elif defined(TARGET_ALLEGRO)
1995 destroy_sample(sound->data_ptr);
1996 #else /* PLATFORM_UNIX */
1997 free(sound->data_ptr);
2001 if (sound->source_filename)
2002 free(sound->source_filename);
2007 void FreeMusic(MusicInfo *music)
2012 if (music->data_ptr)
2014 #if defined(TARGET_SDL)
2015 if (music->type == MUS_TYPE_MOD)
2016 Mix_FreeMusic(music->data_ptr);
2018 Mix_FreeChunk(music->data_ptr);
2019 #elif defined(TARGET_ALLEGRO)
2020 destroy_sample(music->data_ptr);
2021 #else /* PLATFORM_UNIX */
2022 free(music->data_ptr);
2029 void FreeAllSounds()
2036 printf("%s: FREEING SOUNDS ...\n",
2037 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
2039 for(i=0; i<num_sounds; i++)
2040 deleteSoundEntry(&Sound[i]);
2042 FreeSound(Sound[i]);
2045 printf("%s: FREEING SOUNDS -- DONE\n",
2046 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
2061 for(i=0; i<num_music; i++)
2062 FreeMusic(Music[i]);
2070 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2071 /* ========================================================================= */