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(sysinfo.audio_process_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(sysinfo.audio_process_pipe[0], &sound_fdset);
127 while(1) /* wait for sound playing commands from client */
129 FD_SET(sysinfo.audio_process_pipe[0], &sound_fdset);
130 select(sysinfo.audio_process_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
131 if (!FD_ISSET(sysinfo.audio_process_pipe[0], &sound_fdset))
133 if (read(sysinfo.audio_process_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
135 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
139 if (snd_ctrl.fade_sound)
144 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
145 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
146 playlist[i].fade_sound = TRUE;
148 else if (snd_ctrl.stop_all_sounds)
153 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
154 playlist[i]=emptySoundControl;
157 close(sysinfo.audio_fd);
159 else if (snd_ctrl.stop_sound)
164 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
165 if (playlist[i].nr == snd_ctrl.nr)
167 playlist[i]=emptySoundControl;
172 close(sysinfo.audio_fd);
175 if (playing_sounds || snd_ctrl.active)
177 struct timeval delay = { 0, 0 };
180 static long max_sample_size = 0;
181 static long fragment_size = 0;
182 /* Even if the stereo flag is used as being boolean, it must be
183 defined as an integer, else 'ioctl()' will fail! */
186 int sample_rate = 8000;
188 int sample_rate = 22050;
191 if (playing_sounds ||
192 (sysinfo.audio_fd = OpenAudio(sound_device_name)) >= 0)
194 if (!playing_sounds) /* we just opened the audio device */
196 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
197 /* (with stereo the effective buffer size will shrink to 256) */
198 fragment_size = 0x00020009;
200 if (ioctl(sysinfo.audio_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_size)
202 Error(ERR_EXIT_SOUND_SERVER,
203 "cannot set fragment size of /dev/dsp - no sounds");
205 /* try if we can use stereo sound */
206 if (ioctl(sysinfo.audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
209 static boolean reported = FALSE;
213 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
220 if (ioctl(sysinfo.audio_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
221 Error(ERR_EXIT_SOUND_SERVER,
222 "cannot set sample rate of /dev/dsp - no sounds");
224 /* get the real fragmentation size; this should return 512 */
225 if (ioctl(sysinfo.audio_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size)
227 Error(ERR_EXIT_SOUND_SERVER,
228 "cannot get fragment size of /dev/dsp - no sounds");
230 max_sample_size = fragment_size / (stereo ? 2 : 1);
233 if (snd_ctrl.active) /* new sound has arrived */
234 SoundServer_InsertNewSound(snd_ctrl);
236 while(playing_sounds &&
237 select(sysinfo.audio_process_pipe[0] + 1,
238 &sound_fdset, NULL, NULL, &delay) < 1)
240 FD_SET(sysinfo.audio_process_pipe[0], &sound_fdset);
242 /* first clear the last premixing buffer */
243 memset(premix_last_buffer,0,fragment_size*sizeof(int));
245 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
249 if (!playlist[i].active)
252 /* get pointer and size of the actual sound sample */
253 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
255 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
256 playlist[i].playingpos += sample_size;
258 /* fill the first mixing buffer with original sample */
259 memcpy(premix_first_buffer,sample_ptr,sample_size);
261 /* are we about to restart a looping sound? */
262 if (playlist[i].loop && sample_size<max_sample_size)
264 playlist[i].playingpos = max_sample_size-sample_size;
265 memcpy(premix_first_buffer+sample_size,
266 playlist[i].data_ptr,max_sample_size-sample_size);
267 sample_size = max_sample_size;
270 /* decrease volume if sound is fading out */
271 if (playlist[i].fade_sound &&
272 playlist[i].volume>=PSND_MAX_VOLUME/10)
273 playlist[i].volume-=PSND_MAX_VOLUME/20;
275 /* adjust volume of actual sound sample */
276 if (playlist[i].volume != PSND_MAX_VOLUME)
277 for(j=0;j<sample_size;j++)
278 premix_first_buffer[j] =
279 (playlist[i].volume * (int)premix_first_buffer[j])
280 >> PSND_MAX_VOLUME_BITS;
282 /* fill the last mixing buffer with stereo or mono sound */
285 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
286 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
287 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
289 for(j=0;j<sample_size;j++)
291 premix_left_buffer[j] =
292 (left_volume * (int)premix_first_buffer[j])
293 >> PSND_MAX_LEFT2RIGHT_BITS;
294 premix_right_buffer[j] =
295 (right_volume * (int)premix_first_buffer[j])
296 >> PSND_MAX_LEFT2RIGHT_BITS;
297 premix_last_buffer[2*j+0] += premix_left_buffer[j];
298 premix_last_buffer[2*j+1] += premix_right_buffer[j];
303 for(j=0;j<sample_size;j++)
304 premix_last_buffer[j] += (int)premix_first_buffer[j];
307 /* delete completed sound entries from the playlist */
308 if (playlist[i].playingpos >= playlist[i].data_len)
310 if (playlist[i].loop)
311 playlist[i].playingpos = 0;
314 playlist[i] = emptySoundControl;
318 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
320 playlist[i] = emptySoundControl;
325 /* put last mixing buffer to final playing buffer */
326 for(i=0;i<fragment_size;i++)
328 if (premix_last_buffer[i]<-255)
329 playing_buffer[i] = 0;
330 else if (premix_last_buffer[i]>255)
331 playing_buffer[i] = 255;
333 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
336 /* finally play the sound fragment */
337 write(sysinfo.audio_fd, playing_buffer,fragment_size);
340 /* if no sounds playing, free device for other sound programs */
342 close(sysinfo.audio_fd);
348 if (snd_ctrl.active && !snd_ctrl.loop)
350 struct timeval delay = { 0, 0 };
352 long sample_size, max_sample_size = SND_BLOCKSIZE;
353 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
354 int wait_percent = 90; /* wait 90% of the real playing time */
357 if ((sysinfo.audio_fd = OpenAudio(sound_device_name)) >= 0)
361 while(playing_sounds &&
362 select(sysinfo.audio_process_pipe[0] + 1,
363 &sound_fdset, NULL, NULL, &delay) < 1)
365 FD_SET(sysinfo.audio_process_pipe[0], &sound_fdset);
367 /* get pointer and size of the actual sound sample */
368 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
370 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
371 snd_ctrl.playingpos += sample_size;
373 /* fill the first mixing buffer with original sample */
374 memcpy(premix_first_buffer,sample_ptr,sample_size);
377 /* adjust volume of actual sound sample */
378 if (snd_ctrl.volume != PSND_MAX_VOLUME)
379 for(i=0;i<sample_size;i++)
380 premix_first_buffer[i] =
381 (snd_ctrl.volume * (int)premix_first_buffer[i])
382 >> PSND_MAX_VOLUME_BITS;
384 for(i=0;i<sample_size;i++)
386 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
388 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
391 /* finally play the sound fragment */
392 write(sysinfo.audio_fd,playing_buffer,sample_size);
395 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
397 close(sysinfo.audio_fd);
401 #endif /* !VOXWARE */
405 #endif /* PLATFORM_UNIX */
409 #if defined(PLATFORM_MSDOS)
410 static void sound_handler(struct SoundControl snd_ctrl)
414 if (snd_ctrl.fade_sound)
419 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
420 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
421 !playlist[i].fade_sound)
423 playlist[i].fade_sound = TRUE;
424 if (voice_check(playlist[i].voice))
425 voice_ramp_volume(playlist[i].voice, 1000, 0);
426 playlist[i].loop = PSND_NO_LOOP;
429 else if (snd_ctrl.stop_all_sounds)
433 SoundServer_StopAllSounds();
435 else if (snd_ctrl.stop_sound)
439 SoundServer_StopSound(snd_ctrl.nr);
442 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
444 if (!playlist[i].active || playlist[i].loop)
447 playlist[i].playingpos = voice_get_position(playlist[i].voice);
448 playlist[i].volume = voice_get_volume(playlist[i].voice);
449 if (playlist[i].playingpos == -1 || !playlist[i].volume)
451 deallocate_voice(playlist[i].voice);
452 playlist[i] = emptySoundControl;
458 SoundServer_InsertNewSound(snd_ctrl);
460 #endif /* PLATFORM_MSDOS */
462 #if !defined(PLATFORM_WIN32)
463 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
467 /* if playlist is full, remove oldest sound */
468 if (playing_sounds==MAX_SOUNDS_PLAYING)
470 int longest=0, longest_nr=0;
472 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
474 #if !defined(PLATFORM_MSDOS)
475 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
477 int actual = playlist[i].playingpos;
480 if (!playlist[i].loop && actual>longest)
486 #if defined(PLATFORM_MSDOS)
487 voice_set_volume(playlist[longest_nr].voice, 0);
488 deallocate_voice(playlist[longest_nr].voice);
490 playlist[longest_nr] = emptySoundControl;
494 /* check if sound is already being played (and how often) */
495 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
497 if (playlist[i].nr == snd_ctrl.nr)
501 /* restart loop sounds only if they are just fading out */
502 if (k>=1 && snd_ctrl.loop)
504 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
506 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
508 playlist[i].fade_sound = FALSE;
509 playlist[i].volume = PSND_MAX_VOLUME;
510 #if defined(PLATFORM_MSDOS)
511 playlist[i].loop = PSND_LOOP;
512 voice_stop_volumeramp(playlist[i].voice);
513 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
520 /* don't play sound more than n times simultaneously (with n == 2 for now) */
523 int longest=0, longest_nr=0;
525 /* look for oldest equal sound */
526 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
530 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
533 #if !defined(PLATFORM_MSDOS)
534 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
536 actual = playlist[i].playingpos;
545 #if defined(PLATFORM_MSDOS)
546 voice_set_volume(playlist[longest_nr].voice, 0);
547 deallocate_voice(playlist[longest_nr].voice);
549 playlist[longest_nr] = emptySoundControl;
553 /* neuen Sound in Liste packen */
554 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
556 if (!playlist[i].active)
558 playlist[i] = snd_ctrl;
561 #if defined(PLATFORM_MSDOS)
562 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
564 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
565 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
566 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
567 voice_start(playlist[i].voice);
573 #endif /* !PLATFORM_WIN32 */
576 void SoundServer_FadeSound(int nr)
583 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
584 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
585 playlist[i].fade_sound = TRUE;
589 #if !defined(PLATFORM_WIN32)
590 #if defined(PLATFORM_MSDOS)
591 static void SoundServer_StopSound(int nr)
598 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
599 if (playlist[i].nr == nr)
601 #if defined(PLATFORM_MSDOS)
602 voice_set_volume(playlist[i].voice, 0);
603 deallocate_voice(playlist[i].voice);
605 playlist[i] = emptySoundControl;
609 #if !defined(PLATFORM_MSDOS)
611 close(sysinfo.audio_fd);
615 static void SoundServer_StopAllSounds()
619 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
621 #if defined(PLATFORM_MSDOS)
622 voice_set_volume(playlist[i].voice, 0);
623 deallocate_voice(playlist[i].voice);
625 playlist[i]=emptySoundControl;
629 #if !defined(PLATFORM_MSDOS)
630 close(sysinfo.audio_fd);
633 #endif /* PLATFORM_MSDOS */
634 #endif /* !PLATFORM_WIN32 */
637 static void HPUX_Audio_Control()
639 struct audio_describe ainfo;
642 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
644 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
646 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
647 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
649 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
650 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
652 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
653 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
657 #endif /* HPUX_AUDIO */
659 #if !defined(VOXWARE) && defined(PLATFORM_UNIX)
661 /* these two are stolen from "sox"... :) */
664 ** This routine converts from linear to ulaw.
666 ** Craig Reese: IDA/Supercomputing Research Center
667 ** Joe Campbell: Department of Defense
671 ** 1) CCITT Recommendation G.711 (very difficult to follow)
672 ** 2) "A New Digital Technique for Implementation of Any
673 ** Continuous PCM Companding Law," Villeret, Michel,
674 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
675 ** 1973, pg. 11.12-11.17
676 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
677 ** for Analog-to_Digital Conversion Techniques,"
680 ** Input: Signed 16 bit linear sample
681 ** Output: 8 bit ulaw sample
684 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
685 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
688 static unsigned char linear_to_ulaw(int sample)
690 static int exp_lut[256] =
692 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
693 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
694 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
695 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
696 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
697 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
698 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
699 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
703 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
704 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
705 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
706 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
707 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
710 int sign, exponent, mantissa;
711 unsigned char ulawbyte;
713 /* Get the sample into sign-magnitude. */
714 sign = (sample >> 8) & 0x80; /* set aside the sign */
716 sample = -sample; /* get magnitude */
718 sample = CLIP; /* clip the magnitude */
720 /* Convert from 16 bit linear to ulaw. */
721 sample = sample + BIAS;
722 exponent = exp_lut[( sample >> 7 ) & 0xFF];
723 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
724 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
727 ulawbyte = 0x02; /* optional CCITT trap */
734 ** This routine converts from ulaw to 16 bit linear.
736 ** Craig Reese: IDA/Supercomputing Research Center
740 ** 1) CCITT Recommendation G.711 (very difficult to follow)
741 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
742 ** for Analog-to_Digital Conversion Techniques,"
745 ** Input: 8 bit ulaw sample
746 ** Output: signed 16 bit linear sample
749 static int ulaw_to_linear(unsigned char ulawbyte)
751 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
752 int sign, exponent, mantissa, sample;
754 ulawbyte = ~ ulawbyte;
755 sign = ( ulawbyte & 0x80 );
756 exponent = ( ulawbyte >> 4 ) & 0x07;
757 mantissa = ulawbyte & 0x0F;
758 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
764 #endif /* !VOXWARE && PLATFORM_UNIX */
766 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
768 /*===========================================================================*/
770 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
772 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
773 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
775 boolean LoadSound(struct SampleInfo *snd_info)
778 char *sound_ext = "wav";
779 #if !defined(TARGET_SDL)
780 #if !defined(PLATFORM_MSDOS)
781 byte sound_header_buffer[WAV_HEADER_SIZE];
782 char chunk[CHUNK_ID_LEN + 1];
783 int chunk_length, dummy;
789 sprintf(filename, "%s/%s/%s.%s",
790 options.ro_base_directory, SOUNDS_DIRECTORY,
791 snd_info->name, sound_ext);
793 #if defined(TARGET_SDL)
795 snd_info->mix_chunk = Mix_LoadWAV(filename);
796 if (snd_info->mix_chunk == NULL)
798 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
802 #else /* !TARGET_SDL */
804 #if !defined(PLATFORM_MSDOS)
806 if ((file = fopen(filename, "r")) == NULL)
808 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
812 /* read chunk "RIFF" */
813 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
814 if (strcmp(chunk, "RIFF") != 0)
816 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
821 /* read chunk "WAVE" */
822 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
823 if (strcmp(chunk, "WAVE") != 0)
825 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
830 /* read header information */
831 for (i=0; i<WAV_HEADER_SIZE; i++)
832 sound_header_buffer[i] = fgetc(file);
834 /* read chunk "data" */
835 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
836 if (strcmp(chunk, "data") != 0)
838 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
843 snd_info->data_len = chunk_length;
844 snd_info->data_ptr = checked_malloc(snd_info->data_len);
846 /* read sound data */
847 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
850 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
857 for (i=0; i<snd_info->data_len; i++)
858 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
860 #else /* PLATFORM_MSDOS */
862 snd_info->sample_ptr = load_sample(filename);
863 if (!snd_info->sample_ptr)
865 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
869 #endif /* PLATFORM_MSDOS */
870 #endif /* !TARGET_SDL */
875 void PlaySound(int nr)
877 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
880 void PlaySoundStereo(int nr, int stereo)
882 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
885 void PlaySoundLoop(int nr)
887 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
890 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
892 struct SoundControl snd_ctrl = emptySoundControl;
894 if (!sysinfo.audio_available || !setup.sound)
897 if (volume<PSND_MIN_VOLUME)
898 volume = PSND_MIN_VOLUME;
899 else if (volume>PSND_MAX_VOLUME)
900 volume = PSND_MAX_VOLUME;
902 if (stereo<PSND_MAX_LEFT)
903 stereo = PSND_MAX_LEFT;
904 else if (stereo>PSND_MAX_RIGHT)
905 stereo = PSND_MAX_RIGHT;
908 snd_ctrl.volume = volume;
909 snd_ctrl.stereo = stereo;
910 snd_ctrl.loop = loop;
911 snd_ctrl.active = TRUE;
912 snd_ctrl.data_ptr = Sound[nr].data_ptr;
913 snd_ctrl.data_len = Sound[nr].data_len;
915 #if defined(TARGET_SDL)
917 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
918 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
920 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
923 #if !defined(PLATFORM_MSDOS)
924 if (write(sysinfo.audio_process_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
926 Error(ERR_WARN, "cannot pipe to child process - no sounds");
927 sysinfo.audio_available = FALSE;
931 sound_handler(snd_ctrl);
936 void FadeSound(int nr)
938 StopSoundExt(nr, SSND_FADE_SOUND);
943 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
946 void StopSound(int nr)
948 StopSoundExt(nr, SSND_STOP_SOUND);
953 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
956 void StopSoundExt(int nr, int method)
958 struct SoundControl snd_ctrl = emptySoundControl;
960 if (!sysinfo.audio_available)
963 if (SSND_FADING(method))
964 snd_ctrl.fade_sound = TRUE;
966 if (SSND_ALL(method))
967 snd_ctrl.stop_all_sounds = TRUE;
971 snd_ctrl.stop_sound = TRUE;
974 #if defined(TARGET_SDL)
976 if (SSND_FADING(method))
978 Mix_FadeOutChannel(-1, 1000);
979 Mix_FadeOutMusic(1000);
988 #if !defined(PLATFORM_MSDOS)
989 if (write(sysinfo.audio_process_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
991 Error(ERR_WARN, "cannot pipe to child process - no sounds");
992 sysinfo.audio_available = FALSE;
996 sound_handler(snd_ctrl);
1001 void FreeSounds(int num_sounds)
1005 if (!sysinfo.audio_available)
1008 for(i=0; i<num_sounds; i++)
1009 #if !defined(PLATFORM_MSDOS)
1010 free(Sound[i].data_ptr);
1012 destroy_sample(Sound[i].sample_ptr);
1016 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/