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 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
36 static int playing_sounds = 0;
37 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
38 static struct SoundControl emptySoundControl =
40 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
43 #if defined(PLATFORM_UNIX)
44 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
45 static char premix_first_buffer[SND_BLOCKSIZE];
46 #if defined(AUDIO_STREAMING_DSP)
47 static char premix_left_buffer[SND_BLOCKSIZE];
48 static char premix_right_buffer[SND_BLOCKSIZE];
49 static int premix_last_buffer[SND_BLOCKSIZE];
51 static unsigned char playing_buffer[SND_BLOCKSIZE];
54 /* forward declaration of internal functions */
55 #if defined(AUDIO_STREAMING_DSP)
56 static void SoundServer_InsertNewSound(struct SoundControl);
57 #elif defined(PLATFORM_UNIX)
58 static unsigned char linear_to_ulaw(int);
59 static int ulaw_to_linear(unsigned char);
62 #if defined(PLATFORM_HPUX)
63 static void HPUX_Audio_Control();
66 #if defined(PLATFORM_MSDOS)
67 static void SoundServer_InsertNewSound(struct SoundControl);
68 static void SoundServer_StopSound(int);
69 static void SoundServer_StopAllSounds();
72 #if defined(PLATFORM_UNIX)
73 static int OpenAudioDevice(char *audio_device_name)
77 /* check if desired audio device is accessible */
78 if (access(audio_device_name, W_OK) != 0)
81 /* try to open audio device in non-blocking mode */
82 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
85 /* re-open audio device in blocking mode */
87 audio_fd = open(audio_device_name, O_WRONLY);
92 static boolean TestAudioDevices(void)
94 static char *audio_device_name[] =
102 /* look for available audio devices, starting with preferred ones */
103 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
104 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
109 Error(ERR_WARN, "cannot open audio device - no sound");
115 audio.device_name = audio_device_name[i];
120 #if !defined(TARGET_SDL)
121 static boolean ForkAudioProcess(void)
123 if (pipe(audio.soundserver_pipe) < 0)
125 Error(ERR_WARN, "cannot create pipe - no sounds");
129 if ((audio.soundserver_pid = fork()) < 0)
131 Error(ERR_WARN, "cannot create sound server process - no sounds");
135 if (audio.soundserver_pid == 0) /* we are child */
142 else /* we are parent */
143 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
149 void UnixOpenAudio(void)
151 if (!TestAudioDevices())
154 audio.sound_available = TRUE;
155 audio.sound_enabled = TRUE;
157 #if defined(AUDIO_STREAMING_DSP)
158 audio.music_available = TRUE;
159 audio.loops_available = TRUE;
163 void UnixCloseAudio(void)
166 close(audio.device_fd);
168 if (audio.soundserver_pid)
169 kill(audio.soundserver_pid, SIGTERM);
171 #endif /* PLATFORM_UNIX */
173 void InitPlaylist(void)
177 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
178 playlist[i] = emptySoundControl;
182 void StartSoundserver(void)
184 if (!audio.sound_available)
187 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
188 if (!ForkAudioProcess())
189 audio.sound_available = FALSE;
193 #if defined(PLATFORM_UNIX)
194 void SoundServer(void)
198 struct SoundControl snd_ctrl;
201 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
205 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
206 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
208 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
210 #if defined(PLATFORM_HPUX)
211 HPUX_Audio_Control();
214 FD_ZERO(&sound_fdset);
215 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
217 while(1) /* wait for sound playing commands from client */
219 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
220 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
221 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
223 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
225 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
227 #if defined(AUDIO_STREAMING_DSP)
229 if (snd_ctrl.fade_sound)
234 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
235 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
236 playlist[i].fade_sound = TRUE;
238 else if (snd_ctrl.stop_all_sounds)
243 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
244 playlist[i]=emptySoundControl;
247 close(audio.device_fd);
249 else if (snd_ctrl.stop_sound)
254 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
255 if (playlist[i].nr == snd_ctrl.nr)
257 playlist[i]=emptySoundControl;
262 close(audio.device_fd);
265 if (playing_sounds || snd_ctrl.active)
267 struct timeval delay = { 0, 0 };
270 static long max_sample_size = 0;
271 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
272 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
274 /* 'ioctl()' expects pointer to integer value for stereo flag
275 (boolean is defined as 'char', which will not work here) */
277 if (playing_sounds ||
278 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
280 if (!playing_sounds) /* we just opened the audio device */
282 unsigned long fragment_spec = 0;
284 /* determine logarithm (log2) of the fragment size */
285 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
288 /* use two fragments (play one fragment, prepare the other);
289 one fragment would result in interrupted audio output, more
290 than two fragments would raise audio output latency to much */
291 fragment_spec |= 0x00020000;
293 /* Example for fragment specification:
294 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
295 - (with stereo the effective buffer size will shrink to 256)
296 => fragment_size = 0x00020009 */
298 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0)
299 Error(ERR_EXIT_SOUND_SERVER,
300 "cannot set fragment size of /dev/dsp - no sounds");
302 /* try if we can use stereo sound */
303 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
306 static boolean reported = FALSE;
310 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
317 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
318 Error(ERR_EXIT_SOUND_SERVER,
319 "cannot set sample rate of /dev/dsp - no sounds");
321 /* get the real fragmentation size; this should return 512 */
322 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
323 Error(ERR_EXIT_SOUND_SERVER,
324 "cannot get fragment size of /dev/dsp - no sounds");
326 max_sample_size = fragment_size / (stereo ? 2 : 1);
329 if (snd_ctrl.active) /* new sound has arrived */
330 SoundServer_InsertNewSound(snd_ctrl);
332 while(playing_sounds &&
333 select(audio.soundserver_pipe[0] + 1,
334 &sound_fdset, NULL, NULL, &delay) < 1)
336 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
338 /* first clear the last premixing buffer */
339 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
341 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
345 if (!playlist[i].active)
348 /* get pointer and size of the actual sound sample */
349 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
351 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
352 playlist[i].playingpos += sample_size;
354 /* fill the first mixing buffer with original sample */
355 memcpy(premix_first_buffer,sample_ptr,sample_size);
357 /* are we about to restart a looping sound? */
358 if (playlist[i].loop && sample_size<max_sample_size)
360 playlist[i].playingpos = max_sample_size-sample_size;
361 memcpy(premix_first_buffer+sample_size,
362 playlist[i].data_ptr,max_sample_size-sample_size);
363 sample_size = max_sample_size;
366 /* decrease volume if sound is fading out */
367 if (playlist[i].fade_sound &&
368 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
369 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
371 /* adjust volume of actual sound sample */
372 if (playlist[i].volume != PSND_MAX_VOLUME)
373 for(j=0;j<sample_size;j++)
374 premix_first_buffer[j] =
375 (playlist[i].volume * (int)premix_first_buffer[j])
376 >> PSND_MAX_VOLUME_BITS;
378 /* fill the last mixing buffer with stereo or mono sound */
381 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
382 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
383 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
385 for(j=0;j<sample_size;j++)
387 premix_left_buffer[j] =
388 (left_volume * (int)premix_first_buffer[j])
389 >> PSND_MAX_LEFT2RIGHT_BITS;
390 premix_right_buffer[j] =
391 (right_volume * (int)premix_first_buffer[j])
392 >> PSND_MAX_LEFT2RIGHT_BITS;
393 premix_last_buffer[2*j+0] += premix_left_buffer[j];
394 premix_last_buffer[2*j+1] += premix_right_buffer[j];
399 for(j=0;j<sample_size;j++)
400 premix_last_buffer[j] += (int)premix_first_buffer[j];
403 /* delete completed sound entries from the playlist */
404 if (playlist[i].playingpos >= playlist[i].data_len)
406 if (playlist[i].loop)
407 playlist[i].playingpos = 0;
410 playlist[i] = emptySoundControl;
414 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
416 playlist[i] = emptySoundControl;
421 /* put last mixing buffer to final playing buffer */
422 for(i=0; i<fragment_size; i++)
424 if (premix_last_buffer[i]<-255)
425 playing_buffer[i] = 0;
426 else if (premix_last_buffer[i]>255)
427 playing_buffer[i] = 255;
429 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
432 /* finally play the sound fragment */
433 write(audio.device_fd, playing_buffer, fragment_size);
436 /* if no sounds playing, free device for other sound programs */
438 close(audio.device_fd);
442 #else /* !AUDIO_STREAMING_DSP */
444 if (snd_ctrl.active && !snd_ctrl.loop)
446 struct timeval delay = { 0, 0 };
448 long sample_size, max_sample_size = SND_BLOCKSIZE;
449 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
450 int wait_percent = 90; /* wait 90% of the real playing time */
453 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
457 while(playing_sounds &&
458 select(audio.soundserver_pipe[0] + 1,
459 &sound_fdset, NULL, NULL, &delay) < 1)
461 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
463 /* get pointer and size of the actual sound sample */
464 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
466 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
467 snd_ctrl.playingpos += sample_size;
469 /* fill the first mixing buffer with original sample */
470 memcpy(premix_first_buffer,sample_ptr,sample_size);
473 /* adjust volume of actual sound sample */
474 if (snd_ctrl.volume != PSND_MAX_VOLUME)
475 for(i=0;i<sample_size;i++)
476 premix_first_buffer[i] =
477 (snd_ctrl.volume * (int)premix_first_buffer[i])
478 >> PSND_MAX_VOLUME_BITS;
480 for(i=0;i<sample_size;i++)
482 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
484 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
487 /* finally play the sound fragment */
488 write(audio.device_fd,playing_buffer,sample_size);
491 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
493 close(audio.device_fd);
496 #endif /* !AUDIO_STREAMING_DSP */
499 #endif /* PLATFORM_UNIX */
501 #if defined(PLATFORM_MSDOS)
502 static void sound_handler(struct SoundControl snd_ctrl)
506 if (snd_ctrl.fade_sound)
511 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
512 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
513 !playlist[i].fade_sound)
515 playlist[i].fade_sound = TRUE;
516 if (voice_check(playlist[i].voice))
517 voice_ramp_volume(playlist[i].voice, 1000, 0);
518 playlist[i].loop = PSND_NO_LOOP;
521 else if (snd_ctrl.stop_all_sounds)
525 SoundServer_StopAllSounds();
527 else if (snd_ctrl.stop_sound)
531 SoundServer_StopSound(snd_ctrl.nr);
534 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
536 if (!playlist[i].active || playlist[i].loop)
539 playlist[i].playingpos = voice_get_position(playlist[i].voice);
540 playlist[i].volume = voice_get_volume(playlist[i].voice);
541 if (playlist[i].playingpos == -1 || !playlist[i].volume)
543 deallocate_voice(playlist[i].voice);
544 playlist[i] = emptySoundControl;
550 SoundServer_InsertNewSound(snd_ctrl);
552 #endif /* PLATFORM_MSDOS */
554 #if !defined(PLATFORM_WIN32)
555 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
559 /* if playlist is full, remove oldest sound */
560 if (playing_sounds==MAX_SOUNDS_PLAYING)
562 int longest=0, longest_nr=0;
564 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
566 #if !defined(PLATFORM_MSDOS)
567 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
569 int actual = playlist[i].playingpos;
572 if (!playlist[i].loop && actual>longest)
578 #if defined(PLATFORM_MSDOS)
579 voice_set_volume(playlist[longest_nr].voice, 0);
580 deallocate_voice(playlist[longest_nr].voice);
582 playlist[longest_nr] = emptySoundControl;
586 /* check if sound is already being played (and how often) */
587 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
589 if (playlist[i].nr == snd_ctrl.nr)
593 /* restart loop sounds only if they are just fading out */
594 if (k>=1 && snd_ctrl.loop)
596 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
598 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
600 playlist[i].fade_sound = FALSE;
601 playlist[i].volume = PSND_MAX_VOLUME;
602 #if defined(PLATFORM_MSDOS)
603 playlist[i].loop = PSND_LOOP;
604 voice_stop_volumeramp(playlist[i].voice);
605 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
612 /* don't play sound more than n times simultaneously (with n == 2 for now) */
615 int longest=0, longest_nr=0;
617 /* look for oldest equal sound */
618 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
622 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
625 #if !defined(PLATFORM_MSDOS)
626 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
628 actual = playlist[i].playingpos;
637 #if defined(PLATFORM_MSDOS)
638 voice_set_volume(playlist[longest_nr].voice, 0);
639 deallocate_voice(playlist[longest_nr].voice);
641 playlist[longest_nr] = emptySoundControl;
645 /* neuen Sound in Liste packen */
646 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
648 if (!playlist[i].active)
650 playlist[i] = snd_ctrl;
653 #if defined(PLATFORM_MSDOS)
654 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
656 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
657 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
658 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
659 voice_start(playlist[i].voice);
665 #endif /* !PLATFORM_WIN32 */
668 void SoundServer_FadeSound(int nr)
675 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
676 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
677 playlist[i].fade_sound = TRUE;
681 #if !defined(PLATFORM_WIN32)
682 #if defined(PLATFORM_MSDOS)
683 static void SoundServer_StopSound(int nr)
690 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
691 if (playlist[i].nr == nr)
693 #if defined(PLATFORM_MSDOS)
694 voice_set_volume(playlist[i].voice, 0);
695 deallocate_voice(playlist[i].voice);
697 playlist[i] = emptySoundControl;
701 #if !defined(PLATFORM_MSDOS)
703 close(audio.device_fd);
707 static void SoundServer_StopAllSounds()
711 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
713 #if defined(PLATFORM_MSDOS)
714 voice_set_volume(playlist[i].voice, 0);
715 deallocate_voice(playlist[i].voice);
717 playlist[i]=emptySoundControl;
721 #if !defined(PLATFORM_MSDOS)
722 close(audio.device_fd);
725 #endif /* PLATFORM_MSDOS */
726 #endif /* !PLATFORM_WIN32 */
728 #if defined(PLATFORM_HPUX)
729 static void HPUX_Audio_Control()
731 struct audio_describe ainfo;
734 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
736 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
738 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
739 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
741 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
742 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
744 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
745 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
749 #endif /* PLATFORM_HPUX */
751 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
753 /* these two are stolen from "sox"... :) */
756 ** This routine converts from linear to ulaw.
758 ** Craig Reese: IDA/Supercomputing Research Center
759 ** Joe Campbell: Department of Defense
763 ** 1) CCITT Recommendation G.711 (very difficult to follow)
764 ** 2) "A New Digital Technique for Implementation of Any
765 ** Continuous PCM Companding Law," Villeret, Michel,
766 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
767 ** 1973, pg. 11.12-11.17
768 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
769 ** for Analog-to_Digital Conversion Techniques,"
772 ** Input: Signed 16 bit linear sample
773 ** Output: 8 bit ulaw sample
776 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
777 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
780 static unsigned char linear_to_ulaw(int sample)
782 static int exp_lut[256] =
784 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
785 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
786 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
787 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
788 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
789 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
790 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
791 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
792 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
793 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
794 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
795 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
796 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
797 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
798 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
799 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
802 int sign, exponent, mantissa;
803 unsigned char ulawbyte;
805 /* Get the sample into sign-magnitude. */
806 sign = (sample >> 8) & 0x80; /* set aside the sign */
808 sample = -sample; /* get magnitude */
810 sample = CLIP; /* clip the magnitude */
812 /* Convert from 16 bit linear to ulaw. */
813 sample = sample + BIAS;
814 exponent = exp_lut[( sample >> 7 ) & 0xFF];
815 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
816 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
819 ulawbyte = 0x02; /* optional CCITT trap */
826 ** This routine converts from ulaw to 16 bit linear.
828 ** Craig Reese: IDA/Supercomputing Research Center
832 ** 1) CCITT Recommendation G.711 (very difficult to follow)
833 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
834 ** for Analog-to_Digital Conversion Techniques,"
837 ** Input: 8 bit ulaw sample
838 ** Output: signed 16 bit linear sample
841 static int ulaw_to_linear(unsigned char ulawbyte)
843 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
844 int sign, exponent, mantissa, sample;
846 ulawbyte = ~ ulawbyte;
847 sign = ( ulawbyte & 0x80 );
848 exponent = ( ulawbyte >> 4 ) & 0x07;
849 mantissa = ulawbyte & 0x0F;
850 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
856 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
858 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
860 /*===========================================================================*/
862 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
864 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
865 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
867 static boolean LoadSoundExt(char *sound_name, boolean is_music)
869 struct SampleInfo *snd_info;
871 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
872 byte sound_header_buffer[WAV_HEADER_SIZE];
873 char chunk[CHUNK_ID_LEN + 1];
874 int chunk_length, dummy;
879 if (!audio.sound_available)
883 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
885 snd_info = &Sound[num_sounds - 1];
886 snd_info->name = sound_name;
888 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
889 (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name);
891 #if defined(TARGET_SDL)
893 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
895 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
899 #elif defined(PLATFORM_UNIX)
901 if ((file = fopen(filename, MODE_READ)) == NULL)
903 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
907 /* read chunk "RIFF" */
908 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
909 if (strcmp(chunk, "RIFF") != 0)
911 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
916 /* read chunk "WAVE" */
917 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
918 if (strcmp(chunk, "WAVE") != 0)
920 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
925 /* read header information */
926 for (i=0; i<WAV_HEADER_SIZE; i++)
927 sound_header_buffer[i] = fgetc(file);
929 /* read chunk "data" */
930 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
931 if (strcmp(chunk, "data") != 0)
933 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
938 snd_info->data_len = chunk_length;
939 snd_info->data_ptr = checked_malloc(snd_info->data_len);
941 /* read sound data */
942 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
945 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
952 for (i=0; i<snd_info->data_len; i++)
953 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
955 #else /* PLATFORM_MSDOS */
957 snd_info->sample_ptr = load_sample(filename);
958 if (!snd_info->sample_ptr)
960 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
969 boolean LoadSound(char *sound_name)
971 return LoadSoundExt(sound_name, FALSE);
974 boolean LoadMod(char *mod_name)
976 #if defined(TARGET_SDL)
977 struct SampleInfo *mod_info;
981 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
983 mod_info = &Mod[num_mods - 1];
984 mod_info->name = mod_name;
986 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
987 MUSIC_DIRECTORY, mod_info->name);
989 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
991 Error(ERR_WARN, "cannot read music file '%s' - no music", filename);
1004 struct dirent *dir_entry;
1005 char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
1006 int num_wav_music = 0;
1007 int num_mod_music = 0;
1009 if (!audio.sound_available)
1012 if ((dir = opendir(music_directory)) == NULL)
1014 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1015 audio.music_available = FALSE;
1016 free(music_directory);
1020 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1022 char *filename = dir_entry->d_name;
1024 if (strlen(filename) > 4 &&
1025 strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
1027 if (LoadSoundExt(filename, TRUE))
1030 else if (strlen(filename) > 4 &&
1031 (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
1032 strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
1033 strncmp(filename, "mod.", 4) == 0 ||
1034 strncmp(filename, "MOD.", 4) == 0))
1036 if (LoadMod(filename))
1043 if (num_wav_music == 0 && num_mod_music == 0)
1044 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1047 free(music_directory);
1049 num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1051 audio.mods_available = (num_mod_music > 0);
1052 audio.music_available = (num_music > 0);
1057 void PlayMusic(int nr)
1059 if (!audio.music_available)
1062 if (!audio.mods_available)
1063 nr = num_sounds - num_music + nr;
1065 #if defined(TARGET_SDL)
1066 if (audio.mods_available) /* play MOD music */
1068 Mix_VolumeMusic(SOUND_MAX_VOLUME);
1069 Mix_PlayMusic(Mod[nr].mix_music, -1);
1071 else /* play WAV music loop */
1073 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1074 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1077 audio.music_nr = nr;
1082 void PlaySound(int nr)
1084 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1087 void PlaySoundStereo(int nr, int stereo)
1089 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1092 void PlaySoundLoop(int nr)
1094 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1097 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1099 struct SoundControl snd_ctrl = emptySoundControl;
1101 if (!audio.sound_available || !audio.sound_enabled)
1104 if (volume<PSND_MIN_VOLUME)
1105 volume = PSND_MIN_VOLUME;
1106 else if (volume>PSND_MAX_VOLUME)
1107 volume = PSND_MAX_VOLUME;
1109 if (stereo<PSND_MAX_LEFT)
1110 stereo = PSND_MAX_LEFT;
1111 else if (stereo>PSND_MAX_RIGHT)
1112 stereo = PSND_MAX_RIGHT;
1115 snd_ctrl.volume = volume;
1116 snd_ctrl.stereo = stereo;
1117 snd_ctrl.loop = loop;
1118 snd_ctrl.active = TRUE;
1119 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1120 snd_ctrl.data_len = Sound[nr].data_len;
1122 #if defined(TARGET_SDL)
1123 Mix_Volume(-1, SOUND_MAX_VOLUME);
1124 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1125 #elif defined(PLATFORM_UNIX)
1126 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1128 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1129 audio.sound_available = audio.sound_enabled = FALSE;
1132 #elif defined(PLATFORM_MSDOS)
1133 sound_handler(snd_ctrl);
1137 void FadeMusic(void)
1139 #if defined(TARGET_SDL)
1140 if (!audio.sound_available)
1143 if (audio.mods_available)
1144 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1146 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1148 FadeSound(audio.music_nr);
1152 void FadeSound(int nr)
1154 StopSoundExt(nr, SSND_FADE_SOUND);
1160 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1163 void StopMusic(void)
1165 #if defined(TARGET_SDL)
1166 if (audio.mods_available)
1169 Mix_HaltChannel(audio.music_channel);
1171 StopSound(audio.music_nr);
1175 void StopSound(int nr)
1177 StopSoundExt(nr, SSND_STOP_SOUND);
1182 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1185 void StopSoundExt(int nr, int method)
1187 struct SoundControl snd_ctrl = emptySoundControl;
1189 if (!audio.sound_available)
1192 if (SSND_FADING(method))
1193 snd_ctrl.fade_sound = TRUE;
1195 if (SSND_ALL(method))
1196 snd_ctrl.stop_all_sounds = TRUE;
1200 snd_ctrl.stop_sound = TRUE;
1203 #if defined(TARGET_SDL)
1205 if (SSND_FADING(method))
1209 for (i=0; i<audio.channels; i++)
1210 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1211 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1212 if (snd_ctrl.stop_all_sounds)
1213 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1219 for (i=0; i<audio.channels; i++)
1220 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1222 if (snd_ctrl.stop_all_sounds)
1227 #if !defined(PLATFORM_MSDOS)
1228 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1230 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1231 audio.sound_available = audio.sound_enabled = FALSE;
1235 sound_handler(snd_ctrl);
1240 void FreeSounds(int num_sounds)
1244 if (!audio.sound_available)
1247 for(i=0; i<num_sounds; i++)
1248 #if defined(TARGET_SDL)
1249 free(Sound[i].mix_chunk);
1250 #elif !defined(PLATFORM_MSDOS)
1251 free(Sound[i].data_ptr);
1253 destroy_sample(Sound[i].sample_ptr);
1257 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/