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(PLATFORM_UNIX)
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);
41 #if defined(PLATFORM_UNIX)
42 static unsigned char linear_to_ulaw(int);
43 static int ulaw_to_linear(unsigned char);
48 static void HPUX_Audio_Control();
51 #if defined(PLATFORM_MSDOS)
52 static void SoundServer_InsertNewSound(struct SoundControl);
53 static void SoundServer_StopSound(int);
54 static void SoundServer_StopAllSounds();
57 #if defined(PLATFORM_UNIX)
58 int OpenAudio(char *audio_device_name)
62 /* try to open audio device in non-blocking mode */
63 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
66 /* re-open audio device in blocking mode */
68 audio_fd = open(audio_device_name, O_WRONLY);
73 int CheckAudio(char *audio_device_name)
77 if (access(audio_device_name, W_OK) != 0)
79 Error(ERR_WARN, "cannot access audio device - no sound");
83 if ((audio_fd = OpenAudio(sound_device_name)) < 0)
85 Error(ERR_WARN, "cannot open audio device - no sound");
91 return SOUND_AVAILABLE;
94 boolean UnixInitAudio(void)
98 #endif /* PLATFORM_UNIX */
103 #if defined(PLATFORM_UNIX)
104 struct SoundControl snd_ctrl;
107 close(sound_pipe[1]); /* no writing into pipe needed */
110 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
111 playlist[i] = emptySoundControl;
114 #if defined(PLATFORM_UNIX)
115 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
116 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
118 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
121 HPUX_Audio_Control();
124 FD_ZERO(&sound_fdset);
125 FD_SET(sound_pipe[0], &sound_fdset);
127 while(1) /* wait for sound playing commands from client */
129 FD_SET(sound_pipe[0], &sound_fdset);
130 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
131 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
133 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
134 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
138 if (snd_ctrl.fade_sound)
143 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
144 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
145 playlist[i].fade_sound = TRUE;
147 else if (snd_ctrl.stop_all_sounds)
152 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
153 playlist[i]=emptySoundControl;
158 else if (snd_ctrl.stop_sound)
163 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
164 if (playlist[i].nr == snd_ctrl.nr)
166 playlist[i]=emptySoundControl;
174 if (playing_sounds || snd_ctrl.active)
176 struct timeval delay = { 0, 0 };
179 static long max_sample_size = 0;
180 static long fragment_size = 0;
181 /* Even if the stereo flag is used as being boolean, it must be
182 defined as an integer, else 'ioctl()' will fail! */
185 int sample_rate = 8000;
187 int sample_rate = 22050;
190 if (playing_sounds ||
191 (sound_device = OpenAudio(sound_device_name)) >= 0)
193 if (!playing_sounds) /* we just opened the audio device */
195 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
196 /* (with stereo the effective buffer size will shrink to 256) */
197 fragment_size = 0x00020009;
199 if (ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size) < 0)
200 Error(ERR_EXIT_SOUND_SERVER,
201 "cannot set fragment size of /dev/dsp - no sounds");
203 /* try if we can use stereo sound */
204 if (ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo) < 0)
207 static boolean reported = FALSE;
211 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
218 if (ioctl(sound_device, SNDCTL_DSP_SPEED, &sample_rate) < 0)
219 Error(ERR_EXIT_SOUND_SERVER,
220 "cannot set sample rate of /dev/dsp - no sounds");
222 /* get the real fragmentation size; this should return 512 */
223 if (ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
224 Error(ERR_EXIT_SOUND_SERVER,
225 "cannot get fragment size of /dev/dsp - no sounds");
227 max_sample_size = fragment_size / (stereo ? 2 : 1);
230 if (snd_ctrl.active) /* new sound has arrived */
231 SoundServer_InsertNewSound(snd_ctrl);
233 while(playing_sounds &&
234 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
236 FD_SET(sound_pipe[0], &sound_fdset);
238 /* first clear the last premixing buffer */
239 memset(premix_last_buffer,0,fragment_size*sizeof(int));
241 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
245 if (!playlist[i].active)
248 /* get pointer and size of the actual sound sample */
249 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
251 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
252 playlist[i].playingpos += sample_size;
254 /* fill the first mixing buffer with original sample */
255 memcpy(premix_first_buffer,sample_ptr,sample_size);
257 /* are we about to restart a looping sound? */
258 if (playlist[i].loop && sample_size<max_sample_size)
260 playlist[i].playingpos = max_sample_size-sample_size;
261 memcpy(premix_first_buffer+sample_size,
262 playlist[i].data_ptr,max_sample_size-sample_size);
263 sample_size = max_sample_size;
266 /* decrease volume if sound is fading out */
267 if (playlist[i].fade_sound &&
268 playlist[i].volume>=PSND_MAX_VOLUME/10)
269 playlist[i].volume-=PSND_MAX_VOLUME/20;
271 /* adjust volume of actual sound sample */
272 if (playlist[i].volume != PSND_MAX_VOLUME)
273 for(j=0;j<sample_size;j++)
274 premix_first_buffer[j] =
275 (playlist[i].volume * (int)premix_first_buffer[j])
276 >> PSND_MAX_VOLUME_BITS;
278 /* fill the last mixing buffer with stereo or mono sound */
281 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
282 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
283 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
285 for(j=0;j<sample_size;j++)
287 premix_left_buffer[j] =
288 (left_volume * (int)premix_first_buffer[j])
289 >> PSND_MAX_LEFT2RIGHT_BITS;
290 premix_right_buffer[j] =
291 (right_volume * (int)premix_first_buffer[j])
292 >> PSND_MAX_LEFT2RIGHT_BITS;
293 premix_last_buffer[2*j+0] += premix_left_buffer[j];
294 premix_last_buffer[2*j+1] += premix_right_buffer[j];
299 for(j=0;j<sample_size;j++)
300 premix_last_buffer[j] += (int)premix_first_buffer[j];
303 /* delete completed sound entries from the playlist */
304 if (playlist[i].playingpos >= playlist[i].data_len)
306 if (playlist[i].loop)
307 playlist[i].playingpos = 0;
310 playlist[i] = emptySoundControl;
314 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
316 playlist[i] = emptySoundControl;
321 /* put last mixing buffer to final playing buffer */
322 for(i=0;i<fragment_size;i++)
324 if (premix_last_buffer[i]<-255)
325 playing_buffer[i] = 0;
326 else if (premix_last_buffer[i]>255)
327 playing_buffer[i] = 255;
329 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
332 /* finally play the sound fragment */
333 write(sound_device,playing_buffer,fragment_size);
336 /* if no sounds playing, free device for other sound programs */
344 if (snd_ctrl.active && !snd_ctrl.loop)
346 struct timeval delay = { 0, 0 };
348 long sample_size, max_sample_size = SND_BLOCKSIZE;
349 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
350 int wait_percent = 90; /* wait 90% of the real playing time */
353 if ((sound_device = OpenAudio(sound_device_name)) >= 0)
357 while(playing_sounds &&
358 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
360 FD_SET(sound_pipe[0], &sound_fdset);
362 /* get pointer and size of the actual sound sample */
363 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
365 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
366 snd_ctrl.playingpos += sample_size;
368 /* fill the first mixing buffer with original sample */
369 memcpy(premix_first_buffer,sample_ptr,sample_size);
372 /* adjust volume of actual sound sample */
373 if (snd_ctrl.volume != PSND_MAX_VOLUME)
374 for(i=0;i<sample_size;i++)
375 premix_first_buffer[i] =
376 (snd_ctrl.volume * (int)premix_first_buffer[i])
377 >> PSND_MAX_VOLUME_BITS;
379 for(i=0;i<sample_size;i++)
381 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
383 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
386 /* finally play the sound fragment */
387 write(sound_device,playing_buffer,sample_size);
390 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
396 #endif /* !VOXWARE */
400 #endif /* PLATFORM_UNIX */
404 #if defined(PLATFORM_MSDOS)
405 static void sound_handler(struct SoundControl snd_ctrl)
409 if (snd_ctrl.fade_sound)
414 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
415 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
416 !playlist[i].fade_sound)
418 playlist[i].fade_sound = TRUE;
419 if (voice_check(playlist[i].voice))
420 voice_ramp_volume(playlist[i].voice, 1000, 0);
421 playlist[i].loop = PSND_NO_LOOP;
424 else if (snd_ctrl.stop_all_sounds)
428 SoundServer_StopAllSounds();
430 else if (snd_ctrl.stop_sound)
434 SoundServer_StopSound(snd_ctrl.nr);
437 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
439 if (!playlist[i].active || playlist[i].loop)
442 playlist[i].playingpos = voice_get_position(playlist[i].voice);
443 playlist[i].volume = voice_get_volume(playlist[i].voice);
444 if (playlist[i].playingpos == -1 || !playlist[i].volume)
446 deallocate_voice(playlist[i].voice);
447 playlist[i] = emptySoundControl;
453 SoundServer_InsertNewSound(snd_ctrl);
455 #endif /* PLATFORM_MSDOS */
457 #if !defined(PLATFORM_WIN32)
458 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
462 /* if playlist is full, remove oldest sound */
463 if (playing_sounds==MAX_SOUNDS_PLAYING)
465 int longest=0, longest_nr=0;
467 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
469 #if !defined(PLATFORM_MSDOS)
470 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
472 int actual = playlist[i].playingpos;
475 if (!playlist[i].loop && actual>longest)
481 #if defined(PLATFORM_MSDOS)
482 voice_set_volume(playlist[longest_nr].voice, 0);
483 deallocate_voice(playlist[longest_nr].voice);
485 playlist[longest_nr] = emptySoundControl;
489 /* check if sound is already being played (and how often) */
490 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
492 if (playlist[i].nr == snd_ctrl.nr)
496 /* restart loop sounds only if they are just fading out */
497 if (k>=1 && snd_ctrl.loop)
499 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
501 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
503 playlist[i].fade_sound = FALSE;
504 playlist[i].volume = PSND_MAX_VOLUME;
505 #if defined(PLATFORM_MSDOS)
506 playlist[i].loop = PSND_LOOP;
507 voice_stop_volumeramp(playlist[i].voice);
508 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
515 /* don't play sound more than n times simultaneously (with n == 2 for now) */
518 int longest=0, longest_nr=0;
520 /* look for oldest equal sound */
521 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
525 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
528 #if !defined(PLATFORM_MSDOS)
529 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
531 actual = playlist[i].playingpos;
540 #if defined(PLATFORM_MSDOS)
541 voice_set_volume(playlist[longest_nr].voice, 0);
542 deallocate_voice(playlist[longest_nr].voice);
544 playlist[longest_nr] = emptySoundControl;
548 /* neuen Sound in Liste packen */
549 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
551 if (!playlist[i].active)
553 playlist[i] = snd_ctrl;
556 #if defined(PLATFORM_MSDOS)
557 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
559 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
560 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
561 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
562 voice_start(playlist[i].voice);
568 #endif /* !PLATFORM_WIN32 */
571 void SoundServer_FadeSound(int nr)
578 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
579 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
580 playlist[i].fade_sound = TRUE;
584 #if !defined(PLATFORM_WIN32)
585 #if defined(PLATFORM_MSDOS)
586 static void SoundServer_StopSound(int nr)
593 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
594 if (playlist[i].nr == nr)
596 #if defined(PLATFORM_MSDOS)
597 voice_set_volume(playlist[i].voice, 0);
598 deallocate_voice(playlist[i].voice);
600 playlist[i] = emptySoundControl;
604 #if !defined(PLATFORM_MSDOS)
610 static void SoundServer_StopAllSounds()
614 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
616 #if defined(PLATFORM_MSDOS)
617 voice_set_volume(playlist[i].voice, 0);
618 deallocate_voice(playlist[i].voice);
620 playlist[i]=emptySoundControl;
624 #if !defined(PLATFORM_MSDOS)
628 #endif /* PLATFORM_MSDOS */
629 #endif /* !PLATFORM_WIN32 */
632 static void HPUX_Audio_Control()
634 struct audio_describe ainfo;
637 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
639 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
641 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
642 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
644 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
645 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
647 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
648 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
652 #endif /* HPUX_AUDIO */
654 #if !defined(VOXWARE) && defined(PLATFORM_UNIX)
656 /* these two are stolen from "sox"... :) */
659 ** This routine converts from linear to ulaw.
661 ** Craig Reese: IDA/Supercomputing Research Center
662 ** Joe Campbell: Department of Defense
666 ** 1) CCITT Recommendation G.711 (very difficult to follow)
667 ** 2) "A New Digital Technique for Implementation of Any
668 ** Continuous PCM Companding Law," Villeret, Michel,
669 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
670 ** 1973, pg. 11.12-11.17
671 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
672 ** for Analog-to_Digital Conversion Techniques,"
675 ** Input: Signed 16 bit linear sample
676 ** Output: 8 bit ulaw sample
679 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
680 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
683 static unsigned char linear_to_ulaw(int sample)
685 static int exp_lut[256] =
687 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
688 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
689 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
690 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
691 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
692 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
693 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
694 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
699 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
700 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
701 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
702 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
705 int sign, exponent, mantissa;
706 unsigned char ulawbyte;
708 /* Get the sample into sign-magnitude. */
709 sign = (sample >> 8) & 0x80; /* set aside the sign */
711 sample = -sample; /* get magnitude */
713 sample = CLIP; /* clip the magnitude */
715 /* Convert from 16 bit linear to ulaw. */
716 sample = sample + BIAS;
717 exponent = exp_lut[( sample >> 7 ) & 0xFF];
718 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
719 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
722 ulawbyte = 0x02; /* optional CCITT trap */
729 ** This routine converts from ulaw to 16 bit linear.
731 ** Craig Reese: IDA/Supercomputing Research Center
735 ** 1) CCITT Recommendation G.711 (very difficult to follow)
736 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
737 ** for Analog-to_Digital Conversion Techniques,"
740 ** Input: 8 bit ulaw sample
741 ** Output: signed 16 bit linear sample
744 static int ulaw_to_linear(unsigned char ulawbyte)
746 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
747 int sign, exponent, mantissa, sample;
749 ulawbyte = ~ ulawbyte;
750 sign = ( ulawbyte & 0x80 );
751 exponent = ( ulawbyte >> 4 ) & 0x07;
752 mantissa = ulawbyte & 0x0F;
753 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
759 #endif /* !VOXWARE && PLATFORM_UNIX */
761 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
763 /*===========================================================================*/
765 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
767 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
768 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
770 boolean LoadSound(struct SoundInfo *snd_info)
773 char *sound_ext = "wav";
774 #if !defined(TARGET_SDL)
775 #if !defined(PLATFORM_MSDOS)
776 byte sound_header_buffer[WAV_HEADER_SIZE];
777 char chunk[CHUNK_ID_LEN + 1];
778 int chunk_length, dummy;
784 sprintf(filename, "%s/%s/%s.%s",
785 options.ro_base_directory, SOUNDS_DIRECTORY,
786 snd_info->name, sound_ext);
788 #if defined(TARGET_SDL)
790 snd_info->mix_chunk = Mix_LoadWAV(filename);
791 if (snd_info->mix_chunk == NULL)
793 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
797 #else /* !TARGET_SDL */
799 #if !defined(PLATFORM_MSDOS)
801 if ((file = fopen(filename, "r")) == NULL)
803 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
807 /* read chunk "RIFF" */
808 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
809 if (strcmp(chunk, "RIFF") != 0)
811 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
816 /* read chunk "WAVE" */
817 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
818 if (strcmp(chunk, "WAVE") != 0)
820 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
825 /* read header information */
826 for (i=0; i<WAV_HEADER_SIZE; i++)
827 sound_header_buffer[i] = fgetc(file);
829 /* read chunk "data" */
830 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
831 if (strcmp(chunk, "data") != 0)
833 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
838 snd_info->data_len = chunk_length;
839 snd_info->data_ptr = checked_malloc(snd_info->data_len);
841 /* read sound data */
842 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
845 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
852 for (i=0; i<snd_info->data_len; i++)
853 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
855 #else /* PLATFORM_MSDOS */
857 snd_info->sample_ptr = load_sample(filename);
858 if (!snd_info->sample_ptr)
860 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
864 #endif /* PLATFORM_MSDOS */
865 #endif /* !TARGET_SDL */
870 void PlaySound(int nr)
872 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
875 void PlaySoundStereo(int nr, int stereo)
877 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
880 void PlaySoundLoop(int nr)
882 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
885 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
887 struct SoundControl snd_ctrl = emptySoundControl;
889 if (sound_status==SOUND_OFF || !setup.sound)
892 if (volume<PSND_MIN_VOLUME)
893 volume = PSND_MIN_VOLUME;
894 else if (volume>PSND_MAX_VOLUME)
895 volume = PSND_MAX_VOLUME;
897 if (stereo<PSND_MAX_LEFT)
898 stereo = PSND_MAX_LEFT;
899 else if (stereo>PSND_MAX_RIGHT)
900 stereo = PSND_MAX_RIGHT;
903 snd_ctrl.volume = volume;
904 snd_ctrl.stereo = stereo;
905 snd_ctrl.loop = loop;
906 snd_ctrl.active = TRUE;
907 snd_ctrl.data_ptr = Sound[nr].data_ptr;
908 snd_ctrl.data_len = Sound[nr].data_len;
910 #if defined(TARGET_SDL)
912 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
913 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
915 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
918 #if !defined(PLATFORM_MSDOS)
919 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
921 Error(ERR_WARN, "cannot pipe to child process - no sounds");
922 sound_status = SOUND_OFF;
926 sound_handler(snd_ctrl);
931 void FadeSound(int nr)
933 StopSoundExt(nr, SSND_FADE_SOUND);
938 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
941 void StopSound(int nr)
943 StopSoundExt(nr, SSND_STOP_SOUND);
948 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
951 void StopSoundExt(int nr, int method)
953 struct SoundControl snd_ctrl = emptySoundControl;
955 if (sound_status==SOUND_OFF)
958 if (SSND_FADING(method))
959 snd_ctrl.fade_sound = TRUE;
961 if (SSND_ALL(method))
962 snd_ctrl.stop_all_sounds = TRUE;
966 snd_ctrl.stop_sound = TRUE;
969 #if defined(TARGET_SDL)
971 if (SSND_FADING(method))
973 Mix_FadeOutChannel(-1, 1000);
974 Mix_FadeOutMusic(1000);
983 #if !defined(PLATFORM_MSDOS)
984 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
986 Error(ERR_WARN, "cannot pipe to child process - no sounds");
987 sound_status = SOUND_OFF;
991 sound_handler(snd_ctrl);
996 void FreeSounds(int num_sounds)
1000 if (sound_status == SOUND_OFF)
1003 for(i=0; i<num_sounds; i++)
1004 #if !defined(PLATFORM_MSDOS)
1005 free(Sound[i].data_ptr);
1007 destroy_sample(Sound[i].sample_ptr);
1011 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/