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
27 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
28 static char premix_first_buffer[SND_BLOCKSIZE];
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 */
39 static void SoundServer_InsertNewSound(struct SoundControl);
43 static unsigned char linear_to_ulaw(int);
44 static int ulaw_to_linear(unsigned char);
48 static void HPUX_Audio_Control();
51 static void SoundServer_InsertNewSound(struct SoundControl);
52 static void SoundServer_StopSound(int);
53 static void SoundServer_StopAllSounds();
60 struct SoundControl snd_ctrl;
63 close(sound_pipe[1]); /* no writing into pipe needed */
66 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
67 playlist[i] = emptySoundControl;
71 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
72 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
74 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
80 FD_ZERO(&sound_fdset);
81 FD_SET(sound_pipe[0], &sound_fdset);
83 while(1) /* wait for sound playing commands from client */
85 FD_SET(sound_pipe[0], &sound_fdset);
86 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
87 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
89 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
90 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
94 if (snd_ctrl.fade_sound)
99 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
100 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
101 playlist[i].fade_sound = TRUE;
103 else if (snd_ctrl.stop_all_sounds)
108 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
109 playlist[i]=emptySoundControl;
114 else if (snd_ctrl.stop_sound)
119 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
120 if (playlist[i].nr == snd_ctrl.nr)
122 playlist[i]=emptySoundControl;
130 if (playing_sounds || snd_ctrl.active)
132 struct timeval delay = { 0, 0 };
135 static long max_sample_size = 0;
136 static long fragment_size = 0;
139 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
141 if (!playing_sounds) /* we just opened the audio device */
143 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
144 /* (with stereo the effective buffer size will shrink to 256) */
145 fragment_size = 0x00020009;
146 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
147 /* try if we can use stereo sound */
149 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
150 /* get the real fragmentation size; this should return 512 */
151 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
152 max_sample_size = fragment_size / (stereo ? 2 : 1);
155 if (snd_ctrl.active) /* new sound has arrived */
156 SoundServer_InsertNewSound(snd_ctrl);
158 while(playing_sounds &&
159 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
161 FD_SET(sound_pipe[0], &sound_fdset);
163 /* first clear the last premixing buffer */
164 memset(premix_last_buffer,0,fragment_size*sizeof(int));
166 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
170 if (!playlist[i].active)
173 /* get pointer and size of the actual sound sample */
174 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
176 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
177 playlist[i].playingpos += sample_size;
179 /* fill the first mixing buffer with original sample */
180 memcpy(premix_first_buffer,sample_ptr,sample_size);
182 /* are we about to restart a looping sound? */
183 if (playlist[i].loop && sample_size<max_sample_size)
185 playlist[i].playingpos = max_sample_size-sample_size;
186 memcpy(premix_first_buffer+sample_size,
187 playlist[i].data_ptr,max_sample_size-sample_size);
188 sample_size = max_sample_size;
191 /* decrease volume if sound is fading out */
192 if (playlist[i].fade_sound &&
193 playlist[i].volume>=PSND_MAX_VOLUME/10)
194 playlist[i].volume-=PSND_MAX_VOLUME/20;
196 /* adjust volume of actual sound sample */
197 if (playlist[i].volume != PSND_MAX_VOLUME)
198 for(j=0;j<sample_size;j++)
199 premix_first_buffer[j] =
200 (playlist[i].volume * (int)premix_first_buffer[j])
201 >> PSND_MAX_VOLUME_BITS;
203 /* fill the last mixing buffer with stereo or mono sound */
206 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
207 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
208 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
210 for(j=0;j<sample_size;j++)
212 premix_left_buffer[j] =
213 (left_volume * (int)premix_first_buffer[j])
214 >> PSND_MAX_LEFT2RIGHT_BITS;
215 premix_right_buffer[j] =
216 (right_volume * (int)premix_first_buffer[j])
217 >> PSND_MAX_LEFT2RIGHT_BITS;
218 premix_last_buffer[2*j+0] += premix_left_buffer[j];
219 premix_last_buffer[2*j+1] += premix_right_buffer[j];
224 for(j=0;j<sample_size;j++)
225 premix_last_buffer[j] += (int)premix_first_buffer[j];
228 /* delete completed sound entries from the playlist */
229 if (playlist[i].playingpos >= playlist[i].data_len)
231 if (playlist[i].loop)
232 playlist[i].playingpos = 0;
235 playlist[i] = emptySoundControl;
239 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
241 playlist[i] = emptySoundControl;
246 /* put last mixing buffer to final playing buffer */
247 for(i=0;i<fragment_size;i++)
249 if (premix_last_buffer[i]<-255)
250 playing_buffer[i] = 0;
251 else if (premix_last_buffer[i]>255)
252 playing_buffer[i] = 255;
254 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
257 /* finally play the sound fragment */
258 write(sound_device,playing_buffer,fragment_size);
261 /* if no sounds playing, free device for other sound programs */
269 if (snd_ctrl.active && !snd_ctrl.loop)
271 struct timeval delay = { 0, 0 };
273 long sample_size, max_sample_size = SND_BLOCKSIZE;
274 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
275 int wait_percent = 90; /* wait 90% of the real playing time */
278 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
282 while(playing_sounds &&
283 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
285 FD_SET(sound_pipe[0], &sound_fdset);
287 /* get pointer and size of the actual sound sample */
288 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
290 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
291 snd_ctrl.playingpos += sample_size;
293 /* fill the first mixing buffer with original sample */
294 memcpy(premix_first_buffer,sample_ptr,sample_size);
297 /* adjust volume of actual sound sample */
298 if (snd_ctrl.volume != PSND_MAX_VOLUME)
299 for(i=0;i<sample_size;i++)
300 premix_first_buffer[i] =
301 (snd_ctrl.volume * (int)premix_first_buffer[i])
302 >> PSND_MAX_VOLUME_BITS;
304 for(i=0;i<sample_size;i++)
306 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
308 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
311 /* finally play the sound fragment */
312 write(sound_device,playing_buffer,sample_size);
315 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
321 #endif /* !VOXWARE */
328 static void sound_handler(struct SoundControl snd_ctrl)
332 if (snd_ctrl.fade_sound)
337 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
338 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
339 !playlist[i].fade_sound)
341 playlist[i].fade_sound = TRUE;
342 if (voice_check(playlist[i].voice))
343 voice_ramp_volume(playlist[i].voice, 1000, 0);
344 playlist[i].loop = PSND_NO_LOOP;
347 else if (snd_ctrl.stop_all_sounds)
351 SoundServer_StopAllSounds();
353 else if (snd_ctrl.stop_sound)
357 SoundServer_StopSound(snd_ctrl.nr);
360 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
362 if (!playlist[i].active || playlist[i].loop)
365 playlist[i].playingpos = voice_get_position(playlist[i].voice);
366 playlist[i].volume = voice_get_volume(playlist[i].voice);
367 if (playlist[i].playingpos == -1 || !playlist[i].volume)
369 deallocate_voice(playlist[i].voice);
370 playlist[i] = emptySoundControl;
376 SoundServer_InsertNewSound(snd_ctrl);
380 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
384 /* if playlist is full, remove oldest sound */
385 if (playing_sounds==MAX_SOUNDS_PLAYING)
387 int longest=0, longest_nr=0;
389 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
392 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
394 int actual = playlist[i].playingpos;
397 if (!playlist[i].loop && actual>longest)
404 voice_set_volume(playlist[longest_nr].voice, 0);
405 deallocate_voice(playlist[longest_nr].voice);
407 playlist[longest_nr] = emptySoundControl;
411 /* check if sound is already being played (and how often) */
412 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
414 if (playlist[i].nr == snd_ctrl.nr)
418 /* restart loop sounds only if they are just fading out */
419 if (k>=1 && snd_ctrl.loop)
421 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
423 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
425 playlist[i].fade_sound = FALSE;
426 playlist[i].volume = PSND_MAX_VOLUME;
428 playlist[i].loop = PSND_LOOP;
429 voice_stop_volumeramp(playlist[i].voice);
430 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
437 /* don't play sound more than n times simultaneously (with n == 2 for now) */
440 int longest=0, longest_nr=0;
442 /* look for oldest equal sound */
443 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
447 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
451 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
453 actual = playlist[i].playingpos;
462 voice_set_volume(playlist[longest_nr].voice, 0);
463 deallocate_voice(playlist[longest_nr].voice);
465 playlist[longest_nr] = emptySoundControl;
469 /* neuen Sound in Liste packen */
470 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
472 if (!playlist[i].active)
474 playlist[i] = snd_ctrl;
477 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
479 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
480 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
481 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
482 voice_start(playlist[i].voice);
490 void SoundServer_FadeSound(int nr)
497 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
498 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
499 playlist[i].fade_sound = TRUE;
504 static void SoundServer_StopSound(int nr)
511 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
512 if (playlist[i].nr == nr)
515 voice_set_volume(playlist[i].voice, 0);
516 deallocate_voice(playlist[i].voice);
518 playlist[i] = emptySoundControl;
528 static void SoundServer_StopAllSounds()
532 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
535 voice_set_volume(playlist[i].voice, 0);
536 deallocate_voice(playlist[i].voice);
538 playlist[i]=emptySoundControl;
549 static void HPUX_Audio_Control()
551 struct audio_describe ainfo;
554 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
556 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
558 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
559 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
561 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
562 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
564 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
565 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
569 #endif /* HPUX_AUDIO */
573 /* these two are stolen from "sox"... :) */
576 ** This routine converts from linear to ulaw.
578 ** Craig Reese: IDA/Supercomputing Research Center
579 ** Joe Campbell: Department of Defense
583 ** 1) CCITT Recommendation G.711 (very difficult to follow)
584 ** 2) "A New Digital Technique for Implementation of Any
585 ** Continuous PCM Companding Law," Villeret, Michel,
586 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
587 ** 1973, pg. 11.12-11.17
588 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
589 ** for Analog-to_Digital Conversion Techniques,"
592 ** Input: Signed 16 bit linear sample
593 ** Output: 8 bit ulaw sample
596 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
597 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
600 static unsigned char linear_to_ulaw(int sample)
602 static int exp_lut[256] =
604 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
605 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
606 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
607 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
608 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
609 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
610 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
611 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
612 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
613 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
614 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
615 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
616 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
617 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
618 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
619 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
622 int sign, exponent, mantissa;
623 unsigned char ulawbyte;
625 /* Get the sample into sign-magnitude. */
626 sign = (sample >> 8) & 0x80; /* set aside the sign */
628 sample = -sample; /* get magnitude */
630 sample = CLIP; /* clip the magnitude */
632 /* Convert from 16 bit linear to ulaw. */
633 sample = sample + BIAS;
634 exponent = exp_lut[( sample >> 7 ) & 0xFF];
635 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
636 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
639 ulawbyte = 0x02; /* optional CCITT trap */
646 ** This routine converts from ulaw to 16 bit linear.
648 ** Craig Reese: IDA/Supercomputing Research Center
652 ** 1) CCITT Recommendation G.711 (very difficult to follow)
653 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
654 ** for Analog-to_Digital Conversion Techniques,"
657 ** Input: 8 bit ulaw sample
658 ** Output: signed 16 bit linear sample
661 static int ulaw_to_linear(unsigned char ulawbyte)
663 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
664 int sign, exponent, mantissa, sample;
666 ulawbyte = ~ ulawbyte;
667 sign = ( ulawbyte & 0x80 );
668 exponent = ( ulawbyte >> 4 ) & 0x07;
669 mantissa = ulawbyte & 0x0F;
670 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
677 #endif /* !VOXWARE */
679 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
681 /*===========================================================================*/
683 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
686 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
688 unsigned char *ptr = (unsigned char *)be;
690 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
693 static unsigned long le2long(unsigned long *be) /* little-endian -> longword */
695 unsigned char *ptr = (unsigned char *)be;
697 return(ptr[3]<<24 | ptr[2]<<16 | ptr[1]<<8 | ptr[0]);
701 boolean LoadSound(struct SoundInfo *snd_info)
704 char *sound_ext = "wav";
706 struct SoundHeader_WAV *sound_header;
711 sprintf(filename, "%s/%s/%s.%s",
712 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
716 if ((file = fopen(filename, "r")) == NULL)
718 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
722 if (fseek(file, 0, SEEK_END) < 0)
724 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
729 snd_info->file_len = ftell(file);
732 snd_info->file_ptr = checked_malloc(snd_info->file_len);
734 if (fread(snd_info->file_ptr, 1, snd_info->file_len, file) !=
737 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
744 sound_header = (struct SoundHeader_WAV *)snd_info->file_ptr;
746 if (strncmp(sound_header->magic_RIFF, "RIFF", 4) ||
747 snd_info->file_len != le2long(&sound_header->header_size) + 8 ||
748 strncmp(sound_header->magic_WAVE, "WAVE", 4) ||
749 strncmp(sound_header->magic_DATA, "data", 4) ||
750 snd_info->file_len != le2long(&sound_header->data_size) + 44)
752 Error(ERR_WARN, "'%s' is not a RIFF/WAVE file or broken - no sounds",
757 snd_info->data_ptr = snd_info->file_ptr + 44;
758 snd_info->data_len = le2long(&sound_header->data_size);
760 for (i=0; i<snd_info->data_len; i++)
761 snd_info->data_ptr[i] = snd_info->data_ptr[i]^0x80;
765 snd_info->sample_ptr = load_sample(filename);
766 if (!snd_info->sample_ptr)
768 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
777 boolean LoadSound_8SVX(struct SoundInfo *snd_info)
781 struct SoundHeader_8SVX *sound_header;
784 char *sound_ext = "8svx";
786 char *sound_ext = "wav";
789 sprintf(filename, "%s/%s/%s.%s",
790 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
793 if (!(file=fopen(filename,"r")))
795 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
799 if (fseek(file,0,SEEK_END)<0)
801 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
806 snd_info->file_len = ftell(file);
809 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
811 Error(ERR_WARN, "out of memory (this shouldn't happen :) - no sounds");
816 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
818 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
825 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
827 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
828 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
829 strncmp(sound_header->magic_8SVX,"8SVX",4))
831 Error(ERR_WARN, "'%s' is not an IFF/8SVX file or broken - no sounds",
836 ptr = (char *)snd_info->file_ptr + 12;
838 while(ptr < (char *)(snd_info->file_ptr + snd_info->file_len))
840 if (!strncmp(ptr,"VHDR",4))
842 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
845 else if (!strncmp(ptr,"ANNO",4))
847 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
850 else if (!strncmp(ptr,"CHAN",4))
852 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
855 else if (!strncmp(ptr,"BODY",4))
857 snd_info->data_ptr = (byte *)ptr + 8;
858 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
863 /* other chunk not recognized here */
864 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
871 snd_info->sample_ptr = load_sample(filename);
872 if(!snd_info->sample_ptr)
874 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
881 void PlaySound(int nr)
883 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
886 void PlaySoundStereo(int nr, int stereo)
888 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
891 void PlaySoundLoop(int nr)
893 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
896 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
898 struct SoundControl snd_ctrl = emptySoundControl;
900 if (sound_status==SOUND_OFF || !setup.sound)
903 if (volume<PSND_MIN_VOLUME)
904 volume = PSND_MIN_VOLUME;
905 else if (volume>PSND_MAX_VOLUME)
906 volume = PSND_MAX_VOLUME;
908 if (stereo<PSND_MAX_LEFT)
909 stereo = PSND_MAX_LEFT;
910 else if (stereo>PSND_MAX_RIGHT)
911 stereo = PSND_MAX_RIGHT;
914 snd_ctrl.volume = volume;
915 snd_ctrl.stereo = stereo;
916 snd_ctrl.loop = loop;
917 snd_ctrl.active = TRUE;
918 snd_ctrl.data_ptr = Sound[nr].data_ptr;
919 snd_ctrl.data_len = Sound[nr].data_len;
922 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
924 Error(ERR_WARN, "cannot pipe to child process - no sounds");
925 sound_status = SOUND_OFF;
929 sound_handler(snd_ctrl);
933 void FadeSound(int nr)
935 StopSoundExt(nr, SSND_FADE_SOUND);
940 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
943 void StopSound(int nr)
945 StopSoundExt(nr, SSND_STOP_SOUND);
950 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
953 void StopSoundExt(int nr, int method)
955 struct SoundControl snd_ctrl = emptySoundControl;
957 if (sound_status==SOUND_OFF)
960 if (SSND_FADING(method))
961 snd_ctrl.fade_sound = TRUE;
963 if (SSND_ALL(method))
964 snd_ctrl.stop_all_sounds = TRUE;
968 snd_ctrl.stop_sound = TRUE;
972 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
974 Error(ERR_WARN, "cannot pipe to child process - no sounds");
975 sound_status = SOUND_OFF;
979 sound_handler(snd_ctrl);
983 void FreeSounds(int max)
987 if (sound_status==SOUND_OFF)
992 free(Sound[i].file_ptr);
994 destroy_sample(Sound[i].sample_ptr);
998 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/