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 LoadSoundExt(char *sound_name, boolean is_music)
945 struct SampleInfo *snd_info;
947 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
948 byte sound_header_buffer[WAV_HEADER_SIZE];
949 char chunk_name[CHUNK_ID_LEN + 1];
955 if (!audio.sound_available)
959 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
961 snd_info = &Sound[num_sounds - 1];
962 snd_info->data_len = 0;
963 snd_info->data_ptr = NULL;
965 snd_info->name = sound_name;
969 filename = getPath2(options.music_directory, sound_name);
971 filename = getStringCopy(sound_name);
973 #if defined(TARGET_SDL)
975 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
977 Error(ERR_WARN, "cannot read sound file '%s'", filename);
982 #elif defined(PLATFORM_UNIX)
984 if ((file = fopen(filename, MODE_READ)) == NULL)
986 Error(ERR_WARN, "cannot open sound file '%s'", filename);
991 /* read chunk id "RIFF" */
992 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
993 if (strcmp(chunk_name, "RIFF") != 0)
995 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1001 /* read "RIFF" type id "WAVE" */
1002 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1003 if (strcmp(chunk_name, "WAVE") != 0)
1005 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1011 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1014 printf("DEBUG: file '%s', chunk id '%s', chunk size '%d' [%d]\n",
1015 filename, chunk_name, chunk_size, feof(file));
1018 if (strcmp(chunk_name, "fmt ") == 0)
1020 /* read header information */
1021 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1022 sound_header_buffer[i] = fgetc(file);
1024 if (chunk_size > WAV_HEADER_SIZE)
1025 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1027 else if (strcmp(chunk_name, "data") == 0)
1029 snd_info->data_len = chunk_size;
1030 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1032 /* read sound data */
1033 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1036 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1042 /* check for odd number of sample bytes (data chunk is word aligned) */
1043 if ((chunk_size % 2) == 1)
1044 ReadUnusedBytesFromFile(file, 1);
1046 else /* unknown chunk -- ignore */
1047 ReadUnusedBytesFromFile(file, chunk_size);
1052 if (snd_info->data_ptr == NULL)
1054 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1059 for (i=0; i<snd_info->data_len; i++)
1060 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
1062 #else /* PLATFORM_MSDOS */
1064 snd_info->sample_ptr = load_sample(filename);
1065 if (!snd_info->sample_ptr)
1067 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1078 boolean LoadSound(char *sound_name)
1080 return LoadSoundExt(sound_name, FALSE);
1083 boolean LoadCustomSound(char *basename)
1085 char *filename = getCustomSoundFilename(basename);
1087 if (filename == NULL)
1089 Error(ERR_WARN, "cannot find sound file '%s' -- no sounds", filename);
1093 return LoadSound(filename);
1096 boolean LoadMod(char *mod_name)
1098 #if defined(TARGET_SDL)
1099 struct SampleInfo *mod_info;
1103 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
1105 mod_info = &Mod[num_mods - 1];
1106 mod_info->name = mod_name;
1108 filename = getPath2(options.music_directory, mod_info->name);
1110 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
1112 Error(ERR_WARN, "cannot read music file '%s' -- no music", filename);
1128 struct dirent *dir_entry;
1129 int num_wav_music = 0;
1130 int num_mod_music = 0;
1132 if (!audio.sound_available)
1135 if ((dir = opendir(options.music_directory)) == NULL)
1137 Error(ERR_WARN, "cannot read music directory '%s'",
1138 options.music_directory);
1139 audio.music_available = FALSE;
1143 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1145 char *filename = dir_entry->d_name;
1147 if (FileIsSound(filename) && LoadSoundExt(filename, TRUE))
1149 else if (FileIsMusic(filename) && LoadMod(filename))
1155 if (num_wav_music == 0 && num_mod_music == 0)
1156 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1157 options.music_directory);
1159 num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1161 audio.mods_available = (num_mod_music > 0);
1162 audio.music_available = (num_music > 0);
1167 void PlayMusic(int nr)
1169 if (!audio.music_available)
1172 if (!audio.mods_available)
1173 nr = num_sounds - num_music + nr;
1175 #if defined(TARGET_SDL)
1176 if (audio.mods_available) /* play MOD music */
1178 Mix_PlayMusic(Mod[nr].mix_music, -1);
1179 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1181 else /* play WAV music loop */
1183 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1184 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1187 audio.music_nr = nr;
1192 void PlaySound(int nr)
1194 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1197 void PlaySoundStereo(int nr, int stereo)
1199 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1202 void PlaySoundLoop(int nr)
1204 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1207 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1209 struct SoundControl snd_ctrl = emptySoundControl;
1211 if (!audio.sound_available ||
1212 !audio.sound_enabled ||
1213 audio.sound_deactivated)
1216 if (volume<PSND_MIN_VOLUME)
1217 volume = PSND_MIN_VOLUME;
1218 else if (volume>PSND_MAX_VOLUME)
1219 volume = PSND_MAX_VOLUME;
1221 if (stereo<PSND_MAX_LEFT)
1222 stereo = PSND_MAX_LEFT;
1223 else if (stereo>PSND_MAX_RIGHT)
1224 stereo = PSND_MAX_RIGHT;
1227 snd_ctrl.volume = volume;
1228 snd_ctrl.stereo = stereo;
1229 snd_ctrl.loop = loop;
1230 snd_ctrl.active = TRUE;
1231 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1232 snd_ctrl.data_len = Sound[nr].data_len;
1234 #if defined(TARGET_SDL)
1235 Mix_Volume(-1, SOUND_MAX_VOLUME);
1236 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1237 #elif defined(PLATFORM_UNIX)
1238 if (audio.soundserver_pid == 0) /* we are child process */
1241 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1243 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1244 audio.sound_available = audio.sound_enabled = FALSE;
1247 #elif defined(PLATFORM_MSDOS)
1248 sound_handler(snd_ctrl);
1252 void FadeMusic(void)
1254 #if defined(TARGET_SDL)
1255 if (!audio.sound_available)
1258 if (audio.mods_available)
1259 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1261 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1263 FadeSound(audio.music_nr);
1267 void FadeSound(int nr)
1269 StopSoundExt(nr, SSND_FADE_SOUND);
1275 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1278 void StopMusic(void)
1280 #if defined(TARGET_SDL)
1281 if (!audio.sound_available)
1284 if (audio.mods_available)
1287 Mix_HaltChannel(audio.music_channel);
1289 StopSound(audio.music_nr);
1293 void StopSound(int nr)
1295 StopSoundExt(nr, SSND_STOP_SOUND);
1300 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1303 void StopSoundExt(int nr, int method)
1305 struct SoundControl snd_ctrl = emptySoundControl;
1307 if (!audio.sound_available)
1310 if (SSND_FADING(method))
1311 snd_ctrl.fade_sound = TRUE;
1313 if (SSND_ALL(method))
1314 snd_ctrl.stop_all_sounds = TRUE;
1318 snd_ctrl.stop_sound = TRUE;
1321 #if defined(TARGET_SDL)
1323 if (SSND_FADING(method))
1327 for (i=0; i<audio.channels; i++)
1328 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1329 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1330 if (snd_ctrl.stop_all_sounds)
1331 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1337 for (i=0; i<audio.channels; i++)
1338 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1340 if (snd_ctrl.stop_all_sounds)
1345 #if !defined(PLATFORM_MSDOS)
1346 if (audio.soundserver_pid == 0) /* we are child process */
1349 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1351 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1352 audio.sound_available = audio.sound_enabled = FALSE;
1356 sound_handler(snd_ctrl);
1361 void InitReloadSounds(char *set_name)
1363 struct SoundControl snd_ctrl = emptySoundControl;
1365 if (!audio.sound_available)
1368 snd_ctrl.reload_sounds = TRUE;
1370 #if defined(TARGET_SDL)
1372 #elif defined(PLATFORM_UNIX)
1373 if (audio.soundserver_pid == 0) /* we are child process */
1376 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1378 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1379 audio.sound_available = audio.sound_enabled = FALSE;
1382 #elif defined(PLATFORM_MSDOS)
1383 sound_handler(snd_ctrl);
1387 void InitReloadMusic(char *set_name)
1389 struct SoundControl snd_ctrl = emptySoundControl;
1391 if (!audio.sound_available)
1394 snd_ctrl.reload_music = TRUE;
1396 #if defined(TARGET_SDL)
1398 #elif defined(PLATFORM_UNIX)
1399 if (audio.soundserver_pid == 0) /* we are child process */
1402 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1404 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1405 audio.sound_available = audio.sound_enabled = FALSE;
1408 #elif defined(PLATFORM_MSDOS)
1409 sound_handler(snd_ctrl);
1413 void FreeSounds(int num_sounds)
1417 if (!audio.sound_available)
1420 for(i=0; i<num_sounds; i++)
1421 #if defined(TARGET_SDL)
1422 free(Sound[i].mix_chunk);
1423 #elif !defined(PLATFORM_MSDOS)
1424 free(Sound[i].data_ptr);
1426 destroy_sample(Sound[i].sample_ptr);
1430 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1431 /* ========================================================================= */