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 ***********************************************************/
26 static int num_sounds = 0, num_music = 0;
27 static struct SampleInfo *Sound = NULL;
28 #if defined(TARGET_SDL)
29 static int num_mods = 0;
30 static struct SampleInfo *Mod = NULL;
34 /* ========================================================================= */
35 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
37 static int playing_sounds = 0;
38 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
39 static struct SoundControl emptySoundControl =
41 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
44 #if defined(PLATFORM_UNIX)
45 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
46 static char premix_first_buffer[SND_BLOCKSIZE];
47 #if defined(AUDIO_STREAMING_DSP)
48 static char premix_left_buffer[SND_BLOCKSIZE];
49 static char premix_right_buffer[SND_BLOCKSIZE];
50 static int premix_last_buffer[SND_BLOCKSIZE];
52 static unsigned char playing_buffer[SND_BLOCKSIZE];
55 /* forward declaration of internal functions */
56 #if defined(AUDIO_STREAMING_DSP)
57 static void SoundServer_InsertNewSound(struct SoundControl);
58 #elif defined(PLATFORM_UNIX)
59 static unsigned char linear_to_ulaw(int);
60 static int ulaw_to_linear(unsigned char);
63 #if defined(AUDIO_LINUX_IOCTL)
64 static boolean InitAudioDevice_Linux();
65 #elif defined(PLATFORM_NETBSD)
66 static boolean InitAudioDevice_NetBSD();
67 #elif defined(PLATFORM_HPUX)
68 static boolean InitAudioDevice_HPUX();
69 #elif defined(PLATFORM_MSDOS)
70 static void SoundServer_InsertNewSound(struct SoundControl);
71 static void SoundServer_StopSound(int);
72 static void SoundServer_StopAllSounds();
75 #if defined(PLATFORM_UNIX)
76 static int OpenAudioDevice(char *audio_device_name)
80 /* check if desired audio device is accessible */
81 if (access(audio_device_name, W_OK) != 0)
84 /* try to open audio device in non-blocking mode */
85 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
88 /* re-open audio device in blocking mode */
90 audio_fd = open(audio_device_name, O_WRONLY);
95 static boolean TestAudioDevices(void)
97 static char *audio_device_name[] =
105 /* look for available audio devices, starting with preferred ones */
106 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
107 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
112 Error(ERR_WARN, "cannot open audio device -- no sound");
118 audio.device_name = audio_device_name[i];
123 #if !defined(TARGET_SDL)
124 static boolean ForkAudioProcess(void)
126 if (pipe(audio.soundserver_pipe) < 0)
128 Error(ERR_WARN, "cannot create pipe -- no sounds");
132 if ((audio.soundserver_pid = fork()) < 0)
134 Error(ERR_WARN, "cannot create sound server process -- no sounds");
138 if (audio.soundserver_pid == 0) /* we are child */
145 else /* we are parent */
146 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
152 void UnixOpenAudio(void)
154 if (!TestAudioDevices())
157 audio.sound_available = TRUE;
158 audio.sound_enabled = TRUE;
160 #if defined(AUDIO_STREAMING_DSP)
161 audio.music_available = TRUE;
162 audio.loops_available = TRUE;
166 void UnixCloseAudio(void)
169 close(audio.device_fd);
171 if (audio.soundserver_pid)
172 kill(audio.soundserver_pid, SIGTERM);
174 #endif /* PLATFORM_UNIX */
176 void InitPlaylist(void)
180 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
181 playlist[i] = emptySoundControl;
185 void StartSoundserver(void)
187 if (!audio.sound_available)
190 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
191 if (!ForkAudioProcess())
192 audio.sound_available = FALSE;
196 #if defined(PLATFORM_UNIX)
197 void SoundServer(void)
201 struct SoundControl snd_ctrl;
204 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
208 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
209 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
211 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
213 #if defined(PLATFORM_HPUX)
214 InitAudioDevice_HPUX();
217 FD_ZERO(&sound_fdset);
218 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
220 while(1) /* wait for sound playing commands from client */
222 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
223 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
224 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
226 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
228 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
230 #if defined(AUDIO_STREAMING_DSP)
232 if (snd_ctrl.fade_sound)
237 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
238 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
239 playlist[i].fade_sound = TRUE;
241 else if (snd_ctrl.stop_all_sounds)
246 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
247 playlist[i]=emptySoundControl;
250 close(audio.device_fd);
252 else if (snd_ctrl.stop_sound)
257 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
258 if (playlist[i].nr == snd_ctrl.nr)
260 playlist[i]=emptySoundControl;
265 close(audio.device_fd);
268 if (playing_sounds || snd_ctrl.active)
270 struct timeval delay = { 0, 0 };
273 static long max_sample_size = 0;
274 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
275 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
276 boolean stereo = TRUE;
278 if (playing_sounds ||
279 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
281 if (!playing_sounds) /* we just opened the audio device */
283 #if defined(AUDIO_LINUX_IOCTL)
284 stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
285 #elif defined(PLATFORM_NETBSD)
286 stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
288 max_sample_size = fragment_size / (stereo ? 2 : 1);
291 if (snd_ctrl.active) /* new sound has arrived */
292 SoundServer_InsertNewSound(snd_ctrl);
294 while(playing_sounds &&
295 select(audio.soundserver_pipe[0] + 1,
296 &sound_fdset, NULL, NULL, &delay) < 1)
298 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
300 /* first clear the last premixing buffer */
301 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
303 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
307 if (!playlist[i].active)
310 /* get pointer and size of the actual sound sample */
311 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
313 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
314 playlist[i].playingpos += sample_size;
316 /* fill the first mixing buffer with original sample */
317 memcpy(premix_first_buffer,sample_ptr,sample_size);
319 /* are we about to restart a looping sound? */
320 if (playlist[i].loop && sample_size<max_sample_size)
322 playlist[i].playingpos = max_sample_size-sample_size;
323 memcpy(premix_first_buffer+sample_size,
324 playlist[i].data_ptr,max_sample_size-sample_size);
325 sample_size = max_sample_size;
328 /* decrease volume if sound is fading out */
329 if (playlist[i].fade_sound &&
330 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
331 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
333 /* adjust volume of actual sound sample */
334 if (playlist[i].volume != PSND_MAX_VOLUME)
335 for(j=0;j<sample_size;j++)
336 premix_first_buffer[j] =
337 (playlist[i].volume * (int)premix_first_buffer[j])
338 >> PSND_MAX_VOLUME_BITS;
340 /* fill the last mixing buffer with stereo or mono sound */
343 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
344 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
345 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
347 for(j=0;j<sample_size;j++)
349 premix_left_buffer[j] =
350 (left_volume * (int)premix_first_buffer[j])
351 >> PSND_MAX_LEFT2RIGHT_BITS;
352 premix_right_buffer[j] =
353 (right_volume * (int)premix_first_buffer[j])
354 >> PSND_MAX_LEFT2RIGHT_BITS;
355 premix_last_buffer[2*j+0] += premix_left_buffer[j];
356 premix_last_buffer[2*j+1] += premix_right_buffer[j];
361 for(j=0;j<sample_size;j++)
362 premix_last_buffer[j] += (int)premix_first_buffer[j];
365 /* delete completed sound entries from the playlist */
366 if (playlist[i].playingpos >= playlist[i].data_len)
368 if (playlist[i].loop)
369 playlist[i].playingpos = 0;
372 playlist[i] = emptySoundControl;
376 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
378 playlist[i] = emptySoundControl;
383 /* put last mixing buffer to final playing buffer */
384 for(i=0; i<fragment_size; i++)
386 if (premix_last_buffer[i]<-255)
387 playing_buffer[i] = 0;
388 else if (premix_last_buffer[i]>255)
389 playing_buffer[i] = 255;
391 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
394 /* finally play the sound fragment */
395 write(audio.device_fd, playing_buffer, fragment_size);
398 /* if no sounds playing, free device for other sound programs */
400 close(audio.device_fd);
404 #else /* !AUDIO_STREAMING_DSP */
406 if (snd_ctrl.active && !snd_ctrl.loop)
408 struct timeval delay = { 0, 0 };
410 long sample_size, max_sample_size = SND_BLOCKSIZE;
411 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
412 int wait_percent = 90; /* wait 90% of the real playing time */
415 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
419 while(playing_sounds &&
420 select(audio.soundserver_pipe[0] + 1,
421 &sound_fdset, NULL, NULL, &delay) < 1)
423 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
425 /* get pointer and size of the actual sound sample */
426 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
428 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
429 snd_ctrl.playingpos += sample_size;
431 /* fill the first mixing buffer with original sample */
432 memcpy(premix_first_buffer,sample_ptr,sample_size);
434 /* adjust volume of actual sound sample */
435 if (snd_ctrl.volume != PSND_MAX_VOLUME)
436 for(i=0;i<sample_size;i++)
437 premix_first_buffer[i] =
438 (snd_ctrl.volume * (int)premix_first_buffer[i])
439 >> PSND_MAX_VOLUME_BITS;
441 for(i=0;i<sample_size;i++)
443 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
445 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
448 /* finally play the sound fragment */
449 write(audio.device_fd,playing_buffer,sample_size);
452 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
454 close(audio.device_fd);
457 #endif /* !AUDIO_STREAMING_DSP */
460 #endif /* PLATFORM_UNIX */
462 #if defined(PLATFORM_MSDOS)
463 static void sound_handler(struct SoundControl snd_ctrl)
467 if (snd_ctrl.fade_sound)
472 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
473 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
474 !playlist[i].fade_sound)
476 playlist[i].fade_sound = TRUE;
477 if (voice_check(playlist[i].voice))
478 voice_ramp_volume(playlist[i].voice, 1000, 0);
479 playlist[i].loop = PSND_NO_LOOP;
482 else if (snd_ctrl.stop_all_sounds)
486 SoundServer_StopAllSounds();
488 else if (snd_ctrl.stop_sound)
492 SoundServer_StopSound(snd_ctrl.nr);
495 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
497 if (!playlist[i].active || playlist[i].loop)
500 playlist[i].playingpos = voice_get_position(playlist[i].voice);
501 playlist[i].volume = voice_get_volume(playlist[i].voice);
502 if (playlist[i].playingpos == -1 || !playlist[i].volume)
504 deallocate_voice(playlist[i].voice);
505 playlist[i] = emptySoundControl;
511 SoundServer_InsertNewSound(snd_ctrl);
513 #endif /* PLATFORM_MSDOS */
515 #if !defined(PLATFORM_WIN32)
516 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
520 /* if playlist is full, remove oldest sound */
521 if (playing_sounds==MAX_SOUNDS_PLAYING)
523 int longest=0, longest_nr=0;
525 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
527 #if !defined(PLATFORM_MSDOS)
528 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
530 int actual = playlist[i].playingpos;
533 if (!playlist[i].loop && actual>longest)
539 #if defined(PLATFORM_MSDOS)
540 voice_set_volume(playlist[longest_nr].voice, 0);
541 deallocate_voice(playlist[longest_nr].voice);
543 playlist[longest_nr] = emptySoundControl;
547 /* check if sound is already being played (and how often) */
548 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
550 if (playlist[i].nr == snd_ctrl.nr)
554 /* restart loop sounds only if they are just fading out */
555 if (k>=1 && snd_ctrl.loop)
557 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
559 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
561 playlist[i].fade_sound = FALSE;
562 playlist[i].volume = PSND_MAX_VOLUME;
563 #if defined(PLATFORM_MSDOS)
564 playlist[i].loop = PSND_LOOP;
565 voice_stop_volumeramp(playlist[i].voice);
566 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
573 /* don't play sound more than n times simultaneously (with n == 2 for now) */
576 int longest=0, longest_nr=0;
578 /* look for oldest equal sound */
579 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
583 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
586 #if !defined(PLATFORM_MSDOS)
587 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
589 actual = playlist[i].playingpos;
598 #if defined(PLATFORM_MSDOS)
599 voice_set_volume(playlist[longest_nr].voice, 0);
600 deallocate_voice(playlist[longest_nr].voice);
602 playlist[longest_nr] = emptySoundControl;
606 /* neuen Sound in Liste packen */
607 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
609 if (!playlist[i].active)
611 playlist[i] = snd_ctrl;
614 #if defined(PLATFORM_MSDOS)
615 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
617 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
618 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
619 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
620 voice_start(playlist[i].voice);
626 #endif /* !PLATFORM_WIN32 */
629 void SoundServer_FadeSound(int nr)
636 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
637 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
638 playlist[i].fade_sound = TRUE;
642 #if !defined(PLATFORM_WIN32)
643 #if defined(PLATFORM_MSDOS)
644 static void SoundServer_StopSound(int nr)
651 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
652 if (playlist[i].nr == nr)
654 #if defined(PLATFORM_MSDOS)
655 voice_set_volume(playlist[i].voice, 0);
656 deallocate_voice(playlist[i].voice);
658 playlist[i] = emptySoundControl;
662 #if !defined(PLATFORM_MSDOS)
664 close(audio.device_fd);
668 static void SoundServer_StopAllSounds()
672 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
674 #if defined(PLATFORM_MSDOS)
675 voice_set_volume(playlist[i].voice, 0);
676 deallocate_voice(playlist[i].voice);
678 playlist[i]=emptySoundControl;
682 #if !defined(PLATFORM_MSDOS)
683 close(audio.device_fd);
686 #endif /* PLATFORM_MSDOS */
687 #endif /* !PLATFORM_WIN32 */
690 /* ------------------------------------------------------------------------- */
691 /* platform dependant audio initialization code */
692 /* ------------------------------------------------------------------------- */
694 #if defined(AUDIO_LINUX_IOCTL)
695 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
697 /* "ioctl()" expects pointer to 'int' value for stereo flag
698 (boolean is defined as 'char', which will not work here) */
700 unsigned long fragment_spec = 0;
702 /* determine logarithm (log2) of the fragment size */
703 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
706 /* use two fragments (play one fragment, prepare the other);
707 one fragment would result in interrupted audio output, more
708 than two fragments would raise audio output latency to much */
709 fragment_spec |= 0x00020000;
711 /* Example for fragment specification:
712 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
713 - (with stereo the effective buffer size will shrink to 256)
714 => fragment_size = 0x00020009 */
716 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
717 Error(ERR_EXIT_SOUND_SERVER,
718 "cannot set fragment size of /dev/dsp -- no sounds");
720 /* try if we can use stereo sound */
721 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
724 static boolean reported = FALSE;
728 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
735 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
736 Error(ERR_EXIT_SOUND_SERVER,
737 "cannot set sample rate of /dev/dsp -- no sounds");
739 /* get the real fragmentation size; this should return 512 */
740 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
741 Error(ERR_EXIT_SOUND_SERVER,
742 "cannot get fragment size of /dev/dsp -- no sounds");
744 return (boolean)stereo;
746 #endif /* AUDIO_LINUX_IOCTL */
748 #if defined(PLATFORM_NETBSD)
749 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
752 boolean stereo = TRUE;
754 AUDIO_INITINFO(&a_info);
755 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
756 a_info.play.precision = 8;
757 a_info.play.channels = 2;
758 a_info.play.sample_rate = sample_rate;
759 a_info.blocksize = fragment_size;
761 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
763 /* try to disable stereo */
764 a_info.play.channels = 1;
767 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
768 Error(ERR_EXIT_SOUND_SERVER,
769 "cannot set sample rate of /dev/audio -- no sounds");
774 #endif /* PLATFORM_NETBSD */
776 #if defined(PLATFORM_HPUX)
777 static boolean InitAudioDevice_HPUX()
779 struct audio_describe ainfo;
782 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
784 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
786 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
787 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
789 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
790 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
792 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
793 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
797 return TRUE; /* to provide common interface for InitAudioDevice_...() */
799 #endif /* PLATFORM_HPUX */
801 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
803 /* these two are stolen from "sox"... :) */
806 ** This routine converts from linear to ulaw.
808 ** Craig Reese: IDA/Supercomputing Research Center
809 ** Joe Campbell: Department of Defense
813 ** 1) CCITT Recommendation G.711 (very difficult to follow)
814 ** 2) "A New Digital Technique for Implementation of Any
815 ** Continuous PCM Companding Law," Villeret, Michel,
816 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
817 ** 1973, pg. 11.12-11.17
818 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
819 ** for Analog-to_Digital Conversion Techniques,"
822 ** Input: Signed 16 bit linear sample
823 ** Output: 8 bit ulaw sample
826 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
827 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
830 static unsigned char linear_to_ulaw(int sample)
832 static int exp_lut[256] =
834 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
835 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
836 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
837 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
838 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
839 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
840 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
841 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
842 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
843 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
844 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
845 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
846 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
847 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
848 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
849 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
852 int sign, exponent, mantissa;
853 unsigned char ulawbyte;
855 /* Get the sample into sign-magnitude. */
856 sign = (sample >> 8) & 0x80; /* set aside the sign */
858 sample = -sample; /* get magnitude */
860 sample = CLIP; /* clip the magnitude */
862 /* Convert from 16 bit linear to ulaw. */
863 sample = sample + BIAS;
864 exponent = exp_lut[( sample >> 7 ) & 0xFF];
865 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
866 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
869 ulawbyte = 0x02; /* optional CCITT trap */
876 ** This routine converts from ulaw to 16 bit linear.
878 ** Craig Reese: IDA/Supercomputing Research Center
882 ** 1) CCITT Recommendation G.711 (very difficult to follow)
883 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
884 ** for Analog-to_Digital Conversion Techniques,"
887 ** Input: 8 bit ulaw sample
888 ** Output: signed 16 bit linear sample
891 static int ulaw_to_linear(unsigned char ulawbyte)
893 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
894 int sign, exponent, mantissa, sample;
896 ulawbyte = ~ ulawbyte;
897 sign = ( ulawbyte & 0x80 );
898 exponent = ( ulawbyte >> 4 ) & 0x07;
899 mantissa = ulawbyte & 0x0F;
900 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
906 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
909 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
910 /* ========================================================================= */
911 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
914 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
915 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
917 static boolean LoadSoundExt(char *sound_name, boolean is_music)
919 struct SampleInfo *snd_info;
921 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
922 byte sound_header_buffer[WAV_HEADER_SIZE];
923 char chunk[CHUNK_ID_LEN + 1];
924 int chunk_size, dummy;
929 if (!audio.sound_available)
933 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
935 snd_info = &Sound[num_sounds - 1];
936 snd_info->name = sound_name;
938 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
939 (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name);
941 #if defined(TARGET_SDL)
943 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
945 Error(ERR_WARN, "cannot read sound file '%s' -- no sounds", filename);
949 #elif defined(PLATFORM_UNIX)
951 if ((file = fopen(filename, MODE_READ)) == NULL)
953 Error(ERR_WARN, "cannot open sound file '%s' -- no sounds", filename);
957 /* read chunk "RIFF" */
958 getFileChunk(file, chunk, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
959 if (strcmp(chunk, "RIFF") != 0)
961 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
966 /* read chunk "WAVE" */
967 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
968 if (strcmp(chunk, "WAVE") != 0)
970 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
975 /* read header information */
976 for (i=0; i<WAV_HEADER_SIZE; i++)
977 sound_header_buffer[i] = fgetc(file);
979 /* read chunk "data" */
980 getFileChunk(file, chunk, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
981 if (strcmp(chunk, "data") != 0)
983 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
988 snd_info->data_len = chunk_size;
989 snd_info->data_ptr = checked_malloc(snd_info->data_len);
991 /* read sound data */
992 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
995 Error(ERR_WARN, "cannot read sound file '%s' -- no sounds", filename);
1002 for (i=0; i<snd_info->data_len; i++)
1003 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
1005 #else /* PLATFORM_MSDOS */
1007 snd_info->sample_ptr = load_sample(filename);
1008 if (!snd_info->sample_ptr)
1010 Error(ERR_WARN, "cannot read sound file '%s' -- no sounds", filename);
1019 boolean LoadSound(char *sound_name)
1021 return LoadSoundExt(sound_name, FALSE);
1024 boolean LoadMod(char *mod_name)
1026 #if defined(TARGET_SDL)
1027 struct SampleInfo *mod_info;
1031 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
1033 mod_info = &Mod[num_mods - 1];
1034 mod_info->name = mod_name;
1036 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
1037 MUSIC_DIRECTORY, mod_info->name);
1039 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
1041 Error(ERR_WARN, "cannot read music file '%s' -- no music", filename);
1054 struct dirent *dir_entry;
1055 char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
1056 int num_wav_music = 0;
1057 int num_mod_music = 0;
1059 if (!audio.sound_available)
1062 if ((dir = opendir(music_directory)) == NULL)
1064 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1065 audio.music_available = FALSE;
1066 free(music_directory);
1070 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1072 char *filename = dir_entry->d_name;
1074 if (strlen(filename) > 4 &&
1075 strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
1077 if (LoadSoundExt(filename, TRUE))
1080 else if (strlen(filename) > 4 &&
1081 (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
1082 strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
1083 strncmp(filename, "mod.", 4) == 0 ||
1084 strncmp(filename, "MOD.", 4) == 0))
1086 if (LoadMod(filename))
1093 if (num_wav_music == 0 && num_mod_music == 0)
1094 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1097 free(music_directory);
1099 num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1101 audio.mods_available = (num_mod_music > 0);
1102 audio.music_available = (num_music > 0);
1107 void PlayMusic(int nr)
1109 if (!audio.music_available)
1112 if (!audio.mods_available)
1113 nr = num_sounds - num_music + nr;
1115 #if defined(TARGET_SDL)
1116 if (audio.mods_available) /* play MOD music */
1118 Mix_PlayMusic(Mod[nr].mix_music, -1);
1119 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1121 else /* play WAV music loop */
1123 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1124 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1127 audio.music_nr = nr;
1132 void PlaySound(int nr)
1134 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1137 void PlaySoundStereo(int nr, int stereo)
1139 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1142 void PlaySoundLoop(int nr)
1144 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1147 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1149 struct SoundControl snd_ctrl = emptySoundControl;
1151 if (!audio.sound_available || !audio.sound_enabled)
1154 if (volume<PSND_MIN_VOLUME)
1155 volume = PSND_MIN_VOLUME;
1156 else if (volume>PSND_MAX_VOLUME)
1157 volume = PSND_MAX_VOLUME;
1159 if (stereo<PSND_MAX_LEFT)
1160 stereo = PSND_MAX_LEFT;
1161 else if (stereo>PSND_MAX_RIGHT)
1162 stereo = PSND_MAX_RIGHT;
1165 snd_ctrl.volume = volume;
1166 snd_ctrl.stereo = stereo;
1167 snd_ctrl.loop = loop;
1168 snd_ctrl.active = TRUE;
1169 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1170 snd_ctrl.data_len = Sound[nr].data_len;
1172 #if defined(TARGET_SDL)
1173 Mix_Volume(-1, SOUND_MAX_VOLUME);
1174 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1175 #elif defined(PLATFORM_UNIX)
1176 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1178 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1179 audio.sound_available = audio.sound_enabled = FALSE;
1182 #elif defined(PLATFORM_MSDOS)
1183 sound_handler(snd_ctrl);
1187 void FadeMusic(void)
1189 #if defined(TARGET_SDL)
1190 if (!audio.sound_available)
1193 if (audio.mods_available)
1194 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1196 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1198 FadeSound(audio.music_nr);
1202 void FadeSound(int nr)
1204 StopSoundExt(nr, SSND_FADE_SOUND);
1210 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1213 void StopMusic(void)
1215 #if defined(TARGET_SDL)
1216 if (!audio.sound_available)
1219 if (audio.mods_available)
1222 Mix_HaltChannel(audio.music_channel);
1224 StopSound(audio.music_nr);
1228 void StopSound(int nr)
1230 StopSoundExt(nr, SSND_STOP_SOUND);
1235 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1238 void StopSoundExt(int nr, int method)
1240 struct SoundControl snd_ctrl = emptySoundControl;
1242 if (!audio.sound_available)
1245 if (SSND_FADING(method))
1246 snd_ctrl.fade_sound = TRUE;
1248 if (SSND_ALL(method))
1249 snd_ctrl.stop_all_sounds = TRUE;
1253 snd_ctrl.stop_sound = TRUE;
1256 #if defined(TARGET_SDL)
1258 if (SSND_FADING(method))
1262 for (i=0; i<audio.channels; i++)
1263 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1264 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1265 if (snd_ctrl.stop_all_sounds)
1266 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1272 for (i=0; i<audio.channels; i++)
1273 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1275 if (snd_ctrl.stop_all_sounds)
1280 #if !defined(PLATFORM_MSDOS)
1281 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1283 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1284 audio.sound_available = audio.sound_enabled = FALSE;
1288 sound_handler(snd_ctrl);
1293 void FreeSounds(int num_sounds)
1297 if (!audio.sound_available)
1300 for(i=0; i<num_sounds; i++)
1301 #if defined(TARGET_SDL)
1302 free(Sound[i].mix_chunk);
1303 #elif !defined(PLATFORM_MSDOS)
1304 free(Sound[i].data_ptr);
1306 destroy_sample(Sound[i].sample_ptr);
1310 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1311 /* ========================================================================= */