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 =
54 TRUE, 0, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_FRAGMENT_SIZE
57 static int playing_sounds = 0;
58 static struct SoundControl playlist[NUM_MIXER_CHANNELS];
59 static struct SoundControl emptySoundControl =
62 FALSE, -1, 0, 0, FALSE, 0, 0, 0, NULL
64 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
68 /* forward declaration of internal functions */
69 static void SoundServer_InsertNewSound(struct SoundControl);
70 static void InitAudioDevice(struct AudioFormatInfo *);
72 #if defined(PLATFORM_UNIX)
73 #if !defined(AUDIO_STREAMING_DSP)
74 static unsigned char linear_to_ulaw(int);
75 static int ulaw_to_linear(unsigned char);
77 #elif defined(PLATFORM_MSDOS)
78 static void SoundServer_InsertNewSound(struct SoundControl);
79 static void SoundServer_StopSound(struct SoundControl);
80 static void SoundServer_StopAllSounds();
83 static void ReloadCustomSounds();
84 static void ReloadCustomMusic();
85 static void FreeSound(void *);
87 #if defined(PLATFORM_UNIX)
88 static int OpenAudioDevice(char *audio_device_name)
92 /* check if desired audio device is accessible */
93 if (access(audio_device_name, W_OK) != 0)
96 /* try to open audio device in non-blocking mode */
97 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
98 return audio_device_fd;
100 /* re-open audio device in blocking mode */
101 close(audio_device_fd);
102 audio_device_fd = open(audio_device_name, O_WRONLY);
104 return audio_device_fd;
107 static void CloseAudioDevice(int *audio_device_fd)
109 if (*audio_device_fd == 0)
112 close(*audio_device_fd);
113 *audio_device_fd = -1;
116 static boolean TestAudioDevices(void)
118 static char *audio_device_name[] =
123 int audio_device_fd = -1;
126 /* look for available audio devices, starting with preferred ones */
127 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
128 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
131 if (audio_device_fd < 0)
133 Error(ERR_WARN, "cannot open audio device -- no sound");
137 close(audio_device_fd);
139 audio.device_name = audio_device_name[i];
144 #if !defined(TARGET_SDL)
145 static boolean ForkAudioProcess(void)
147 if (pipe(audio.soundserver_pipe) < 0)
149 Error(ERR_WARN, "cannot create pipe -- no sounds");
153 if ((audio.soundserver_pid = fork()) < 0)
155 Error(ERR_WARN, "cannot create sound server process -- no sounds");
159 if (audio.soundserver_pid == 0) /* we are child process */
166 else /* we are parent */
167 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
173 void UnixOpenAudio(void)
175 if (!TestAudioDevices())
178 audio.sound_available = TRUE;
179 audio.sound_enabled = TRUE;
181 #if defined(AUDIO_STREAMING_DSP)
182 audio.music_available = TRUE;
183 audio.loops_available = TRUE;
187 void UnixCloseAudio(void)
190 close(audio.device_fd);
192 if (audio.soundserver_pid > 0) /* we are parent process */
193 kill(audio.soundserver_pid, SIGTERM);
195 #endif /* PLATFORM_UNIX */
197 void InitPlaylist(void)
201 for(i=0; i<NUM_MIXER_CHANNELS; i++)
202 playlist[i] = emptySoundControl;
207 static void PlaylistRemoveSound(int pos)
209 if (!playing_sounds || !playlist[pos].active)
212 playlist[pos] = emptySoundControl;
216 static void WriteReloadInfoToPipe(char *set_name, int type)
218 struct SoundControl snd_ctrl = emptySoundControl;
219 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
220 artwork.mus_current);
221 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
222 unsigned long str_size2 = strlen(ti->basepath) + 1;
223 unsigned long str_size3 = strlen(ti->fullpath) + 1;
225 snd_ctrl.state = type;
226 snd_ctrl.data_len = strlen(set_name) + 1;
228 if (write(audio.soundserver_pipe[1], &snd_ctrl,
229 sizeof(snd_ctrl)) < 0 ||
230 write(audio.soundserver_pipe[1], set_name,
231 snd_ctrl.data_len) < 0 ||
232 write(audio.soundserver_pipe[1], leveldir_current,
233 sizeof(TreeInfo)) < 0 ||
234 write(audio.soundserver_pipe[1], ti,
235 sizeof(TreeInfo)) < 0 ||
236 write(audio.soundserver_pipe[1], &str_size1,
237 sizeof(unsigned long)) < 0 ||
238 write(audio.soundserver_pipe[1], &str_size2,
239 sizeof(unsigned long)) < 0 ||
240 write(audio.soundserver_pipe[1], &str_size3,
241 sizeof(unsigned long)) < 0 ||
242 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
244 write(audio.soundserver_pipe[1], ti->basepath,
246 write(audio.soundserver_pipe[1], ti->fullpath,
249 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
250 audio.sound_available = audio.sound_enabled = FALSE;
255 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
257 TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
258 &artwork.snd_current : &artwork.mus_current);
259 TreeInfo *ti = *ti_ptr;
260 unsigned long str_size1, str_size2, str_size3;
261 static char *set_name = NULL;
266 set_name = checked_malloc(snd_ctrl.data_len);
268 if (leveldir_current == NULL)
269 leveldir_current = checked_calloc(sizeof(TreeInfo));
271 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
272 if (leveldir_current->fullpath != NULL)
273 free(leveldir_current->fullpath);
274 if (ti->basepath != NULL)
276 if (ti->fullpath != NULL)
279 if (read(audio.soundserver_pipe[0], set_name,
280 snd_ctrl.data_len) != snd_ctrl.data_len ||
281 read(audio.soundserver_pipe[0], leveldir_current,
282 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
283 read(audio.soundserver_pipe[0], ti,
284 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
285 read(audio.soundserver_pipe[0], &str_size1,
286 sizeof(unsigned long)) != sizeof(unsigned long) ||
287 read(audio.soundserver_pipe[0], &str_size2,
288 sizeof(unsigned long)) != sizeof(unsigned long) ||
289 read(audio.soundserver_pipe[0], &str_size3,
290 sizeof(unsigned long)) != sizeof(unsigned long))
291 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
293 leveldir_current->fullpath = checked_calloc(str_size1);
294 ti->basepath = checked_calloc(str_size2);
295 ti->fullpath = checked_calloc(str_size3);
297 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
298 str_size1) != str_size1 ||
299 read(audio.soundserver_pipe[0], ti->basepath,
300 str_size2) != str_size2 ||
301 read(audio.soundserver_pipe[0], ti->fullpath,
302 str_size3) != str_size3)
303 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
305 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
306 artwork.sounds_set_current = set_name;
308 artwork.music_set_current = set_name;
311 static void HandleSoundRequest(struct SoundControl snd_ctrl)
315 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
317 ReadReloadInfoFromPipe(snd_ctrl);
319 CloseAudioDevice(&audio.device_fd);
321 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
322 ReloadCustomSounds();
326 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
331 if (IS_MUSIC(snd_ctrl))
333 playlist[MUSIC_CHANNEL].state |= SND_CTRL_FADE;
337 for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
338 if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
339 playlist[i].state |= SND_CTRL_FADE;
341 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
346 if (IS_MUSIC(snd_ctrl))
348 PlaylistRemoveSound(MUSIC_CHANNEL);
352 for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
353 if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
354 PlaylistRemoveSound(i);
357 CloseAudioDevice(&audio.device_fd);
359 else if (snd_ctrl.active) /* add new sound to playlist */
361 SoundServer_InsertNewSound(snd_ctrl);
366 void StartSoundserver(void)
368 if (!audio.sound_available)
371 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
372 if (!ForkAudioProcess())
373 audio.sound_available = FALSE;
377 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
379 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
380 int sample_pos, int sample_size,
383 void *sample_ptr = snd_ctrl->data_ptr;
386 if (snd_ctrl->format == AUDIO_FORMAT_U8)
387 for (i=0; i<sample_size; i++)
389 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
390 else /* AUDIO_FORMAT_S16 */
391 for (i=0; i<sample_size; i++)
393 ((short *)sample_ptr)[sample_pos + i];
396 #if defined(AUDIO_STREAMING_DSP)
397 static void SoundServer_Mixer()
399 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
400 static boolean stereo_volume_calculated = FALSE;
401 static short premix_first_buffer[SND_BLOCKSIZE];
402 static short premix_left_buffer[SND_BLOCKSIZE];
403 static short premix_right_buffer[SND_BLOCKSIZE];
404 static long premix_last_buffer[SND_BLOCKSIZE];
405 static byte playing_buffer[SND_BLOCKSIZE];
407 int fragment_size = afmt.fragment_size;
408 int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
409 boolean stereo = afmt.stereo;
412 if (!stereo_volume_calculated)
414 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
416 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
418 stereo_volume_calculated = TRUE;
424 if (audio.device_fd < 0)
426 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
429 InitAudioDevice(&afmt);
432 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
434 /* first clear the last premixing buffer */
435 memset(premix_last_buffer, 0,
436 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
438 for(i=0; i<NUM_MIXER_CHANNELS; i++)
445 if (!playlist[i].active)
448 /* pointer, lenght and actual playing position of sound sample */
449 sample_ptr = playlist[i].data_ptr;
450 sample_len = playlist[i].data_len;
451 sample_pos = playlist[i].playingpos;
452 sample_size = MIN(max_sample_size, sample_len - sample_pos);
453 playlist[i].playingpos += sample_size;
455 /* copy original sample to first mixing buffer */
456 CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
457 premix_first_buffer);
459 /* are we about to restart a looping sound? */
460 if (IS_LOOP(playlist[i]) && sample_size < max_sample_size)
462 while (sample_size < max_sample_size)
464 int restarted_sample_size =
465 MIN(max_sample_size - sample_size, sample_len);
467 if (playlist[i].format == AUDIO_FORMAT_U8)
468 for (j=0; j<restarted_sample_size; j++)
469 premix_first_buffer[sample_size + j] =
470 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
472 for (j=0; j<restarted_sample_size; j++)
473 premix_first_buffer[sample_size + j] =
474 ((short *)sample_ptr)[j];
476 playlist[i].playingpos = restarted_sample_size;
477 sample_size += restarted_sample_size;
481 /* decrease volume if sound is fading out */
482 if (IS_FADING(playlist[i]) &&
483 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
484 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
486 /* adjust volume of actual sound sample */
487 if (playlist[i].volume != PSND_MAX_VOLUME)
488 for(j=0; j<sample_size; j++)
489 premix_first_buffer[j] =
490 (playlist[i].volume * (long)premix_first_buffer[j])
491 >> PSND_MAX_VOLUME_BITS;
493 /* fill the last mixing buffer with stereo or mono sound */
496 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
497 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
498 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
500 for(j=0; j<sample_size; j++)
502 premix_left_buffer[j] =
503 (left_volume * premix_first_buffer[j])
504 >> PSND_MAX_LEFT2RIGHT_BITS;
505 premix_right_buffer[j] =
506 (right_volume * premix_first_buffer[j])
507 >> PSND_MAX_LEFT2RIGHT_BITS;
509 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
510 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
515 for(j=0; j<sample_size; j++)
516 premix_last_buffer[j] += premix_first_buffer[j];
519 /* delete completed sound entries from the playlist */
520 if (playlist[i].playingpos >= playlist[i].data_len)
522 if (IS_LOOP(playlist[i]))
523 playlist[i].playingpos = 0;
525 PlaylistRemoveSound(i);
527 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
528 PlaylistRemoveSound(i);
531 /* prepare final playing buffer according to system audio format */
532 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
534 /* cut off at 17 bit value */
535 if (premix_last_buffer[i] < -65535)
536 premix_last_buffer[i] = -65535;
537 else if (premix_last_buffer[i] > 65535)
538 premix_last_buffer[i] = 65535;
540 /* shift to 16 bit value */
541 premix_last_buffer[i] >>= 1;
543 if (afmt.format & AUDIO_FORMAT_U8)
545 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
547 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
549 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
550 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
552 else /* big endian */
554 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
555 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
559 /* finally play the sound fragment */
560 write(audio.device_fd, playing_buffer, fragment_size);
563 CloseAudioDevice(&audio.device_fd);
566 #else /* !AUDIO_STREAMING_DSP */
568 static int SoundServer_SimpleAudio(struct SoundControl snd_ctrl)
570 static short premix_first_buffer[SND_BLOCKSIZE];
571 static byte playing_buffer[SND_BLOCKSIZE];
572 int max_sample_size = SND_BLOCKSIZE;
581 /* pointer, lenght and actual playing position of sound sample */
582 sample_ptr = playlist[i].data_ptr;
583 sample_len = playlist[i].data_len;
584 sample_pos = playlist[i].playingpos;
585 sample_size = MIN(max_sample_size, sample_len - sample_pos);
586 playlist[i].playingpos += sample_size;
588 /* copy original sample to first mixing buffer */
589 CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
590 premix_first_buffer);
592 /* adjust volume of actual sound sample */
593 if (playlist[i].volume != PSND_MAX_VOLUME)
594 for(j=0; j<sample_size; j++)
595 premix_first_buffer[j] =
596 (playlist[i].volume * (long)premix_first_buffer[j])
597 >> PSND_MAX_VOLUME_BITS;
599 /* might be needed for u-law /dev/audio */
601 for(j=0; j<sample_size; j++)
603 linear_to_ulaw(premix_first_buffer[j]);
606 /* delete completed sound entries from the playlist */
607 if (playlist[i].playingpos >= playlist[i].data_len)
608 PlaylistRemoveSound(i);
610 for(i=0; i<sample_size; i++)
611 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
613 /* finally play the sound fragment */
614 write(audio.device_fd, playing_buffer, sample_size);
618 #endif /* !AUDIO_STREAMING_DSP */
622 struct SoundControl snd_ctrl;
625 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
629 #if defined(PLATFORM_HPUX)
630 InitAudioDevice(&afmt);
633 FD_ZERO(&sound_fdset);
634 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
636 while(1) /* wait for sound playing commands from client */
638 struct timeval delay = { 0, 0 };
640 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
641 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
642 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
644 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
646 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
648 HandleSoundRequest(snd_ctrl);
650 #if defined(AUDIO_STREAMING_DSP)
652 while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
653 &sound_fdset, NULL, NULL, &delay) < 1)
655 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
660 #else /* !AUDIO_STREAMING_DSP */
662 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
663 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
666 InitAudioDevice(&afmt);
671 while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
672 &sound_fdset, NULL, NULL, &delay) < 1)
674 int wait_percent = 90; /* wait 90% of the real playing time */
677 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
679 sample_size = SoundServer_SimpleAudio(snd_ctrl);
683 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
686 CloseAudioDevice(&audio.device_fd);
688 /* delete all sounds from playlist */
691 #endif /* !AUDIO_STREAMING_DSP */
694 #endif /* PLATFORM_UNIX */
696 #if defined(PLATFORM_MSDOS)
697 static void sound_handler(struct SoundControl snd_ctrl)
701 if (snd_ctrl.fade_sound)
706 for (i=0; i<NUM_MIXER_CHANNELS; i++)
707 if ((snd_ctrl.stop_all_sounds ||
708 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
709 (i == audio.music_channel && snd_ctrl.music)) &&
710 !playlist[i].fade_sound)
712 playlist[i].fade_sound = TRUE;
713 if (voice_check(playlist[i].voice))
714 voice_ramp_volume(playlist[i].voice, 1000, 0);
715 playlist[i].state &= ~SND_CTRL_IS_LOOP;
718 else if (snd_ctrl.stop_all_sounds)
722 SoundServer_StopAllSounds();
724 else if (snd_ctrl.stop_sound)
728 SoundServer_StopSound(snd_ctrl);
731 for (i=0; i<NUM_MIXER_CHANNELS; i++)
733 if (!playlist[i].active || playlist[i].loop)
736 playlist[i].playingpos = voice_get_position(playlist[i].voice);
737 playlist[i].volume = voice_get_volume(playlist[i].voice);
738 if (playlist[i].playingpos == -1 || !playlist[i].volume)
740 deallocate_voice(playlist[i].voice);
741 playlist[i] = emptySoundControl;
747 SoundServer_InsertNewSound(snd_ctrl);
749 #endif /* PLATFORM_MSDOS */
752 #if defined(TARGET_SDL)
753 static void sound_handler_SDL(struct SoundControl snd_ctrl)
755 /* copy sound_handler() here ... */
757 #endif /* TARGET_SDL */
760 #if !defined(PLATFORM_WIN32)
761 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
767 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
770 if (IS_MUSIC(snd_ctrl))
771 snd_ctrl.nr = snd_ctrl.nr % num_music;
772 else if (snd_ctrl.nr >= num_sounds)
775 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
776 if (snd_info == NULL)
779 printf("sound/music %d undefined\n", snd_ctrl.nr);
785 printf("-> %d\n", playing_sounds);
788 if (playing_sounds == NUM_MIXER_CHANNELS)
790 for (i=0; i<NUM_MIXER_CHANNELS; i++)
792 if (playlist[i].data_ptr == NULL)
795 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
798 playlist[i] = emptySoundControl;
804 /* if playlist is full, remove oldest sound */
805 if (playing_sounds == NUM_MIXER_CHANNELS)
807 int longest = 0, longest_nr = 0;
809 for (i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
811 #if !defined(PLATFORM_MSDOS)
812 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
814 int actual = playlist[i].playingpos;
817 if (!IS_LOOP(playlist[i]) && actual > longest)
823 #if defined(PLATFORM_MSDOS)
824 voice_set_volume(playlist[longest_nr].voice, 0);
825 deallocate_voice(playlist[longest_nr].voice);
827 playlist[longest_nr] = emptySoundControl;
831 /* check if sound is already being played (and how often) */
832 for (k=0, i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
833 if (playlist[i].nr == snd_ctrl.nr)
836 /* restart loop sounds only if they are just fading out */
837 if (k >= 1 && IS_LOOP(snd_ctrl))
839 for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
841 if (playlist[i].nr == snd_ctrl.nr && IS_FADING(playlist[i]))
843 playlist[i].state &= ~SND_CTRL_FADE;
844 playlist[i].volume = PSND_MAX_VOLUME;
845 #if defined(PLATFORM_MSDOS)
846 playlist[i].state |= SND_CTRL_LOOP;
847 voice_stop_volumeramp(playlist[i].voice);
848 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
856 /* don't play sound more than n times simultaneously (with n == 2 for now) */
859 int longest = 0, longest_nr = 0;
861 /* look for oldest equal sound */
862 for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
866 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
869 #if !defined(PLATFORM_MSDOS)
870 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
872 actual = playlist[i].playingpos;
874 if (actual >= longest)
881 #if defined(PLATFORM_MSDOS)
882 voice_set_volume(playlist[longest_nr].voice, 0);
883 deallocate_voice(playlist[longest_nr].voice);
885 playlist[longest_nr] = emptySoundControl;
889 /* add new sound to playlist */
890 for(i=0; i<NUM_MIXER_CHANNELS; i++)
893 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
897 if (!playlist[i].active ||
898 (IS_MUSIC(snd_ctrl) && i == MUSIC_CHANNEL))
900 if ((i == MUSIC_CHANNEL && IS_MUSIC(snd_ctrl)) ||
901 (i != MUSIC_CHANNEL && !playlist[i].active))
903 snd_ctrl.data_ptr = snd_info->data_ptr;
904 snd_ctrl.data_len = snd_info->data_len;
905 snd_ctrl.format = snd_info->format;
908 if (snd_info->data_len == 0)
910 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
915 if (IS_MUSIC(snd_ctrl) && i == MUSIC_CHANNEL && playlist[i].active)
917 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
920 playlist[i] = emptySoundControl;
926 playlist[i] = snd_ctrl;
930 printf("NEW SOUND %d ADDED TO PLAYLIST\n", snd_ctrl.nr);
933 #if defined(PLATFORM_MSDOS)
934 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
937 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
939 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
940 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
941 voice_start(playlist[i].voice);
947 #endif /* !PLATFORM_WIN32 */
950 void SoundServer_FadeSound(int nr)
957 for(i=0;i<NUM_MIXER_CHANNELS;i++)
958 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
959 playlist[i].fade_sound = TRUE;
963 #if !defined(PLATFORM_WIN32)
964 #if defined(PLATFORM_MSDOS)
965 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
967 int nr = snd_ctrl.nr;
973 for(i=0; i<NUM_MIXER_CHANNELS; i++)
975 if ((i == audio.music_channel && snd_ctrl.music) ||
976 (i != audio.music_channel && playlist[i].nr == nr))
978 #if defined(PLATFORM_MSDOS)
979 voice_set_volume(playlist[i].voice, 0);
980 deallocate_voice(playlist[i].voice);
982 playlist[i] = emptySoundControl;
987 #if !defined(PLATFORM_MSDOS)
989 close(audio.device_fd);
993 static void SoundServer_StopAllSounds()
997 for(i=0; i<NUM_MIXER_CHANNELS; i++)
999 #if defined(PLATFORM_MSDOS)
1000 voice_set_volume(playlist[i].voice, 0);
1001 deallocate_voice(playlist[i].voice);
1003 playlist[i] = emptySoundControl;
1007 #if !defined(PLATFORM_MSDOS)
1008 close(audio.device_fd);
1011 #endif /* PLATFORM_MSDOS */
1012 #endif /* !PLATFORM_WIN32 */
1015 /* ------------------------------------------------------------------------- */
1016 /* platform dependant audio initialization code */
1017 /* ------------------------------------------------------------------------- */
1019 #if defined(AUDIO_LINUX_IOCTL)
1020 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1022 /* "ioctl()" expects pointer to 'int' value for stereo flag
1023 (boolean is defined as 'char', which will not work here) */
1024 unsigned int fragment_spec = 0;
1025 int fragment_size_query;
1034 /* supported audio format in preferred order */
1035 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1036 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1037 { AFMT_U8, AUDIO_FORMAT_U8 },
1042 /* determine logarithm (log2) of the fragment size */
1043 while ((1 << fragment_spec) < afmt->fragment_size)
1046 /* use two fragments (play one fragment, prepare the other);
1047 one fragment would result in interrupted audio output, more
1048 than two fragments would raise audio output latency to much */
1049 fragment_spec |= 0x00020000;
1051 /* Example for fragment specification:
1052 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1053 - (with stereo the effective buffer size will shrink to 256)
1054 => fragment_size = 0x00020009 */
1056 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1057 Error(ERR_EXIT_SOUND_SERVER,
1058 "cannot set fragment size of /dev/dsp -- no sounds");
1062 while (formats[i].format_result != -1)
1064 unsigned int audio_format = formats[i].format_ioctl;
1065 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1067 afmt->format = formats[i].format_result;
1072 if (afmt->format == 0) /* no supported audio format found */
1073 Error(ERR_EXIT_SOUND_SERVER,
1074 "cannot set audio format of /dev/dsp -- no sounds");
1076 /* try if we can use stereo sound */
1077 afmt->stereo = TRUE;
1078 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1079 afmt->stereo = FALSE;
1081 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1082 Error(ERR_EXIT_SOUND_SERVER,
1083 "cannot set sample rate of /dev/dsp -- no sounds");
1085 /* get the real fragmentation size; this should return 512 */
1086 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1087 Error(ERR_EXIT_SOUND_SERVER,
1088 "cannot get fragment size of /dev/dsp -- no sounds");
1089 if (fragment_size_query != afmt->fragment_size)
1090 Error(ERR_EXIT_SOUND_SERVER,
1091 "cannot set fragment size of /dev/dsp -- no sounds");
1093 #endif /* AUDIO_LINUX_IOCTL */
1095 #if defined(PLATFORM_NETBSD)
1096 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1098 audio_info_t a_info;
1099 boolean stereo = TRUE;
1101 AUDIO_INITINFO(&a_info);
1102 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1103 a_info.play.precision = 8;
1104 a_info.play.channels = 2;
1105 a_info.play.sample_rate = sample_rate;
1106 a_info.blocksize = fragment_size;
1108 afmt->format = AUDIO_FORMAT_U8;
1109 afmt->stereo = TRUE;
1111 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1113 /* try to disable stereo */
1114 a_info.play.channels = 1;
1116 afmt->stereo = FALSE;
1118 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1119 Error(ERR_EXIT_SOUND_SERVER,
1120 "cannot set sample rate of /dev/audio -- no sounds");
1123 #endif /* PLATFORM_NETBSD */
1125 #if defined(PLATFORM_HPUX)
1126 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1128 struct audio_describe ainfo;
1131 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1132 if (audio_ctl == -1)
1133 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1135 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1136 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1138 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1139 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1141 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1142 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1144 afmt->format = AUDIO_FORMAT_U8;
1145 afmt->stereo = FALSE;
1146 afmt->sample_rate = 8000;
1150 #endif /* PLATFORM_HPUX */
1152 #if defined(PLATFORM_UNIX)
1153 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1155 #if defined(AUDIO_LINUX_IOCTL)
1156 InitAudioDevice_Linux(afmt);
1157 #elif defined(PLATFORM_NETBSD)
1158 InitAudioDevice_NetBSD(afmt);
1159 #elif defined(PLATFORM_HPUX)
1160 InitAudioDevice_HPUX(afmt);
1162 /* generic /dev/audio stuff might be placed here */
1165 #endif /* PLATFORM_UNIX */
1167 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1169 /* these two are stolen from "sox"... :) */
1172 ** This routine converts from linear to ulaw.
1174 ** Craig Reese: IDA/Supercomputing Research Center
1175 ** Joe Campbell: Department of Defense
1176 ** 29 September 1989
1179 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1180 ** 2) "A New Digital Technique for Implementation of Any
1181 ** Continuous PCM Companding Law," Villeret, Michel,
1182 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1183 ** 1973, pg. 11.12-11.17
1184 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1185 ** for Analog-to_Digital Conversion Techniques,"
1188 ** Input: Signed 16 bit linear sample
1189 ** Output: 8 bit ulaw sample
1192 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1193 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1196 static unsigned char linear_to_ulaw(int sample)
1198 static int exp_lut[256] =
1200 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1201 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1202 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1203 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1204 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1205 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1206 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1207 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1208 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1209 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1210 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1211 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1212 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1213 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1214 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1215 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1218 int sign, exponent, mantissa;
1219 unsigned char ulawbyte;
1221 /* Get the sample into sign-magnitude. */
1222 sign = (sample >> 8) & 0x80; /* set aside the sign */
1224 sample = -sample; /* get magnitude */
1226 sample = CLIP; /* clip the magnitude */
1228 /* Convert from 16 bit linear to ulaw. */
1229 sample = sample + BIAS;
1230 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1231 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1232 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1235 ulawbyte = 0x02; /* optional CCITT trap */
1242 ** This routine converts from ulaw to 16 bit linear.
1244 ** Craig Reese: IDA/Supercomputing Research Center
1245 ** 29 September 1989
1248 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1249 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1250 ** for Analog-to_Digital Conversion Techniques,"
1253 ** Input: 8 bit ulaw sample
1254 ** Output: signed 16 bit linear sample
1257 static int ulaw_to_linear(unsigned char ulawbyte)
1259 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1260 int sign, exponent, mantissa, sample;
1262 ulawbyte = ~ ulawbyte;
1263 sign = ( ulawbyte & 0x80 );
1264 exponent = ( ulawbyte >> 4 ) & 0x07;
1265 mantissa = ulawbyte & 0x0F;
1266 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1272 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1275 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1276 /* ========================================================================= */
1277 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1279 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1280 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1282 static SoundInfo *Load_WAV(char *filename)
1284 SoundInfo *snd_info;
1285 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1286 byte sound_header_buffer[WAV_HEADER_SIZE];
1287 char chunk_name[CHUNK_ID_LEN + 1];
1293 if (!audio.sound_available)
1297 printf("loading WAV file '%s'\n", filename);
1300 snd_info = checked_calloc(sizeof(SoundInfo));
1302 #if defined(TARGET_SDL)
1304 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1306 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1311 #elif defined(TARGET_ALLEGRO)
1313 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1315 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1320 #else /* PLATFORM_UNIX */
1322 if ((file = fopen(filename, MODE_READ)) == NULL)
1324 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1329 /* read chunk id "RIFF" */
1330 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1331 if (strcmp(chunk_name, "RIFF") != 0)
1333 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1339 /* read "RIFF" type id "WAVE" */
1340 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1341 if (strcmp(chunk_name, "WAVE") != 0)
1343 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1349 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1351 if (strcmp(chunk_name, "fmt ") == 0)
1353 /* read header information */
1354 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1355 sound_header_buffer[i] = fgetc(file);
1357 if (chunk_size > WAV_HEADER_SIZE)
1358 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1360 else if (strcmp(chunk_name, "data") == 0)
1362 snd_info->data_len = chunk_size;
1363 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1365 /* read sound data */
1366 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1369 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1371 free(snd_info->data_ptr);
1376 /* check for odd number of sample bytes (data chunk is word aligned) */
1377 if ((chunk_size % 2) == 1)
1378 ReadUnusedBytesFromFile(file, 1);
1380 else /* unknown chunk -- ignore */
1381 ReadUnusedBytesFromFile(file, chunk_size);
1386 if (snd_info->data_ptr == NULL)
1388 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1393 snd_info->format = AUDIO_FORMAT_U8;
1395 #endif /* PLATFORM_UNIX */
1397 snd_info->type = SND_TYPE_WAV;
1398 snd_info->source_filename = getStringCopy(filename);
1403 static void deleteSoundEntry(SoundInfo **snd_info)
1407 char *filename = (*snd_info)->source_filename;
1410 printf("[decrementing reference counter of sound '%s']\n", filename);
1413 if (--(*snd_info)->num_references <= 0)
1416 printf("[deleting sound '%s']\n", filename);
1420 FreeSound(*snd_info);
1422 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1429 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1433 /* check if the old and the new sound file are the same */
1434 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1436 /* The old and new sound are the same (have the same filename and path).
1437 This usually means that this sound does not exist in this sound set
1438 and a fallback to the existing sound is done. */
1441 printf("[sound '%s' already exists (same list entry)]\n", filename);
1447 /* delete existing sound file entry */
1448 deleteSoundEntry(snd_info);
1450 /* check if the new sound file already exists in the list of sounds */
1451 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1454 printf("[sound '%s' already exists (other list entry)]\n", filename);
1457 *snd_info = (SoundInfo *)node->content;
1458 (*snd_info)->num_references++;
1460 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1462 (*snd_info)->num_references = 1;
1463 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1467 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1469 char *filename = getCustomSoundFilename(basename);
1471 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1473 deleteSoundEntry(snd_info);
1477 if (filename == NULL)
1479 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1483 replaceSoundEntry(snd_info, filename);
1486 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1489 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1491 sound_effect = sounds_list;
1492 num_sounds = num_list_entries;
1495 void LoadSoundToList(char *basename, int list_pos)
1497 if (Sound == NULL || list_pos >= num_sounds)
1501 printf("loading sound '%s' ... [%d]\n",
1502 basename, getNumNodes(SoundFileList));
1505 LoadCustomSound(&Sound[list_pos], basename);
1508 printf("loading sound '%s' done [%d]\n",
1509 basename, getNumNodes(SoundFileList));
1513 static MusicInfo *Load_MOD(char *filename)
1515 #if defined(TARGET_SDL)
1516 MusicInfo *mod_info;
1518 if (!audio.sound_available)
1521 mod_info = checked_calloc(sizeof(MusicInfo));
1523 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1525 Error(ERR_WARN, "cannot read music file '%s'", filename);
1530 mod_info->type = MUS_TYPE_MOD;
1531 mod_info->source_filename = getStringCopy(filename);
1539 void LoadCustomMusic(void)
1541 char *music_directory = getCustomMusicDirectory();
1543 struct dirent *dir_entry;
1545 if (!audio.sound_available)
1548 if ((dir = opendir(music_directory)) == NULL)
1550 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1551 audio.music_available = FALSE;
1555 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1557 char *basename = dir_entry->d_name;
1558 char *filename = getPath2(music_directory, basename);
1559 MusicInfo *mus_info = NULL;
1561 if (FileIsSound(basename))
1562 mus_info = Load_WAV(filename);
1563 else if (FileIsMusic(basename))
1564 mus_info = Load_MOD(filename);
1571 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1572 Music[num_music -1] = mus_info;
1579 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1583 void PlayMusic(int nr)
1585 if (!audio.music_available)
1588 #if defined(TARGET_SDL)
1590 nr = nr % num_music;
1592 if (Music[nr]->type == MUS_TYPE_MOD)
1594 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1595 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1597 else /* play WAV music loop */
1599 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1600 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1610 void PlaySound(int nr)
1612 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1615 void PlaySoundStereo(int nr, int stereo)
1617 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1620 void PlaySoundLoop(int nr)
1622 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1625 void PlaySoundMusic(int nr)
1627 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1630 void PlaySoundExt(int nr, int volume, int stereo, int state)
1632 struct SoundControl snd_ctrl = emptySoundControl;
1634 if (!audio.sound_available ||
1635 !audio.sound_enabled ||
1636 audio.sound_deactivated)
1639 if (volume < PSND_MIN_VOLUME)
1640 volume = PSND_MIN_VOLUME;
1641 else if (volume > PSND_MAX_VOLUME)
1642 volume = PSND_MAX_VOLUME;
1644 if (stereo < PSND_MAX_LEFT)
1645 stereo = PSND_MAX_LEFT;
1646 else if (stereo > PSND_MAX_RIGHT)
1647 stereo = PSND_MAX_RIGHT;
1649 snd_ctrl.active = TRUE;
1651 snd_ctrl.volume = volume;
1652 snd_ctrl.stereo = stereo;
1653 snd_ctrl.state = state;
1655 #if defined(TARGET_SDL)
1658 Mix_Volume(-1, SOUND_MAX_VOLUME);
1659 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1661 #elif defined(PLATFORM_UNIX)
1662 if (audio.soundserver_pid == 0) /* we are child process */
1665 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1667 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1668 audio.sound_available = audio.sound_enabled = FALSE;
1671 #elif defined(PLATFORM_MSDOS)
1672 sound_handler(snd_ctrl);
1676 void FadeMusic(void)
1678 if (!audio.sound_available)
1681 #if defined(TARGET_SDL)
1682 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1683 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1685 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1689 void FadeSound(int nr)
1691 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1697 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1700 void StopMusic(void)
1702 #if defined(TARGET_SDL)
1703 if (!audio.sound_available)
1707 Mix_HaltChannel(audio.music_channel);
1709 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1713 void StopSound(int nr)
1715 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1721 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1724 void StopSoundExt(int nr, int state)
1726 struct SoundControl snd_ctrl = emptySoundControl;
1728 if (!audio.sound_available)
1732 snd_ctrl.state = state;
1734 #if defined(TARGET_SDL)
1736 if (state & SND_CTRL_FADE)
1740 for (i=0; i<audio.channels; i++)
1741 if (i != audio.music_channel || snd_ctrl.music)
1742 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1743 if (state & SND_CTRL_MUSIC)
1744 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1750 for (i=0; i<audio.channels; i++)
1751 if (i != audio.music_channel || snd_ctrl.music)
1753 if (state & SND_CTRL_MUSIC)
1757 #elif !defined(PLATFORM_MSDOS)
1759 if (audio.soundserver_pid == 0) /* we are child process */
1762 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1764 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1765 audio.sound_available = audio.sound_enabled = FALSE;
1768 #else /* PLATFORM_MSDOS */
1769 sound_handler(snd_ctrl);
1773 ListNode *newListNode()
1775 return checked_calloc(sizeof(ListNode));
1778 void addNodeToList(ListNode **node_first, char *key, void *content)
1780 ListNode *node_new = newListNode();
1783 printf("LIST: adding node with key '%s'\n", key);
1786 node_new->key = getStringCopy(key);
1787 node_new->content = content;
1788 node_new->next = *node_first;
1789 *node_first = node_new;
1792 void deleteNodeFromList(ListNode **node_first, char *key,
1793 void (*destructor_function)(void *))
1795 if (node_first == NULL || *node_first == NULL)
1799 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1800 (*node_first)->key, key);
1803 if (strcmp((*node_first)->key, key) == 0)
1806 printf("[DELETING LIST ENTRY]\n");
1809 free((*node_first)->key);
1810 if (destructor_function)
1811 destructor_function((*node_first)->content);
1812 *node_first = (*node_first)->next;
1815 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1818 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1820 if (node_first == NULL)
1823 if (strcmp(node_first->key, key) == 0)
1826 return getNodeFromKey(node_first->next, key);
1829 int getNumNodes(ListNode *node_first)
1831 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1834 void dumpList(ListNode *node_first)
1836 ListNode *node = node_first;
1840 printf("['%s' (%d)]\n", node->key,
1841 ((SoundInfo *)node->content)->num_references);
1845 printf("[%d nodes]\n", getNumNodes(node_first));
1848 static void LoadSoundsInfo()
1850 char *filename = getCustomSoundConfigFilename();
1851 struct SetupFileList *setup_file_list;
1854 /* always start with reliable default values */
1855 for (i=0; i<num_sounds; i++)
1856 sound_effect[i].filename = NULL;
1858 if (filename == NULL)
1861 if ((setup_file_list = loadSetupFileList(filename)))
1863 for (i=0; i<num_sounds; i++)
1864 sound_effect[i].filename =
1865 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1867 freeSetupFileList(setup_file_list);
1870 for (i=0; i<num_sounds; i++)
1872 printf("'%s' ", sound_effect[i].text);
1873 if (sound_effect[i].filename)
1874 printf("-> '%s'\n", sound_effect[i].filename);
1876 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1882 static void ReloadCustomSounds()
1887 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1893 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1896 for(i=0; i<num_sounds; i++)
1898 if (sound_effect[i].filename)
1899 LoadSoundToList(sound_effect[i].filename, i);
1901 LoadSoundToList(sound_effect[i].default_filename, i);
1905 printf("list size == %d\n", getNumNodes(SoundFileList));
1909 dumpList(SoundFileList);
1913 static void ReloadCustomMusic()
1916 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1924 static void InitReloadSoundsOrMusic(char *set_name, int type)
1927 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1928 struct SoundControl snd_ctrl = emptySoundControl;
1929 TreeInfo *ti = (state == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
1930 artwork.mus_current);
1931 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1932 unsigned long str_size2 = strlen(ti->basepath) + 1;
1933 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1937 if (!audio.sound_available)
1940 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1941 if (type == SND_CTRL_RELOAD_SOUNDS)
1942 ReloadCustomSounds();
1944 ReloadCustomMusic();
1945 #elif defined(PLATFORM_UNIX)
1946 if (audio.soundserver_pid == 0) /* we are child process */
1949 if (leveldir_current == NULL) /* should never happen */
1950 Error(ERR_EXIT, "leveldir_current == NULL");
1953 WriteReloadInfoToPipe(set_name, type);
1956 snd_ctrl.state = type;
1957 snd_ctrl.data_len = strlen(set_name) + 1;
1959 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1960 sizeof(snd_ctrl)) < 0 ||
1961 write(audio.soundserver_pipe[1], set_name,
1962 snd_ctrl.data_len) < 0 ||
1963 write(audio.soundserver_pipe[1], leveldir_current,
1964 sizeof(TreeInfo)) < 0 ||
1965 write(audio.soundserver_pipe[1], ti,
1966 sizeof(TreeInfo)) < 0 ||
1967 write(audio.soundserver_pipe[1], &str_size1,
1968 sizeof(unsigned long)) < 0 ||
1969 write(audio.soundserver_pipe[1], &str_size2,
1970 sizeof(unsigned long)) < 0 ||
1971 write(audio.soundserver_pipe[1], &str_size3,
1972 sizeof(unsigned long)) < 0 ||
1973 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1975 write(audio.soundserver_pipe[1], ti->basepath,
1977 write(audio.soundserver_pipe[1], ti->fullpath,
1980 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1981 audio.sound_available = audio.sound_enabled = FALSE;
1989 void InitReloadSounds(char *set_name)
1991 InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_SOUNDS);
1994 void InitReloadMusic(char *set_name)
1996 InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_MUSIC);
1999 void FreeSound(void *ptr)
2001 SoundInfo *sound = (SoundInfo *)ptr;
2006 if (sound->data_ptr)
2008 #if defined(TARGET_SDL)
2009 Mix_FreeChunk(sound->data_ptr);
2010 #elif defined(TARGET_ALLEGRO)
2011 destroy_sample(sound->data_ptr);
2012 #else /* PLATFORM_UNIX */
2013 free(sound->data_ptr);
2017 if (sound->source_filename)
2018 free(sound->source_filename);
2023 void FreeMusic(MusicInfo *music)
2028 if (music->data_ptr)
2030 #if defined(TARGET_SDL)
2031 if (music->type == MUS_TYPE_MOD)
2032 Mix_FreeMusic(music->data_ptr);
2034 Mix_FreeChunk(music->data_ptr);
2035 #elif defined(TARGET_ALLEGRO)
2036 destroy_sample(music->data_ptr);
2037 #else /* PLATFORM_UNIX */
2038 free(music->data_ptr);
2045 void FreeAllSounds()
2052 printf("%s: FREEING SOUNDS ...\n",
2053 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2055 for(i=0; i<num_sounds; i++)
2056 deleteSoundEntry(&Sound[i]);
2058 FreeSound(Sound[i]);
2061 printf("%s: FREEING SOUNDS -- DONE\n",
2062 audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2077 for(i=0; i<num_music; i++)
2078 FreeMusic(Music[i]);
2086 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2087 /* ========================================================================= */