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 #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 defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
185 if (!ForkAudioProcess())
186 audio.sound_available = FALSE;
190 #if defined(PLATFORM_UNIX)
191 void SoundServer(void)
195 struct SoundControl snd_ctrl;
198 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
202 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
203 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
205 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
207 #if defined(PLATFORM_HPUX)
208 HPUX_Audio_Control();
211 FD_ZERO(&sound_fdset);
212 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
214 while(1) /* wait for sound playing commands from client */
216 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
217 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
218 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
220 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
222 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
224 #if defined(AUDIO_STREAMING_DSP)
226 if (snd_ctrl.fade_sound)
231 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
232 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
233 playlist[i].fade_sound = TRUE;
235 else if (snd_ctrl.stop_all_sounds)
240 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
241 playlist[i]=emptySoundControl;
244 close(audio.device_fd);
246 else if (snd_ctrl.stop_sound)
251 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
252 if (playlist[i].nr == snd_ctrl.nr)
254 playlist[i]=emptySoundControl;
259 close(audio.device_fd);
262 if (playing_sounds || snd_ctrl.active)
264 struct timeval delay = { 0, 0 };
267 static long max_sample_size = 0;
268 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
269 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
271 /* 'ioctl()' expects pointer to integer value for stereo flag
272 (boolean is defined as 'char', which will not work here) */
274 if (playing_sounds ||
275 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
277 if (!playing_sounds) /* we just opened the audio device */
279 unsigned long fragment_spec = 0;
281 /* determine logarithm (log2) of the fragment size */
282 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
285 /* use two fragments (play one fragment, prepare the other);
286 one fragment would result in interrupted audio output, more
287 than two fragments would raise audio output latency to much */
288 fragment_spec |= 0x00020000;
290 /* Example for fragment specification:
291 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
292 - (with stereo the effective buffer size will shrink to 256)
293 => fragment_size = 0x00020009 */
295 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0)
296 Error(ERR_EXIT_SOUND_SERVER,
297 "cannot set fragment size of /dev/dsp - no sounds");
299 /* try if we can use stereo sound */
300 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
303 static boolean reported = FALSE;
307 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
314 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
315 Error(ERR_EXIT_SOUND_SERVER,
316 "cannot set sample rate of /dev/dsp - no sounds");
318 /* get the real fragmentation size; this should return 512 */
319 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
320 Error(ERR_EXIT_SOUND_SERVER,
321 "cannot get fragment size of /dev/dsp - no sounds");
323 max_sample_size = fragment_size / (stereo ? 2 : 1);
326 if (snd_ctrl.active) /* new sound has arrived */
327 SoundServer_InsertNewSound(snd_ctrl);
329 while(playing_sounds &&
330 select(audio.soundserver_pipe[0] + 1,
331 &sound_fdset, NULL, NULL, &delay) < 1)
333 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
335 /* first clear the last premixing buffer */
336 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
338 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
342 if (!playlist[i].active)
345 /* get pointer and size of the actual sound sample */
346 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
348 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
349 playlist[i].playingpos += sample_size;
351 /* fill the first mixing buffer with original sample */
352 memcpy(premix_first_buffer,sample_ptr,sample_size);
354 /* are we about to restart a looping sound? */
355 if (playlist[i].loop && sample_size<max_sample_size)
357 playlist[i].playingpos = max_sample_size-sample_size;
358 memcpy(premix_first_buffer+sample_size,
359 playlist[i].data_ptr,max_sample_size-sample_size);
360 sample_size = max_sample_size;
363 /* decrease volume if sound is fading out */
364 if (playlist[i].fade_sound &&
365 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
366 playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
368 /* adjust volume of actual sound sample */
369 if (playlist[i].volume != PSND_MAX_VOLUME)
370 for(j=0;j<sample_size;j++)
371 premix_first_buffer[j] =
372 (playlist[i].volume * (int)premix_first_buffer[j])
373 >> PSND_MAX_VOLUME_BITS;
375 /* fill the last mixing buffer with stereo or mono sound */
378 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
379 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
380 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
382 for(j=0;j<sample_size;j++)
384 premix_left_buffer[j] =
385 (left_volume * (int)premix_first_buffer[j])
386 >> PSND_MAX_LEFT2RIGHT_BITS;
387 premix_right_buffer[j] =
388 (right_volume * (int)premix_first_buffer[j])
389 >> PSND_MAX_LEFT2RIGHT_BITS;
390 premix_last_buffer[2*j+0] += premix_left_buffer[j];
391 premix_last_buffer[2*j+1] += premix_right_buffer[j];
396 for(j=0;j<sample_size;j++)
397 premix_last_buffer[j] += (int)premix_first_buffer[j];
400 /* delete completed sound entries from the playlist */
401 if (playlist[i].playingpos >= playlist[i].data_len)
403 if (playlist[i].loop)
404 playlist[i].playingpos = 0;
407 playlist[i] = emptySoundControl;
411 else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
413 playlist[i] = emptySoundControl;
418 /* put last mixing buffer to final playing buffer */
419 for(i=0; i<fragment_size; i++)
421 if (premix_last_buffer[i]<-255)
422 playing_buffer[i] = 0;
423 else if (premix_last_buffer[i]>255)
424 playing_buffer[i] = 255;
426 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
429 /* finally play the sound fragment */
430 write(audio.device_fd, playing_buffer, fragment_size);
433 /* if no sounds playing, free device for other sound programs */
435 close(audio.device_fd);
439 #else /* !AUDIO_STREAMING_DSP */
441 if (snd_ctrl.active && !snd_ctrl.loop)
443 struct timeval delay = { 0, 0 };
445 long sample_size, max_sample_size = SND_BLOCKSIZE;
446 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
447 int wait_percent = 90; /* wait 90% of the real playing time */
450 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
454 while(playing_sounds &&
455 select(audio.soundserver_pipe[0] + 1,
456 &sound_fdset, NULL, NULL, &delay) < 1)
458 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
460 /* get pointer and size of the actual sound sample */
461 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
463 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
464 snd_ctrl.playingpos += sample_size;
466 /* fill the first mixing buffer with original sample */
467 memcpy(premix_first_buffer,sample_ptr,sample_size);
470 /* adjust volume of actual sound sample */
471 if (snd_ctrl.volume != PSND_MAX_VOLUME)
472 for(i=0;i<sample_size;i++)
473 premix_first_buffer[i] =
474 (snd_ctrl.volume * (int)premix_first_buffer[i])
475 >> PSND_MAX_VOLUME_BITS;
477 for(i=0;i<sample_size;i++)
479 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
481 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
484 /* finally play the sound fragment */
485 write(audio.device_fd,playing_buffer,sample_size);
488 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
490 close(audio.device_fd);
493 #endif /* !AUDIO_STREAMING_DSP */
496 #endif /* PLATFORM_UNIX */
498 #if defined(PLATFORM_MSDOS)
499 static void sound_handler(struct SoundControl snd_ctrl)
503 if (snd_ctrl.fade_sound)
508 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
509 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
510 !playlist[i].fade_sound)
512 playlist[i].fade_sound = TRUE;
513 if (voice_check(playlist[i].voice))
514 voice_ramp_volume(playlist[i].voice, 1000, 0);
515 playlist[i].loop = PSND_NO_LOOP;
518 else if (snd_ctrl.stop_all_sounds)
522 SoundServer_StopAllSounds();
524 else if (snd_ctrl.stop_sound)
528 SoundServer_StopSound(snd_ctrl.nr);
531 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
533 if (!playlist[i].active || playlist[i].loop)
536 playlist[i].playingpos = voice_get_position(playlist[i].voice);
537 playlist[i].volume = voice_get_volume(playlist[i].voice);
538 if (playlist[i].playingpos == -1 || !playlist[i].volume)
540 deallocate_voice(playlist[i].voice);
541 playlist[i] = emptySoundControl;
547 SoundServer_InsertNewSound(snd_ctrl);
549 #endif /* PLATFORM_MSDOS */
551 #if !defined(PLATFORM_WIN32)
552 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
556 /* if playlist is full, remove oldest sound */
557 if (playing_sounds==MAX_SOUNDS_PLAYING)
559 int longest=0, longest_nr=0;
561 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
563 #if !defined(PLATFORM_MSDOS)
564 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
566 int actual = playlist[i].playingpos;
569 if (!playlist[i].loop && actual>longest)
575 #if defined(PLATFORM_MSDOS)
576 voice_set_volume(playlist[longest_nr].voice, 0);
577 deallocate_voice(playlist[longest_nr].voice);
579 playlist[longest_nr] = emptySoundControl;
583 /* check if sound is already being played (and how often) */
584 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
586 if (playlist[i].nr == snd_ctrl.nr)
590 /* restart loop sounds only if they are just fading out */
591 if (k>=1 && snd_ctrl.loop)
593 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
595 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
597 playlist[i].fade_sound = FALSE;
598 playlist[i].volume = PSND_MAX_VOLUME;
599 #if defined(PLATFORM_MSDOS)
600 playlist[i].loop = PSND_LOOP;
601 voice_stop_volumeramp(playlist[i].voice);
602 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
609 /* don't play sound more than n times simultaneously (with n == 2 for now) */
612 int longest=0, longest_nr=0;
614 /* look for oldest equal sound */
615 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
619 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
622 #if !defined(PLATFORM_MSDOS)
623 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
625 actual = playlist[i].playingpos;
634 #if defined(PLATFORM_MSDOS)
635 voice_set_volume(playlist[longest_nr].voice, 0);
636 deallocate_voice(playlist[longest_nr].voice);
638 playlist[longest_nr] = emptySoundControl;
642 /* neuen Sound in Liste packen */
643 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
645 if (!playlist[i].active)
647 playlist[i] = snd_ctrl;
650 #if defined(PLATFORM_MSDOS)
651 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
653 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
654 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
655 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
656 voice_start(playlist[i].voice);
662 #endif /* !PLATFORM_WIN32 */
665 void SoundServer_FadeSound(int nr)
672 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
673 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
674 playlist[i].fade_sound = TRUE;
678 #if !defined(PLATFORM_WIN32)
679 #if defined(PLATFORM_MSDOS)
680 static void SoundServer_StopSound(int nr)
687 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
688 if (playlist[i].nr == nr)
690 #if defined(PLATFORM_MSDOS)
691 voice_set_volume(playlist[i].voice, 0);
692 deallocate_voice(playlist[i].voice);
694 playlist[i] = emptySoundControl;
698 #if !defined(PLATFORM_MSDOS)
700 close(audio.device_fd);
704 static void SoundServer_StopAllSounds()
708 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
710 #if defined(PLATFORM_MSDOS)
711 voice_set_volume(playlist[i].voice, 0);
712 deallocate_voice(playlist[i].voice);
714 playlist[i]=emptySoundControl;
718 #if !defined(PLATFORM_MSDOS)
719 close(audio.device_fd);
722 #endif /* PLATFORM_MSDOS */
723 #endif /* !PLATFORM_WIN32 */
725 #if defined(PLATFORM_HPUX)
726 static void HPUX_Audio_Control()
728 struct audio_describe ainfo;
731 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
733 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
735 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
736 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
738 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
739 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
741 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
742 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
746 #endif /* PLATFORM_HPUX */
748 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
750 /* these two are stolen from "sox"... :) */
753 ** This routine converts from linear to ulaw.
755 ** Craig Reese: IDA/Supercomputing Research Center
756 ** Joe Campbell: Department of Defense
760 ** 1) CCITT Recommendation G.711 (very difficult to follow)
761 ** 2) "A New Digital Technique for Implementation of Any
762 ** Continuous PCM Companding Law," Villeret, Michel,
763 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
764 ** 1973, pg. 11.12-11.17
765 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
766 ** for Analog-to_Digital Conversion Techniques,"
769 ** Input: Signed 16 bit linear sample
770 ** Output: 8 bit ulaw sample
773 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
774 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
777 static unsigned char linear_to_ulaw(int sample)
779 static int exp_lut[256] =
781 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
782 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
783 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
784 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
788 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
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
799 int sign, exponent, mantissa;
800 unsigned char ulawbyte;
802 /* Get the sample into sign-magnitude. */
803 sign = (sample >> 8) & 0x80; /* set aside the sign */
805 sample = -sample; /* get magnitude */
807 sample = CLIP; /* clip the magnitude */
809 /* Convert from 16 bit linear to ulaw. */
810 sample = sample + BIAS;
811 exponent = exp_lut[( sample >> 7 ) & 0xFF];
812 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
813 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
816 ulawbyte = 0x02; /* optional CCITT trap */
823 ** This routine converts from ulaw to 16 bit linear.
825 ** Craig Reese: IDA/Supercomputing Research Center
829 ** 1) CCITT Recommendation G.711 (very difficult to follow)
830 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
831 ** for Analog-to_Digital Conversion Techniques,"
834 ** Input: 8 bit ulaw sample
835 ** Output: signed 16 bit linear sample
838 static int ulaw_to_linear(unsigned char ulawbyte)
840 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
841 int sign, exponent, mantissa, sample;
843 ulawbyte = ~ ulawbyte;
844 sign = ( ulawbyte & 0x80 );
845 exponent = ( ulawbyte >> 4 ) & 0x07;
846 mantissa = ulawbyte & 0x0F;
847 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
853 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
855 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
857 /*===========================================================================*/
859 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
861 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
862 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
864 static boolean LoadSoundExt(char *sound_name, boolean is_music)
866 struct SampleInfo *snd_info;
868 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
869 byte sound_header_buffer[WAV_HEADER_SIZE];
870 char chunk[CHUNK_ID_LEN + 1];
871 int chunk_length, dummy;
877 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
879 snd_info = &Sound[num_sounds - 1];
880 snd_info->name = sound_name;
882 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
883 (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name);
885 #if defined(TARGET_SDL)
887 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
889 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
893 #elif defined(PLATFORM_UNIX)
895 if ((file = fopen(filename, MODE_READ)) == NULL)
897 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
901 /* read chunk "RIFF" */
902 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
903 if (strcmp(chunk, "RIFF") != 0)
905 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
910 /* read chunk "WAVE" */
911 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
912 if (strcmp(chunk, "WAVE") != 0)
914 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
919 /* read header information */
920 for (i=0; i<WAV_HEADER_SIZE; i++)
921 sound_header_buffer[i] = fgetc(file);
923 /* read chunk "data" */
924 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
925 if (strcmp(chunk, "data") != 0)
927 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
932 snd_info->data_len = chunk_length;
933 snd_info->data_ptr = checked_malloc(snd_info->data_len);
935 /* read sound data */
936 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
939 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
946 for (i=0; i<snd_info->data_len; i++)
947 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
949 #else /* PLATFORM_MSDOS */
951 snd_info->sample_ptr = load_sample(filename);
952 if (!snd_info->sample_ptr)
954 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
963 boolean LoadSound(char *sound_name)
965 return LoadSoundExt(sound_name, FALSE);
968 boolean LoadMod(char *mod_name)
970 #if defined(TARGET_SDL)
971 struct SampleInfo *mod_info;
975 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
977 mod_info = &Mod[num_mods - 1];
978 mod_info->name = mod_name;
980 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
981 MUSIC_DIRECTORY, mod_info->name);
983 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
985 Error(ERR_WARN, "cannot read music file '%s' - no music", filename);
998 struct dirent *dir_entry;
999 char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
1000 int num_wav_music = 0;
1001 int num_mod_music = 0;
1003 if ((dir = opendir(music_directory)) == NULL)
1005 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1006 audio.music_available = FALSE;
1007 free(music_directory);
1011 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1013 char *filename = dir_entry->d_name;
1015 if (strlen(filename) > 4 &&
1016 strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
1018 if (LoadSoundExt(filename, TRUE))
1021 else if (strlen(filename) > 4 &&
1022 (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
1023 strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
1024 strncmp(filename, "mod.", 4) == 0 ||
1025 strncmp(filename, "MOD.", 4) == 0))
1027 if (LoadMod(filename))
1034 if (num_wav_music == 0 && num_mod_music == 0)
1035 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1038 free(music_directory);
1040 num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1042 audio.mods_available = (num_mod_music > 0);
1043 audio.music_available = (num_music > 0);
1048 void PlayMusic(int nr)
1050 if (!audio.music_available)
1053 if (!audio.mods_available)
1054 nr = num_sounds - num_music + nr;
1056 #if defined(TARGET_SDL)
1057 if (audio.mods_available) /* play MOD music */
1059 Mix_VolumeMusic(SOUND_MAX_VOLUME);
1060 Mix_PlayMusic(Mod[nr].mix_music, -1);
1062 else /* play WAV music loop */
1064 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1065 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1068 audio.music_nr = nr;
1073 void PlaySound(int nr)
1075 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1078 void PlaySoundStereo(int nr, int stereo)
1080 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1083 void PlaySoundLoop(int nr)
1085 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1088 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1090 struct SoundControl snd_ctrl = emptySoundControl;
1092 if (!audio.sound_available || !audio.sound_enabled)
1095 if (volume<PSND_MIN_VOLUME)
1096 volume = PSND_MIN_VOLUME;
1097 else if (volume>PSND_MAX_VOLUME)
1098 volume = PSND_MAX_VOLUME;
1100 if (stereo<PSND_MAX_LEFT)
1101 stereo = PSND_MAX_LEFT;
1102 else if (stereo>PSND_MAX_RIGHT)
1103 stereo = PSND_MAX_RIGHT;
1106 snd_ctrl.volume = volume;
1107 snd_ctrl.stereo = stereo;
1108 snd_ctrl.loop = loop;
1109 snd_ctrl.active = TRUE;
1110 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1111 snd_ctrl.data_len = Sound[nr].data_len;
1113 #if defined(TARGET_SDL)
1114 Mix_Volume(-1, SOUND_MAX_VOLUME);
1115 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1116 #elif defined(PLATFORM_UNIX)
1117 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1119 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1120 audio.sound_available = audio.sound_enabled = FALSE;
1123 #elif defined(PLATFORM_MSDOS)
1124 sound_handler(snd_ctrl);
1128 void FadeMusic(void)
1130 #if defined(TARGET_SDL)
1131 if (audio.mods_available)
1132 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1134 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1136 FadeSound(audio.music_nr);
1140 void FadeSound(int nr)
1142 StopSoundExt(nr, SSND_FADE_SOUND);
1147 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1150 void StopMusic(void)
1152 #if defined(TARGET_SDL)
1153 if (audio.mods_available)
1156 Mix_HaltChannel(audio.music_channel);
1158 StopSound(audio.music_nr);
1162 void StopSound(int nr)
1164 StopSoundExt(nr, SSND_STOP_SOUND);
1169 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1172 void StopSoundExt(int nr, int method)
1174 struct SoundControl snd_ctrl = emptySoundControl;
1176 if (!audio.sound_available)
1179 if (SSND_FADING(method))
1180 snd_ctrl.fade_sound = TRUE;
1182 if (SSND_ALL(method))
1183 snd_ctrl.stop_all_sounds = TRUE;
1187 snd_ctrl.stop_sound = TRUE;
1190 #if defined(TARGET_SDL)
1192 if (SSND_FADING(method))
1196 for (i=0; i<audio.channels; i++)
1197 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1198 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1199 if (snd_ctrl.stop_all_sounds)
1200 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1206 for (i=0; i<audio.channels; i++)
1207 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1209 if (snd_ctrl.stop_all_sounds)
1214 #if !defined(PLATFORM_MSDOS)
1215 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1217 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1218 audio.sound_available = audio.sound_enabled = FALSE;
1222 sound_handler(snd_ctrl);
1227 void FreeSounds(int num_sounds)
1231 if (!audio.sound_available)
1234 for(i=0; i<num_sounds; i++)
1235 #if defined(TARGET_SDL)
1236 free(Sound[i].mix_chunk);
1237 #elif !defined(PLATFORM_MSDOS)
1238 free(Sound[i].data_ptr);
1240 destroy_sample(Sound[i].sample_ptr);
1244 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/