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 ***********************************************************/
27 static SoundInfo **Sound = NULL;
28 static MusicInfo **Music = NULL;
29 static int num_sounds = 0, num_music = 0;
32 /* ========================================================================= */
33 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
35 static struct AudioFormatInfo afmt =
37 TRUE, 0, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_FRAGMENT_SIZE
40 static int playing_sounds = 0;
41 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
42 static struct SoundControl emptySoundControl =
44 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
47 #if defined(PLATFORM_UNIX)
48 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
49 static short premix_first_buffer[SND_BLOCKSIZE];
50 #if defined(AUDIO_STREAMING_DSP)
51 static short premix_left_buffer[SND_BLOCKSIZE];
52 static short premix_right_buffer[SND_BLOCKSIZE];
53 static long premix_last_buffer[SND_BLOCKSIZE];
55 static byte playing_buffer[SND_BLOCKSIZE];
58 /* forward declaration of internal functions */
59 #if defined(AUDIO_STREAMING_DSP)
60 static void SoundServer_InsertNewSound(struct SoundControl);
61 static void InitAudioDevice_DSP(struct AudioFormatInfo *);
62 #elif defined(PLATFORM_HPUX)
63 static void InitAudioDevice_HPUX(struct AudioFormatInfo *);
64 #elif defined(PLATFORM_UNIX)
65 static unsigned char linear_to_ulaw(int);
66 static int ulaw_to_linear(unsigned char);
67 #elif defined(PLATFORM_MSDOS)
68 static void SoundServer_InsertNewSound(struct SoundControl);
69 static void SoundServer_StopSound(struct SoundControl);
70 static void SoundServer_StopAllSounds();
73 #if defined(PLATFORM_UNIX)
74 static int OpenAudioDevice(char *audio_device_name)
78 /* check if desired audio device is accessible */
79 if (access(audio_device_name, W_OK) != 0)
82 /* try to open audio device in non-blocking mode */
83 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
86 /* re-open audio device in blocking mode */
88 audio_fd = open(audio_device_name, O_WRONLY);
93 static boolean TestAudioDevices(void)
95 static char *audio_device_name[] =
103 /* look for available audio devices, starting with preferred ones */
104 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
105 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
110 Error(ERR_WARN, "cannot open audio device -- no sound");
116 audio.device_name = audio_device_name[i];
121 #if !defined(TARGET_SDL)
122 static boolean ForkAudioProcess(void)
124 if (pipe(audio.soundserver_pipe) < 0)
126 Error(ERR_WARN, "cannot create pipe -- no sounds");
130 if ((audio.soundserver_pid = fork()) < 0)
132 Error(ERR_WARN, "cannot create sound server process -- no sounds");
136 if (audio.soundserver_pid == 0) /* we are child process */
143 else /* we are parent */
144 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
150 void UnixOpenAudio(void)
152 if (!TestAudioDevices())
155 audio.sound_available = TRUE;
156 audio.sound_enabled = TRUE;
158 #if defined(AUDIO_STREAMING_DSP)
159 audio.music_available = TRUE;
160 audio.loops_available = TRUE;
164 void UnixCloseAudio(void)
167 close(audio.device_fd);
169 if (audio.soundserver_pid > 0) /* we are parent process */
170 kill(audio.soundserver_pid, SIGTERM);
172 #endif /* PLATFORM_UNIX */
174 void InitPlaylist(void)
178 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
179 playlist[i] = emptySoundControl;
183 void StartSoundserver(void)
185 if (!audio.sound_available)
188 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
189 if (!ForkAudioProcess())
190 audio.sound_available = FALSE;
194 #if defined(PLATFORM_UNIX)
195 void SoundServer(void)
199 struct SoundControl snd_ctrl;
202 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
206 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
207 for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
209 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
211 #if defined(PLATFORM_HPUX)
212 InitAudioDevice_HPUX(&afmt);
215 FD_ZERO(&sound_fdset);
216 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
218 while(1) /* wait for sound playing commands from client */
220 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
221 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
222 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
224 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
226 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
228 if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
230 char *set_name = checked_malloc(snd_ctrl.data_len);
232 (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
233 TreeInfo *ti = *ti_ptr;
234 unsigned long str_size1, str_size2, str_size3;
236 if (leveldir_current == NULL)
237 leveldir_current = checked_calloc(sizeof(TreeInfo));
239 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
240 if (leveldir_current->fullpath != NULL)
241 free(leveldir_current->fullpath);
242 if (ti->basepath != NULL)
244 if (ti->fullpath != NULL)
247 if (read(audio.soundserver_pipe[0], set_name,
248 snd_ctrl.data_len) != snd_ctrl.data_len ||
249 read(audio.soundserver_pipe[0], leveldir_current,
250 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
251 read(audio.soundserver_pipe[0], ti,
252 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
253 read(audio.soundserver_pipe[0], &str_size1,
254 sizeof(unsigned long)) != sizeof(unsigned long) ||
255 read(audio.soundserver_pipe[0], &str_size2,
256 sizeof(unsigned long)) != sizeof(unsigned long) ||
257 read(audio.soundserver_pipe[0], &str_size3,
258 sizeof(unsigned long)) != sizeof(unsigned long))
259 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
261 leveldir_current->fullpath = checked_calloc(str_size1);
262 ti->basepath = checked_calloc(str_size2);
263 ti->fullpath = checked_calloc(str_size3);
265 if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
266 str_size1) != str_size1 ||
267 read(audio.soundserver_pipe[0], ti->basepath,
268 str_size2) != str_size2 ||
269 read(audio.soundserver_pipe[0], ti->fullpath,
270 str_size3) != str_size3)
271 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
275 close(audio.device_fd);
277 if (snd_ctrl.reload_sounds)
279 artwork.sounds_set_current = set_name;
280 audio.func_reload_sounds();
284 artwork.music_set_current = set_name;
285 audio.func_reload_music();
293 #if defined(AUDIO_STREAMING_DSP)
295 if (snd_ctrl.fade_sound)
301 playlist[audio.music_channel].fade_sound = TRUE;
303 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
304 if (snd_ctrl.stop_all_sounds ||
305 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
306 playlist[i].fade_sound = TRUE;
308 else if (snd_ctrl.stop_all_sounds)
313 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
314 playlist[i] = emptySoundControl;
317 close(audio.device_fd);
319 else if (snd_ctrl.stop_sound)
326 playlist[audio.music_channel] = emptySoundControl;
330 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
332 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
334 playlist[i] = emptySoundControl;
340 close(audio.device_fd);
343 if (playing_sounds || snd_ctrl.active)
345 if (playing_sounds ||
346 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
348 struct timeval delay = { 0, 0 };
350 if (!playing_sounds) /* we just opened the audio device */
351 InitAudioDevice_DSP(&afmt);
353 if (snd_ctrl.active) /* new sound has arrived */
354 SoundServer_InsertNewSound(snd_ctrl);
356 while (playing_sounds &&
357 select(audio.soundserver_pipe[0] + 1,
358 &sound_fdset, NULL, NULL, &delay) < 1)
363 int fragment_size = afmt.fragment_size;
364 int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
365 boolean stereo = afmt.stereo;
367 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
369 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
371 /* first clear the last premixing buffer */
372 memset(premix_last_buffer, 0,
373 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
375 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
379 if (!playlist[i].active)
382 /* get pointer and size of the actual sound sample */
383 if (playlist[i].format == AUDIO_FORMAT_U8)
385 (byte *)playlist[i].data_ptr + playlist[i].playingpos;
388 (short *)playlist[i].data_ptr + playlist[i].playingpos;
390 sample_size = MIN(max_sample_size,
391 playlist[i].data_len - playlist[i].playingpos);
392 playlist[i].playingpos += sample_size;
394 /* fill the first mixing buffer with original sample */
396 if (playlist[i].format == AUDIO_FORMAT_U8)
397 for (j=0; j<sample_size; j++)
398 premix_first_buffer[j] =
399 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
401 for (j=0; j<sample_size; j++)
402 premix_first_buffer[j] = ((short *)sample_ptr)[j];
404 memcpy(premix_first_buffer, sample_ptr,
405 sample_size * (playlist[i].format == AUDIO_FORMAT_U8 ?
406 sizeof(byte) : sizeof(short)));
409 /* are we about to restart a looping sound? */
410 if (playlist[i].loop && sample_size < max_sample_size)
413 while (sample_size < max_sample_size)
415 int restarted_sample_size =
416 MIN(max_sample_size - sample_size, playlist[i].data_len);
418 if (playlist[i].format == AUDIO_FORMAT_U8)
419 for (j=0; j<restarted_sample_size; j++)
420 premix_first_buffer[sample_size + j] =
421 ((short)(((byte *)playlist[i].data_ptr)[j] ^ 0x80)) << 8;
423 for (j=0; j<restarted_sample_size; j++)
424 premix_first_buffer[sample_size + j] =
425 ((short *)playlist[i].data_ptr)[j];
427 playlist[i].playingpos = restarted_sample_size;
428 sample_size += restarted_sample_size;
431 playlist[i].playingpos = max_sample_size - sample_size;
432 memcpy(premix_first_buffer + sample_size * sizeof(short),
433 playlist[i].data_ptr,
434 (max_sample_size - sample_size) * sizeof(short));
435 sample_size = max_sample_size;
439 /* decrease volume if sound is fading out */
440 if (playlist[i].fade_sound &&
441 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
442 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
444 /* adjust volume of actual sound sample */
445 if (playlist[i].volume != PSND_MAX_VOLUME)
446 for(j=0; j<sample_size; j++)
447 premix_first_buffer[j] =
448 (playlist[i].volume * (long)premix_first_buffer[j])
449 >> PSND_MAX_VOLUME_BITS;
451 /* fill the last mixing buffer with stereo or mono sound */
454 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
455 int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
456 int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
458 for(j=0; j<sample_size; j++)
460 premix_left_buffer[j] =
461 (left_volume * premix_first_buffer[j])
462 >> PSND_MAX_LEFT2RIGHT_BITS;
463 premix_right_buffer[j] =
464 (right_volume * premix_first_buffer[j])
465 >> PSND_MAX_LEFT2RIGHT_BITS;
467 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
468 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
473 for(j=0; j<sample_size; j++)
474 premix_last_buffer[j] += premix_first_buffer[j];
477 /* delete completed sound entries from the playlist */
478 if (playlist[i].playingpos >= playlist[i].data_len)
480 if (playlist[i].loop)
481 playlist[i].playingpos = 0;
484 playlist[i] = emptySoundControl;
488 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
490 playlist[i] = emptySoundControl;
495 /* prepare final playing buffer according to system audio format */
496 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
498 /* cut off at 17 bit value */
499 if (premix_last_buffer[i] < -65535)
500 premix_last_buffer[i] = -65535;
501 else if (premix_last_buffer[i] > 65535)
502 premix_last_buffer[i] = 65535;
504 /* shift to 16 bit value */
505 premix_last_buffer[i] >>= 1;
507 if (afmt.format & AUDIO_FORMAT_U8)
509 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
511 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
513 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
514 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
516 else /* big endian */
518 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
519 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
523 /* finally play the sound fragment */
524 write(audio.device_fd, playing_buffer, fragment_size);
527 /* if no sounds playing, free device for other sound programs */
529 close(audio.device_fd);
533 #else /* !AUDIO_STREAMING_DSP */
535 if (snd_ctrl.active && !snd_ctrl.loop)
537 struct timeval delay = { 0, 0 };
539 long sample_size, max_sample_size = SND_BLOCKSIZE;
540 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
541 int wait_percent = 90; /* wait 90% of the real playing time */
544 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
548 while (playing_sounds &&
549 select(audio.soundserver_pipe[0] + 1,
550 &sound_fdset, NULL, NULL, &delay) < 1)
552 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
554 /* get pointer and size of the actual sound sample */
555 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
557 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
558 snd_ctrl.playingpos += sample_size;
560 /* fill the first mixing buffer with original sample */
561 memcpy(premix_first_buffer,sample_ptr,sample_size);
563 /* adjust volume of actual sound sample */
564 if (snd_ctrl.volume != PSND_MAX_VOLUME)
565 for(i=0;i<sample_size;i++)
566 premix_first_buffer[i] =
567 (snd_ctrl.volume * (int)premix_first_buffer[i])
568 >> PSND_MAX_VOLUME_BITS;
570 for(i=0;i<sample_size;i++)
572 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
574 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
577 /* finally play the sound fragment */
578 write(audio.device_fd,playing_buffer,sample_size);
581 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
583 close(audio.device_fd);
586 #endif /* !AUDIO_STREAMING_DSP */
589 #endif /* PLATFORM_UNIX */
591 #if defined(PLATFORM_MSDOS)
592 static void sound_handler(struct SoundControl snd_ctrl)
596 if (snd_ctrl.fade_sound)
601 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
602 if ((snd_ctrl.stop_all_sounds ||
603 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
604 (i == audio.music_channel && snd_ctrl.music)) &&
605 !playlist[i].fade_sound)
607 playlist[i].fade_sound = TRUE;
608 if (voice_check(playlist[i].voice))
609 voice_ramp_volume(playlist[i].voice, 1000, 0);
610 playlist[i].loop = PSND_NO_LOOP;
613 else if (snd_ctrl.stop_all_sounds)
617 SoundServer_StopAllSounds();
619 else if (snd_ctrl.stop_sound)
623 SoundServer_StopSound(snd_ctrl);
626 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
628 if (!playlist[i].active || playlist[i].loop)
631 playlist[i].playingpos = voice_get_position(playlist[i].voice);
632 playlist[i].volume = voice_get_volume(playlist[i].voice);
633 if (playlist[i].playingpos == -1 || !playlist[i].volume)
635 deallocate_voice(playlist[i].voice);
636 playlist[i] = emptySoundControl;
642 SoundServer_InsertNewSound(snd_ctrl);
644 #endif /* PLATFORM_MSDOS */
646 #if !defined(PLATFORM_WIN32)
647 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
652 snd_ctrl.nr = snd_ctrl.nr % num_music;
654 /* if playlist is full, remove oldest sound */
655 if (playing_sounds == MAX_SOUNDS_PLAYING)
657 int longest = 0, longest_nr = 0;
659 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
661 #if !defined(PLATFORM_MSDOS)
662 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
664 int actual = playlist[i].playingpos;
667 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
673 #if defined(PLATFORM_MSDOS)
674 voice_set_volume(playlist[longest_nr].voice, 0);
675 deallocate_voice(playlist[longest_nr].voice);
677 playlist[longest_nr] = emptySoundControl;
681 /* check if sound is already being played (and how often) */
682 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
683 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
686 /* restart loop sounds only if they are just fading out */
687 if (k >= 1 && snd_ctrl.loop)
689 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
691 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
692 playlist[i].fade_sound)
694 playlist[i].fade_sound = FALSE;
695 playlist[i].volume = PSND_MAX_VOLUME;
696 #if defined(PLATFORM_MSDOS)
697 playlist[i].loop = PSND_LOOP;
698 voice_stop_volumeramp(playlist[i].voice);
699 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
707 /* don't play sound more than n times simultaneously (with n == 2 for now) */
710 int longest = 0, longest_nr = 0;
712 /* look for oldest equal sound */
713 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
717 if (!playlist[i].active ||
718 i == audio.music_channel ||
719 playlist[i].nr != snd_ctrl.nr)
722 #if !defined(PLATFORM_MSDOS)
723 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
725 actual = playlist[i].playingpos;
727 if (actual >= longest)
734 #if defined(PLATFORM_MSDOS)
735 voice_set_volume(playlist[longest_nr].voice, 0);
736 deallocate_voice(playlist[longest_nr].voice);
738 playlist[longest_nr] = emptySoundControl;
742 /* add new sound to playlist */
743 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
745 if (!playlist[i].active ||
746 (snd_ctrl.music && i == audio.music_channel))
748 SoundInfo *snd_info =
749 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
751 snd_ctrl.data_ptr = snd_info->data_ptr;
752 snd_ctrl.data_len = snd_info->data_len;
753 snd_ctrl.format = snd_info->format;
755 playlist[i] = snd_ctrl;
758 #if defined(PLATFORM_MSDOS)
759 playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
762 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
764 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
765 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
766 voice_start(playlist[i].voice);
772 #endif /* !PLATFORM_WIN32 */
775 void SoundServer_FadeSound(int nr)
782 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
783 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
784 playlist[i].fade_sound = TRUE;
788 #if !defined(PLATFORM_WIN32)
789 #if defined(PLATFORM_MSDOS)
790 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
792 int nr = snd_ctrl.nr;
798 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
800 if ((i == audio.music_channel && snd_ctrl.music) ||
801 (i != audio.music_channel && playlist[i].nr == nr))
803 #if defined(PLATFORM_MSDOS)
804 voice_set_volume(playlist[i].voice, 0);
805 deallocate_voice(playlist[i].voice);
807 playlist[i] = emptySoundControl;
812 #if !defined(PLATFORM_MSDOS)
814 close(audio.device_fd);
818 static void SoundServer_StopAllSounds()
822 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
824 #if defined(PLATFORM_MSDOS)
825 voice_set_volume(playlist[i].voice, 0);
826 deallocate_voice(playlist[i].voice);
828 playlist[i]=emptySoundControl;
832 #if !defined(PLATFORM_MSDOS)
833 close(audio.device_fd);
836 #endif /* PLATFORM_MSDOS */
837 #endif /* !PLATFORM_WIN32 */
840 /* ------------------------------------------------------------------------- */
841 /* platform dependant audio initialization code */
842 /* ------------------------------------------------------------------------- */
844 #if defined(AUDIO_LINUX_IOCTL)
845 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
847 /* "ioctl()" expects pointer to 'int' value for stereo flag
848 (boolean is defined as 'char', which will not work here) */
849 unsigned int fragment_spec = 0;
850 int fragment_size_query;
859 /* supported audio format in preferred order */
860 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
861 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
862 { AFMT_U8, AUDIO_FORMAT_U8 },
867 /* determine logarithm (log2) of the fragment size */
868 while ((1 << fragment_spec) < afmt->fragment_size)
871 /* use two fragments (play one fragment, prepare the other);
872 one fragment would result in interrupted audio output, more
873 than two fragments would raise audio output latency to much */
874 fragment_spec |= 0x00020000;
876 /* Example for fragment specification:
877 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
878 - (with stereo the effective buffer size will shrink to 256)
879 => fragment_size = 0x00020009 */
881 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
882 Error(ERR_EXIT_SOUND_SERVER,
883 "cannot set fragment size of /dev/dsp -- no sounds");
887 while (formats[i].format_result != -1)
889 unsigned int audio_format = formats[i].format_ioctl;
890 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
892 afmt->format = formats[i].format_result;
897 if (afmt->format == 0) /* no supported audio format found */
898 Error(ERR_EXIT_SOUND_SERVER,
899 "cannot set audio format of /dev/dsp -- no sounds");
901 /* try if we can use stereo sound */
903 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
904 afmt->stereo = FALSE;
906 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
907 Error(ERR_EXIT_SOUND_SERVER,
908 "cannot set sample rate of /dev/dsp -- no sounds");
910 /* get the real fragmentation size; this should return 512 */
911 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
912 Error(ERR_EXIT_SOUND_SERVER,
913 "cannot get fragment size of /dev/dsp -- no sounds");
914 if (fragment_size_query != afmt->fragment_size)
915 Error(ERR_EXIT_SOUND_SERVER,
916 "cannot set fragment size of /dev/dsp -- no sounds");
918 #endif /* AUDIO_LINUX_IOCTL */
920 #if defined(PLATFORM_NETBSD)
921 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
924 boolean stereo = TRUE;
926 AUDIO_INITINFO(&a_info);
927 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
928 a_info.play.precision = 8;
929 a_info.play.channels = 2;
930 a_info.play.sample_rate = sample_rate;
931 a_info.blocksize = fragment_size;
933 afmt->format = AUDIO_FORMAT_U8;
936 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
938 /* try to disable stereo */
939 a_info.play.channels = 1;
941 afmt->stereo = FALSE;
943 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
944 Error(ERR_EXIT_SOUND_SERVER,
945 "cannot set sample rate of /dev/audio -- no sounds");
948 #endif /* PLATFORM_NETBSD */
950 #if defined(PLATFORM_HPUX)
951 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
953 struct audio_describe ainfo;
956 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
958 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
960 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
961 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
963 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
964 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
966 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
967 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
969 afmt->format = AUDIO_FORMAT_U8;
970 afmt->stereo = FALSE;
971 afmt->sample_rate = 8000;
975 #endif /* PLATFORM_HPUX */
977 #if defined(PLATFORM_UNIX)
978 static void InitAudioDevice_DSP(struct AudioFormatInfo *afmt)
980 #if defined(AUDIO_LINUX_IOCTL)
981 InitAudioDevice_Linux(afmt);
982 #elif defined(PLATFORM_NETBSD)
983 InitAudioDevice_NetBSD(afmt);
984 #elif defined(PLATFORM_HPUX)
985 InitAudioDevice_HPUX(afmt);
988 #endif /* PLATFORM_UNIX */
990 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
992 /* these two are stolen from "sox"... :) */
995 ** This routine converts from linear to ulaw.
997 ** Craig Reese: IDA/Supercomputing Research Center
998 ** Joe Campbell: Department of Defense
1002 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1003 ** 2) "A New Digital Technique for Implementation of Any
1004 ** Continuous PCM Companding Law," Villeret, Michel,
1005 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1006 ** 1973, pg. 11.12-11.17
1007 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1008 ** for Analog-to_Digital Conversion Techniques,"
1011 ** Input: Signed 16 bit linear sample
1012 ** Output: 8 bit ulaw sample
1015 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1016 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1019 static unsigned char linear_to_ulaw(int sample)
1021 static int exp_lut[256] =
1023 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1024 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1025 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1026 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1027 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1028 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1029 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1030 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1031 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1032 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1033 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1034 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1035 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1036 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1037 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1038 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1041 int sign, exponent, mantissa;
1042 unsigned char ulawbyte;
1044 /* Get the sample into sign-magnitude. */
1045 sign = (sample >> 8) & 0x80; /* set aside the sign */
1047 sample = -sample; /* get magnitude */
1049 sample = CLIP; /* clip the magnitude */
1051 /* Convert from 16 bit linear to ulaw. */
1052 sample = sample + BIAS;
1053 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1054 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1055 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1058 ulawbyte = 0x02; /* optional CCITT trap */
1065 ** This routine converts from ulaw to 16 bit linear.
1067 ** Craig Reese: IDA/Supercomputing Research Center
1068 ** 29 September 1989
1071 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1072 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1073 ** for Analog-to_Digital Conversion Techniques,"
1076 ** Input: 8 bit ulaw sample
1077 ** Output: signed 16 bit linear sample
1080 static int ulaw_to_linear(unsigned char ulawbyte)
1082 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1083 int sign, exponent, mantissa, sample;
1085 ulawbyte = ~ ulawbyte;
1086 sign = ( ulawbyte & 0x80 );
1087 exponent = ( ulawbyte >> 4 ) & 0x07;
1088 mantissa = ulawbyte & 0x0F;
1089 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1095 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1098 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1099 /* ========================================================================= */
1100 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1102 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1103 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1105 static SoundInfo *Load_WAV(char *filename)
1107 SoundInfo *snd_info;
1108 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1109 byte sound_header_buffer[WAV_HEADER_SIZE];
1110 char chunk_name[CHUNK_ID_LEN + 1];
1117 if (!audio.sound_available)
1120 snd_info = checked_calloc(sizeof(SoundInfo));
1122 #if defined(TARGET_SDL)
1124 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1126 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1131 #elif defined(TARGET_ALLEGRO)
1133 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1135 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1140 #else /* PLATFORM_UNIX */
1142 if ((file = fopen(filename, MODE_READ)) == NULL)
1144 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1149 /* read chunk id "RIFF" */
1150 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1151 if (strcmp(chunk_name, "RIFF") != 0)
1153 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1159 /* read "RIFF" type id "WAVE" */
1160 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1161 if (strcmp(chunk_name, "WAVE") != 0)
1163 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1169 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1171 if (strcmp(chunk_name, "fmt ") == 0)
1173 /* read header information */
1174 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1175 sound_header_buffer[i] = fgetc(file);
1177 if (chunk_size > WAV_HEADER_SIZE)
1178 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1180 else if (strcmp(chunk_name, "data") == 0)
1182 snd_info->data_len = chunk_size;
1183 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1185 /* read sound data */
1186 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1189 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1191 free(snd_info->data_ptr);
1196 /* check for odd number of sample bytes (data chunk is word aligned) */
1197 if ((chunk_size % 2) == 1)
1198 ReadUnusedBytesFromFile(file, 1);
1200 else /* unknown chunk -- ignore */
1201 ReadUnusedBytesFromFile(file, chunk_size);
1206 if (snd_info->data_ptr == NULL)
1208 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1215 /* convert unsigned 8 bit sample data to signed 16 bit sample data */
1217 data_ptr = checked_malloc(snd_info->data_len * sizeof(short));
1219 for (i=0; i<snd_info->data_len; i++)
1220 data_ptr[i] = ((short)(((byte *)snd_info->data_ptr)[i] ^ 0x80)) << 8;
1222 free(snd_info->data_ptr);
1223 snd_info->data_ptr = data_ptr;
1225 snd_info->format = AUDIO_FORMAT_S16;
1229 snd_info->format = AUDIO_FORMAT_U8;
1232 #endif /* PLATFORM_UNIX */
1234 snd_info->type = SND_TYPE_WAV;
1235 snd_info->source_filename = getStringCopy(filename);
1240 SoundInfo *LoadCustomSound(char *basename)
1242 char *filename = getCustomSoundFilename(basename);
1244 if (filename == NULL)
1246 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1250 return Load_WAV(filename);
1253 void InitSoundList(int num_list_entries)
1255 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1256 num_sounds = num_list_entries;
1259 void LoadSoundToList(char *basename, int list_pos)
1261 if (Sound == NULL || list_pos >= num_sounds)
1264 if (Sound[list_pos])
1265 FreeSound(Sound[list_pos]);
1267 Sound[list_pos] = LoadCustomSound(basename);
1270 static MusicInfo *Load_MOD(char *filename)
1272 #if defined(TARGET_SDL)
1273 MusicInfo *mod_info;
1275 if (!audio.sound_available)
1278 mod_info = checked_calloc(sizeof(MusicInfo));
1280 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1282 Error(ERR_WARN, "cannot read music file '%s'", filename);
1287 mod_info->type = MUS_TYPE_MOD;
1288 mod_info->source_filename = getStringCopy(filename);
1296 void LoadCustomMusic(void)
1298 char *music_directory = getCustomMusicDirectory();
1300 struct dirent *dir_entry;
1302 if (!audio.sound_available)
1305 if ((dir = opendir(music_directory)) == NULL)
1307 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1308 audio.music_available = FALSE;
1312 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1314 char *basename = dir_entry->d_name;
1315 char *filename = getPath2(music_directory, basename);
1316 MusicInfo *mus_info = NULL;
1318 if (FileIsSound(basename))
1319 mus_info = Load_WAV(filename);
1320 else if (FileIsMusic(basename))
1321 mus_info = Load_MOD(filename);
1328 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1329 Music[num_music -1] = mus_info;
1336 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1340 void PlayMusic(int nr)
1342 if (!audio.music_available)
1345 #if defined(TARGET_SDL)
1347 nr = nr % num_music;
1349 if (Music[nr]->type == MUS_TYPE_MOD)
1351 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1352 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1354 else /* play WAV music loop */
1356 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1357 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1367 void PlaySound(int nr)
1369 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1372 void PlaySoundStereo(int nr, int stereo)
1374 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1377 void PlaySoundLoop(int nr)
1379 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1382 void PlaySoundMusic(int nr)
1384 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1387 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1389 struct SoundControl snd_ctrl = emptySoundControl;
1391 if (!audio.sound_available ||
1392 !audio.sound_enabled ||
1393 audio.sound_deactivated)
1396 if (volume < PSND_MIN_VOLUME)
1397 volume = PSND_MIN_VOLUME;
1398 else if (volume > PSND_MAX_VOLUME)
1399 volume = PSND_MAX_VOLUME;
1401 if (stereo < PSND_MAX_LEFT)
1402 stereo = PSND_MAX_LEFT;
1403 else if (stereo > PSND_MAX_RIGHT)
1404 stereo = PSND_MAX_RIGHT;
1407 snd_ctrl.volume = volume;
1408 snd_ctrl.stereo = stereo;
1409 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1410 snd_ctrl.music = (loop_type == PSND_MUSIC);
1411 snd_ctrl.active = TRUE;
1414 /* now only used internally in sound server child process */
1415 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1416 snd_ctrl.data_len = Sound[nr].data_len;
1419 #if defined(TARGET_SDL)
1420 Mix_Volume(-1, SOUND_MAX_VOLUME);
1421 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1422 #elif defined(PLATFORM_UNIX)
1423 if (audio.soundserver_pid == 0) /* we are child process */
1426 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1428 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1429 audio.sound_available = audio.sound_enabled = FALSE;
1432 #elif defined(PLATFORM_MSDOS)
1433 sound_handler(snd_ctrl);
1437 void FadeMusic(void)
1439 if (!audio.sound_available)
1442 #if defined(TARGET_SDL)
1443 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1444 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1446 StopSoundExt(-1, SSND_FADE_MUSIC);
1450 void FadeSound(int nr)
1452 StopSoundExt(nr, SSND_FADE_SOUND);
1458 StopSoundExt(-1, SSND_FADE_ALL);
1461 void StopMusic(void)
1463 #if defined(TARGET_SDL)
1464 if (!audio.sound_available)
1468 Mix_HaltChannel(audio.music_channel);
1470 StopSoundExt(-1, SSND_STOP_MUSIC);
1474 void StopSound(int nr)
1476 StopSoundExt(nr, SSND_STOP_SOUND);
1481 StopSoundExt(-1, SSND_STOP_ALL);
1484 void StopSoundExt(int nr, int method)
1486 struct SoundControl snd_ctrl = emptySoundControl;
1488 if (!audio.sound_available)
1491 if (method & SSND_FADING)
1492 snd_ctrl.fade_sound = TRUE;
1494 if (method & SSND_ALL)
1495 snd_ctrl.stop_all_sounds = TRUE;
1498 snd_ctrl.stop_sound = TRUE;
1502 if (method & SSND_MUSIC)
1503 snd_ctrl.music = TRUE;
1505 #if defined(TARGET_SDL)
1507 if (method & SSND_FADING)
1511 for (i=0; i<audio.channels; i++)
1512 if (i != audio.music_channel || snd_ctrl.music)
1513 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1515 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1521 for (i=0; i<audio.channels; i++)
1522 if (i != audio.music_channel || snd_ctrl.music)
1528 #elif !defined(PLATFORM_MSDOS)
1530 if (audio.soundserver_pid == 0) /* we are child process */
1533 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1535 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1536 audio.sound_available = audio.sound_enabled = FALSE;
1540 sound_handler(snd_ctrl);
1544 static void InitReloadSoundsOrMusic(char *set_name, int type)
1546 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1547 struct SoundControl snd_ctrl = emptySoundControl;
1549 (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1550 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1551 unsigned long str_size2 = strlen(ti->basepath) + 1;
1552 unsigned long str_size3 = strlen(ti->fullpath) + 1;
1555 if (!audio.sound_available)
1558 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1559 if (type == SND_RELOAD_SOUNDS)
1560 audio.func_reload_sounds();
1562 audio.func_reload_music();
1563 #elif defined(PLATFORM_UNIX)
1564 if (audio.soundserver_pid == 0) /* we are child process */
1567 if (leveldir_current == NULL) /* should never happen */
1568 Error(ERR_EXIT, "leveldir_current == NULL");
1570 snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1571 snd_ctrl.reload_music = (type == SND_RELOAD_MUSIC);
1572 snd_ctrl.data_len = strlen(set_name) + 1;
1574 if (write(audio.soundserver_pipe[1], &snd_ctrl,
1575 sizeof(snd_ctrl)) < 0 ||
1576 write(audio.soundserver_pipe[1], set_name,
1577 snd_ctrl.data_len) < 0 ||
1578 write(audio.soundserver_pipe[1], leveldir_current,
1579 sizeof(TreeInfo)) < 0 ||
1580 write(audio.soundserver_pipe[1], ti,
1581 sizeof(TreeInfo)) < 0 ||
1582 write(audio.soundserver_pipe[1], &str_size1,
1583 sizeof(unsigned long)) < 0 ||
1584 write(audio.soundserver_pipe[1], &str_size2,
1585 sizeof(unsigned long)) < 0 ||
1586 write(audio.soundserver_pipe[1], &str_size3,
1587 sizeof(unsigned long)) < 0 ||
1588 write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1590 write(audio.soundserver_pipe[1], ti->basepath,
1592 write(audio.soundserver_pipe[1], ti->fullpath,
1595 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1596 audio.sound_available = audio.sound_enabled = FALSE;
1602 void InitReloadSounds(char *set_name)
1604 InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1607 void InitReloadMusic(char *set_name)
1609 InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1612 void FreeSound(SoundInfo *sound)
1617 if (sound->data_ptr)
1619 #if defined(TARGET_SDL)
1620 Mix_FreeChunk(sound->data_ptr);
1621 #elif defined(TARGET_ALLEGRO)
1622 destroy_sample(sound->data_ptr);
1623 #else /* PLATFORM_UNIX */
1624 free(sound->data_ptr);
1631 void FreeMusic(MusicInfo *music)
1636 if (music->data_ptr)
1638 #if defined(TARGET_SDL)
1639 if (music->type == MUS_TYPE_MOD)
1640 Mix_FreeMusic(music->data_ptr);
1642 Mix_FreeChunk(music->data_ptr);
1643 #elif defined(TARGET_ALLEGRO)
1644 destroy_sample(music->data_ptr);
1645 #else /* PLATFORM_UNIX */
1646 free(music->data_ptr);
1653 void FreeAllSounds()
1660 for(i=0; i<num_sounds; i++)
1661 FreeSound(Sound[i]);
1676 for(i=0; i<num_music; i++)
1677 FreeMusic(Music[i]);
1685 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1686 /* ========================================================================= */