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(MSDOS) && !defined(WIN32)
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];
35 #endif /* !MSDOS && !WIN32 */
37 /* forward declaration of internal functions */
39 static void SoundServer_InsertNewSound(struct SoundControl);
42 #if !defined(VOXWARE) && !defined(MSDOS) && !defined(WIN32)
43 static unsigned char linear_to_ulaw(int);
44 static int ulaw_to_linear(unsigned char);
48 static void HPUX_Audio_Control();
52 static void SoundServer_InsertNewSound(struct SoundControl);
53 static void SoundServer_StopSound(int);
54 static void SoundServer_StopAllSounds();
57 int OpenAudio(char *audio_device_name)
61 /* try to open audio device in non-blocking mode */
62 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
65 /* re-open audio device in blocking mode */
67 audio_fd = open(audio_device_name, O_WRONLY);
75 #if !defined(MSDOS) && !defined(WIN32)
76 struct SoundControl snd_ctrl;
79 close(sound_pipe[1]); /* no writing into pipe needed */
82 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
83 playlist[i] = emptySoundControl;
86 #if !defined(MSDOS) && !defined(WIN32)
87 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
88 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
90 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
96 FD_ZERO(&sound_fdset);
97 FD_SET(sound_pipe[0], &sound_fdset);
99 while(1) /* wait for sound playing commands from client */
101 FD_SET(sound_pipe[0], &sound_fdset);
102 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
103 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
105 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
106 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
110 if (snd_ctrl.fade_sound)
115 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
116 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
117 playlist[i].fade_sound = TRUE;
119 else if (snd_ctrl.stop_all_sounds)
124 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
125 playlist[i]=emptySoundControl;
130 else if (snd_ctrl.stop_sound)
135 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
136 if (playlist[i].nr == snd_ctrl.nr)
138 playlist[i]=emptySoundControl;
146 if (playing_sounds || snd_ctrl.active)
148 struct timeval delay = { 0, 0 };
151 static long max_sample_size = 0;
152 static long fragment_size = 0;
153 /* Even if the stereo flag is used as being boolean, it must be
154 defined as an integer, else 'ioctl()' will fail! */
157 int sample_rate = 8000;
159 int sample_rate = 22050;
162 if (playing_sounds ||
163 (sound_device = OpenAudio(sound_device_name)) >= 0)
165 if (!playing_sounds) /* we just opened the audio device */
167 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
168 /* (with stereo the effective buffer size will shrink to 256) */
169 fragment_size = 0x00020009;
171 if (ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size) < 0)
172 Error(ERR_EXIT_SOUND_SERVER,
173 "cannot set fragment size of /dev/dsp - no sounds");
175 /* try if we can use stereo sound */
176 if (ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo) < 0)
179 static boolean reported = FALSE;
183 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
190 if (ioctl(sound_device, SNDCTL_DSP_SPEED, &sample_rate) < 0)
191 Error(ERR_EXIT_SOUND_SERVER,
192 "cannot set sample rate of /dev/dsp - no sounds");
194 /* get the real fragmentation size; this should return 512 */
195 if (ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
196 Error(ERR_EXIT_SOUND_SERVER,
197 "cannot get fragment size of /dev/dsp - no sounds");
199 max_sample_size = fragment_size / (stereo ? 2 : 1);
202 if (snd_ctrl.active) /* new sound has arrived */
203 SoundServer_InsertNewSound(snd_ctrl);
205 while(playing_sounds &&
206 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
208 FD_SET(sound_pipe[0], &sound_fdset);
210 /* first clear the last premixing buffer */
211 memset(premix_last_buffer,0,fragment_size*sizeof(int));
213 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
217 if (!playlist[i].active)
220 /* get pointer and size of the actual sound sample */
221 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
223 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
224 playlist[i].playingpos += sample_size;
226 /* fill the first mixing buffer with original sample */
227 memcpy(premix_first_buffer,sample_ptr,sample_size);
229 /* are we about to restart a looping sound? */
230 if (playlist[i].loop && sample_size<max_sample_size)
232 playlist[i].playingpos = max_sample_size-sample_size;
233 memcpy(premix_first_buffer+sample_size,
234 playlist[i].data_ptr,max_sample_size-sample_size);
235 sample_size = max_sample_size;
238 /* decrease volume if sound is fading out */
239 if (playlist[i].fade_sound &&
240 playlist[i].volume>=PSND_MAX_VOLUME/10)
241 playlist[i].volume-=PSND_MAX_VOLUME/20;
243 /* adjust volume of actual sound sample */
244 if (playlist[i].volume != PSND_MAX_VOLUME)
245 for(j=0;j<sample_size;j++)
246 premix_first_buffer[j] =
247 (playlist[i].volume * (int)premix_first_buffer[j])
248 >> PSND_MAX_VOLUME_BITS;
250 /* fill the last mixing buffer with stereo or mono sound */
253 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
254 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
255 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
257 for(j=0;j<sample_size;j++)
259 premix_left_buffer[j] =
260 (left_volume * (int)premix_first_buffer[j])
261 >> PSND_MAX_LEFT2RIGHT_BITS;
262 premix_right_buffer[j] =
263 (right_volume * (int)premix_first_buffer[j])
264 >> PSND_MAX_LEFT2RIGHT_BITS;
265 premix_last_buffer[2*j+0] += premix_left_buffer[j];
266 premix_last_buffer[2*j+1] += premix_right_buffer[j];
271 for(j=0;j<sample_size;j++)
272 premix_last_buffer[j] += (int)premix_first_buffer[j];
275 /* delete completed sound entries from the playlist */
276 if (playlist[i].playingpos >= playlist[i].data_len)
278 if (playlist[i].loop)
279 playlist[i].playingpos = 0;
282 playlist[i] = emptySoundControl;
286 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
288 playlist[i] = emptySoundControl;
293 /* put last mixing buffer to final playing buffer */
294 for(i=0;i<fragment_size;i++)
296 if (premix_last_buffer[i]<-255)
297 playing_buffer[i] = 0;
298 else if (premix_last_buffer[i]>255)
299 playing_buffer[i] = 255;
301 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
304 /* finally play the sound fragment */
305 write(sound_device,playing_buffer,fragment_size);
308 /* if no sounds playing, free device for other sound programs */
316 if (snd_ctrl.active && !snd_ctrl.loop)
318 struct timeval delay = { 0, 0 };
320 long sample_size, max_sample_size = SND_BLOCKSIZE;
321 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
322 int wait_percent = 90; /* wait 90% of the real playing time */
325 if ((sound_device = OpenAudio(sound_device_name)) >= 0)
329 while(playing_sounds &&
330 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
332 FD_SET(sound_pipe[0], &sound_fdset);
334 /* get pointer and size of the actual sound sample */
335 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
337 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
338 snd_ctrl.playingpos += sample_size;
340 /* fill the first mixing buffer with original sample */
341 memcpy(premix_first_buffer,sample_ptr,sample_size);
344 /* adjust volume of actual sound sample */
345 if (snd_ctrl.volume != PSND_MAX_VOLUME)
346 for(i=0;i<sample_size;i++)
347 premix_first_buffer[i] =
348 (snd_ctrl.volume * (int)premix_first_buffer[i])
349 >> PSND_MAX_VOLUME_BITS;
351 for(i=0;i<sample_size;i++)
353 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
355 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
358 /* finally play the sound fragment */
359 write(sound_device,playing_buffer,sample_size);
362 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
368 #endif /* !VOXWARE */
372 #endif /* !MSDOS && !WIN32 */
377 static void sound_handler(struct SoundControl snd_ctrl)
381 if (snd_ctrl.fade_sound)
386 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
387 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
388 !playlist[i].fade_sound)
390 playlist[i].fade_sound = TRUE;
391 if (voice_check(playlist[i].voice))
392 voice_ramp_volume(playlist[i].voice, 1000, 0);
393 playlist[i].loop = PSND_NO_LOOP;
396 else if (snd_ctrl.stop_all_sounds)
400 SoundServer_StopAllSounds();
402 else if (snd_ctrl.stop_sound)
406 SoundServer_StopSound(snd_ctrl.nr);
409 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
411 if (!playlist[i].active || playlist[i].loop)
414 playlist[i].playingpos = voice_get_position(playlist[i].voice);
415 playlist[i].volume = voice_get_volume(playlist[i].voice);
416 if (playlist[i].playingpos == -1 || !playlist[i].volume)
418 deallocate_voice(playlist[i].voice);
419 playlist[i] = emptySoundControl;
425 SoundServer_InsertNewSound(snd_ctrl);
430 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
434 /* if playlist is full, remove oldest sound */
435 if (playing_sounds==MAX_SOUNDS_PLAYING)
437 int longest=0, longest_nr=0;
439 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
442 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
444 int actual = playlist[i].playingpos;
447 if (!playlist[i].loop && actual>longest)
454 voice_set_volume(playlist[longest_nr].voice, 0);
455 deallocate_voice(playlist[longest_nr].voice);
457 playlist[longest_nr] = emptySoundControl;
461 /* check if sound is already being played (and how often) */
462 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
464 if (playlist[i].nr == snd_ctrl.nr)
468 /* restart loop sounds only if they are just fading out */
469 if (k>=1 && snd_ctrl.loop)
471 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
473 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
475 playlist[i].fade_sound = FALSE;
476 playlist[i].volume = PSND_MAX_VOLUME;
478 playlist[i].loop = PSND_LOOP;
479 voice_stop_volumeramp(playlist[i].voice);
480 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
487 /* don't play sound more than n times simultaneously (with n == 2 for now) */
490 int longest=0, longest_nr=0;
492 /* look for oldest equal sound */
493 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
497 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
501 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
503 actual = playlist[i].playingpos;
512 voice_set_volume(playlist[longest_nr].voice, 0);
513 deallocate_voice(playlist[longest_nr].voice);
515 playlist[longest_nr] = emptySoundControl;
519 /* neuen Sound in Liste packen */
520 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
522 if (!playlist[i].active)
524 playlist[i] = snd_ctrl;
527 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
529 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
530 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
531 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
532 voice_start(playlist[i].voice);
541 void SoundServer_FadeSound(int nr)
548 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
549 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
550 playlist[i].fade_sound = TRUE;
556 static void SoundServer_StopSound(int nr)
563 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
564 if (playlist[i].nr == nr)
567 voice_set_volume(playlist[i].voice, 0);
568 deallocate_voice(playlist[i].voice);
570 playlist[i] = emptySoundControl;
580 static void SoundServer_StopAllSounds()
584 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
587 voice_set_volume(playlist[i].voice, 0);
588 deallocate_voice(playlist[i].voice);
590 playlist[i]=emptySoundControl;
602 static void HPUX_Audio_Control()
604 struct audio_describe ainfo;
607 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
609 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
611 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
612 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
614 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
615 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
617 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
618 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
622 #endif /* HPUX_AUDIO */
624 #if !defined(VOXWARE) && !defined(MSDOS) && !defined(WIN32)
626 /* these two are stolen from "sox"... :) */
629 ** This routine converts from linear to ulaw.
631 ** Craig Reese: IDA/Supercomputing Research Center
632 ** Joe Campbell: Department of Defense
636 ** 1) CCITT Recommendation G.711 (very difficult to follow)
637 ** 2) "A New Digital Technique for Implementation of Any
638 ** Continuous PCM Companding Law," Villeret, Michel,
639 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
640 ** 1973, pg. 11.12-11.17
641 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
642 ** for Analog-to_Digital Conversion Techniques,"
645 ** Input: Signed 16 bit linear sample
646 ** Output: 8 bit ulaw sample
649 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
650 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
653 static unsigned char linear_to_ulaw(int sample)
655 static int exp_lut[256] =
657 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
658 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
659 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
660 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
661 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
662 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
663 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
664 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
665 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
666 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
667 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
668 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
669 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
670 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
671 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
672 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
675 int sign, exponent, mantissa;
676 unsigned char ulawbyte;
678 /* Get the sample into sign-magnitude. */
679 sign = (sample >> 8) & 0x80; /* set aside the sign */
681 sample = -sample; /* get magnitude */
683 sample = CLIP; /* clip the magnitude */
685 /* Convert from 16 bit linear to ulaw. */
686 sample = sample + BIAS;
687 exponent = exp_lut[( sample >> 7 ) & 0xFF];
688 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
689 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
692 ulawbyte = 0x02; /* optional CCITT trap */
699 ** This routine converts from ulaw to 16 bit linear.
701 ** Craig Reese: IDA/Supercomputing Research Center
705 ** 1) CCITT Recommendation G.711 (very difficult to follow)
706 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
707 ** for Analog-to_Digital Conversion Techniques,"
710 ** Input: 8 bit ulaw sample
711 ** Output: signed 16 bit linear sample
714 static int ulaw_to_linear(unsigned char ulawbyte)
716 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
717 int sign, exponent, mantissa, sample;
719 ulawbyte = ~ ulawbyte;
720 sign = ( ulawbyte & 0x80 );
721 exponent = ( ulawbyte >> 4 ) & 0x07;
722 mantissa = ulawbyte & 0x0F;
723 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
729 #endif /* !VOXWARE && !MSDOS && !WIN32 */
731 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
733 /*===========================================================================*/
735 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
737 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
738 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
740 boolean LoadSound(struct SoundInfo *snd_info)
743 char *sound_ext = "wav";
744 #ifndef USE_SDL_LIBRARY
746 byte sound_header_buffer[WAV_HEADER_SIZE];
747 char chunk[CHUNK_ID_LEN + 1];
748 int chunk_length, dummy;
754 sprintf(filename, "%s/%s/%s.%s",
755 options.ro_base_directory, SOUNDS_DIRECTORY,
756 snd_info->name, sound_ext);
758 #ifdef USE_SDL_LIBRARY
760 snd_info->mix_chunk = Mix_LoadWAV(filename);
761 if (snd_info->mix_chunk == NULL)
763 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
767 #else /* !USE_SDL_LIBRARY */
771 if ((file = fopen(filename, "r")) == NULL)
773 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
777 /* read chunk "RIFF" */
778 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
779 if (strcmp(chunk, "RIFF") != 0)
781 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
786 /* read chunk "WAVE" */
787 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
788 if (strcmp(chunk, "WAVE") != 0)
790 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
795 /* read header information */
796 for (i=0; i<WAV_HEADER_SIZE; i++)
797 sound_header_buffer[i] = fgetc(file);
799 /* read chunk "data" */
800 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
801 if (strcmp(chunk, "data") != 0)
803 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
808 snd_info->data_len = chunk_length;
809 snd_info->data_ptr = checked_malloc(snd_info->data_len);
811 /* read sound data */
812 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
815 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
822 for (i=0; i<snd_info->data_len; i++)
823 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
827 snd_info->sample_ptr = load_sample(filename);
828 if (!snd_info->sample_ptr)
830 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
835 #endif /* !USE_SDL_LIBRARY */
840 void PlaySound(int nr)
842 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
845 void PlaySoundStereo(int nr, int stereo)
847 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
850 void PlaySoundLoop(int nr)
852 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
855 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
857 struct SoundControl snd_ctrl = emptySoundControl;
859 if (sound_status==SOUND_OFF || !setup.sound)
862 if (volume<PSND_MIN_VOLUME)
863 volume = PSND_MIN_VOLUME;
864 else if (volume>PSND_MAX_VOLUME)
865 volume = PSND_MAX_VOLUME;
867 if (stereo<PSND_MAX_LEFT)
868 stereo = PSND_MAX_LEFT;
869 else if (stereo>PSND_MAX_RIGHT)
870 stereo = PSND_MAX_RIGHT;
873 snd_ctrl.volume = volume;
874 snd_ctrl.stereo = stereo;
875 snd_ctrl.loop = loop;
876 snd_ctrl.active = TRUE;
877 snd_ctrl.data_ptr = Sound[nr].data_ptr;
878 snd_ctrl.data_len = Sound[nr].data_len;
880 #ifdef USE_SDL_LIBRARY
882 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
883 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
885 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
889 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
891 Error(ERR_WARN, "cannot pipe to child process - no sounds");
892 sound_status = SOUND_OFF;
896 sound_handler(snd_ctrl);
901 void FadeSound(int nr)
903 StopSoundExt(nr, SSND_FADE_SOUND);
908 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
911 void StopSound(int nr)
913 StopSoundExt(nr, SSND_STOP_SOUND);
918 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
921 void StopSoundExt(int nr, int method)
923 struct SoundControl snd_ctrl = emptySoundControl;
925 if (sound_status==SOUND_OFF)
928 if (SSND_FADING(method))
929 snd_ctrl.fade_sound = TRUE;
931 if (SSND_ALL(method))
932 snd_ctrl.stop_all_sounds = TRUE;
936 snd_ctrl.stop_sound = TRUE;
939 #ifdef USE_SDL_LIBRARY
941 if (SSND_FADING(method))
943 Mix_FadeOutChannel(-1, 1000);
944 Mix_FadeOutMusic(1000);
954 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
956 Error(ERR_WARN, "cannot pipe to child process - no sounds");
957 sound_status = SOUND_OFF;
961 sound_handler(snd_ctrl);
966 void FreeSounds(int num_sounds)
970 if (sound_status == SOUND_OFF)
973 for(i=0; i<num_sounds; i++)
975 free(Sound[i].data_ptr);
977 destroy_sample(Sound[i].sample_ptr);
981 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/