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 ***********************************************************/
21 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
23 static int playing_sounds = 0;
24 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
25 static struct SoundControl emptySoundControl =
27 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
30 #if defined(PLATFORM_UNIX)
31 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
32 static char premix_first_buffer[SND_BLOCKSIZE];
33 #if defined(AUDIO_STREAMING_DSP)
34 static char premix_left_buffer[SND_BLOCKSIZE];
35 static char premix_right_buffer[SND_BLOCKSIZE];
36 static int premix_last_buffer[SND_BLOCKSIZE];
38 static unsigned char playing_buffer[SND_BLOCKSIZE];
41 /* forward declaration of internal functions */
42 #if defined(AUDIO_STREAMING_DSP)
43 static void SoundServer_InsertNewSound(struct SoundControl);
44 #elif defined(PLATFORM_UNIX)
45 static unsigned char linear_to_ulaw(int);
46 static int ulaw_to_linear(unsigned char);
49 #if defined(PLATFORM_HPUX)
50 static void HPUX_Audio_Control();
53 #if defined(PLATFORM_MSDOS)
54 static void SoundServer_InsertNewSound(struct SoundControl);
55 static void SoundServer_StopSound(int);
56 static void SoundServer_StopAllSounds();
59 #if defined(PLATFORM_UNIX)
60 int OpenAudioDevice(char *audio_device_name)
64 /* check if desired audio device is accessible */
65 if (access(audio_device_name, W_OK) != 0)
68 /* try to open audio device in non-blocking mode */
69 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
72 /* re-open audio device in blocking mode */
74 audio_fd = open(audio_device_name, O_WRONLY);
79 void UnixOpenAudio(struct AudioSystemInfo *audio)
81 static char *audio_device_name[] =
89 /* look for available audio devices, starting with preferred ones */
90 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
91 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
96 Error(ERR_WARN, "cannot open audio device - no sound");
102 audio->device_name = audio_device_name[i];
103 audio->sound_available = TRUE;
105 #if defined(AUDIO_STREAMING_DSP)
106 audio->loops_available = TRUE;
110 void UnixCloseAudio(struct AudioSystemInfo *audio)
112 if (audio->device_fd)
113 close(audio->device_fd);
116 #endif /* PLATFORM_UNIX */
121 #if defined(PLATFORM_UNIX)
122 struct SoundControl snd_ctrl;
125 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
128 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
129 playlist[i] = emptySoundControl;
132 #if defined(PLATFORM_UNIX)
133 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
134 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
136 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
138 #if defined(PLATFORM_HPUX)
139 HPUX_Audio_Control();
142 FD_ZERO(&sound_fdset);
143 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
145 while(1) /* wait for sound playing commands from client */
147 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
148 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
149 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
151 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
153 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
155 #if defined(AUDIO_STREAMING_DSP)
157 if (snd_ctrl.fade_sound)
162 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
163 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
164 playlist[i].fade_sound = TRUE;
166 else if (snd_ctrl.stop_all_sounds)
171 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
172 playlist[i]=emptySoundControl;
175 close(audio.device_fd);
177 else if (snd_ctrl.stop_sound)
182 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
183 if (playlist[i].nr == snd_ctrl.nr)
185 playlist[i]=emptySoundControl;
190 close(audio.device_fd);
193 if (playing_sounds || snd_ctrl.active)
195 struct timeval delay = { 0, 0 };
198 static long max_sample_size = 0;
199 static long fragment_size = 0;
200 /* Even if the stereo flag is used as being boolean, it must be
201 defined as an integer, else 'ioctl()' will fail! */
204 int sample_rate = 8000;
206 int sample_rate = 22050;
209 if (playing_sounds ||
210 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
212 if (!playing_sounds) /* we just opened the audio device */
214 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
215 /* (with stereo the effective buffer size will shrink to 256) */
216 fragment_size = 0x00020009;
218 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_size) < 0)
219 Error(ERR_EXIT_SOUND_SERVER,
220 "cannot set fragment size of /dev/dsp - no sounds");
222 /* try if we can use stereo sound */
223 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
226 static boolean reported = FALSE;
230 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
237 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
238 Error(ERR_EXIT_SOUND_SERVER,
239 "cannot set sample rate of /dev/dsp - no sounds");
241 /* get the real fragmentation size; this should return 512 */
242 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
243 Error(ERR_EXIT_SOUND_SERVER,
244 "cannot get fragment size of /dev/dsp - no sounds");
246 max_sample_size = fragment_size / (stereo ? 2 : 1);
249 if (snd_ctrl.active) /* new sound has arrived */
250 SoundServer_InsertNewSound(snd_ctrl);
252 while(playing_sounds &&
253 select(audio.soundserver_pipe[0] + 1,
254 &sound_fdset, NULL, NULL, &delay) < 1)
256 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
258 /* first clear the last premixing buffer */
259 memset(premix_last_buffer,0,fragment_size*sizeof(int));
261 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
265 if (!playlist[i].active)
268 /* get pointer and size of the actual sound sample */
269 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
271 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
272 playlist[i].playingpos += sample_size;
274 /* fill the first mixing buffer with original sample */
275 memcpy(premix_first_buffer,sample_ptr,sample_size);
277 /* are we about to restart a looping sound? */
278 if (playlist[i].loop && sample_size<max_sample_size)
280 playlist[i].playingpos = max_sample_size-sample_size;
281 memcpy(premix_first_buffer+sample_size,
282 playlist[i].data_ptr,max_sample_size-sample_size);
283 sample_size = max_sample_size;
286 /* decrease volume if sound is fading out */
287 if (playlist[i].fade_sound &&
288 playlist[i].volume>=PSND_MAX_VOLUME/10)
289 playlist[i].volume-=PSND_MAX_VOLUME/20;
291 /* adjust volume of actual sound sample */
292 if (playlist[i].volume != PSND_MAX_VOLUME)
293 for(j=0;j<sample_size;j++)
294 premix_first_buffer[j] =
295 (playlist[i].volume * (int)premix_first_buffer[j])
296 >> PSND_MAX_VOLUME_BITS;
298 /* fill the last mixing buffer with stereo or mono sound */
301 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
302 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
303 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
305 for(j=0;j<sample_size;j++)
307 premix_left_buffer[j] =
308 (left_volume * (int)premix_first_buffer[j])
309 >> PSND_MAX_LEFT2RIGHT_BITS;
310 premix_right_buffer[j] =
311 (right_volume * (int)premix_first_buffer[j])
312 >> PSND_MAX_LEFT2RIGHT_BITS;
313 premix_last_buffer[2*j+0] += premix_left_buffer[j];
314 premix_last_buffer[2*j+1] += premix_right_buffer[j];
319 for(j=0;j<sample_size;j++)
320 premix_last_buffer[j] += (int)premix_first_buffer[j];
323 /* delete completed sound entries from the playlist */
324 if (playlist[i].playingpos >= playlist[i].data_len)
326 if (playlist[i].loop)
327 playlist[i].playingpos = 0;
330 playlist[i] = emptySoundControl;
334 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
336 playlist[i] = emptySoundControl;
341 /* put last mixing buffer to final playing buffer */
342 for(i=0;i<fragment_size;i++)
344 if (premix_last_buffer[i]<-255)
345 playing_buffer[i] = 0;
346 else if (premix_last_buffer[i]>255)
347 playing_buffer[i] = 255;
349 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
352 /* finally play the sound fragment */
353 write(audio.device_fd, playing_buffer,fragment_size);
356 /* if no sounds playing, free device for other sound programs */
358 close(audio.device_fd);
362 #else /* !AUDIO_STREAMING_DSP */
364 if (snd_ctrl.active && !snd_ctrl.loop)
366 struct timeval delay = { 0, 0 };
368 long sample_size, max_sample_size = SND_BLOCKSIZE;
369 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
370 int wait_percent = 90; /* wait 90% of the real playing time */
373 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
377 while(playing_sounds &&
378 select(audio.soundserver_pipe[0] + 1,
379 &sound_fdset, NULL, NULL, &delay) < 1)
381 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
383 /* get pointer and size of the actual sound sample */
384 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
386 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
387 snd_ctrl.playingpos += sample_size;
389 /* fill the first mixing buffer with original sample */
390 memcpy(premix_first_buffer,sample_ptr,sample_size);
393 /* adjust volume of actual sound sample */
394 if (snd_ctrl.volume != PSND_MAX_VOLUME)
395 for(i=0;i<sample_size;i++)
396 premix_first_buffer[i] =
397 (snd_ctrl.volume * (int)premix_first_buffer[i])
398 >> PSND_MAX_VOLUME_BITS;
400 for(i=0;i<sample_size;i++)
402 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
404 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
407 /* finally play the sound fragment */
408 write(audio.device_fd,playing_buffer,sample_size);
411 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
413 close(audio.device_fd);
417 #endif /* !AUDIO_STREAMING_DSP */
421 #endif /* PLATFORM_UNIX */
425 #if defined(PLATFORM_MSDOS)
426 static void sound_handler(struct SoundControl snd_ctrl)
430 if (snd_ctrl.fade_sound)
435 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
436 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
437 !playlist[i].fade_sound)
439 playlist[i].fade_sound = TRUE;
440 if (voice_check(playlist[i].voice))
441 voice_ramp_volume(playlist[i].voice, 1000, 0);
442 playlist[i].loop = PSND_NO_LOOP;
445 else if (snd_ctrl.stop_all_sounds)
449 SoundServer_StopAllSounds();
451 else if (snd_ctrl.stop_sound)
455 SoundServer_StopSound(snd_ctrl.nr);
458 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
460 if (!playlist[i].active || playlist[i].loop)
463 playlist[i].playingpos = voice_get_position(playlist[i].voice);
464 playlist[i].volume = voice_get_volume(playlist[i].voice);
465 if (playlist[i].playingpos == -1 || !playlist[i].volume)
467 deallocate_voice(playlist[i].voice);
468 playlist[i] = emptySoundControl;
474 SoundServer_InsertNewSound(snd_ctrl);
476 #endif /* PLATFORM_MSDOS */
478 #if !defined(PLATFORM_WIN32)
479 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
483 /* if playlist is full, remove oldest sound */
484 if (playing_sounds==MAX_SOUNDS_PLAYING)
486 int longest=0, longest_nr=0;
488 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
490 #if !defined(PLATFORM_MSDOS)
491 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
493 int actual = playlist[i].playingpos;
496 if (!playlist[i].loop && actual>longest)
502 #if defined(PLATFORM_MSDOS)
503 voice_set_volume(playlist[longest_nr].voice, 0);
504 deallocate_voice(playlist[longest_nr].voice);
506 playlist[longest_nr] = emptySoundControl;
510 /* check if sound is already being played (and how often) */
511 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
513 if (playlist[i].nr == snd_ctrl.nr)
517 /* restart loop sounds only if they are just fading out */
518 if (k>=1 && snd_ctrl.loop)
520 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
522 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
524 playlist[i].fade_sound = FALSE;
525 playlist[i].volume = PSND_MAX_VOLUME;
526 #if defined(PLATFORM_MSDOS)
527 playlist[i].loop = PSND_LOOP;
528 voice_stop_volumeramp(playlist[i].voice);
529 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
536 /* don't play sound more than n times simultaneously (with n == 2 for now) */
539 int longest=0, longest_nr=0;
541 /* look for oldest equal sound */
542 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
546 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
549 #if !defined(PLATFORM_MSDOS)
550 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
552 actual = playlist[i].playingpos;
561 #if defined(PLATFORM_MSDOS)
562 voice_set_volume(playlist[longest_nr].voice, 0);
563 deallocate_voice(playlist[longest_nr].voice);
565 playlist[longest_nr] = emptySoundControl;
569 /* neuen Sound in Liste packen */
570 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
572 if (!playlist[i].active)
574 playlist[i] = snd_ctrl;
577 #if defined(PLATFORM_MSDOS)
578 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
580 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
581 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
582 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
583 voice_start(playlist[i].voice);
589 #endif /* !PLATFORM_WIN32 */
592 void SoundServer_FadeSound(int nr)
599 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
600 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
601 playlist[i].fade_sound = TRUE;
605 #if !defined(PLATFORM_WIN32)
606 #if defined(PLATFORM_MSDOS)
607 static void SoundServer_StopSound(int nr)
614 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
615 if (playlist[i].nr == nr)
617 #if defined(PLATFORM_MSDOS)
618 voice_set_volume(playlist[i].voice, 0);
619 deallocate_voice(playlist[i].voice);
621 playlist[i] = emptySoundControl;
625 #if !defined(PLATFORM_MSDOS)
627 close(audio.device_fd);
631 static void SoundServer_StopAllSounds()
635 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
637 #if defined(PLATFORM_MSDOS)
638 voice_set_volume(playlist[i].voice, 0);
639 deallocate_voice(playlist[i].voice);
641 playlist[i]=emptySoundControl;
645 #if !defined(PLATFORM_MSDOS)
646 close(audio.device_fd);
649 #endif /* PLATFORM_MSDOS */
650 #endif /* !PLATFORM_WIN32 */
652 #if defined(PLATFORM_HPUX)
653 static void HPUX_Audio_Control()
655 struct audio_describe ainfo;
658 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
660 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
662 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
663 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
665 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
666 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
668 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
669 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
673 #endif /* PLATFORM_HPUX */
675 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
677 /* these two are stolen from "sox"... :) */
680 ** This routine converts from linear to ulaw.
682 ** Craig Reese: IDA/Supercomputing Research Center
683 ** Joe Campbell: Department of Defense
687 ** 1) CCITT Recommendation G.711 (very difficult to follow)
688 ** 2) "A New Digital Technique for Implementation of Any
689 ** Continuous PCM Companding Law," Villeret, Michel,
690 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
691 ** 1973, pg. 11.12-11.17
692 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
693 ** for Analog-to_Digital Conversion Techniques,"
696 ** Input: Signed 16 bit linear sample
697 ** Output: 8 bit ulaw sample
700 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
701 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
704 static unsigned char linear_to_ulaw(int sample)
706 static int exp_lut[256] =
708 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
709 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
710 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
711 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
712 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
713 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
714 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
715 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
719 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
720 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
721 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
722 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
723 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
726 int sign, exponent, mantissa;
727 unsigned char ulawbyte;
729 /* Get the sample into sign-magnitude. */
730 sign = (sample >> 8) & 0x80; /* set aside the sign */
732 sample = -sample; /* get magnitude */
734 sample = CLIP; /* clip the magnitude */
736 /* Convert from 16 bit linear to ulaw. */
737 sample = sample + BIAS;
738 exponent = exp_lut[( sample >> 7 ) & 0xFF];
739 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
740 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
743 ulawbyte = 0x02; /* optional CCITT trap */
750 ** This routine converts from ulaw to 16 bit linear.
752 ** Craig Reese: IDA/Supercomputing Research Center
756 ** 1) CCITT Recommendation G.711 (very difficult to follow)
757 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
758 ** for Analog-to_Digital Conversion Techniques,"
761 ** Input: 8 bit ulaw sample
762 ** Output: signed 16 bit linear sample
765 static int ulaw_to_linear(unsigned char ulawbyte)
767 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
768 int sign, exponent, mantissa, sample;
770 ulawbyte = ~ ulawbyte;
771 sign = ( ulawbyte & 0x80 );
772 exponent = ( ulawbyte >> 4 ) & 0x07;
773 mantissa = ulawbyte & 0x0F;
774 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
780 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
782 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
784 /*===========================================================================*/
786 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
788 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
789 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
791 boolean LoadSound(struct SampleInfo *snd_info)
794 char *sound_ext = "wav";
795 #if !defined(TARGET_SDL)
796 #if !defined(PLATFORM_MSDOS)
797 byte sound_header_buffer[WAV_HEADER_SIZE];
798 char chunk[CHUNK_ID_LEN + 1];
799 int chunk_length, dummy;
805 sprintf(filename, "%s/%s/%s.%s",
806 options.ro_base_directory, SOUNDS_DIRECTORY,
807 snd_info->name, sound_ext);
809 #if defined(TARGET_SDL)
811 snd_info->mix_chunk = Mix_LoadWAV(filename);
812 if (snd_info->mix_chunk == NULL)
814 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
818 #else /* !TARGET_SDL */
820 #if !defined(PLATFORM_MSDOS)
822 if ((file = fopen(filename, "r")) == NULL)
824 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
828 /* read chunk "RIFF" */
829 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
830 if (strcmp(chunk, "RIFF") != 0)
832 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
837 /* read chunk "WAVE" */
838 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
839 if (strcmp(chunk, "WAVE") != 0)
841 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
846 /* read header information */
847 for (i=0; i<WAV_HEADER_SIZE; i++)
848 sound_header_buffer[i] = fgetc(file);
850 /* read chunk "data" */
851 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
852 if (strcmp(chunk, "data") != 0)
854 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
859 snd_info->data_len = chunk_length;
860 snd_info->data_ptr = checked_malloc(snd_info->data_len);
862 /* read sound data */
863 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
866 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
873 for (i=0; i<snd_info->data_len; i++)
874 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
876 #else /* PLATFORM_MSDOS */
878 snd_info->sample_ptr = load_sample(filename);
879 if (!snd_info->sample_ptr)
881 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
885 #endif /* PLATFORM_MSDOS */
886 #endif /* !TARGET_SDL */
891 void PlaySound(int nr)
893 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
896 void PlaySoundStereo(int nr, int stereo)
898 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
901 void PlaySoundLoop(int nr)
903 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
906 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
908 struct SoundControl snd_ctrl = emptySoundControl;
910 if (!audio.sound_available || !setup.sound)
913 if (volume<PSND_MIN_VOLUME)
914 volume = PSND_MIN_VOLUME;
915 else if (volume>PSND_MAX_VOLUME)
916 volume = PSND_MAX_VOLUME;
918 if (stereo<PSND_MAX_LEFT)
919 stereo = PSND_MAX_LEFT;
920 else if (stereo>PSND_MAX_RIGHT)
921 stereo = PSND_MAX_RIGHT;
924 snd_ctrl.volume = volume;
925 snd_ctrl.stereo = stereo;
926 snd_ctrl.loop = loop;
927 snd_ctrl.active = TRUE;
928 snd_ctrl.data_ptr = Sound[nr].data_ptr;
929 snd_ctrl.data_len = Sound[nr].data_len;
931 #if defined(TARGET_SDL)
933 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
934 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
936 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
939 #if !defined(PLATFORM_MSDOS)
940 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
942 Error(ERR_WARN, "cannot pipe to child process - no sounds");
943 audio.sound_available = FALSE;
947 sound_handler(snd_ctrl);
952 void FadeSound(int nr)
954 StopSoundExt(nr, SSND_FADE_SOUND);
959 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
962 void StopSound(int nr)
964 StopSoundExt(nr, SSND_STOP_SOUND);
969 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
972 void StopSoundExt(int nr, int method)
974 struct SoundControl snd_ctrl = emptySoundControl;
976 if (!audio.sound_available)
979 if (SSND_FADING(method))
980 snd_ctrl.fade_sound = TRUE;
982 if (SSND_ALL(method))
983 snd_ctrl.stop_all_sounds = TRUE;
987 snd_ctrl.stop_sound = TRUE;
990 #if defined(TARGET_SDL)
992 if (SSND_FADING(method))
994 Mix_FadeOutChannel(-1, 1000);
995 Mix_FadeOutMusic(1000);
1004 #if !defined(PLATFORM_MSDOS)
1005 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1007 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1008 audio.sound_available = FALSE;
1012 sound_handler(snd_ctrl);
1017 void FreeSounds(int num_sounds)
1021 if (!audio.sound_available)
1024 for(i=0; i<num_sounds; i++)
1025 #if !defined(PLATFORM_MSDOS)
1026 free(Sound[i].data_ptr);
1028 destroy_sample(Sound[i].sample_ptr);
1032 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/