1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
19 static int playing_sounds = 0;
20 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
21 static struct SoundControl emptySoundControl =
23 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
26 #if defined(PLATFORM_UNIX)
27 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
28 static char premix_first_buffer[SND_BLOCKSIZE];
29 #if defined(AUDIO_STREAMING_DSP)
30 static char premix_left_buffer[SND_BLOCKSIZE];
31 static char premix_right_buffer[SND_BLOCKSIZE];
32 static int premix_last_buffer[SND_BLOCKSIZE];
34 static unsigned char playing_buffer[SND_BLOCKSIZE];
37 /* forward declaration of internal functions */
38 #if defined(AUDIO_STREAMING_DSP)
39 static void SoundServer_InsertNewSound(struct SoundControl);
40 #elif defined(PLATFORM_UNIX)
41 static unsigned char linear_to_ulaw(int);
42 static int ulaw_to_linear(unsigned char);
45 #if defined(PLATFORM_HPUX)
46 static void HPUX_Audio_Control();
49 #if defined(PLATFORM_MSDOS)
50 static void SoundServer_InsertNewSound(struct SoundControl);
51 static void SoundServer_StopSound(int);
52 static void SoundServer_StopAllSounds();
55 #if defined(PLATFORM_UNIX)
56 int OpenAudioDevice(char *audio_device_name)
60 /* check if desired audio device is accessible */
61 if (access(sound_device_name, W_OK) != 0)
64 /* try to open audio device in non-blocking mode */
65 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
68 /* re-open audio device in blocking mode */
70 audio_fd = open(audio_device_name, O_WRONLY);
75 void UnixOpenAudio(struct AudioSystemInfo *audio)
77 static char *audio_device_name[] =
85 /* look for available audio devices, starting with preferred ones */
86 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
87 if ((audio_fd = OpenAudioDevice(sound_device_name)) >= 0)
92 Error(ERR_WARN, "cannot open audio device - no sound");
98 audio->sound_available = TRUE;
100 #if defined(AUDIO_STREAMING_DSP)
101 audio->loops_available = TRUE;
105 void UnixCloseAudio(struct AudioSystemInfo *audio)
107 if (audio->device_fd)
108 close(audio->device_fd);
111 #endif /* PLATFORM_UNIX */
116 #if defined(PLATFORM_UNIX)
117 struct SoundControl snd_ctrl;
120 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
123 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
124 playlist[i] = emptySoundControl;
127 #if defined(PLATFORM_UNIX)
128 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
129 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
131 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
133 #if defined(PLATFORM_HPUX)
134 HPUX_Audio_Control();
137 FD_ZERO(&sound_fdset);
138 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
140 while(1) /* wait for sound playing commands from client */
142 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
143 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
144 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
146 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
148 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
150 #if defined(AUDIO_STREAMING_DSP)
152 if (snd_ctrl.fade_sound)
157 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
158 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
159 playlist[i].fade_sound = TRUE;
161 else if (snd_ctrl.stop_all_sounds)
166 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
167 playlist[i]=emptySoundControl;
170 close(audio.device_fd);
172 else if (snd_ctrl.stop_sound)
177 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
178 if (playlist[i].nr == snd_ctrl.nr)
180 playlist[i]=emptySoundControl;
185 close(audio.device_fd);
188 if (playing_sounds || snd_ctrl.active)
190 struct timeval delay = { 0, 0 };
193 static long max_sample_size = 0;
194 static long fragment_size = 0;
195 /* Even if the stereo flag is used as being boolean, it must be
196 defined as an integer, else 'ioctl()' will fail! */
199 int sample_rate = 8000;
201 int sample_rate = 22050;
204 if (playing_sounds ||
205 (audio.device_fd = OpenAudioDevice(sound_device_name)) >= 0)
207 if (!playing_sounds) /* we just opened the audio device */
209 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
210 /* (with stereo the effective buffer size will shrink to 256) */
211 fragment_size = 0x00020009;
213 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_size) < 0)
214 Error(ERR_EXIT_SOUND_SERVER,
215 "cannot set fragment size of /dev/dsp - no sounds");
217 /* try if we can use stereo sound */
218 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
221 static boolean reported = FALSE;
225 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
232 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
233 Error(ERR_EXIT_SOUND_SERVER,
234 "cannot set sample rate of /dev/dsp - no sounds");
236 /* get the real fragmentation size; this should return 512 */
237 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
238 Error(ERR_EXIT_SOUND_SERVER,
239 "cannot get fragment size of /dev/dsp - no sounds");
241 max_sample_size = fragment_size / (stereo ? 2 : 1);
244 if (snd_ctrl.active) /* new sound has arrived */
245 SoundServer_InsertNewSound(snd_ctrl);
247 while(playing_sounds &&
248 select(audio.soundserver_pipe[0] + 1,
249 &sound_fdset, NULL, NULL, &delay) < 1)
251 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
253 /* first clear the last premixing buffer */
254 memset(premix_last_buffer,0,fragment_size*sizeof(int));
256 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
260 if (!playlist[i].active)
263 /* get pointer and size of the actual sound sample */
264 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
266 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
267 playlist[i].playingpos += sample_size;
269 /* fill the first mixing buffer with original sample */
270 memcpy(premix_first_buffer,sample_ptr,sample_size);
272 /* are we about to restart a looping sound? */
273 if (playlist[i].loop && sample_size<max_sample_size)
275 playlist[i].playingpos = max_sample_size-sample_size;
276 memcpy(premix_first_buffer+sample_size,
277 playlist[i].data_ptr,max_sample_size-sample_size);
278 sample_size = max_sample_size;
281 /* decrease volume if sound is fading out */
282 if (playlist[i].fade_sound &&
283 playlist[i].volume>=PSND_MAX_VOLUME/10)
284 playlist[i].volume-=PSND_MAX_VOLUME/20;
286 /* adjust volume of actual sound sample */
287 if (playlist[i].volume != PSND_MAX_VOLUME)
288 for(j=0;j<sample_size;j++)
289 premix_first_buffer[j] =
290 (playlist[i].volume * (int)premix_first_buffer[j])
291 >> PSND_MAX_VOLUME_BITS;
293 /* fill the last mixing buffer with stereo or mono sound */
296 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
297 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
298 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
300 for(j=0;j<sample_size;j++)
302 premix_left_buffer[j] =
303 (left_volume * (int)premix_first_buffer[j])
304 >> PSND_MAX_LEFT2RIGHT_BITS;
305 premix_right_buffer[j] =
306 (right_volume * (int)premix_first_buffer[j])
307 >> PSND_MAX_LEFT2RIGHT_BITS;
308 premix_last_buffer[2*j+0] += premix_left_buffer[j];
309 premix_last_buffer[2*j+1] += premix_right_buffer[j];
314 for(j=0;j<sample_size;j++)
315 premix_last_buffer[j] += (int)premix_first_buffer[j];
318 /* delete completed sound entries from the playlist */
319 if (playlist[i].playingpos >= playlist[i].data_len)
321 if (playlist[i].loop)
322 playlist[i].playingpos = 0;
325 playlist[i] = emptySoundControl;
329 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
331 playlist[i] = emptySoundControl;
336 /* put last mixing buffer to final playing buffer */
337 for(i=0;i<fragment_size;i++)
339 if (premix_last_buffer[i]<-255)
340 playing_buffer[i] = 0;
341 else if (premix_last_buffer[i]>255)
342 playing_buffer[i] = 255;
344 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
347 /* finally play the sound fragment */
348 write(audio.device_fd, playing_buffer,fragment_size);
351 /* if no sounds playing, free device for other sound programs */
353 close(audio.device_fd);
357 #else /* !AUDIO_STREAMING_DSP */
359 if (snd_ctrl.active && !snd_ctrl.loop)
361 struct timeval delay = { 0, 0 };
363 long sample_size, max_sample_size = SND_BLOCKSIZE;
364 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
365 int wait_percent = 90; /* wait 90% of the real playing time */
368 if ((audio.device_fd = OpenAudioDevice(sound_device_name)) >= 0)
372 while(playing_sounds &&
373 select(audio.soundserver_pipe[0] + 1,
374 &sound_fdset, NULL, NULL, &delay) < 1)
376 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
378 /* get pointer and size of the actual sound sample */
379 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
381 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
382 snd_ctrl.playingpos += sample_size;
384 /* fill the first mixing buffer with original sample */
385 memcpy(premix_first_buffer,sample_ptr,sample_size);
388 /* adjust volume of actual sound sample */
389 if (snd_ctrl.volume != PSND_MAX_VOLUME)
390 for(i=0;i<sample_size;i++)
391 premix_first_buffer[i] =
392 (snd_ctrl.volume * (int)premix_first_buffer[i])
393 >> PSND_MAX_VOLUME_BITS;
395 for(i=0;i<sample_size;i++)
397 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
399 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
402 /* finally play the sound fragment */
403 write(audio.device_fd,playing_buffer,sample_size);
406 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
408 close(audio.device_fd);
412 #endif /* !AUDIO_STREAMING_DSP */
416 #endif /* PLATFORM_UNIX */
420 #if defined(PLATFORM_MSDOS)
421 static void sound_handler(struct SoundControl snd_ctrl)
425 if (snd_ctrl.fade_sound)
430 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
431 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
432 !playlist[i].fade_sound)
434 playlist[i].fade_sound = TRUE;
435 if (voice_check(playlist[i].voice))
436 voice_ramp_volume(playlist[i].voice, 1000, 0);
437 playlist[i].loop = PSND_NO_LOOP;
440 else if (snd_ctrl.stop_all_sounds)
444 SoundServer_StopAllSounds();
446 else if (snd_ctrl.stop_sound)
450 SoundServer_StopSound(snd_ctrl.nr);
453 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
455 if (!playlist[i].active || playlist[i].loop)
458 playlist[i].playingpos = voice_get_position(playlist[i].voice);
459 playlist[i].volume = voice_get_volume(playlist[i].voice);
460 if (playlist[i].playingpos == -1 || !playlist[i].volume)
462 deallocate_voice(playlist[i].voice);
463 playlist[i] = emptySoundControl;
469 SoundServer_InsertNewSound(snd_ctrl);
471 #endif /* PLATFORM_MSDOS */
473 #if !defined(PLATFORM_WIN32)
474 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
478 /* if playlist is full, remove oldest sound */
479 if (playing_sounds==MAX_SOUNDS_PLAYING)
481 int longest=0, longest_nr=0;
483 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
485 #if !defined(PLATFORM_MSDOS)
486 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
488 int actual = playlist[i].playingpos;
491 if (!playlist[i].loop && actual>longest)
497 #if defined(PLATFORM_MSDOS)
498 voice_set_volume(playlist[longest_nr].voice, 0);
499 deallocate_voice(playlist[longest_nr].voice);
501 playlist[longest_nr] = emptySoundControl;
505 /* check if sound is already being played (and how often) */
506 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
508 if (playlist[i].nr == snd_ctrl.nr)
512 /* restart loop sounds only if they are just fading out */
513 if (k>=1 && snd_ctrl.loop)
515 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
517 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
519 playlist[i].fade_sound = FALSE;
520 playlist[i].volume = PSND_MAX_VOLUME;
521 #if defined(PLATFORM_MSDOS)
522 playlist[i].loop = PSND_LOOP;
523 voice_stop_volumeramp(playlist[i].voice);
524 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
531 /* don't play sound more than n times simultaneously (with n == 2 for now) */
534 int longest=0, longest_nr=0;
536 /* look for oldest equal sound */
537 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
541 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
544 #if !defined(PLATFORM_MSDOS)
545 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
547 actual = playlist[i].playingpos;
556 #if defined(PLATFORM_MSDOS)
557 voice_set_volume(playlist[longest_nr].voice, 0);
558 deallocate_voice(playlist[longest_nr].voice);
560 playlist[longest_nr] = emptySoundControl;
564 /* neuen Sound in Liste packen */
565 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
567 if (!playlist[i].active)
569 playlist[i] = snd_ctrl;
572 #if defined(PLATFORM_MSDOS)
573 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
575 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
576 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
577 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
578 voice_start(playlist[i].voice);
584 #endif /* !PLATFORM_WIN32 */
587 void SoundServer_FadeSound(int nr)
594 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
595 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
596 playlist[i].fade_sound = TRUE;
600 #if !defined(PLATFORM_WIN32)
601 #if defined(PLATFORM_MSDOS)
602 static void SoundServer_StopSound(int nr)
609 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
610 if (playlist[i].nr == nr)
612 #if defined(PLATFORM_MSDOS)
613 voice_set_volume(playlist[i].voice, 0);
614 deallocate_voice(playlist[i].voice);
616 playlist[i] = emptySoundControl;
620 #if !defined(PLATFORM_MSDOS)
622 close(audio.device_fd);
626 static void SoundServer_StopAllSounds()
630 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
632 #if defined(PLATFORM_MSDOS)
633 voice_set_volume(playlist[i].voice, 0);
634 deallocate_voice(playlist[i].voice);
636 playlist[i]=emptySoundControl;
640 #if !defined(PLATFORM_MSDOS)
641 close(audio.device_fd);
644 #endif /* PLATFORM_MSDOS */
645 #endif /* !PLATFORM_WIN32 */
647 #if defined(PLATFORM_HPUX)
648 static void HPUX_Audio_Control()
650 struct audio_describe ainfo;
653 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
655 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
657 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
658 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
660 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
661 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
663 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
664 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
668 #endif /* PLATFORM_HPUX */
670 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
672 /* these two are stolen from "sox"... :) */
675 ** This routine converts from linear to ulaw.
677 ** Craig Reese: IDA/Supercomputing Research Center
678 ** Joe Campbell: Department of Defense
682 ** 1) CCITT Recommendation G.711 (very difficult to follow)
683 ** 2) "A New Digital Technique for Implementation of Any
684 ** Continuous PCM Companding Law," Villeret, Michel,
685 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
686 ** 1973, pg. 11.12-11.17
687 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
688 ** for Analog-to_Digital Conversion Techniques,"
691 ** Input: Signed 16 bit linear sample
692 ** Output: 8 bit ulaw sample
695 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
696 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
699 static unsigned char linear_to_ulaw(int sample)
701 static int exp_lut[256] =
703 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
704 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
705 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
706 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
707 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
708 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
709 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
710 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
711 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
712 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
713 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
714 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
715 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
716 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
717 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
718 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
721 int sign, exponent, mantissa;
722 unsigned char ulawbyte;
724 /* Get the sample into sign-magnitude. */
725 sign = (sample >> 8) & 0x80; /* set aside the sign */
727 sample = -sample; /* get magnitude */
729 sample = CLIP; /* clip the magnitude */
731 /* Convert from 16 bit linear to ulaw. */
732 sample = sample + BIAS;
733 exponent = exp_lut[( sample >> 7 ) & 0xFF];
734 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
735 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
738 ulawbyte = 0x02; /* optional CCITT trap */
745 ** This routine converts from ulaw to 16 bit linear.
747 ** Craig Reese: IDA/Supercomputing Research Center
751 ** 1) CCITT Recommendation G.711 (very difficult to follow)
752 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
753 ** for Analog-to_Digital Conversion Techniques,"
756 ** Input: 8 bit ulaw sample
757 ** Output: signed 16 bit linear sample
760 static int ulaw_to_linear(unsigned char ulawbyte)
762 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
763 int sign, exponent, mantissa, sample;
765 ulawbyte = ~ ulawbyte;
766 sign = ( ulawbyte & 0x80 );
767 exponent = ( ulawbyte >> 4 ) & 0x07;
768 mantissa = ulawbyte & 0x0F;
769 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
775 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
777 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
779 /*===========================================================================*/
781 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
783 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
784 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
786 boolean LoadSound(struct SampleInfo *snd_info)
789 char *sound_ext = "wav";
790 #if !defined(TARGET_SDL)
791 #if !defined(PLATFORM_MSDOS)
792 byte sound_header_buffer[WAV_HEADER_SIZE];
793 char chunk[CHUNK_ID_LEN + 1];
794 int chunk_length, dummy;
800 sprintf(filename, "%s/%s/%s.%s",
801 options.ro_base_directory, SOUNDS_DIRECTORY,
802 snd_info->name, sound_ext);
804 #if defined(TARGET_SDL)
806 snd_info->mix_chunk = Mix_LoadWAV(filename);
807 if (snd_info->mix_chunk == NULL)
809 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
813 #else /* !TARGET_SDL */
815 #if !defined(PLATFORM_MSDOS)
817 if ((file = fopen(filename, "r")) == NULL)
819 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
823 /* read chunk "RIFF" */
824 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
825 if (strcmp(chunk, "RIFF") != 0)
827 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
832 /* read chunk "WAVE" */
833 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
834 if (strcmp(chunk, "WAVE") != 0)
836 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
841 /* read header information */
842 for (i=0; i<WAV_HEADER_SIZE; i++)
843 sound_header_buffer[i] = fgetc(file);
845 /* read chunk "data" */
846 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
847 if (strcmp(chunk, "data") != 0)
849 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
854 snd_info->data_len = chunk_length;
855 snd_info->data_ptr = checked_malloc(snd_info->data_len);
857 /* read sound data */
858 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
861 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
868 for (i=0; i<snd_info->data_len; i++)
869 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
871 #else /* PLATFORM_MSDOS */
873 snd_info->sample_ptr = load_sample(filename);
874 if (!snd_info->sample_ptr)
876 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
880 #endif /* PLATFORM_MSDOS */
881 #endif /* !TARGET_SDL */
886 void PlaySound(int nr)
888 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
891 void PlaySoundStereo(int nr, int stereo)
893 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
896 void PlaySoundLoop(int nr)
898 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
901 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
903 struct SoundControl snd_ctrl = emptySoundControl;
905 if (!audio.sound_available || !setup.sound)
908 if (volume<PSND_MIN_VOLUME)
909 volume = PSND_MIN_VOLUME;
910 else if (volume>PSND_MAX_VOLUME)
911 volume = PSND_MAX_VOLUME;
913 if (stereo<PSND_MAX_LEFT)
914 stereo = PSND_MAX_LEFT;
915 else if (stereo>PSND_MAX_RIGHT)
916 stereo = PSND_MAX_RIGHT;
919 snd_ctrl.volume = volume;
920 snd_ctrl.stereo = stereo;
921 snd_ctrl.loop = loop;
922 snd_ctrl.active = TRUE;
923 snd_ctrl.data_ptr = Sound[nr].data_ptr;
924 snd_ctrl.data_len = Sound[nr].data_len;
926 #if defined(TARGET_SDL)
928 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
929 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
931 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
934 #if !defined(PLATFORM_MSDOS)
935 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
937 Error(ERR_WARN, "cannot pipe to child process - no sounds");
938 audio.sound_available = FALSE;
942 sound_handler(snd_ctrl);
947 void FadeSound(int nr)
949 StopSoundExt(nr, SSND_FADE_SOUND);
954 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
957 void StopSound(int nr)
959 StopSoundExt(nr, SSND_STOP_SOUND);
964 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
967 void StopSoundExt(int nr, int method)
969 struct SoundControl snd_ctrl = emptySoundControl;
971 if (!audio.sound_available)
974 if (SSND_FADING(method))
975 snd_ctrl.fade_sound = TRUE;
977 if (SSND_ALL(method))
978 snd_ctrl.stop_all_sounds = TRUE;
982 snd_ctrl.stop_sound = TRUE;
985 #if defined(TARGET_SDL)
987 if (SSND_FADING(method))
989 Mix_FadeOutChannel(-1, 1000);
990 Mix_FadeOutMusic(1000);
999 #if !defined(PLATFORM_MSDOS)
1000 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1002 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1003 audio.sound_available = FALSE;
1007 sound_handler(snd_ctrl);
1012 void FreeSounds(int num_sounds)
1016 if (!audio.sound_available)
1019 for(i=0; i<num_sounds; i++)
1020 #if !defined(PLATFORM_MSDOS)
1021 free(Sound[i].data_ptr);
1023 destroy_sample(Sound[i].sample_ptr);
1027 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/