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;
502 static void SoundServer_StopSound(int nr)
509 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
510 if (playlist[i].nr == nr)
513 voice_set_volume(playlist[i].voice, 0);
514 deallocate_voice(playlist[i].voice);
516 playlist[i] = emptySoundControl;
526 static void SoundServer_StopAllSounds()
530 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
533 voice_set_volume(playlist[i].voice, 0);
534 deallocate_voice(playlist[i].voice);
536 playlist[i]=emptySoundControl;
547 static void HPUX_Audio_Control()
549 struct audio_describe ainfo;
552 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
554 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
556 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
557 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
559 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
560 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
562 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
563 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
567 #endif /* HPUX_AUDIO */
570 /* these two are stolen from "sox"... :) */
573 ** This routine converts from linear to ulaw.
575 ** Craig Reese: IDA/Supercomputing Research Center
576 ** Joe Campbell: Department of Defense
580 ** 1) CCITT Recommendation G.711 (very difficult to follow)
581 ** 2) "A New Digital Technique for Implementation of Any
582 ** Continuous PCM Companding Law," Villeret, Michel,
583 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
584 ** 1973, pg. 11.12-11.17
585 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
586 ** for Analog-to_Digital Conversion Techniques,"
589 ** Input: Signed 16 bit linear sample
590 ** Output: 8 bit ulaw sample
593 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
594 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
597 static unsigned char linear_to_ulaw(int sample)
599 static int exp_lut[256] =
601 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
602 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
603 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
604 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
605 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
606 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
607 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
608 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
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
619 int sign, exponent, mantissa;
620 unsigned char ulawbyte;
622 /* Get the sample into sign-magnitude. */
623 sign = (sample >> 8) & 0x80; /* set aside the sign */
625 sample = -sample; /* get magnitude */
627 sample = CLIP; /* clip the magnitude */
629 /* Convert from 16 bit linear to ulaw. */
630 sample = sample + BIAS;
631 exponent = exp_lut[( sample >> 7 ) & 0xFF];
632 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
633 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
636 ulawbyte = 0x02; /* optional CCITT trap */
643 ** This routine converts from ulaw to 16 bit linear.
645 ** Craig Reese: IDA/Supercomputing Research Center
649 ** 1) CCITT Recommendation G.711 (very difficult to follow)
650 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
651 ** for Analog-to_Digital Conversion Techniques,"
654 ** Input: 8 bit ulaw sample
655 ** Output: signed 16 bit linear sample
658 static int ulaw_to_linear(unsigned char ulawbyte)
660 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
661 int sign, exponent, mantissa, sample;
663 ulawbyte = ~ ulawbyte;
664 sign = ( ulawbyte & 0x80 );
665 exponent = ( ulawbyte >> 4 ) & 0x07;
666 mantissa = ulawbyte & 0x0F;
667 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
673 #endif /* !VOXWARE */
675 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
677 /*===========================================================================*/
679 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
682 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
684 unsigned char *ptr = (unsigned char *)be;
686 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
689 static unsigned long le2long(unsigned long *be) /* little-endian -> longword */
691 unsigned char *ptr = (unsigned char *)be;
693 return(ptr[3]<<24 | ptr[2]<<16 | ptr[1]<<8 | ptr[0]);
697 boolean LoadSound(struct SoundInfo *snd_info)
700 char *sound_ext = "wav";
702 struct SoundHeader_WAV *sound_header;
707 sprintf(filename, "%s/%s/%s.%s",
708 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
712 if ((file = fopen(filename, "r")) == NULL)
714 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
718 if (fseek(file, 0, SEEK_END) < 0)
720 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
725 snd_info->file_len = ftell(file);
728 snd_info->file_ptr = checked_malloc(snd_info->file_len);
730 if (fread(snd_info->file_ptr, 1, snd_info->file_len, file) !=
733 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
740 sound_header = (struct SoundHeader_WAV *)snd_info->file_ptr;
742 if (strncmp(sound_header->magic_RIFF, "RIFF", 4) ||
743 snd_info->file_len != le2long(&sound_header->header_size) + 8 ||
744 strncmp(sound_header->magic_WAVE, "WAVE", 4) ||
745 strncmp(sound_header->magic_DATA, "data", 4) ||
746 snd_info->file_len != le2long(&sound_header->data_size) + 44)
748 Error(ERR_WARN, "'%s' is not a RIFF/WAVE file or broken - no sounds",
753 snd_info->data_ptr = snd_info->file_ptr + 44;
754 snd_info->data_len = le2long(&sound_header->data_size);
756 for (i=0; i<snd_info->data_len; i++)
757 snd_info->data_ptr[i] = snd_info->data_ptr[i]^0x80;
761 snd_info->sample_ptr = load_sample(filename);
762 if (!snd_info->sample_ptr)
764 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
773 boolean LoadSound_8SVX(struct SoundInfo *snd_info)
777 struct SoundHeader_8SVX *sound_header;
780 char *sound_ext = "8svx";
782 char *sound_ext = "wav";
785 sprintf(filename, "%s/%s/%s.%s",
786 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
789 if (!(file=fopen(filename,"r")))
791 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
795 if (fseek(file,0,SEEK_END)<0)
797 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
802 snd_info->file_len = ftell(file);
805 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
807 Error(ERR_WARN, "out of memory (this shouldn't happen :) - no sounds");
812 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
814 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
821 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
823 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
824 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
825 strncmp(sound_header->magic_8SVX,"8SVX",4))
827 Error(ERR_WARN, "'%s' is not an IFF/8SVX file or broken - no sounds",
832 ptr = (char *)snd_info->file_ptr + 12;
834 while(ptr < (char *)(snd_info->file_ptr + snd_info->file_len))
836 if (!strncmp(ptr,"VHDR",4))
838 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
841 else if (!strncmp(ptr,"ANNO",4))
843 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
846 else if (!strncmp(ptr,"CHAN",4))
848 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
851 else if (!strncmp(ptr,"BODY",4))
853 snd_info->data_ptr = (byte *)ptr + 8;
854 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
859 /* other chunk not recognized here */
860 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
867 snd_info->sample_ptr = load_sample(filename);
868 if(!snd_info->sample_ptr)
870 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
877 void PlaySound(int nr)
879 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
882 void PlaySoundStereo(int nr, int stereo)
884 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
887 void PlaySoundLoop(int nr)
889 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
892 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
894 struct SoundControl snd_ctrl = emptySoundControl;
896 if (sound_status==SOUND_OFF || !setup.sound)
899 if (volume<PSND_MIN_VOLUME)
900 volume = PSND_MIN_VOLUME;
901 else if (volume>PSND_MAX_VOLUME)
902 volume = PSND_MAX_VOLUME;
904 if (stereo<PSND_MAX_LEFT)
905 stereo = PSND_MAX_LEFT;
906 else if (stereo>PSND_MAX_RIGHT)
907 stereo = PSND_MAX_RIGHT;
910 snd_ctrl.volume = volume;
911 snd_ctrl.stereo = stereo;
912 snd_ctrl.loop = loop;
913 snd_ctrl.active = TRUE;
914 snd_ctrl.data_ptr = Sound[nr].data_ptr;
915 snd_ctrl.data_len = Sound[nr].data_len;
918 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
920 Error(ERR_WARN, "cannot pipe to child process - no sounds");
921 sound_status = SOUND_OFF;
925 sound_handler(snd_ctrl);
929 void FadeSound(int nr)
931 StopSoundExt(nr, SSND_FADE_SOUND);
936 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
939 void StopSound(int nr)
941 StopSoundExt(nr, SSND_STOP_SOUND);
946 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
949 void StopSoundExt(int nr, int method)
951 struct SoundControl snd_ctrl = emptySoundControl;
953 if (sound_status==SOUND_OFF)
956 if (SSND_FADING(method))
957 snd_ctrl.fade_sound = TRUE;
959 if (SSND_ALL(method))
960 snd_ctrl.stop_all_sounds = TRUE;
964 snd_ctrl.stop_sound = TRUE;
968 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
970 Error(ERR_WARN, "cannot pipe to child process - no sounds");
971 sound_status = SOUND_OFF;
975 sound_handler(snd_ctrl);
979 void FreeSounds(int max)
983 if (sound_status==SOUND_OFF)
988 free(Sound[i].file_ptr);
990 destroy_sample(Sound[i].sample_ptr);
994 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/