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 int playing_sounds = 0;
36 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
37 static struct SoundControl emptySoundControl =
39 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
42 #if defined(PLATFORM_UNIX)
43 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
44 static char premix_first_buffer[SND_BLOCKSIZE];
45 #if defined(AUDIO_STREAMING_DSP)
46 static char premix_left_buffer[SND_BLOCKSIZE];
47 static char premix_right_buffer[SND_BLOCKSIZE];
48 static int premix_last_buffer[SND_BLOCKSIZE];
50 static unsigned char playing_buffer[SND_BLOCKSIZE];
53 /* forward declaration of internal functions */
54 #if defined(AUDIO_STREAMING_DSP)
55 static void SoundServer_InsertNewSound(struct SoundControl);
56 #elif defined(PLATFORM_UNIX)
57 static unsigned char linear_to_ulaw(int);
58 static int ulaw_to_linear(unsigned char);
61 #if defined(AUDIO_LINUX_IOCTL)
62 static boolean InitAudioDevice_Linux();
63 #elif defined(PLATFORM_NETBSD)
64 static boolean InitAudioDevice_NetBSD();
65 #elif defined(PLATFORM_HPUX)
66 static boolean InitAudioDevice_HPUX();
67 #elif defined(PLATFORM_MSDOS)
68 static void SoundServer_InsertNewSound(struct SoundControl);
69 static void SoundServer_StopSound(int);
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();
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 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
231 playlist[i] = emptySoundControl;
234 close(audio.device_fd);
236 if (snd_ctrl.reload_sounds)
244 #if defined(AUDIO_STREAMING_DSP)
246 if (snd_ctrl.fade_sound)
252 playlist[audio.music_channel].fade_sound = TRUE;
254 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
255 if (snd_ctrl.stop_all_sounds ||
256 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
257 playlist[i].fade_sound = TRUE;
259 else if (snd_ctrl.stop_all_sounds)
264 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
265 playlist[i] = emptySoundControl;
268 close(audio.device_fd);
270 else if (snd_ctrl.stop_sound)
277 playlist[audio.music_channel] = emptySoundControl;
281 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
283 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
285 playlist[i] = emptySoundControl;
291 close(audio.device_fd);
294 if (playing_sounds || snd_ctrl.active)
296 struct timeval delay = { 0, 0 };
299 static long max_sample_size = 0;
300 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
301 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
302 static boolean stereo = TRUE;
304 if (playing_sounds ||
305 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
307 if (!playing_sounds) /* we just opened the audio device */
309 #if defined(AUDIO_LINUX_IOCTL)
310 stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
311 #elif defined(PLATFORM_NETBSD)
312 stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
314 max_sample_size = fragment_size / (stereo ? 2 : 1);
317 if (snd_ctrl.active) /* new sound has arrived */
318 SoundServer_InsertNewSound(snd_ctrl);
320 while(playing_sounds &&
321 select(audio.soundserver_pipe[0] + 1,
322 &sound_fdset, NULL, NULL, &delay) < 1)
324 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
326 /* first clear the last premixing buffer */
327 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
329 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
333 if (!playlist[i].active)
336 /* get pointer and size of the actual sound sample */
337 sample_ptr = playlist[i].data_ptr + playlist[i].playingpos;
338 sample_size = MIN(max_sample_size,
339 playlist[i].data_len - playlist[i].playingpos);
340 playlist[i].playingpos += sample_size;
342 /* fill the first mixing buffer with original sample */
343 memcpy(premix_first_buffer, sample_ptr, sample_size);
345 /* are we about to restart a looping sound? */
346 if (playlist[i].loop && sample_size < max_sample_size)
348 playlist[i].playingpos = max_sample_size - sample_size;
349 memcpy(premix_first_buffer + sample_size,
350 playlist[i].data_ptr, max_sample_size - sample_size);
351 sample_size = max_sample_size;
354 /* decrease volume if sound is fading out */
355 if (playlist[i].fade_sound &&
356 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
357 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
359 /* adjust volume of actual sound sample */
360 if (playlist[i].volume != PSND_MAX_VOLUME)
361 for(j=0; j<sample_size; j++)
362 premix_first_buffer[j] =
363 (playlist[i].volume * (int)premix_first_buffer[j])
364 >> PSND_MAX_VOLUME_BITS;
366 /* fill the last mixing buffer with stereo or mono sound */
369 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
370 int left_volume = stereo_volume[middle_pos +playlist[i].stereo];
371 int right_volume = stereo_volume[middle_pos -playlist[i].stereo];
373 for(j=0; j<sample_size; j++)
375 premix_left_buffer[j] =
376 (left_volume * (int)premix_first_buffer[j])
377 >> PSND_MAX_LEFT2RIGHT_BITS;
378 premix_right_buffer[j] =
379 (right_volume * (int)premix_first_buffer[j])
380 >> PSND_MAX_LEFT2RIGHT_BITS;
381 premix_last_buffer[2*j+0] += premix_left_buffer[j];
382 premix_last_buffer[2*j+1] += premix_right_buffer[j];
387 for(j=0;j<sample_size;j++)
388 premix_last_buffer[j] += (int)premix_first_buffer[j];
391 /* delete completed sound entries from the playlist */
392 if (playlist[i].playingpos >= playlist[i].data_len)
394 if (playlist[i].loop)
395 playlist[i].playingpos = 0;
398 playlist[i] = emptySoundControl;
402 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
404 playlist[i] = emptySoundControl;
409 /* put last mixing buffer to final playing buffer */
410 for(i=0; i<fragment_size; i++)
412 if (premix_last_buffer[i]<-255)
413 playing_buffer[i] = 0;
414 else if (premix_last_buffer[i]>255)
415 playing_buffer[i] = 255;
417 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
420 /* finally play the sound fragment */
421 write(audio.device_fd, playing_buffer, fragment_size);
424 /* if no sounds playing, free device for other sound programs */
426 close(audio.device_fd);
430 #else /* !AUDIO_STREAMING_DSP */
432 if (snd_ctrl.active && !snd_ctrl.loop)
434 struct timeval delay = { 0, 0 };
436 long sample_size, max_sample_size = SND_BLOCKSIZE;
437 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
438 int wait_percent = 90; /* wait 90% of the real playing time */
441 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
445 while(playing_sounds &&
446 select(audio.soundserver_pipe[0] + 1,
447 &sound_fdset, NULL, NULL, &delay) < 1)
449 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
451 /* get pointer and size of the actual sound sample */
452 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
454 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
455 snd_ctrl.playingpos += sample_size;
457 /* fill the first mixing buffer with original sample */
458 memcpy(premix_first_buffer,sample_ptr,sample_size);
460 /* adjust volume of actual sound sample */
461 if (snd_ctrl.volume != PSND_MAX_VOLUME)
462 for(i=0;i<sample_size;i++)
463 premix_first_buffer[i] =
464 (snd_ctrl.volume * (int)premix_first_buffer[i])
465 >> PSND_MAX_VOLUME_BITS;
467 for(i=0;i<sample_size;i++)
469 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
471 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
474 /* finally play the sound fragment */
475 write(audio.device_fd,playing_buffer,sample_size);
478 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
480 close(audio.device_fd);
483 #endif /* !AUDIO_STREAMING_DSP */
486 #endif /* PLATFORM_UNIX */
488 #if defined(PLATFORM_MSDOS)
489 static void sound_handler(struct SoundControl snd_ctrl)
493 if (snd_ctrl.fade_sound)
498 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
499 if ((snd_ctrl.stop_all_sounds ||
500 (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
501 (i == audio.music_channel && snd_ctrl.music)) &&
502 !playlist[i].fade_sound)
504 playlist[i].fade_sound = TRUE;
505 if (voice_check(playlist[i].voice))
506 voice_ramp_volume(playlist[i].voice, 1000, 0);
507 playlist[i].loop = PSND_NO_LOOP;
510 else if (snd_ctrl.stop_all_sounds)
514 SoundServer_StopAllSounds();
516 else if (snd_ctrl.stop_sound)
520 SoundServer_StopSound(snd_ctrl);
523 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
525 if (!playlist[i].active || playlist[i].loop)
528 playlist[i].playingpos = voice_get_position(playlist[i].voice);
529 playlist[i].volume = voice_get_volume(playlist[i].voice);
530 if (playlist[i].playingpos == -1 || !playlist[i].volume)
532 deallocate_voice(playlist[i].voice);
533 playlist[i] = emptySoundControl;
539 SoundServer_InsertNewSound(snd_ctrl);
541 #endif /* PLATFORM_MSDOS */
543 #if !defined(PLATFORM_WIN32)
544 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
549 snd_ctrl.nr = snd_ctrl.nr % num_music;
551 /* if playlist is full, remove oldest sound */
552 if (playing_sounds == MAX_SOUNDS_PLAYING)
554 int longest = 0, longest_nr = 0;
556 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
558 #if !defined(PLATFORM_MSDOS)
559 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
561 int actual = playlist[i].playingpos;
564 if (i != audio.music_channel && !playlist[i].loop && actual > longest)
570 #if defined(PLATFORM_MSDOS)
571 voice_set_volume(playlist[longest_nr].voice, 0);
572 deallocate_voice(playlist[longest_nr].voice);
574 playlist[longest_nr] = emptySoundControl;
578 /* check if sound is already being played (and how often) */
579 for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
580 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
583 /* restart loop sounds only if they are just fading out */
584 if (k >= 1 && snd_ctrl.loop)
586 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
588 if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
589 playlist[i].fade_sound)
591 playlist[i].fade_sound = FALSE;
592 playlist[i].volume = PSND_MAX_VOLUME;
593 #if defined(PLATFORM_MSDOS)
594 playlist[i].loop = PSND_LOOP;
595 voice_stop_volumeramp(playlist[i].voice);
596 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
604 /* don't play sound more than n times simultaneously (with n == 2 for now) */
607 int longest = 0, longest_nr = 0;
609 /* look for oldest equal sound */
610 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
614 if (!playlist[i].active ||
615 i == audio.music_channel ||
616 playlist[i].nr != snd_ctrl.nr)
619 #if !defined(PLATFORM_MSDOS)
620 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
622 actual = playlist[i].playingpos;
624 if (actual >= longest)
631 #if defined(PLATFORM_MSDOS)
632 voice_set_volume(playlist[longest_nr].voice, 0);
633 deallocate_voice(playlist[longest_nr].voice);
635 playlist[longest_nr] = emptySoundControl;
639 /* add new sound to playlist */
640 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
642 if (!playlist[i].active ||
643 (snd_ctrl.music && i == audio.music_channel))
645 SoundInfo *snd_info =
646 (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
648 snd_ctrl.data_ptr = snd_info->data_ptr;
649 snd_ctrl.data_len = snd_info->data_len;
651 playlist[i] = snd_ctrl;
654 #if defined(PLATFORM_MSDOS)
655 playlist[i].voice = allocate_voice(playlist[i].data_ptr);
658 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
660 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
661 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
662 voice_start(playlist[i].voice);
668 #endif /* !PLATFORM_WIN32 */
671 void SoundServer_FadeSound(int nr)
678 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
679 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
680 playlist[i].fade_sound = TRUE;
684 #if !defined(PLATFORM_WIN32)
685 #if defined(PLATFORM_MSDOS)
686 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
688 int nr = snd_ctrl.nr;
694 for(i=0; i<MAX_SOUNDS_PLAYING; i++)
696 if ((i == audio.music_channel && snd_ctrl.music) ||
697 (i != audio.music_channel && playlist[i].nr == nr))
699 #if defined(PLATFORM_MSDOS)
700 voice_set_volume(playlist[i].voice, 0);
701 deallocate_voice(playlist[i].voice);
703 playlist[i] = emptySoundControl;
708 #if !defined(PLATFORM_MSDOS)
710 close(audio.device_fd);
714 static void SoundServer_StopAllSounds()
718 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
720 #if defined(PLATFORM_MSDOS)
721 voice_set_volume(playlist[i].voice, 0);
722 deallocate_voice(playlist[i].voice);
724 playlist[i]=emptySoundControl;
728 #if !defined(PLATFORM_MSDOS)
729 close(audio.device_fd);
732 #endif /* PLATFORM_MSDOS */
733 #endif /* !PLATFORM_WIN32 */
736 /* ------------------------------------------------------------------------- */
737 /* platform dependant audio initialization code */
738 /* ------------------------------------------------------------------------- */
740 #if defined(AUDIO_LINUX_IOCTL)
741 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
743 /* "ioctl()" expects pointer to 'int' value for stereo flag
744 (boolean is defined as 'char', which will not work here) */
746 unsigned long fragment_spec = 0;
748 /* determine logarithm (log2) of the fragment size */
749 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
752 /* use two fragments (play one fragment, prepare the other);
753 one fragment would result in interrupted audio output, more
754 than two fragments would raise audio output latency to much */
755 fragment_spec |= 0x00020000;
757 /* Example for fragment specification:
758 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
759 - (with stereo the effective buffer size will shrink to 256)
760 => fragment_size = 0x00020009 */
762 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
763 Error(ERR_EXIT_SOUND_SERVER,
764 "cannot set fragment size of /dev/dsp -- no sounds");
766 /* try if we can use stereo sound */
767 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
770 static boolean reported = FALSE;
774 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
781 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
782 Error(ERR_EXIT_SOUND_SERVER,
783 "cannot set sample rate of /dev/dsp -- no sounds");
785 /* get the real fragmentation size; this should return 512 */
786 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
787 Error(ERR_EXIT_SOUND_SERVER,
788 "cannot get fragment size of /dev/dsp -- no sounds");
790 return (boolean)stereo;
792 #endif /* AUDIO_LINUX_IOCTL */
794 #if defined(PLATFORM_NETBSD)
795 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
798 boolean stereo = TRUE;
800 AUDIO_INITINFO(&a_info);
801 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
802 a_info.play.precision = 8;
803 a_info.play.channels = 2;
804 a_info.play.sample_rate = sample_rate;
805 a_info.blocksize = fragment_size;
807 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
809 /* try to disable stereo */
810 a_info.play.channels = 1;
813 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
814 Error(ERR_EXIT_SOUND_SERVER,
815 "cannot set sample rate of /dev/audio -- no sounds");
820 #endif /* PLATFORM_NETBSD */
822 #if defined(PLATFORM_HPUX)
823 static boolean InitAudioDevice_HPUX()
825 struct audio_describe ainfo;
828 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
830 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
832 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
833 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
835 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
836 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
838 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
839 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
843 return TRUE; /* to provide common interface for InitAudioDevice_...() */
845 #endif /* PLATFORM_HPUX */
847 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
849 /* these two are stolen from "sox"... :) */
852 ** This routine converts from linear to ulaw.
854 ** Craig Reese: IDA/Supercomputing Research Center
855 ** Joe Campbell: Department of Defense
859 ** 1) CCITT Recommendation G.711 (very difficult to follow)
860 ** 2) "A New Digital Technique for Implementation of Any
861 ** Continuous PCM Companding Law," Villeret, Michel,
862 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
863 ** 1973, pg. 11.12-11.17
864 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
865 ** for Analog-to_Digital Conversion Techniques,"
868 ** Input: Signed 16 bit linear sample
869 ** Output: 8 bit ulaw sample
872 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
873 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
876 static unsigned char linear_to_ulaw(int sample)
878 static int exp_lut[256] =
880 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
881 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
882 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
883 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
884 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
885 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
886 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
887 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
888 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
889 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
890 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
891 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
892 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
893 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
894 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
895 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
898 int sign, exponent, mantissa;
899 unsigned char ulawbyte;
901 /* Get the sample into sign-magnitude. */
902 sign = (sample >> 8) & 0x80; /* set aside the sign */
904 sample = -sample; /* get magnitude */
906 sample = CLIP; /* clip the magnitude */
908 /* Convert from 16 bit linear to ulaw. */
909 sample = sample + BIAS;
910 exponent = exp_lut[( sample >> 7 ) & 0xFF];
911 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
912 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
915 ulawbyte = 0x02; /* optional CCITT trap */
922 ** This routine converts from ulaw to 16 bit linear.
924 ** Craig Reese: IDA/Supercomputing Research Center
928 ** 1) CCITT Recommendation G.711 (very difficult to follow)
929 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
930 ** for Analog-to_Digital Conversion Techniques,"
933 ** Input: 8 bit ulaw sample
934 ** Output: signed 16 bit linear sample
937 static int ulaw_to_linear(unsigned char ulawbyte)
939 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
940 int sign, exponent, mantissa, sample;
942 ulawbyte = ~ ulawbyte;
943 sign = ( ulawbyte & 0x80 );
944 exponent = ( ulawbyte >> 4 ) & 0x07;
945 mantissa = ulawbyte & 0x0F;
946 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
952 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
955 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
956 /* ========================================================================= */
957 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
961 printf("reloading sounds ...\n");
966 printf("reloading music ...\n");
969 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
970 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
972 static SoundInfo *Load_WAV(char *filename)
975 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
976 byte sound_header_buffer[WAV_HEADER_SIZE];
977 char chunk_name[CHUNK_ID_LEN + 1];
983 if (!audio.sound_available)
986 snd_info = checked_calloc(sizeof(SoundInfo));
988 #if defined(TARGET_SDL)
990 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
992 Error(ERR_WARN, "cannot read sound file '%s'", filename);
997 #elif defined(TARGET_ALLEGRO)
999 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1001 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1006 #else /* PLATFORM_UNIX */
1008 if ((file = fopen(filename, MODE_READ)) == NULL)
1010 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1015 /* read chunk id "RIFF" */
1016 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1017 if (strcmp(chunk_name, "RIFF") != 0)
1019 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1025 /* read "RIFF" type id "WAVE" */
1026 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1027 if (strcmp(chunk_name, "WAVE") != 0)
1029 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1035 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1037 if (strcmp(chunk_name, "fmt ") == 0)
1039 /* read header information */
1040 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1041 sound_header_buffer[i] = fgetc(file);
1043 if (chunk_size > WAV_HEADER_SIZE)
1044 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1046 else if (strcmp(chunk_name, "data") == 0)
1048 snd_info->data_len = chunk_size;
1049 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1051 /* read sound data */
1052 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1055 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1057 free(snd_info->data_ptr);
1062 /* check for odd number of sample bytes (data chunk is word aligned) */
1063 if ((chunk_size % 2) == 1)
1064 ReadUnusedBytesFromFile(file, 1);
1066 else /* unknown chunk -- ignore */
1067 ReadUnusedBytesFromFile(file, chunk_size);
1072 if (snd_info->data_ptr == NULL)
1074 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1079 for (i=0; i<snd_info->data_len; i++)
1080 ((byte *)snd_info->data_ptr)[i] = ((byte *)snd_info->data_ptr)[i] ^ 0x80;
1082 #endif /* PLATFORM_UNIX */
1084 snd_info->type = SND_TYPE_WAV;
1085 snd_info->source_filename = getStringCopy(filename);
1090 SoundInfo *LoadCustomSound(char *basename)
1092 char *filename = getCustomSoundFilename(basename);
1094 if (filename == NULL)
1096 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1100 return Load_WAV(filename);
1103 void InitSoundList(int num_list_entries)
1105 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1106 num_sounds = num_list_entries;
1109 void LoadSoundToList(char *basename, int list_pos)
1111 if (Sound == NULL || list_pos >= num_sounds)
1114 if (Sound[list_pos])
1115 FreeSound(Sound[list_pos]);
1117 Sound[list_pos] = LoadCustomSound(basename);
1120 static MusicInfo *Load_MOD(char *filename)
1122 #if defined(TARGET_SDL)
1123 MusicInfo *mod_info;
1125 if (!audio.sound_available)
1128 mod_info = checked_calloc(sizeof(MusicInfo));
1130 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1132 Error(ERR_WARN, "cannot read music file '%s'", filename);
1137 mod_info->type = MUS_TYPE_MOD;
1138 mod_info->source_filename = getStringCopy(filename);
1146 void LoadCustomMusic(void)
1148 char *music_directory = getCustomMusicDirectory();
1150 struct dirent *dir_entry;
1152 if (!audio.sound_available)
1155 if ((dir = opendir(music_directory)) == NULL)
1157 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1158 audio.music_available = FALSE;
1162 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1164 char *basename = dir_entry->d_name;
1165 char *filename = getPath2(music_directory, basename);
1166 MusicInfo *mus_info = NULL;
1168 if (FileIsSound(filename))
1169 mus_info = Load_WAV(filename);
1170 else if (FileIsMusic(filename))
1171 mus_info = Load_MOD(filename);
1178 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1179 Music[num_music -1] = mus_info;
1186 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1190 void PlayMusic(int nr)
1192 if (!audio.music_available)
1195 #if defined(TARGET_SDL)
1197 if (Music[nr]->type == MUS_TYPE_MOD)
1199 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1200 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1202 else /* play WAV music loop */
1204 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1205 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1215 void PlaySound(int nr)
1217 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1220 void PlaySoundStereo(int nr, int stereo)
1222 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1225 void PlaySoundLoop(int nr)
1227 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1230 void PlaySoundMusic(int nr)
1232 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1235 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1237 struct SoundControl snd_ctrl = emptySoundControl;
1239 if (!audio.sound_available ||
1240 !audio.sound_enabled ||
1241 audio.sound_deactivated)
1244 if (volume < PSND_MIN_VOLUME)
1245 volume = PSND_MIN_VOLUME;
1246 else if (volume > PSND_MAX_VOLUME)
1247 volume = PSND_MAX_VOLUME;
1249 if (stereo < PSND_MAX_LEFT)
1250 stereo = PSND_MAX_LEFT;
1251 else if (stereo > PSND_MAX_RIGHT)
1252 stereo = PSND_MAX_RIGHT;
1255 snd_ctrl.volume = volume;
1256 snd_ctrl.stereo = stereo;
1257 snd_ctrl.loop = (loop_type != PSND_NO_LOOP);
1258 snd_ctrl.music = (loop_type == PSND_MUSIC);
1259 snd_ctrl.active = TRUE;
1262 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1263 snd_ctrl.data_len = Sound[nr].data_len;
1266 #if defined(TARGET_SDL)
1267 Mix_Volume(-1, SOUND_MAX_VOLUME);
1268 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1269 #elif defined(PLATFORM_UNIX)
1270 if (audio.soundserver_pid == 0) /* we are child process */
1273 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1275 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1276 audio.sound_available = audio.sound_enabled = FALSE;
1279 #elif defined(PLATFORM_MSDOS)
1280 sound_handler(snd_ctrl);
1284 void FadeMusic(void)
1286 if (!audio.sound_available)
1289 #if defined(TARGET_SDL)
1290 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1291 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1293 StopSoundExt(-1, SSND_FADE_MUSIC);
1297 void FadeSound(int nr)
1299 StopSoundExt(nr, SSND_FADE_SOUND);
1305 StopSoundExt(-1, SSND_FADE_ALL);
1308 void StopMusic(void)
1310 #if defined(TARGET_SDL)
1311 if (!audio.sound_available)
1315 Mix_HaltChannel(audio.music_channel);
1317 StopSoundExt(-1, SSND_STOP_MUSIC);
1321 void StopSound(int nr)
1323 StopSoundExt(nr, SSND_STOP_SOUND);
1328 StopSoundExt(-1, SSND_STOP_ALL);
1331 void StopSoundExt(int nr, int method)
1333 struct SoundControl snd_ctrl = emptySoundControl;
1335 if (!audio.sound_available)
1338 if (method & SSND_FADING)
1339 snd_ctrl.fade_sound = TRUE;
1341 if (method & SSND_ALL)
1342 snd_ctrl.stop_all_sounds = TRUE;
1345 snd_ctrl.stop_sound = TRUE;
1349 if (method & SSND_MUSIC)
1350 snd_ctrl.music = TRUE;
1352 #if defined(TARGET_SDL)
1354 if (method & SSND_FADING)
1358 for (i=0; i<audio.channels; i++)
1359 if (i != audio.music_channel || snd_ctrl.music)
1360 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1362 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1368 for (i=0; i<audio.channels; i++)
1369 if (i != audio.music_channel || snd_ctrl.music)
1376 #if !defined(PLATFORM_MSDOS)
1377 if (audio.soundserver_pid == 0) /* we are child process */
1380 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1382 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1383 audio.sound_available = audio.sound_enabled = FALSE;
1387 sound_handler(snd_ctrl);
1392 void InitReloadSounds(char *set_name)
1394 struct SoundControl snd_ctrl = emptySoundControl;
1396 if (!audio.sound_available)
1399 snd_ctrl.reload_sounds = TRUE;
1401 #if defined(TARGET_SDL)
1403 #elif defined(PLATFORM_UNIX)
1404 if (audio.soundserver_pid == 0) /* we are child process */
1407 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1409 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1410 audio.sound_available = audio.sound_enabled = FALSE;
1413 #elif defined(PLATFORM_MSDOS)
1414 sound_handler(snd_ctrl);
1418 void InitReloadMusic(char *set_name)
1420 struct SoundControl snd_ctrl = emptySoundControl;
1422 if (!audio.sound_available)
1425 snd_ctrl.reload_music = TRUE;
1427 #if defined(TARGET_SDL)
1429 #elif defined(PLATFORM_UNIX)
1430 if (audio.soundserver_pid == 0) /* we are child process */
1433 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1435 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1436 audio.sound_available = audio.sound_enabled = FALSE;
1439 #elif defined(PLATFORM_MSDOS)
1440 sound_handler(snd_ctrl);
1444 void FreeSound(SoundInfo *sound)
1449 if (sound->data_ptr)
1451 #if defined(TARGET_SDL)
1452 Mix_FreeChunk(sound->data_ptr);
1453 #elif defined(TARGET_ALLEGRO)
1454 destroy_sample(sound->data_ptr);
1455 #else /* PLATFORM_UNIX */
1456 free(sound->data_ptr);
1463 void FreeMusic(MusicInfo *music)
1468 if (music->data_ptr)
1470 #if defined(TARGET_SDL)
1471 if (music->type == MUS_TYPE_MOD)
1472 Mix_FreeMusic(music->data_ptr);
1474 Mix_FreeChunk(music->data_ptr);
1475 #elif defined(TARGET_ALLEGRO)
1476 destroy_sample(music->data_ptr);
1477 #else /* PLATFORM_UNIX */
1478 free(music->data_ptr);
1485 void FreeAllSounds()
1492 for(i=0; i<num_sounds; i++)
1493 FreeSound(Sound[i]);
1505 for(i=0; i<num_music; i++)
1506 FreeMusic(Music[i]);
1511 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1512 /* ========================================================================= */