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);
42 static unsigned char linear_to_ulaw(int);
43 static int ulaw_to_linear(unsigned char);
46 static void HPUX_Audio_Control();
49 static void SoundServer_InsertNewSound(struct SoundControl);
50 static void SoundServer_StopSound(int);
51 static void SoundServer_StopAllSounds();
58 struct SoundControl snd_ctrl;
61 close(sound_pipe[1]); /* no writing into pipe needed */
64 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
65 playlist[i] = emptySoundControl;
69 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
70 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
72 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
78 FD_ZERO(&sound_fdset);
79 FD_SET(sound_pipe[0], &sound_fdset);
81 while(1) /* wait for sound playing commands from client */
83 FD_SET(sound_pipe[0], &sound_fdset);
84 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
85 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
87 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
88 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
92 if (snd_ctrl.fade_sound)
97 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
98 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
99 playlist[i].fade_sound = TRUE;
101 else if (snd_ctrl.stop_all_sounds)
106 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
107 playlist[i]=emptySoundControl;
112 else if (snd_ctrl.stop_sound)
117 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
118 if (playlist[i].nr == snd_ctrl.nr)
120 playlist[i]=emptySoundControl;
128 if (playing_sounds || snd_ctrl.active)
130 struct timeval delay = { 0, 0 };
133 static long max_sample_size = 0;
134 static long fragment_size = 0;
137 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
139 if (!playing_sounds) /* we just opened the audio device */
141 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
142 /* (with stereo the effective buffer size will shrink to 256) */
143 fragment_size = 0x00020009;
144 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
145 /* try if we can use stereo sound */
147 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
148 /* get the real fragmentation size; this should return 512 */
149 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
150 max_sample_size = fragment_size / (stereo ? 2 : 1);
153 if (snd_ctrl.active) /* new sound has arrived */
154 SoundServer_InsertNewSound(snd_ctrl);
156 while(playing_sounds &&
157 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
159 FD_SET(sound_pipe[0], &sound_fdset);
161 /* first clear the last premixing buffer */
162 memset(premix_last_buffer,0,fragment_size*sizeof(int));
164 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
168 if (!playlist[i].active)
171 /* get pointer and size of the actual sound sample */
172 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
174 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
175 playlist[i].playingpos += sample_size;
177 /* fill the first mixing buffer with original sample */
178 memcpy(premix_first_buffer,sample_ptr,sample_size);
180 /* are we about to restart a looping sound? */
181 if (playlist[i].loop && sample_size<max_sample_size)
183 playlist[i].playingpos = max_sample_size-sample_size;
184 memcpy(premix_first_buffer+sample_size,
185 playlist[i].data_ptr,max_sample_size-sample_size);
186 sample_size = max_sample_size;
189 /* decrease volume if sound is fading out */
190 if (playlist[i].fade_sound &&
191 playlist[i].volume>=PSND_MAX_VOLUME/10)
192 playlist[i].volume-=PSND_MAX_VOLUME/20;
194 /* adjust volume of actual sound sample */
195 if (playlist[i].volume != PSND_MAX_VOLUME)
196 for(j=0;j<sample_size;j++)
197 premix_first_buffer[j] =
198 (playlist[i].volume * (int)premix_first_buffer[j])
199 >> PSND_MAX_VOLUME_BITS;
201 /* fill the last mixing buffer with stereo or mono sound */
204 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
205 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
206 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
208 for(j=0;j<sample_size;j++)
210 premix_left_buffer[j] =
211 (left_volume * (int)premix_first_buffer[j])
212 >> PSND_MAX_LEFT2RIGHT_BITS;
213 premix_right_buffer[j] =
214 (right_volume * (int)premix_first_buffer[j])
215 >> PSND_MAX_LEFT2RIGHT_BITS;
216 premix_last_buffer[2*j+0] += premix_left_buffer[j];
217 premix_last_buffer[2*j+1] += premix_right_buffer[j];
222 for(j=0;j<sample_size;j++)
223 premix_last_buffer[j] += (int)premix_first_buffer[j];
226 /* delete completed sound entries from the playlist */
227 if (playlist[i].playingpos >= playlist[i].data_len)
229 if (playlist[i].loop)
230 playlist[i].playingpos = 0;
233 playlist[i] = emptySoundControl;
237 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
239 playlist[i] = emptySoundControl;
244 /* put last mixing buffer to final playing buffer */
245 for(i=0;i<fragment_size;i++)
247 if (premix_last_buffer[i]<-255)
248 playing_buffer[i] = 0;
249 else if (premix_last_buffer[i]>255)
250 playing_buffer[i] = 255;
252 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
255 /* finally play the sound fragment */
256 write(sound_device,playing_buffer,fragment_size);
259 /* if no sounds playing, free device for other sound programs */
267 if (snd_ctrl.active && !snd_ctrl.loop)
269 struct timeval delay = { 0, 0 };
271 long sample_size, max_sample_size = SND_BLOCKSIZE;
272 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
273 int wait_percent = 90; /* wait 90% of the real playing time */
276 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
280 while(playing_sounds &&
281 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
283 FD_SET(sound_pipe[0], &sound_fdset);
285 /* get pointer and size of the actual sound sample */
286 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
288 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
289 snd_ctrl.playingpos += sample_size;
291 /* fill the first mixing buffer with original sample */
292 memcpy(premix_first_buffer,sample_ptr,sample_size);
295 /* adjust volume of actual sound sample */
296 if (snd_ctrl.volume != PSND_MAX_VOLUME)
297 for(i=0;i<sample_size;i++)
298 premix_first_buffer[i] =
299 (snd_ctrl.volume * (int)premix_first_buffer[i])
300 >> PSND_MAX_VOLUME_BITS;
302 for(i=0;i<sample_size;i++)
304 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
306 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
309 /* finally play the sound fragment */
310 write(sound_device,playing_buffer,sample_size);
313 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
319 #endif /* !VOXWARE */
326 static void sound_handler(struct SoundControl snd_ctrl)
330 if (snd_ctrl.fade_sound)
335 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
336 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
337 !playlist[i].fade_sound)
339 playlist[i].fade_sound = TRUE;
340 if (voice_check(playlist[i].voice))
341 voice_ramp_volume(playlist[i].voice, 1000, 0);
342 playlist[i].loop = PSND_NO_LOOP;
345 else if (snd_ctrl.stop_all_sounds)
349 SoundServer_StopAllSounds();
351 else if (snd_ctrl.stop_sound)
355 SoundServer_StopSound(snd_ctrl.nr);
358 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
360 if (!playlist[i].active || playlist[i].loop)
363 playlist[i].playingpos = voice_get_position(playlist[i].voice);
364 playlist[i].volume = voice_get_volume(playlist[i].voice);
365 if (playlist[i].playingpos == -1 || !playlist[i].volume)
367 deallocate_voice(playlist[i].voice);
368 playlist[i] = emptySoundControl;
374 SoundServer_InsertNewSound(snd_ctrl);
378 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
382 /* if playlist is full, remove oldest sound */
383 if (playing_sounds==MAX_SOUNDS_PLAYING)
385 int longest=0, longest_nr=0;
387 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
390 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
392 int actual = playlist[i].playingpos;
395 if (!playlist[i].loop && actual>longest)
402 voice_set_volume(playlist[longest_nr].voice, 0);
403 deallocate_voice(playlist[longest_nr].voice);
405 playlist[longest_nr] = emptySoundControl;
409 /* check if sound is already being played (and how often) */
410 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
412 if (playlist[i].nr == snd_ctrl.nr)
416 /* restart loop sounds only if they are just fading out */
417 if (k>=1 && snd_ctrl.loop)
419 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
421 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
423 playlist[i].fade_sound = FALSE;
424 playlist[i].volume = PSND_MAX_VOLUME;
426 playlist[i].loop = PSND_LOOP;
427 voice_stop_volumeramp(playlist[i].voice);
428 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
435 /* don't play sound more than n times simultaneously (with n == 2 for now) */
438 int longest=0, longest_nr=0;
440 /* look for oldest equal sound */
441 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
445 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
449 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
451 actual = playlist[i].playingpos;
460 voice_set_volume(playlist[longest_nr].voice, 0);
461 deallocate_voice(playlist[longest_nr].voice);
463 playlist[longest_nr] = emptySoundControl;
467 /* neuen Sound in Liste packen */
468 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
470 if (!playlist[i].active)
472 playlist[i] = snd_ctrl;
475 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
477 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
478 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
479 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
480 voice_start(playlist[i].voice);
488 void SoundServer_FadeSound(int nr)
495 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
496 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
497 playlist[i].fade_sound = TRUE;
501 static void SoundServer_StopSound(int nr)
508 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
509 if (playlist[i].nr == nr)
512 voice_set_volume(playlist[i].voice, 0);
513 deallocate_voice(playlist[i].voice);
515 playlist[i] = emptySoundControl;
525 static void SoundServer_StopAllSounds()
529 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
532 voice_set_volume(playlist[i].voice, 0);
533 deallocate_voice(playlist[i].voice);
535 playlist[i]=emptySoundControl;
545 static void HPUX_Audio_Control()
547 struct audio_describe ainfo;
550 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
552 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
554 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
555 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
557 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
558 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
560 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
561 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
565 #endif /* HPUX_AUDIO */
567 /* these two are stolen from "sox"... :) */
570 ** This routine converts from linear to ulaw.
572 ** Craig Reese: IDA/Supercomputing Research Center
573 ** Joe Campbell: Department of Defense
577 ** 1) CCITT Recommendation G.711 (very difficult to follow)
578 ** 2) "A New Digital Technique for Implementation of Any
579 ** Continuous PCM Companding Law," Villeret, Michel,
580 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
581 ** 1973, pg. 11.12-11.17
582 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
583 ** for Analog-to_Digital Conversion Techniques,"
586 ** Input: Signed 16 bit linear sample
587 ** Output: 8 bit ulaw sample
590 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
591 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
594 static unsigned char linear_to_ulaw(int sample)
596 static int exp_lut[256] =
598 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
599 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
600 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
601 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
602 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
603 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
604 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
605 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
606 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
607 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
608 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
609 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
610 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
611 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
616 int sign, exponent, mantissa;
617 unsigned char ulawbyte;
619 /* Get the sample into sign-magnitude. */
620 sign = (sample >> 8) & 0x80; /* set aside the sign */
622 sample = -sample; /* get magnitude */
624 sample = CLIP; /* clip the magnitude */
626 /* Convert from 16 bit linear to ulaw. */
627 sample = sample + BIAS;
628 exponent = exp_lut[( sample >> 7 ) & 0xFF];
629 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
630 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
633 ulawbyte = 0x02; /* optional CCITT trap */
640 ** This routine converts from ulaw to 16 bit linear.
642 ** Craig Reese: IDA/Supercomputing Research Center
646 ** 1) CCITT Recommendation G.711 (very difficult to follow)
647 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
648 ** for Analog-to_Digital Conversion Techniques,"
651 ** Input: 8 bit ulaw sample
652 ** Output: signed 16 bit linear sample
655 static int ulaw_to_linear(unsigned char ulawbyte)
657 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
658 int sign, exponent, mantissa, sample;
660 ulawbyte = ~ ulawbyte;
661 sign = ( ulawbyte & 0x80 );
662 exponent = ( ulawbyte >> 4 ) & 0x07;
663 mantissa = ulawbyte & 0x0F;
664 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
671 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
673 /*===========================================================================*/
675 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
678 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
680 unsigned char *ptr = (unsigned char *)be;
682 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
685 static unsigned long le2long(unsigned long *be) /* little-endian -> longword */
687 unsigned char *ptr = (unsigned char *)be;
689 return(ptr[3]<<24 | ptr[2]<<16 | ptr[1]<<8 | ptr[0]);
693 boolean LoadSound(struct SoundInfo *snd_info)
696 char *sound_ext = "wav";
698 struct SoundHeader_WAV *sound_header;
703 sprintf(filename, "%s/%s/%s.%s",
704 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
708 if ((file = fopen(filename, "r")) == NULL)
710 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
714 if (fseek(file, 0, SEEK_END) < 0)
716 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
721 snd_info->file_len = ftell(file);
724 snd_info->file_ptr = checked_malloc(snd_info->file_len);
726 if (fread(snd_info->file_ptr, 1, snd_info->file_len, file) !=
729 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
736 sound_header = (struct SoundHeader_WAV *)snd_info->file_ptr;
738 if (strncmp(sound_header->magic_RIFF, "RIFF", 4) ||
739 snd_info->file_len != le2long(&sound_header->header_size) + 8 ||
740 strncmp(sound_header->magic_WAVE, "WAVE", 4) ||
741 strncmp(sound_header->magic_DATA, "data", 4) ||
742 snd_info->file_len != le2long(&sound_header->data_size) + 44)
744 Error(ERR_WARN, "'%s' is not a RIFF/WAVE file or broken - no sounds",
749 snd_info->data_ptr = snd_info->file_ptr + 44;
750 snd_info->data_len = le2long(&sound_header->data_size);
752 for (i=0; i<snd_info->data_len; i++)
753 snd_info->data_ptr[i] = snd_info->data_ptr[i]^0x80;
757 snd_info->sample_ptr = load_sample(filename);
758 if (!snd_info->sample_ptr)
760 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
769 boolean LoadSound_8SVX(struct SoundInfo *snd_info)
773 struct SoundHeader_8SVX *sound_header;
776 char *sound_ext = "8svx";
778 char *sound_ext = "wav";
781 sprintf(filename, "%s/%s/%s.%s",
782 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
785 if (!(file=fopen(filename,"r")))
787 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
791 if (fseek(file,0,SEEK_END)<0)
793 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
798 snd_info->file_len = ftell(file);
801 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
803 Error(ERR_WARN, "out of memory (this shouldn't happen :) - no sounds");
808 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
810 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
817 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
819 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
820 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
821 strncmp(sound_header->magic_8SVX,"8SVX",4))
823 Error(ERR_WARN, "'%s' is not an IFF/8SVX file or broken - no sounds",
828 ptr = (char *)snd_info->file_ptr + 12;
830 while(ptr < (char *)(snd_info->file_ptr + snd_info->file_len))
832 if (!strncmp(ptr,"VHDR",4))
834 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
837 else if (!strncmp(ptr,"ANNO",4))
839 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
842 else if (!strncmp(ptr,"CHAN",4))
844 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
847 else if (!strncmp(ptr,"BODY",4))
849 snd_info->data_ptr = (byte *)ptr + 8;
850 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
855 /* other chunk not recognized here */
856 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
863 snd_info->sample_ptr = load_sample(filename);
864 if(!snd_info->sample_ptr)
866 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
873 void PlaySound(int nr)
875 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
878 void PlaySoundStereo(int nr, int stereo)
880 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
883 void PlaySoundLoop(int nr)
885 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
888 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
890 struct SoundControl snd_ctrl = emptySoundControl;
892 if (sound_status==SOUND_OFF || !setup.sound)
895 if (volume<PSND_MIN_VOLUME)
896 volume = PSND_MIN_VOLUME;
897 else if (volume>PSND_MAX_VOLUME)
898 volume = PSND_MAX_VOLUME;
900 if (stereo<PSND_MAX_LEFT)
901 stereo = PSND_MAX_LEFT;
902 else if (stereo>PSND_MAX_RIGHT)
903 stereo = PSND_MAX_RIGHT;
906 snd_ctrl.volume = volume;
907 snd_ctrl.stereo = stereo;
908 snd_ctrl.loop = loop;
909 snd_ctrl.active = TRUE;
910 snd_ctrl.data_ptr = Sound[nr].data_ptr;
911 snd_ctrl.data_len = Sound[nr].data_len;
914 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
916 Error(ERR_WARN, "cannot pipe to child process - no sounds");
917 sound_status = SOUND_OFF;
921 sound_handler(snd_ctrl);
925 void FadeSound(int nr)
927 StopSoundExt(nr, SSND_FADE_SOUND);
932 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
935 void StopSound(int nr)
937 StopSoundExt(nr, SSND_STOP_SOUND);
942 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
945 void StopSoundExt(int nr, int method)
947 struct SoundControl snd_ctrl = emptySoundControl;
949 if (sound_status==SOUND_OFF)
952 if (SSND_FADING(method))
953 snd_ctrl.fade_sound = TRUE;
955 if (SSND_ALL(method))
956 snd_ctrl.stop_all_sounds = TRUE;
960 snd_ctrl.stop_sound = TRUE;
964 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
966 Error(ERR_WARN, "cannot pipe to child process - no sounds");
967 sound_status = SOUND_OFF;
971 sound_handler(snd_ctrl);
975 void FreeSounds(int max)
979 if (sound_status==SOUND_OFF)
984 free(Sound[i].file_ptr);
986 destroy_sample(Sound[i].sample_ptr);
990 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/