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);
72 int CheckAudio(char *audio_device_name)
76 if (access(audio_device_name, W_OK) != 0)
78 Error(ERR_WARN, "cannot access audio device - no sound");
82 if ((audio_fd = OpenAudio(sound_device_name)) < 0)
84 Error(ERR_WARN, "cannot open audio device - no sound");
90 return SOUND_AVAILABLE;
93 boolean UnixInitAudio(void)
101 #if !defined(MSDOS) && !defined(WIN32)
102 struct SoundControl snd_ctrl;
105 close(sound_pipe[1]); /* no writing into pipe needed */
108 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
109 playlist[i] = emptySoundControl;
112 #if !defined(MSDOS) && !defined(WIN32)
113 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
114 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
116 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
119 HPUX_Audio_Control();
122 FD_ZERO(&sound_fdset);
123 FD_SET(sound_pipe[0], &sound_fdset);
125 while(1) /* wait for sound playing commands from client */
127 FD_SET(sound_pipe[0], &sound_fdset);
128 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
129 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
131 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
132 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
136 if (snd_ctrl.fade_sound)
141 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
142 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
143 playlist[i].fade_sound = TRUE;
145 else if (snd_ctrl.stop_all_sounds)
150 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
151 playlist[i]=emptySoundControl;
156 else if (snd_ctrl.stop_sound)
161 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
162 if (playlist[i].nr == snd_ctrl.nr)
164 playlist[i]=emptySoundControl;
172 if (playing_sounds || snd_ctrl.active)
174 struct timeval delay = { 0, 0 };
177 static long max_sample_size = 0;
178 static long fragment_size = 0;
179 /* Even if the stereo flag is used as being boolean, it must be
180 defined as an integer, else 'ioctl()' will fail! */
183 int sample_rate = 8000;
185 int sample_rate = 22050;
188 if (playing_sounds ||
189 (sound_device = OpenAudio(sound_device_name)) >= 0)
191 if (!playing_sounds) /* we just opened the audio device */
193 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
194 /* (with stereo the effective buffer size will shrink to 256) */
195 fragment_size = 0x00020009;
197 if (ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size) < 0)
198 Error(ERR_EXIT_SOUND_SERVER,
199 "cannot set fragment size of /dev/dsp - no sounds");
201 /* try if we can use stereo sound */
202 if (ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo) < 0)
205 static boolean reported = FALSE;
209 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
216 if (ioctl(sound_device, SNDCTL_DSP_SPEED, &sample_rate) < 0)
217 Error(ERR_EXIT_SOUND_SERVER,
218 "cannot set sample rate of /dev/dsp - no sounds");
220 /* get the real fragmentation size; this should return 512 */
221 if (ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
222 Error(ERR_EXIT_SOUND_SERVER,
223 "cannot get fragment size of /dev/dsp - no sounds");
225 max_sample_size = fragment_size / (stereo ? 2 : 1);
228 if (snd_ctrl.active) /* new sound has arrived */
229 SoundServer_InsertNewSound(snd_ctrl);
231 while(playing_sounds &&
232 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
234 FD_SET(sound_pipe[0], &sound_fdset);
236 /* first clear the last premixing buffer */
237 memset(premix_last_buffer,0,fragment_size*sizeof(int));
239 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
243 if (!playlist[i].active)
246 /* get pointer and size of the actual sound sample */
247 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
249 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
250 playlist[i].playingpos += sample_size;
252 /* fill the first mixing buffer with original sample */
253 memcpy(premix_first_buffer,sample_ptr,sample_size);
255 /* are we about to restart a looping sound? */
256 if (playlist[i].loop && sample_size<max_sample_size)
258 playlist[i].playingpos = max_sample_size-sample_size;
259 memcpy(premix_first_buffer+sample_size,
260 playlist[i].data_ptr,max_sample_size-sample_size);
261 sample_size = max_sample_size;
264 /* decrease volume if sound is fading out */
265 if (playlist[i].fade_sound &&
266 playlist[i].volume>=PSND_MAX_VOLUME/10)
267 playlist[i].volume-=PSND_MAX_VOLUME/20;
269 /* adjust volume of actual sound sample */
270 if (playlist[i].volume != PSND_MAX_VOLUME)
271 for(j=0;j<sample_size;j++)
272 premix_first_buffer[j] =
273 (playlist[i].volume * (int)premix_first_buffer[j])
274 >> PSND_MAX_VOLUME_BITS;
276 /* fill the last mixing buffer with stereo or mono sound */
279 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
280 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
281 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
283 for(j=0;j<sample_size;j++)
285 premix_left_buffer[j] =
286 (left_volume * (int)premix_first_buffer[j])
287 >> PSND_MAX_LEFT2RIGHT_BITS;
288 premix_right_buffer[j] =
289 (right_volume * (int)premix_first_buffer[j])
290 >> PSND_MAX_LEFT2RIGHT_BITS;
291 premix_last_buffer[2*j+0] += premix_left_buffer[j];
292 premix_last_buffer[2*j+1] += premix_right_buffer[j];
297 for(j=0;j<sample_size;j++)
298 premix_last_buffer[j] += (int)premix_first_buffer[j];
301 /* delete completed sound entries from the playlist */
302 if (playlist[i].playingpos >= playlist[i].data_len)
304 if (playlist[i].loop)
305 playlist[i].playingpos = 0;
308 playlist[i] = emptySoundControl;
312 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
314 playlist[i] = emptySoundControl;
319 /* put last mixing buffer to final playing buffer */
320 for(i=0;i<fragment_size;i++)
322 if (premix_last_buffer[i]<-255)
323 playing_buffer[i] = 0;
324 else if (premix_last_buffer[i]>255)
325 playing_buffer[i] = 255;
327 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
330 /* finally play the sound fragment */
331 write(sound_device,playing_buffer,fragment_size);
334 /* if no sounds playing, free device for other sound programs */
342 if (snd_ctrl.active && !snd_ctrl.loop)
344 struct timeval delay = { 0, 0 };
346 long sample_size, max_sample_size = SND_BLOCKSIZE;
347 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
348 int wait_percent = 90; /* wait 90% of the real playing time */
351 if ((sound_device = OpenAudio(sound_device_name)) >= 0)
355 while(playing_sounds &&
356 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
358 FD_SET(sound_pipe[0], &sound_fdset);
360 /* get pointer and size of the actual sound sample */
361 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
363 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
364 snd_ctrl.playingpos += sample_size;
366 /* fill the first mixing buffer with original sample */
367 memcpy(premix_first_buffer,sample_ptr,sample_size);
370 /* adjust volume of actual sound sample */
371 if (snd_ctrl.volume != PSND_MAX_VOLUME)
372 for(i=0;i<sample_size;i++)
373 premix_first_buffer[i] =
374 (snd_ctrl.volume * (int)premix_first_buffer[i])
375 >> PSND_MAX_VOLUME_BITS;
377 for(i=0;i<sample_size;i++)
379 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
381 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
384 /* finally play the sound fragment */
385 write(sound_device,playing_buffer,sample_size);
388 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
394 #endif /* !VOXWARE */
398 #endif /* !MSDOS && !WIN32 */
403 static void sound_handler(struct SoundControl snd_ctrl)
407 if (snd_ctrl.fade_sound)
412 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
413 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
414 !playlist[i].fade_sound)
416 playlist[i].fade_sound = TRUE;
417 if (voice_check(playlist[i].voice))
418 voice_ramp_volume(playlist[i].voice, 1000, 0);
419 playlist[i].loop = PSND_NO_LOOP;
422 else if (snd_ctrl.stop_all_sounds)
426 SoundServer_StopAllSounds();
428 else if (snd_ctrl.stop_sound)
432 SoundServer_StopSound(snd_ctrl.nr);
435 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
437 if (!playlist[i].active || playlist[i].loop)
440 playlist[i].playingpos = voice_get_position(playlist[i].voice);
441 playlist[i].volume = voice_get_volume(playlist[i].voice);
442 if (playlist[i].playingpos == -1 || !playlist[i].volume)
444 deallocate_voice(playlist[i].voice);
445 playlist[i] = emptySoundControl;
451 SoundServer_InsertNewSound(snd_ctrl);
456 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
460 /* if playlist is full, remove oldest sound */
461 if (playing_sounds==MAX_SOUNDS_PLAYING)
463 int longest=0, longest_nr=0;
465 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
468 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
470 int actual = playlist[i].playingpos;
473 if (!playlist[i].loop && actual>longest)
480 voice_set_volume(playlist[longest_nr].voice, 0);
481 deallocate_voice(playlist[longest_nr].voice);
483 playlist[longest_nr] = emptySoundControl;
487 /* check if sound is already being played (and how often) */
488 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
490 if (playlist[i].nr == snd_ctrl.nr)
494 /* restart loop sounds only if they are just fading out */
495 if (k>=1 && snd_ctrl.loop)
497 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
499 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
501 playlist[i].fade_sound = FALSE;
502 playlist[i].volume = PSND_MAX_VOLUME;
504 playlist[i].loop = PSND_LOOP;
505 voice_stop_volumeramp(playlist[i].voice);
506 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
513 /* don't play sound more than n times simultaneously (with n == 2 for now) */
516 int longest=0, longest_nr=0;
518 /* look for oldest equal sound */
519 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
523 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
527 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
529 actual = playlist[i].playingpos;
538 voice_set_volume(playlist[longest_nr].voice, 0);
539 deallocate_voice(playlist[longest_nr].voice);
541 playlist[longest_nr] = emptySoundControl;
545 /* neuen Sound in Liste packen */
546 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
548 if (!playlist[i].active)
550 playlist[i] = snd_ctrl;
553 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
555 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
556 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
557 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
558 voice_start(playlist[i].voice);
567 void SoundServer_FadeSound(int nr)
574 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
575 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
576 playlist[i].fade_sound = TRUE;
582 static void SoundServer_StopSound(int nr)
589 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
590 if (playlist[i].nr == nr)
593 voice_set_volume(playlist[i].voice, 0);
594 deallocate_voice(playlist[i].voice);
596 playlist[i] = emptySoundControl;
606 static void SoundServer_StopAllSounds()
610 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
613 voice_set_volume(playlist[i].voice, 0);
614 deallocate_voice(playlist[i].voice);
616 playlist[i]=emptySoundControl;
628 static void HPUX_Audio_Control()
630 struct audio_describe ainfo;
633 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
635 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
637 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
638 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
640 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
641 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
643 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
644 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
648 #endif /* HPUX_AUDIO */
650 #if !defined(VOXWARE) && !defined(MSDOS) && !defined(WIN32)
652 /* these two are stolen from "sox"... :) */
655 ** This routine converts from linear to ulaw.
657 ** Craig Reese: IDA/Supercomputing Research Center
658 ** Joe Campbell: Department of Defense
662 ** 1) CCITT Recommendation G.711 (very difficult to follow)
663 ** 2) "A New Digital Technique for Implementation of Any
664 ** Continuous PCM Companding Law," Villeret, Michel,
665 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
666 ** 1973, pg. 11.12-11.17
667 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
668 ** for Analog-to_Digital Conversion Techniques,"
671 ** Input: Signed 16 bit linear sample
672 ** Output: 8 bit ulaw sample
675 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
676 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
679 static unsigned char linear_to_ulaw(int sample)
681 static int exp_lut[256] =
683 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
684 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
685 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
686 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
687 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
688 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
689 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
690 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
691 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
692 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
693 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
694 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
695 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
696 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
697 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
698 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
701 int sign, exponent, mantissa;
702 unsigned char ulawbyte;
704 /* Get the sample into sign-magnitude. */
705 sign = (sample >> 8) & 0x80; /* set aside the sign */
707 sample = -sample; /* get magnitude */
709 sample = CLIP; /* clip the magnitude */
711 /* Convert from 16 bit linear to ulaw. */
712 sample = sample + BIAS;
713 exponent = exp_lut[( sample >> 7 ) & 0xFF];
714 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
715 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
718 ulawbyte = 0x02; /* optional CCITT trap */
725 ** This routine converts from ulaw to 16 bit linear.
727 ** Craig Reese: IDA/Supercomputing Research Center
731 ** 1) CCITT Recommendation G.711 (very difficult to follow)
732 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
733 ** for Analog-to_Digital Conversion Techniques,"
736 ** Input: 8 bit ulaw sample
737 ** Output: signed 16 bit linear sample
740 static int ulaw_to_linear(unsigned char ulawbyte)
742 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
743 int sign, exponent, mantissa, sample;
745 ulawbyte = ~ ulawbyte;
746 sign = ( ulawbyte & 0x80 );
747 exponent = ( ulawbyte >> 4 ) & 0x07;
748 mantissa = ulawbyte & 0x0F;
749 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
755 #endif /* !VOXWARE && !MSDOS && !WIN32 */
757 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
759 /*===========================================================================*/
761 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
763 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
764 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
766 boolean LoadSound(struct SoundInfo *snd_info)
769 char *sound_ext = "wav";
772 byte sound_header_buffer[WAV_HEADER_SIZE];
773 char chunk[CHUNK_ID_LEN + 1];
774 int chunk_length, dummy;
780 sprintf(filename, "%s/%s/%s.%s",
781 options.ro_base_directory, SOUNDS_DIRECTORY,
782 snd_info->name, sound_ext);
786 snd_info->mix_chunk = Mix_LoadWAV(filename);
787 if (snd_info->mix_chunk == NULL)
789 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
793 #else /* !TARGET_SDL */
797 if ((file = fopen(filename, "r")) == NULL)
799 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
803 /* read chunk "RIFF" */
804 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
805 if (strcmp(chunk, "RIFF") != 0)
807 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
812 /* read chunk "WAVE" */
813 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
814 if (strcmp(chunk, "WAVE") != 0)
816 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
821 /* read header information */
822 for (i=0; i<WAV_HEADER_SIZE; i++)
823 sound_header_buffer[i] = fgetc(file);
825 /* read chunk "data" */
826 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
827 if (strcmp(chunk, "data") != 0)
829 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
834 snd_info->data_len = chunk_length;
835 snd_info->data_ptr = checked_malloc(snd_info->data_len);
837 /* read sound data */
838 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
841 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
848 for (i=0; i<snd_info->data_len; i++)
849 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
853 snd_info->sample_ptr = load_sample(filename);
854 if (!snd_info->sample_ptr)
856 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
861 #endif /* !TARGET_SDL */
866 void PlaySound(int nr)
868 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
871 void PlaySoundStereo(int nr, int stereo)
873 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
876 void PlaySoundLoop(int nr)
878 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
881 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
883 struct SoundControl snd_ctrl = emptySoundControl;
885 if (sound_status==SOUND_OFF || !setup.sound)
888 if (volume<PSND_MIN_VOLUME)
889 volume = PSND_MIN_VOLUME;
890 else if (volume>PSND_MAX_VOLUME)
891 volume = PSND_MAX_VOLUME;
893 if (stereo<PSND_MAX_LEFT)
894 stereo = PSND_MAX_LEFT;
895 else if (stereo>PSND_MAX_RIGHT)
896 stereo = PSND_MAX_RIGHT;
899 snd_ctrl.volume = volume;
900 snd_ctrl.stereo = stereo;
901 snd_ctrl.loop = loop;
902 snd_ctrl.active = TRUE;
903 snd_ctrl.data_ptr = Sound[nr].data_ptr;
904 snd_ctrl.data_len = Sound[nr].data_len;
908 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
909 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
911 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
915 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
917 Error(ERR_WARN, "cannot pipe to child process - no sounds");
918 sound_status = SOUND_OFF;
922 sound_handler(snd_ctrl);
927 void FadeSound(int nr)
929 StopSoundExt(nr, SSND_FADE_SOUND);
934 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
937 void StopSound(int nr)
939 StopSoundExt(nr, SSND_STOP_SOUND);
944 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
947 void StopSoundExt(int nr, int method)
949 struct SoundControl snd_ctrl = emptySoundControl;
951 if (sound_status==SOUND_OFF)
954 if (SSND_FADING(method))
955 snd_ctrl.fade_sound = TRUE;
957 if (SSND_ALL(method))
958 snd_ctrl.stop_all_sounds = TRUE;
962 snd_ctrl.stop_sound = TRUE;
967 if (SSND_FADING(method))
969 Mix_FadeOutChannel(-1, 1000);
970 Mix_FadeOutMusic(1000);
980 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
982 Error(ERR_WARN, "cannot pipe to child process - no sounds");
983 sound_status = SOUND_OFF;
987 sound_handler(snd_ctrl);
992 void FreeSounds(int num_sounds)
996 if (sound_status == SOUND_OFF)
999 for(i=0; i<num_sounds; i++)
1001 free(Sound[i].data_ptr);
1003 destroy_sample(Sound[i].sample_ptr);
1007 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/