1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2000 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 static boolean ForkAudioProcess(void)
122 if (pipe(audio.soundserver_pipe) < 0)
124 Error(ERR_WARN, "cannot create pipe - no sounds");
128 if ((audio.soundserver_pid = fork()) < 0)
130 Error(ERR_WARN, "cannot create sound server process - no sounds");
134 if (audio.soundserver_pid == 0) /* we are child */
141 else /* we are parent */
142 close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
147 void UnixOpenAudio(void)
149 if (!TestAudioDevices())
152 audio.sound_available = TRUE;
153 audio.sound_enabled = TRUE;
155 #if defined(AUDIO_STREAMING_DSP)
156 audio.music_available = TRUE;
157 audio.loops_available = TRUE;
161 void UnixCloseAudio(void)
164 close(audio.device_fd);
166 if (audio.soundserver_pid)
167 kill(audio.soundserver_pid, SIGTERM);
169 #endif /* PLATFORM_UNIX */
171 void InitPlaylist(void)
175 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
176 playlist[i] = emptySoundControl;
180 void StartSoundserver(void)
182 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
183 if (!ForkAudioProcess())
184 audio.sound_available = FALSE;
188 #if defined(PLATFORM_UNIX)
189 void SoundServer(void)
193 struct SoundControl snd_ctrl;
196 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
200 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
201 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
203 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
205 #if defined(PLATFORM_HPUX)
206 HPUX_Audio_Control();
209 FD_ZERO(&sound_fdset);
210 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
212 while(1) /* wait for sound playing commands from client */
214 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
215 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
216 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
218 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
220 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
222 #if defined(AUDIO_STREAMING_DSP)
224 if (snd_ctrl.fade_sound)
229 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
230 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
231 playlist[i].fade_sound = TRUE;
233 else if (snd_ctrl.stop_all_sounds)
238 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
239 playlist[i]=emptySoundControl;
242 close(audio.device_fd);
244 else if (snd_ctrl.stop_sound)
249 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
250 if (playlist[i].nr == snd_ctrl.nr)
252 playlist[i]=emptySoundControl;
257 close(audio.device_fd);
260 if (playing_sounds || snd_ctrl.active)
262 struct timeval delay = { 0, 0 };
265 static long max_sample_size = 0;
266 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
267 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
269 /* 'ioctl()' expects pointer to integer value for stereo flag
270 (boolean is defined as 'char', which will not work here) */
272 if (playing_sounds ||
273 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
275 if (!playing_sounds) /* we just opened the audio device */
277 unsigned long fragment_spec = 0;
279 /* determine logarithm (log2) of the fragment size */
280 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
283 /* use two fragments (play one fragment, prepare the other);
284 one fragment would result in interrupted audio output, more
285 than two fragments would raise audio output latency to much */
286 fragment_spec |= 0x00020000;
288 /* Example for fragment specification:
289 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
290 - (with stereo the effective buffer size will shrink to 256)
291 => fragment_size = 0x00020009 */
293 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0)
294 Error(ERR_EXIT_SOUND_SERVER,
295 "cannot set fragment size of /dev/dsp - no sounds");
297 /* try if we can use stereo sound */
298 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
301 static boolean reported = FALSE;
305 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
312 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
313 Error(ERR_EXIT_SOUND_SERVER,
314 "cannot set sample rate of /dev/dsp - no sounds");
316 /* get the real fragmentation size; this should return 512 */
317 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
318 Error(ERR_EXIT_SOUND_SERVER,
319 "cannot get fragment size of /dev/dsp - no sounds");
321 max_sample_size = fragment_size / (stereo ? 2 : 1);
324 if (snd_ctrl.active) /* new sound has arrived */
325 SoundServer_InsertNewSound(snd_ctrl);
327 while(playing_sounds &&
328 select(audio.soundserver_pipe[0] + 1,
329 &sound_fdset, NULL, NULL, &delay) < 1)
331 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
333 /* first clear the last premixing buffer */
334 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
336 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
340 if (!playlist[i].active)
343 /* get pointer and size of the actual sound sample */
344 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
346 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
347 playlist[i].playingpos += sample_size;
349 /* fill the first mixing buffer with original sample */
350 memcpy(premix_first_buffer,sample_ptr,sample_size);
352 /* are we about to restart a looping sound? */
353 if (playlist[i].loop && sample_size<max_sample_size)
355 playlist[i].playingpos = max_sample_size-sample_size;
356 memcpy(premix_first_buffer+sample_size,
357 playlist[i].data_ptr,max_sample_size-sample_size);
358 sample_size = max_sample_size;
361 /* decrease volume if sound is fading out */
362 if (playlist[i].fade_sound &&
363 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
364 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
366 /* adjust volume of actual sound sample */
367 if (playlist[i].volume != PSND_MAX_VOLUME)
368 for(j=0;j<sample_size;j++)
369 premix_first_buffer[j] =
370 (playlist[i].volume * (int)premix_first_buffer[j])
371 >> PSND_MAX_VOLUME_BITS;
373 /* fill the last mixing buffer with stereo or mono sound */
376 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
377 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
378 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
380 for(j=0;j<sample_size;j++)
382 premix_left_buffer[j] =
383 (left_volume * (int)premix_first_buffer[j])
384 >> PSND_MAX_LEFT2RIGHT_BITS;
385 premix_right_buffer[j] =
386 (right_volume * (int)premix_first_buffer[j])
387 >> PSND_MAX_LEFT2RIGHT_BITS;
388 premix_last_buffer[2*j+0] += premix_left_buffer[j];
389 premix_last_buffer[2*j+1] += premix_right_buffer[j];
394 for(j=0;j<sample_size;j++)
395 premix_last_buffer[j] += (int)premix_first_buffer[j];
398 /* delete completed sound entries from the playlist */
399 if (playlist[i].playingpos >= playlist[i].data_len)
401 if (playlist[i].loop)
402 playlist[i].playingpos = 0;
405 playlist[i] = emptySoundControl;
409 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
411 playlist[i] = emptySoundControl;
416 /* put last mixing buffer to final playing buffer */
417 for(i=0; i<fragment_size; i++)
419 if (premix_last_buffer[i]<-255)
420 playing_buffer[i] = 0;
421 else if (premix_last_buffer[i]>255)
422 playing_buffer[i] = 255;
424 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
427 /* finally play the sound fragment */
428 write(audio.device_fd, playing_buffer, fragment_size);
431 /* if no sounds playing, free device for other sound programs */
433 close(audio.device_fd);
437 #else /* !AUDIO_STREAMING_DSP */
439 if (snd_ctrl.active && !snd_ctrl.loop)
441 struct timeval delay = { 0, 0 };
443 long sample_size, max_sample_size = SND_BLOCKSIZE;
444 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
445 int wait_percent = 90; /* wait 90% of the real playing time */
448 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
452 while(playing_sounds &&
453 select(audio.soundserver_pipe[0] + 1,
454 &sound_fdset, NULL, NULL, &delay) < 1)
456 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
458 /* get pointer and size of the actual sound sample */
459 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
461 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
462 snd_ctrl.playingpos += sample_size;
464 /* fill the first mixing buffer with original sample */
465 memcpy(premix_first_buffer,sample_ptr,sample_size);
468 /* adjust volume of actual sound sample */
469 if (snd_ctrl.volume != PSND_MAX_VOLUME)
470 for(i=0;i<sample_size;i++)
471 premix_first_buffer[i] =
472 (snd_ctrl.volume * (int)premix_first_buffer[i])
473 >> PSND_MAX_VOLUME_BITS;
475 for(i=0;i<sample_size;i++)
477 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
479 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
482 /* finally play the sound fragment */
483 write(audio.device_fd,playing_buffer,sample_size);
486 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
488 close(audio.device_fd);
491 #endif /* !AUDIO_STREAMING_DSP */
494 #endif /* PLATFORM_UNIX */
496 #if defined(PLATFORM_MSDOS)
497 static void sound_handler(struct SoundControl snd_ctrl)
501 if (snd_ctrl.fade_sound)
506 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
507 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
508 !playlist[i].fade_sound)
510 playlist[i].fade_sound = TRUE;
511 if (voice_check(playlist[i].voice))
512 voice_ramp_volume(playlist[i].voice, 1000, 0);
513 playlist[i].loop = PSND_NO_LOOP;
516 else if (snd_ctrl.stop_all_sounds)
520 SoundServer_StopAllSounds();
522 else if (snd_ctrl.stop_sound)
526 SoundServer_StopSound(snd_ctrl.nr);
529 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
531 if (!playlist[i].active || playlist[i].loop)
534 playlist[i].playingpos = voice_get_position(playlist[i].voice);
535 playlist[i].volume = voice_get_volume(playlist[i].voice);
536 if (playlist[i].playingpos == -1 || !playlist[i].volume)
538 deallocate_voice(playlist[i].voice);
539 playlist[i] = emptySoundControl;
545 SoundServer_InsertNewSound(snd_ctrl);
547 #endif /* PLATFORM_MSDOS */
549 #if !defined(PLATFORM_WIN32)
550 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
554 /* if playlist is full, remove oldest sound */
555 if (playing_sounds==MAX_SOUNDS_PLAYING)
557 int longest=0, longest_nr=0;
559 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
561 #if !defined(PLATFORM_MSDOS)
562 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
564 int actual = playlist[i].playingpos;
567 if (!playlist[i].loop && actual>longest)
573 #if defined(PLATFORM_MSDOS)
574 voice_set_volume(playlist[longest_nr].voice, 0);
575 deallocate_voice(playlist[longest_nr].voice);
577 playlist[longest_nr] = emptySoundControl;
581 /* check if sound is already being played (and how often) */
582 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
584 if (playlist[i].nr == snd_ctrl.nr)
588 /* restart loop sounds only if they are just fading out */
589 if (k>=1 && snd_ctrl.loop)
591 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
593 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
595 playlist[i].fade_sound = FALSE;
596 playlist[i].volume = PSND_MAX_VOLUME;
597 #if defined(PLATFORM_MSDOS)
598 playlist[i].loop = PSND_LOOP;
599 voice_stop_volumeramp(playlist[i].voice);
600 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
607 /* don't play sound more than n times simultaneously (with n == 2 for now) */
610 int longest=0, longest_nr=0;
612 /* look for oldest equal sound */
613 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
617 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
620 #if !defined(PLATFORM_MSDOS)
621 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
623 actual = playlist[i].playingpos;
632 #if defined(PLATFORM_MSDOS)
633 voice_set_volume(playlist[longest_nr].voice, 0);
634 deallocate_voice(playlist[longest_nr].voice);
636 playlist[longest_nr] = emptySoundControl;
640 /* neuen Sound in Liste packen */
641 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
643 if (!playlist[i].active)
645 playlist[i] = snd_ctrl;
648 #if defined(PLATFORM_MSDOS)
649 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
651 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
652 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
653 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
654 voice_start(playlist[i].voice);
660 #endif /* !PLATFORM_WIN32 */
663 void SoundServer_FadeSound(int nr)
670 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
671 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
672 playlist[i].fade_sound = TRUE;
676 #if !defined(PLATFORM_WIN32)
677 #if defined(PLATFORM_MSDOS)
678 static void SoundServer_StopSound(int nr)
685 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
686 if (playlist[i].nr == nr)
688 #if defined(PLATFORM_MSDOS)
689 voice_set_volume(playlist[i].voice, 0);
690 deallocate_voice(playlist[i].voice);
692 playlist[i] = emptySoundControl;
696 #if !defined(PLATFORM_MSDOS)
698 close(audio.device_fd);
702 static void SoundServer_StopAllSounds()
706 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
708 #if defined(PLATFORM_MSDOS)
709 voice_set_volume(playlist[i].voice, 0);
710 deallocate_voice(playlist[i].voice);
712 playlist[i]=emptySoundControl;
716 #if !defined(PLATFORM_MSDOS)
717 close(audio.device_fd);
720 #endif /* PLATFORM_MSDOS */
721 #endif /* !PLATFORM_WIN32 */
723 #if defined(PLATFORM_HPUX)
724 static void HPUX_Audio_Control()
726 struct audio_describe ainfo;
729 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
731 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
733 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
734 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
736 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
737 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
739 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
740 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
744 #endif /* PLATFORM_HPUX */
746 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
748 /* these two are stolen from "sox"... :) */
751 ** This routine converts from linear to ulaw.
753 ** Craig Reese: IDA/Supercomputing Research Center
754 ** Joe Campbell: Department of Defense
758 ** 1) CCITT Recommendation G.711 (very difficult to follow)
759 ** 2) "A New Digital Technique for Implementation of Any
760 ** Continuous PCM Companding Law," Villeret, Michel,
761 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
762 ** 1973, pg. 11.12-11.17
763 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
764 ** for Analog-to_Digital Conversion Techniques,"
767 ** Input: Signed 16 bit linear sample
768 ** Output: 8 bit ulaw sample
771 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
772 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
775 static unsigned char linear_to_ulaw(int sample)
777 static int exp_lut[256] =
779 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
780 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
781 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
782 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
783 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
784 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
785 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
786 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
787 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
788 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
789 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
790 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
791 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
797 int sign, exponent, mantissa;
798 unsigned char ulawbyte;
800 /* Get the sample into sign-magnitude. */
801 sign = (sample >> 8) & 0x80; /* set aside the sign */
803 sample = -sample; /* get magnitude */
805 sample = CLIP; /* clip the magnitude */
807 /* Convert from 16 bit linear to ulaw. */
808 sample = sample + BIAS;
809 exponent = exp_lut[( sample >> 7 ) & 0xFF];
810 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
811 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
814 ulawbyte = 0x02; /* optional CCITT trap */
821 ** This routine converts from ulaw to 16 bit linear.
823 ** Craig Reese: IDA/Supercomputing Research Center
827 ** 1) CCITT Recommendation G.711 (very difficult to follow)
828 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
829 ** for Analog-to_Digital Conversion Techniques,"
832 ** Input: 8 bit ulaw sample
833 ** Output: signed 16 bit linear sample
836 static int ulaw_to_linear(unsigned char ulawbyte)
838 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
839 int sign, exponent, mantissa, sample;
841 ulawbyte = ~ ulawbyte;
842 sign = ( ulawbyte & 0x80 );
843 exponent = ( ulawbyte >> 4 ) & 0x07;
844 mantissa = ulawbyte & 0x0F;
845 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
851 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
853 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
855 /*===========================================================================*/
857 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
859 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
860 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
862 static boolean LoadSoundExt(char *sound_name, boolean is_music)
864 struct SampleInfo *snd_info;
866 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
867 byte sound_header_buffer[WAV_HEADER_SIZE];
868 char chunk[CHUNK_ID_LEN + 1];
869 int chunk_length, dummy;
875 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
877 snd_info = &Sound[num_sounds - 1];
878 snd_info->name = sound_name;
880 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
881 (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name);
883 #if defined(TARGET_SDL)
885 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
887 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
891 #elif defined(PLATFORM_UNIX)
893 if ((file = fopen(filename, MODE_READ)) == NULL)
895 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
899 /* read chunk "RIFF" */
900 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
901 if (strcmp(chunk, "RIFF") != 0)
903 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
908 /* read chunk "WAVE" */
909 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
910 if (strcmp(chunk, "WAVE") != 0)
912 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
917 /* read header information */
918 for (i=0; i<WAV_HEADER_SIZE; i++)
919 sound_header_buffer[i] = fgetc(file);
921 /* read chunk "data" */
922 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
923 if (strcmp(chunk, "data") != 0)
925 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
930 snd_info->data_len = chunk_length;
931 snd_info->data_ptr = checked_malloc(snd_info->data_len);
933 /* read sound data */
934 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
937 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
944 for (i=0; i<snd_info->data_len; i++)
945 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
947 #else /* PLATFORM_MSDOS */
949 snd_info->sample_ptr = load_sample(filename);
950 if (!snd_info->sample_ptr)
952 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
961 boolean LoadSound(char *sound_name)
963 return LoadSoundExt(sound_name, FALSE);
966 boolean LoadMod(char *mod_name)
968 #if defined(TARGET_SDL)
969 struct SampleInfo *mod_info;
973 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
975 mod_info = &Mod[num_mods - 1];
976 mod_info->name = mod_name;
978 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
979 MUSIC_DIRECTORY, mod_info->name);
981 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
983 Error(ERR_WARN, "cannot read music file '%s' - no music", filename);
996 struct dirent *dir_entry;
997 char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
998 int num_wav_music = 0;
999 int num_mod_music = 0;
1001 if ((dir = opendir(music_directory)) == NULL)
1003 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1004 audio.music_available = FALSE;
1005 free(music_directory);
1009 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1011 char *filename = dir_entry->d_name;
1013 if (strlen(filename) > 4 &&
1014 strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
1016 if (LoadSoundExt(filename, TRUE))
1019 else if (strlen(filename) > 4 &&
1020 (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
1021 strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
1022 strncmp(filename, "mod.", 4) == 0 ||
1023 strncmp(filename, "MOD.", 4) == 0))
1025 if (LoadMod(filename))
1032 if (num_wav_music == 0 && num_mod_music == 0)
1033 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1036 free(music_directory);
1038 num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1040 audio.mods_available = (num_mod_music > 0);
1041 audio.music_available = (num_music > 0);
1046 void PlayMusic(int nr)
1048 if (!audio.music_available)
1051 if (!audio.mods_available)
1052 nr = num_sounds - num_music + nr;
1054 #if defined(TARGET_SDL)
1055 if (audio.mods_available) /* play MOD music */
1057 Mix_VolumeMusic(SOUND_MAX_VOLUME);
1058 Mix_PlayMusic(Mod[nr].mix_music, -1);
1060 else /* play WAV music loop */
1062 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1063 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1066 audio.music_nr = nr;
1071 void PlaySound(int nr)
1073 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1076 void PlaySoundStereo(int nr, int stereo)
1078 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1081 void PlaySoundLoop(int nr)
1083 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1086 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1088 struct SoundControl snd_ctrl = emptySoundControl;
1090 if (!audio.sound_available || !audio.sound_enabled)
1093 if (volume<PSND_MIN_VOLUME)
1094 volume = PSND_MIN_VOLUME;
1095 else if (volume>PSND_MAX_VOLUME)
1096 volume = PSND_MAX_VOLUME;
1098 if (stereo<PSND_MAX_LEFT)
1099 stereo = PSND_MAX_LEFT;
1100 else if (stereo>PSND_MAX_RIGHT)
1101 stereo = PSND_MAX_RIGHT;
1104 snd_ctrl.volume = volume;
1105 snd_ctrl.stereo = stereo;
1106 snd_ctrl.loop = loop;
1107 snd_ctrl.active = TRUE;
1108 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1109 snd_ctrl.data_len = Sound[nr].data_len;
1111 #if defined(TARGET_SDL)
1112 Mix_Volume(-1, SOUND_MAX_VOLUME);
1113 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1114 #elif defined(PLATFORM_UNIX)
1115 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1117 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1118 audio.sound_available = audio.sound_enabled = FALSE;
1121 #elif defined(PLATFORM_MSDOS)
1122 sound_handler(snd_ctrl);
1126 void FadeMusic(void)
1128 #if defined(TARGET_SDL)
1129 if (audio.mods_available)
1130 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1132 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1134 FadeSound(audio.music_nr);
1138 void FadeSound(int nr)
1140 StopSoundExt(nr, SSND_FADE_SOUND);
1145 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1148 void StopMusic(void)
1150 #if defined(TARGET_SDL)
1151 if (audio.mods_available)
1154 Mix_HaltChannel(audio.music_channel);
1156 StopSound(audio.music_nr);
1160 void StopSound(int nr)
1162 StopSoundExt(nr, SSND_STOP_SOUND);
1167 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1170 void StopSoundExt(int nr, int method)
1172 struct SoundControl snd_ctrl = emptySoundControl;
1174 if (!audio.sound_available)
1177 if (SSND_FADING(method))
1178 snd_ctrl.fade_sound = TRUE;
1180 if (SSND_ALL(method))
1181 snd_ctrl.stop_all_sounds = TRUE;
1185 snd_ctrl.stop_sound = TRUE;
1188 #if defined(TARGET_SDL)
1190 if (SSND_FADING(method))
1194 for (i=0; i<audio.channels; i++)
1195 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1196 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1197 if (snd_ctrl.stop_all_sounds)
1198 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1204 for (i=0; i<audio.channels; i++)
1205 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1207 if (snd_ctrl.stop_all_sounds)
1212 #if !defined(PLATFORM_MSDOS)
1213 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1215 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1216 audio.sound_available = audio.sound_enabled = FALSE;
1220 sound_handler(snd_ctrl);
1225 void FreeSounds(int num_sounds)
1229 if (!audio.sound_available)
1232 for(i=0; i<num_sounds; i++)
1233 #if defined(TARGET_SDL)
1234 free(Sound[i].mix_chunk);
1235 #elif !defined(PLATFORM_MSDOS)
1236 free(Sound[i].data_ptr);
1238 destroy_sample(Sound[i].sample_ptr);
1242 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/