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 int num_sounds = 0, num_music = 0;
28 static struct SampleInfo *Sound = NULL;
29 #if defined(TARGET_SDL)
30 static int num_mods = 0;
31 static struct SampleInfo *Mod = NULL;
35 /* ========================================================================= */
36 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
38 static int playing_sounds = 0;
39 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
40 static struct SoundControl emptySoundControl =
42 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
45 #if defined(PLATFORM_UNIX)
46 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
47 static char premix_first_buffer[SND_BLOCKSIZE];
48 #if defined(AUDIO_STREAMING_DSP)
49 static char premix_left_buffer[SND_BLOCKSIZE];
50 static char premix_right_buffer[SND_BLOCKSIZE];
51 static int premix_last_buffer[SND_BLOCKSIZE];
53 static unsigned char playing_buffer[SND_BLOCKSIZE];
56 /* forward declaration of internal functions */
57 #if defined(AUDIO_STREAMING_DSP)
58 static void SoundServer_InsertNewSound(struct SoundControl);
59 #elif defined(PLATFORM_UNIX)
60 static unsigned char linear_to_ulaw(int);
61 static int ulaw_to_linear(unsigned char);
64 #if defined(AUDIO_LINUX_IOCTL)
65 static boolean InitAudioDevice_Linux();
66 #elif defined(PLATFORM_NETBSD)
67 static boolean InitAudioDevice_NetBSD();
68 #elif defined(PLATFORM_HPUX)
69 static boolean InitAudioDevice_HPUX();
70 #elif defined(PLATFORM_MSDOS)
71 static void SoundServer_InsertNewSound(struct SoundControl);
72 static void SoundServer_StopSound(int);
73 static void SoundServer_StopAllSounds();
76 #if defined(PLATFORM_UNIX)
77 static int OpenAudioDevice(char *audio_device_name)
81 /* check if desired audio device is accessible */
82 if (access(audio_device_name, W_OK) != 0)
85 /* try to open audio device in non-blocking mode */
86 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
89 /* re-open audio device in blocking mode */
91 audio_fd = open(audio_device_name, O_WRONLY);
96 static boolean TestAudioDevices(void)
98 static char *audio_device_name[] =
106 /* look for available audio devices, starting with preferred ones */
107 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
108 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
113 Error(ERR_WARN, "cannot open audio device -- no sound");
119 audio.device_name = audio_device_name[i];
124 #if !defined(TARGET_SDL)
125 static boolean ForkAudioProcess(void)
127 if (pipe(audio.soundserver_pipe) < 0)
129 Error(ERR_WARN, "cannot create pipe -- no sounds");
133 if ((audio.soundserver_pid = fork()) < 0)
135 Error(ERR_WARN, "cannot create sound server process -- no sounds");
139 if (audio.soundserver_pid == 0) /* we are child process */
146 else /* we are parent */
147 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
153 void UnixOpenAudio(void)
155 if (!TestAudioDevices())
158 audio.sound_available = TRUE;
159 audio.sound_enabled = TRUE;
161 #if defined(AUDIO_STREAMING_DSP)
162 audio.music_available = TRUE;
163 audio.loops_available = TRUE;
167 void UnixCloseAudio(void)
170 close(audio.device_fd);
172 if (audio.soundserver_pid > 0) /* we are parent process */
173 kill(audio.soundserver_pid, SIGTERM);
175 #endif /* PLATFORM_UNIX */
177 void InitPlaylist(void)
181 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
182 playlist[i] = emptySoundControl;
186 void StartSoundserver(void)
188 if (!audio.sound_available)
191 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
192 if (!ForkAudioProcess())
193 audio.sound_available = FALSE;
197 #if defined(PLATFORM_UNIX)
198 void SoundServer(void)
202 struct SoundControl snd_ctrl;
205 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
209 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
210 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
212 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
214 #if defined(PLATFORM_HPUX)
215 InitAudioDevice_HPUX();
218 FD_ZERO(&sound_fdset);
219 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
221 while(1) /* wait for sound playing commands from client */
223 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
224 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
225 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
227 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
229 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
231 if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
233 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
234 playlist[i] = emptySoundControl;
237 close(audio.device_fd);
239 if (snd_ctrl.reload_sounds)
247 #if defined(AUDIO_STREAMING_DSP)
249 if (snd_ctrl.fade_sound)
254 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
255 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
256 playlist[i].fade_sound = TRUE;
258 else if (snd_ctrl.stop_all_sounds)
263 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
264 playlist[i] = emptySoundControl;
267 close(audio.device_fd);
269 else if (snd_ctrl.stop_sound)
274 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
275 if (playlist[i].nr == snd_ctrl.nr)
277 playlist[i] = emptySoundControl;
282 close(audio.device_fd);
285 if (playing_sounds || snd_ctrl.active)
287 struct timeval delay = { 0, 0 };
290 static long max_sample_size = 0;
291 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
292 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
293 static boolean stereo = TRUE;
295 if (playing_sounds ||
296 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
298 if (!playing_sounds) /* we just opened the audio device */
300 #if defined(AUDIO_LINUX_IOCTL)
301 stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
302 #elif defined(PLATFORM_NETBSD)
303 stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
305 max_sample_size = fragment_size / (stereo ? 2 : 1);
308 if (snd_ctrl.active) /* new sound has arrived */
309 SoundServer_InsertNewSound(snd_ctrl);
311 while(playing_sounds &&
312 select(audio.soundserver_pipe[0] + 1,
313 &sound_fdset, NULL, NULL, &delay) < 1)
315 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
317 /* first clear the last premixing buffer */
318 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
320 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
324 if (!playlist[i].active)
327 /* get pointer and size of the actual sound sample */
328 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
330 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
331 playlist[i].playingpos += sample_size;
333 /* fill the first mixing buffer with original sample */
334 memcpy(premix_first_buffer,sample_ptr,sample_size);
336 /* are we about to restart a looping sound? */
337 if (playlist[i].loop && sample_size<max_sample_size)
339 playlist[i].playingpos = max_sample_size-sample_size;
340 memcpy(premix_first_buffer+sample_size,
341 playlist[i].data_ptr,max_sample_size-sample_size);
342 sample_size = max_sample_size;
345 /* decrease volume if sound is fading out */
346 if (playlist[i].fade_sound &&
347 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
348 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
350 /* adjust volume of actual sound sample */
351 if (playlist[i].volume != PSND_MAX_VOLUME)
352 for(j=0;j<sample_size;j++)
353 premix_first_buffer[j] =
354 (playlist[i].volume * (int)premix_first_buffer[j])
355 >> PSND_MAX_VOLUME_BITS;
357 /* fill the last mixing buffer with stereo or mono sound */
360 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
361 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
362 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
364 for(j=0;j<sample_size;j++)
366 premix_left_buffer[j] =
367 (left_volume * (int)premix_first_buffer[j])
368 >> PSND_MAX_LEFT2RIGHT_BITS;
369 premix_right_buffer[j] =
370 (right_volume * (int)premix_first_buffer[j])
371 >> PSND_MAX_LEFT2RIGHT_BITS;
372 premix_last_buffer[2*j+0] += premix_left_buffer[j];
373 premix_last_buffer[2*j+1] += premix_right_buffer[j];
378 for(j=0;j<sample_size;j++)
379 premix_last_buffer[j] += (int)premix_first_buffer[j];
382 /* delete completed sound entries from the playlist */
383 if (playlist[i].playingpos >= playlist[i].data_len)
385 if (playlist[i].loop)
386 playlist[i].playingpos = 0;
389 playlist[i] = emptySoundControl;
393 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
395 playlist[i] = emptySoundControl;
400 /* put last mixing buffer to final playing buffer */
401 for(i=0; i<fragment_size; i++)
403 if (premix_last_buffer[i]<-255)
404 playing_buffer[i] = 0;
405 else if (premix_last_buffer[i]>255)
406 playing_buffer[i] = 255;
408 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
411 /* finally play the sound fragment */
412 write(audio.device_fd, playing_buffer, fragment_size);
415 /* if no sounds playing, free device for other sound programs */
417 close(audio.device_fd);
421 #else /* !AUDIO_STREAMING_DSP */
423 if (snd_ctrl.active && !snd_ctrl.loop)
425 struct timeval delay = { 0, 0 };
427 long sample_size, max_sample_size = SND_BLOCKSIZE;
428 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
429 int wait_percent = 90; /* wait 90% of the real playing time */
432 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
436 while(playing_sounds &&
437 select(audio.soundserver_pipe[0] + 1,
438 &sound_fdset, NULL, NULL, &delay) < 1)
440 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
442 /* get pointer and size of the actual sound sample */
443 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
445 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
446 snd_ctrl.playingpos += sample_size;
448 /* fill the first mixing buffer with original sample */
449 memcpy(premix_first_buffer,sample_ptr,sample_size);
451 /* adjust volume of actual sound sample */
452 if (snd_ctrl.volume != PSND_MAX_VOLUME)
453 for(i=0;i<sample_size;i++)
454 premix_first_buffer[i] =
455 (snd_ctrl.volume * (int)premix_first_buffer[i])
456 >> PSND_MAX_VOLUME_BITS;
458 for(i=0;i<sample_size;i++)
460 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
462 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
465 /* finally play the sound fragment */
466 write(audio.device_fd,playing_buffer,sample_size);
469 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
471 close(audio.device_fd);
474 #endif /* !AUDIO_STREAMING_DSP */
477 #endif /* PLATFORM_UNIX */
479 #if defined(PLATFORM_MSDOS)
480 static void sound_handler(struct SoundControl snd_ctrl)
484 if (snd_ctrl.fade_sound)
489 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
490 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
491 !playlist[i].fade_sound)
493 playlist[i].fade_sound = TRUE;
494 if (voice_check(playlist[i].voice))
495 voice_ramp_volume(playlist[i].voice, 1000, 0);
496 playlist[i].loop = PSND_NO_LOOP;
499 else if (snd_ctrl.stop_all_sounds)
503 SoundServer_StopAllSounds();
505 else if (snd_ctrl.stop_sound)
509 SoundServer_StopSound(snd_ctrl.nr);
512 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
514 if (!playlist[i].active || playlist[i].loop)
517 playlist[i].playingpos = voice_get_position(playlist[i].voice);
518 playlist[i].volume = voice_get_volume(playlist[i].voice);
519 if (playlist[i].playingpos == -1 || !playlist[i].volume)
521 deallocate_voice(playlist[i].voice);
522 playlist[i] = emptySoundControl;
528 SoundServer_InsertNewSound(snd_ctrl);
530 #endif /* PLATFORM_MSDOS */
532 #if !defined(PLATFORM_WIN32)
533 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
537 /* if playlist is full, remove oldest sound */
538 if (playing_sounds==MAX_SOUNDS_PLAYING)
540 int longest=0, longest_nr=0;
542 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
544 #if !defined(PLATFORM_MSDOS)
545 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
547 int actual = playlist[i].playingpos;
550 if (!playlist[i].loop && actual>longest)
556 #if defined(PLATFORM_MSDOS)
557 voice_set_volume(playlist[longest_nr].voice, 0);
558 deallocate_voice(playlist[longest_nr].voice);
560 playlist[longest_nr] = emptySoundControl;
564 /* check if sound is already being played (and how often) */
565 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
567 if (playlist[i].nr == snd_ctrl.nr)
571 /* restart loop sounds only if they are just fading out */
572 if (k>=1 && snd_ctrl.loop)
574 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
576 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
578 playlist[i].fade_sound = FALSE;
579 playlist[i].volume = PSND_MAX_VOLUME;
580 #if defined(PLATFORM_MSDOS)
581 playlist[i].loop = PSND_LOOP;
582 voice_stop_volumeramp(playlist[i].voice);
583 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
590 /* don't play sound more than n times simultaneously (with n == 2 for now) */
593 int longest=0, longest_nr=0;
595 /* look for oldest equal sound */
596 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
600 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
603 #if !defined(PLATFORM_MSDOS)
604 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
606 actual = playlist[i].playingpos;
615 #if defined(PLATFORM_MSDOS)
616 voice_set_volume(playlist[longest_nr].voice, 0);
617 deallocate_voice(playlist[longest_nr].voice);
619 playlist[longest_nr] = emptySoundControl;
623 /* neuen Sound in Liste packen */
624 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
626 if (!playlist[i].active)
628 playlist[i] = snd_ctrl;
631 #if defined(PLATFORM_MSDOS)
632 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
634 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
635 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
636 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
637 voice_start(playlist[i].voice);
643 #endif /* !PLATFORM_WIN32 */
646 void SoundServer_FadeSound(int nr)
653 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
654 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
655 playlist[i].fade_sound = TRUE;
659 #if !defined(PLATFORM_WIN32)
660 #if defined(PLATFORM_MSDOS)
661 static void SoundServer_StopSound(int nr)
668 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
669 if (playlist[i].nr == nr)
671 #if defined(PLATFORM_MSDOS)
672 voice_set_volume(playlist[i].voice, 0);
673 deallocate_voice(playlist[i].voice);
675 playlist[i] = emptySoundControl;
679 #if !defined(PLATFORM_MSDOS)
681 close(audio.device_fd);
685 static void SoundServer_StopAllSounds()
689 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
691 #if defined(PLATFORM_MSDOS)
692 voice_set_volume(playlist[i].voice, 0);
693 deallocate_voice(playlist[i].voice);
695 playlist[i]=emptySoundControl;
699 #if !defined(PLATFORM_MSDOS)
700 close(audio.device_fd);
703 #endif /* PLATFORM_MSDOS */
704 #endif /* !PLATFORM_WIN32 */
707 /* ------------------------------------------------------------------------- */
708 /* platform dependant audio initialization code */
709 /* ------------------------------------------------------------------------- */
711 #if defined(AUDIO_LINUX_IOCTL)
712 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
714 /* "ioctl()" expects pointer to 'int' value for stereo flag
715 (boolean is defined as 'char', which will not work here) */
717 unsigned long fragment_spec = 0;
719 /* determine logarithm (log2) of the fragment size */
720 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
723 /* use two fragments (play one fragment, prepare the other);
724 one fragment would result in interrupted audio output, more
725 than two fragments would raise audio output latency to much */
726 fragment_spec |= 0x00020000;
728 /* Example for fragment specification:
729 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
730 - (with stereo the effective buffer size will shrink to 256)
731 => fragment_size = 0x00020009 */
733 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
734 Error(ERR_EXIT_SOUND_SERVER,
735 "cannot set fragment size of /dev/dsp -- no sounds");
737 /* try if we can use stereo sound */
738 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
741 static boolean reported = FALSE;
745 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
752 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
753 Error(ERR_EXIT_SOUND_SERVER,
754 "cannot set sample rate of /dev/dsp -- no sounds");
756 /* get the real fragmentation size; this should return 512 */
757 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
758 Error(ERR_EXIT_SOUND_SERVER,
759 "cannot get fragment size of /dev/dsp -- no sounds");
761 return (boolean)stereo;
763 #endif /* AUDIO_LINUX_IOCTL */
765 #if defined(PLATFORM_NETBSD)
766 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
769 boolean stereo = TRUE;
771 AUDIO_INITINFO(&a_info);
772 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
773 a_info.play.precision = 8;
774 a_info.play.channels = 2;
775 a_info.play.sample_rate = sample_rate;
776 a_info.blocksize = fragment_size;
778 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
780 /* try to disable stereo */
781 a_info.play.channels = 1;
784 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
785 Error(ERR_EXIT_SOUND_SERVER,
786 "cannot set sample rate of /dev/audio -- no sounds");
791 #endif /* PLATFORM_NETBSD */
793 #if defined(PLATFORM_HPUX)
794 static boolean InitAudioDevice_HPUX()
796 struct audio_describe ainfo;
799 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
801 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
803 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
804 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
806 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
807 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
809 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
810 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
814 return TRUE; /* to provide common interface for InitAudioDevice_...() */
816 #endif /* PLATFORM_HPUX */
818 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
820 /* these two are stolen from "sox"... :) */
823 ** This routine converts from linear to ulaw.
825 ** Craig Reese: IDA/Supercomputing Research Center
826 ** Joe Campbell: Department of Defense
830 ** 1) CCITT Recommendation G.711 (very difficult to follow)
831 ** 2) "A New Digital Technique for Implementation of Any
832 ** Continuous PCM Companding Law," Villeret, Michel,
833 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
834 ** 1973, pg. 11.12-11.17
835 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
836 ** for Analog-to_Digital Conversion Techniques,"
839 ** Input: Signed 16 bit linear sample
840 ** Output: 8 bit ulaw sample
843 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
844 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
847 static unsigned char linear_to_ulaw(int sample)
849 static int exp_lut[256] =
851 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
852 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
853 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
854 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
855 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
856 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
857 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
858 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
859 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
860 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
861 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
862 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
863 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
864 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
865 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
866 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
869 int sign, exponent, mantissa;
870 unsigned char ulawbyte;
872 /* Get the sample into sign-magnitude. */
873 sign = (sample >> 8) & 0x80; /* set aside the sign */
875 sample = -sample; /* get magnitude */
877 sample = CLIP; /* clip the magnitude */
879 /* Convert from 16 bit linear to ulaw. */
880 sample = sample + BIAS;
881 exponent = exp_lut[( sample >> 7 ) & 0xFF];
882 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
883 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
886 ulawbyte = 0x02; /* optional CCITT trap */
893 ** This routine converts from ulaw to 16 bit linear.
895 ** Craig Reese: IDA/Supercomputing Research Center
899 ** 1) CCITT Recommendation G.711 (very difficult to follow)
900 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
901 ** for Analog-to_Digital Conversion Techniques,"
904 ** Input: 8 bit ulaw sample
905 ** Output: signed 16 bit linear sample
908 static int ulaw_to_linear(unsigned char ulawbyte)
910 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
911 int sign, exponent, mantissa, sample;
913 ulawbyte = ~ ulawbyte;
914 sign = ( ulawbyte & 0x80 );
915 exponent = ( ulawbyte >> 4 ) & 0x07;
916 mantissa = ulawbyte & 0x0F;
917 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
923 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
926 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
927 /* ========================================================================= */
928 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
932 printf("reloading sounds ...\n");
937 printf("reloading music ...\n");
940 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
941 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
943 static boolean Load_WAV(char *filename)
945 struct SampleInfo *snd_info;
946 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
947 byte sound_header_buffer[WAV_HEADER_SIZE];
948 char chunk_name[CHUNK_ID_LEN + 1];
954 if (!audio.sound_available)
958 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
960 snd_info = &Sound[num_sounds - 1];
961 snd_info->data_len = 0;
962 snd_info->data_ptr = NULL;
964 #if defined(TARGET_SDL)
966 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
968 Error(ERR_WARN, "cannot read sound file '%s'", filename);
972 #elif defined(PLATFORM_UNIX)
974 if ((file = fopen(filename, MODE_READ)) == NULL)
976 Error(ERR_WARN, "cannot open sound file '%s'", filename);
980 /* read chunk id "RIFF" */
981 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
982 if (strcmp(chunk_name, "RIFF") != 0)
984 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
989 /* read "RIFF" type id "WAVE" */
990 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
991 if (strcmp(chunk_name, "WAVE") != 0)
993 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
998 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1001 printf("DEBUG: file '%s', chunk id '%s', chunk size '%d' [%d]\n",
1002 filename, chunk_name, chunk_size, feof(file));
1005 if (strcmp(chunk_name, "fmt ") == 0)
1007 /* read header information */
1008 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1009 sound_header_buffer[i] = fgetc(file);
1011 if (chunk_size > WAV_HEADER_SIZE)
1012 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1014 else if (strcmp(chunk_name, "data") == 0)
1016 snd_info->data_len = chunk_size;
1017 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1019 /* read sound data */
1020 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1023 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1028 /* check for odd number of sample bytes (data chunk is word aligned) */
1029 if ((chunk_size % 2) == 1)
1030 ReadUnusedBytesFromFile(file, 1);
1032 else /* unknown chunk -- ignore */
1033 ReadUnusedBytesFromFile(file, chunk_size);
1038 if (snd_info->data_ptr == NULL)
1040 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1044 for (i=0; i<snd_info->data_len; i++)
1045 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
1047 #else /* PLATFORM_MSDOS */
1049 snd_info->sample_ptr = load_sample(filename);
1050 if (!snd_info->sample_ptr)
1052 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1061 boolean LoadCustomSound(char *basename)
1063 char *filename = getCustomSoundFilename(basename);
1065 if (filename == NULL)
1067 Error(ERR_WARN, "cannot find sound file '%s' -- no sounds", filename);
1071 return Load_WAV(filename);
1074 static boolean Load_MOD(char *mod_name)
1076 #if defined(TARGET_SDL)
1077 struct SampleInfo *mod_info;
1081 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
1083 mod_info = &Mod[num_mods - 1];
1084 mod_info->name = mod_name;
1086 filename = getPath2(options.music_directory, mod_info->name);
1088 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
1090 Error(ERR_WARN, "cannot read music file '%s' -- no music", filename);
1103 int LoadCustomMusic(void)
1105 char *music_directory = getCustomMusicDirectory();
1107 struct dirent *dir_entry;
1108 int num_wav_music = 0;
1109 int num_mod_music = 0;
1111 if (!audio.sound_available)
1114 if ((dir = opendir(music_directory)) == NULL)
1116 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1117 audio.music_available = FALSE;
1121 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1123 char *filename = getPath2(music_directory, dir_entry->d_name);
1125 if (FileIsSound(filename) && Load_WAV(filename))
1127 else if (FileIsMusic(filename) && Load_MOD(filename))
1135 if (num_wav_music == 0 && num_mod_music == 0)
1136 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1137 options.music_directory);
1139 num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1141 audio.mods_available = (num_mod_music > 0);
1142 audio.music_available = (num_music > 0);
1147 void PlayMusic(int nr)
1149 if (!audio.music_available)
1152 if (!audio.mods_available)
1153 nr = num_sounds - num_music + nr;
1155 #if defined(TARGET_SDL)
1156 if (audio.mods_available) /* play MOD music */
1158 Mix_PlayMusic(Mod[nr].mix_music, -1);
1159 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1161 else /* play WAV music loop */
1163 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1164 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1167 audio.music_nr = nr;
1172 void PlaySound(int nr)
1174 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1177 void PlaySoundStereo(int nr, int stereo)
1179 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1182 void PlaySoundLoop(int nr)
1184 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1187 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1189 struct SoundControl snd_ctrl = emptySoundControl;
1191 if (!audio.sound_available ||
1192 !audio.sound_enabled ||
1193 audio.sound_deactivated)
1196 if (volume<PSND_MIN_VOLUME)
1197 volume = PSND_MIN_VOLUME;
1198 else if (volume>PSND_MAX_VOLUME)
1199 volume = PSND_MAX_VOLUME;
1201 if (stereo<PSND_MAX_LEFT)
1202 stereo = PSND_MAX_LEFT;
1203 else if (stereo>PSND_MAX_RIGHT)
1204 stereo = PSND_MAX_RIGHT;
1207 snd_ctrl.volume = volume;
1208 snd_ctrl.stereo = stereo;
1209 snd_ctrl.loop = loop;
1210 snd_ctrl.active = TRUE;
1211 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1212 snd_ctrl.data_len = Sound[nr].data_len;
1214 #if defined(TARGET_SDL)
1215 Mix_Volume(-1, SOUND_MAX_VOLUME);
1216 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1217 #elif defined(PLATFORM_UNIX)
1218 if (audio.soundserver_pid == 0) /* we are child process */
1221 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1223 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1224 audio.sound_available = audio.sound_enabled = FALSE;
1227 #elif defined(PLATFORM_MSDOS)
1228 sound_handler(snd_ctrl);
1232 void FadeMusic(void)
1234 #if defined(TARGET_SDL)
1235 if (!audio.sound_available)
1238 if (audio.mods_available)
1239 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1241 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1243 FadeSound(audio.music_nr);
1247 void FadeSound(int nr)
1249 StopSoundExt(nr, SSND_FADE_SOUND);
1255 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1258 void StopMusic(void)
1260 #if defined(TARGET_SDL)
1261 if (!audio.sound_available)
1264 if (audio.mods_available)
1267 Mix_HaltChannel(audio.music_channel);
1269 StopSound(audio.music_nr);
1273 void StopSound(int nr)
1275 StopSoundExt(nr, SSND_STOP_SOUND);
1280 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1283 void StopSoundExt(int nr, int method)
1285 struct SoundControl snd_ctrl = emptySoundControl;
1287 if (!audio.sound_available)
1290 if (SSND_FADING(method))
1291 snd_ctrl.fade_sound = TRUE;
1293 if (SSND_ALL(method))
1294 snd_ctrl.stop_all_sounds = TRUE;
1298 snd_ctrl.stop_sound = TRUE;
1301 #if defined(TARGET_SDL)
1303 if (SSND_FADING(method))
1307 for (i=0; i<audio.channels; i++)
1308 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1309 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1310 if (snd_ctrl.stop_all_sounds)
1311 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1317 for (i=0; i<audio.channels; i++)
1318 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1320 if (snd_ctrl.stop_all_sounds)
1325 #if !defined(PLATFORM_MSDOS)
1326 if (audio.soundserver_pid == 0) /* we are child process */
1329 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1331 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1332 audio.sound_available = audio.sound_enabled = FALSE;
1336 sound_handler(snd_ctrl);
1341 void InitReloadSounds(char *set_name)
1343 struct SoundControl snd_ctrl = emptySoundControl;
1345 if (!audio.sound_available)
1348 snd_ctrl.reload_sounds = TRUE;
1350 #if defined(TARGET_SDL)
1352 #elif defined(PLATFORM_UNIX)
1353 if (audio.soundserver_pid == 0) /* we are child process */
1356 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1358 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1359 audio.sound_available = audio.sound_enabled = FALSE;
1362 #elif defined(PLATFORM_MSDOS)
1363 sound_handler(snd_ctrl);
1367 void InitReloadMusic(char *set_name)
1369 struct SoundControl snd_ctrl = emptySoundControl;
1371 if (!audio.sound_available)
1374 snd_ctrl.reload_music = TRUE;
1376 #if defined(TARGET_SDL)
1378 #elif defined(PLATFORM_UNIX)
1379 if (audio.soundserver_pid == 0) /* we are child process */
1382 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1384 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1385 audio.sound_available = audio.sound_enabled = FALSE;
1388 #elif defined(PLATFORM_MSDOS)
1389 sound_handler(snd_ctrl);
1393 void FreeSounds(int num_sounds)
1397 if (!audio.sound_available)
1400 for(i=0; i<num_sounds; i++)
1401 #if defined(TARGET_SDL)
1402 free(Sound[i].mix_chunk);
1403 #elif !defined(PLATFORM_MSDOS)
1404 free(Sound[i].data_ptr);
1406 destroy_sample(Sound[i].sample_ptr);
1410 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1411 /* ========================================================================= */