1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2000 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
23 static int num_sounds = 0;
24 static struct SampleInfo *Sound = NULL;
27 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
29 static int playing_sounds = 0;
30 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
31 static struct SoundControl emptySoundControl =
33 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
36 #if defined(PLATFORM_UNIX)
37 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
38 static char premix_first_buffer[SND_BLOCKSIZE];
39 #if defined(AUDIO_STREAMING_DSP)
40 static char premix_left_buffer[SND_BLOCKSIZE];
41 static char premix_right_buffer[SND_BLOCKSIZE];
42 static int premix_last_buffer[SND_BLOCKSIZE];
44 static unsigned char playing_buffer[SND_BLOCKSIZE];
47 /* forward declaration of internal functions */
48 #if defined(AUDIO_STREAMING_DSP)
49 static void SoundServer_InsertNewSound(struct SoundControl);
50 #elif defined(PLATFORM_UNIX)
51 static unsigned char linear_to_ulaw(int);
52 static int ulaw_to_linear(unsigned char);
55 #if defined(PLATFORM_HPUX)
56 static void HPUX_Audio_Control();
59 #if defined(PLATFORM_MSDOS)
60 static void SoundServer_InsertNewSound(struct SoundControl);
61 static void SoundServer_StopSound(int);
62 static void SoundServer_StopAllSounds();
65 #if defined(PLATFORM_UNIX)
66 int OpenAudioDevice(char *audio_device_name)
70 /* check if desired audio device is accessible */
71 if (access(audio_device_name, W_OK) != 0)
74 /* try to open audio device in non-blocking mode */
75 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
78 /* re-open audio device in blocking mode */
80 audio_fd = open(audio_device_name, O_WRONLY);
85 void UnixOpenAudio(void)
87 static char *audio_device_name[] =
95 /* look for available audio devices, starting with preferred ones */
96 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
97 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
102 Error(ERR_WARN, "cannot open audio device - no sound");
108 audio.device_name = audio_device_name[i];
109 audio.sound_available = TRUE;
110 audio.sound_enabled = TRUE;
112 #if defined(AUDIO_STREAMING_DSP)
113 audio.music_available = TRUE;
114 audio.loops_available = TRUE;
118 void UnixCloseAudio(void)
121 close(audio.device_fd);
124 #endif /* PLATFORM_UNIX */
129 #if defined(PLATFORM_UNIX)
130 struct SoundControl snd_ctrl;
133 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
136 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
137 playlist[i] = emptySoundControl;
140 #if defined(PLATFORM_UNIX)
141 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
142 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
144 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
146 #if defined(PLATFORM_HPUX)
147 HPUX_Audio_Control();
150 FD_ZERO(&sound_fdset);
151 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
153 while(1) /* wait for sound playing commands from client */
155 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
156 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
157 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
159 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
161 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
163 #if defined(AUDIO_STREAMING_DSP)
165 if (snd_ctrl.fade_sound)
170 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
171 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
172 playlist[i].fade_sound = TRUE;
174 else if (snd_ctrl.stop_all_sounds)
179 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
180 playlist[i]=emptySoundControl;
183 close(audio.device_fd);
185 else if (snd_ctrl.stop_sound)
190 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
191 if (playlist[i].nr == snd_ctrl.nr)
193 playlist[i]=emptySoundControl;
198 close(audio.device_fd);
201 if (playing_sounds || snd_ctrl.active)
203 struct timeval delay = { 0, 0 };
206 static long max_sample_size = 0;
207 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
208 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
210 /* 'ioctl()' expects pointer to integer value for stereo flag
211 (boolean is defined as 'char', which will not work here) */
213 if (playing_sounds ||
214 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
216 if (!playing_sounds) /* we just opened the audio device */
218 unsigned long fragment_spec = 0;
220 /* determine logarithm (log2) of the fragment size */
221 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
224 /* use two fragments (play one fragment, prepare the other);
225 one fragment would result in interrupted audio output, more
226 than two fragments would raise audio output latency to much */
227 fragment_spec |= 0x00020000;
229 /* Example for fragment specification:
230 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
231 - (with stereo the effective buffer size will shrink to 256)
232 => fragment_size = 0x00020009 */
234 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0)
235 Error(ERR_EXIT_SOUND_SERVER,
236 "cannot set fragment size of /dev/dsp - no sounds");
238 /* try if we can use stereo sound */
239 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
242 static boolean reported = FALSE;
246 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
253 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
254 Error(ERR_EXIT_SOUND_SERVER,
255 "cannot set sample rate of /dev/dsp - no sounds");
257 /* get the real fragmentation size; this should return 512 */
258 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
259 Error(ERR_EXIT_SOUND_SERVER,
260 "cannot get fragment size of /dev/dsp - no sounds");
262 max_sample_size = fragment_size / (stereo ? 2 : 1);
265 if (snd_ctrl.active) /* new sound has arrived */
266 SoundServer_InsertNewSound(snd_ctrl);
268 while(playing_sounds &&
269 select(audio.soundserver_pipe[0] + 1,
270 &sound_fdset, NULL, NULL, &delay) < 1)
272 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
274 /* first clear the last premixing buffer */
275 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
277 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
281 if (!playlist[i].active)
284 /* get pointer and size of the actual sound sample */
285 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
287 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
288 playlist[i].playingpos += sample_size;
290 /* fill the first mixing buffer with original sample */
291 memcpy(premix_first_buffer,sample_ptr,sample_size);
293 /* are we about to restart a looping sound? */
294 if (playlist[i].loop && sample_size<max_sample_size)
296 playlist[i].playingpos = max_sample_size-sample_size;
297 memcpy(premix_first_buffer+sample_size,
298 playlist[i].data_ptr,max_sample_size-sample_size);
299 sample_size = max_sample_size;
302 /* decrease volume if sound is fading out */
303 if (playlist[i].fade_sound &&
304 playlist[i].volume>=PSND_MAX_VOLUME/10)
305 playlist[i].volume-=PSND_MAX_VOLUME/20;
307 /* adjust volume of actual sound sample */
308 if (playlist[i].volume != PSND_MAX_VOLUME)
309 for(j=0;j<sample_size;j++)
310 premix_first_buffer[j] =
311 (playlist[i].volume * (int)premix_first_buffer[j])
312 >> PSND_MAX_VOLUME_BITS;
314 /* fill the last mixing buffer with stereo or mono sound */
317 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
318 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
319 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
321 for(j=0;j<sample_size;j++)
323 premix_left_buffer[j] =
324 (left_volume * (int)premix_first_buffer[j])
325 >> PSND_MAX_LEFT2RIGHT_BITS;
326 premix_right_buffer[j] =
327 (right_volume * (int)premix_first_buffer[j])
328 >> PSND_MAX_LEFT2RIGHT_BITS;
329 premix_last_buffer[2*j+0] += premix_left_buffer[j];
330 premix_last_buffer[2*j+1] += premix_right_buffer[j];
335 for(j=0;j<sample_size;j++)
336 premix_last_buffer[j] += (int)premix_first_buffer[j];
339 /* delete completed sound entries from the playlist */
340 if (playlist[i].playingpos >= playlist[i].data_len)
342 if (playlist[i].loop)
343 playlist[i].playingpos = 0;
346 playlist[i] = emptySoundControl;
350 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
352 playlist[i] = emptySoundControl;
357 /* put last mixing buffer to final playing buffer */
358 for(i=0; i<fragment_size; i++)
360 if (premix_last_buffer[i]<-255)
361 playing_buffer[i] = 0;
362 else if (premix_last_buffer[i]>255)
363 playing_buffer[i] = 255;
365 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
368 /* finally play the sound fragment */
369 write(audio.device_fd, playing_buffer, fragment_size);
372 /* if no sounds playing, free device for other sound programs */
374 close(audio.device_fd);
378 #else /* !AUDIO_STREAMING_DSP */
380 if (snd_ctrl.active && !snd_ctrl.loop)
382 struct timeval delay = { 0, 0 };
384 long sample_size, max_sample_size = SND_BLOCKSIZE;
385 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
386 int wait_percent = 90; /* wait 90% of the real playing time */
389 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
393 while(playing_sounds &&
394 select(audio.soundserver_pipe[0] + 1,
395 &sound_fdset, NULL, NULL, &delay) < 1)
397 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
399 /* get pointer and size of the actual sound sample */
400 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
402 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
403 snd_ctrl.playingpos += sample_size;
405 /* fill the first mixing buffer with original sample */
406 memcpy(premix_first_buffer,sample_ptr,sample_size);
409 /* adjust volume of actual sound sample */
410 if (snd_ctrl.volume != PSND_MAX_VOLUME)
411 for(i=0;i<sample_size;i++)
412 premix_first_buffer[i] =
413 (snd_ctrl.volume * (int)premix_first_buffer[i])
414 >> PSND_MAX_VOLUME_BITS;
416 for(i=0;i<sample_size;i++)
418 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
420 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
423 /* finally play the sound fragment */
424 write(audio.device_fd,playing_buffer,sample_size);
427 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
429 close(audio.device_fd);
433 #endif /* !AUDIO_STREAMING_DSP */
437 #endif /* PLATFORM_UNIX */
441 #if defined(PLATFORM_MSDOS)
442 static void sound_handler(struct SoundControl snd_ctrl)
446 if (snd_ctrl.fade_sound)
451 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
452 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
453 !playlist[i].fade_sound)
455 playlist[i].fade_sound = TRUE;
456 if (voice_check(playlist[i].voice))
457 voice_ramp_volume(playlist[i].voice, 1000, 0);
458 playlist[i].loop = PSND_NO_LOOP;
461 else if (snd_ctrl.stop_all_sounds)
465 SoundServer_StopAllSounds();
467 else if (snd_ctrl.stop_sound)
471 SoundServer_StopSound(snd_ctrl.nr);
474 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
476 if (!playlist[i].active || playlist[i].loop)
479 playlist[i].playingpos = voice_get_position(playlist[i].voice);
480 playlist[i].volume = voice_get_volume(playlist[i].voice);
481 if (playlist[i].playingpos == -1 || !playlist[i].volume)
483 deallocate_voice(playlist[i].voice);
484 playlist[i] = emptySoundControl;
490 SoundServer_InsertNewSound(snd_ctrl);
492 #endif /* PLATFORM_MSDOS */
494 #if !defined(PLATFORM_WIN32)
495 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
499 /* if playlist is full, remove oldest sound */
500 if (playing_sounds==MAX_SOUNDS_PLAYING)
502 int longest=0, longest_nr=0;
504 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
506 #if !defined(PLATFORM_MSDOS)
507 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
509 int actual = playlist[i].playingpos;
512 if (!playlist[i].loop && actual>longest)
518 #if defined(PLATFORM_MSDOS)
519 voice_set_volume(playlist[longest_nr].voice, 0);
520 deallocate_voice(playlist[longest_nr].voice);
522 playlist[longest_nr] = emptySoundControl;
526 /* check if sound is already being played (and how often) */
527 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
529 if (playlist[i].nr == snd_ctrl.nr)
533 /* restart loop sounds only if they are just fading out */
534 if (k>=1 && snd_ctrl.loop)
536 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
538 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
540 playlist[i].fade_sound = FALSE;
541 playlist[i].volume = PSND_MAX_VOLUME;
542 #if defined(PLATFORM_MSDOS)
543 playlist[i].loop = PSND_LOOP;
544 voice_stop_volumeramp(playlist[i].voice);
545 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
552 /* don't play sound more than n times simultaneously (with n == 2 for now) */
555 int longest=0, longest_nr=0;
557 /* look for oldest equal sound */
558 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
562 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
565 #if !defined(PLATFORM_MSDOS)
566 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
568 actual = playlist[i].playingpos;
577 #if defined(PLATFORM_MSDOS)
578 voice_set_volume(playlist[longest_nr].voice, 0);
579 deallocate_voice(playlist[longest_nr].voice);
581 playlist[longest_nr] = emptySoundControl;
585 /* neuen Sound in Liste packen */
586 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
588 if (!playlist[i].active)
590 playlist[i] = snd_ctrl;
593 #if defined(PLATFORM_MSDOS)
594 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
596 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
597 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
598 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
599 voice_start(playlist[i].voice);
605 #endif /* !PLATFORM_WIN32 */
608 void SoundServer_FadeSound(int nr)
615 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
616 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
617 playlist[i].fade_sound = TRUE;
621 #if !defined(PLATFORM_WIN32)
622 #if defined(PLATFORM_MSDOS)
623 static void SoundServer_StopSound(int nr)
630 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
631 if (playlist[i].nr == nr)
633 #if defined(PLATFORM_MSDOS)
634 voice_set_volume(playlist[i].voice, 0);
635 deallocate_voice(playlist[i].voice);
637 playlist[i] = emptySoundControl;
641 #if !defined(PLATFORM_MSDOS)
643 close(audio.device_fd);
647 static void SoundServer_StopAllSounds()
651 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
653 #if defined(PLATFORM_MSDOS)
654 voice_set_volume(playlist[i].voice, 0);
655 deallocate_voice(playlist[i].voice);
657 playlist[i]=emptySoundControl;
661 #if !defined(PLATFORM_MSDOS)
662 close(audio.device_fd);
665 #endif /* PLATFORM_MSDOS */
666 #endif /* !PLATFORM_WIN32 */
668 #if defined(PLATFORM_HPUX)
669 static void HPUX_Audio_Control()
671 struct audio_describe ainfo;
674 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
676 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
678 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
679 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
681 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
682 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
684 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
685 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
689 #endif /* PLATFORM_HPUX */
691 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
693 /* these two are stolen from "sox"... :) */
696 ** This routine converts from linear to ulaw.
698 ** Craig Reese: IDA/Supercomputing Research Center
699 ** Joe Campbell: Department of Defense
703 ** 1) CCITT Recommendation G.711 (very difficult to follow)
704 ** 2) "A New Digital Technique for Implementation of Any
705 ** Continuous PCM Companding Law," Villeret, Michel,
706 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
707 ** 1973, pg. 11.12-11.17
708 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
709 ** for Analog-to_Digital Conversion Techniques,"
712 ** Input: Signed 16 bit linear sample
713 ** Output: 8 bit ulaw sample
716 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
717 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
720 static unsigned char linear_to_ulaw(int sample)
722 static int exp_lut[256] =
724 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
725 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
726 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
727 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
728 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
729 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
730 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
731 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
732 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
733 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
734 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
735 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
736 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
737 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
738 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
739 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
742 int sign, exponent, mantissa;
743 unsigned char ulawbyte;
745 /* Get the sample into sign-magnitude. */
746 sign = (sample >> 8) & 0x80; /* set aside the sign */
748 sample = -sample; /* get magnitude */
750 sample = CLIP; /* clip the magnitude */
752 /* Convert from 16 bit linear to ulaw. */
753 sample = sample + BIAS;
754 exponent = exp_lut[( sample >> 7 ) & 0xFF];
755 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
756 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
759 ulawbyte = 0x02; /* optional CCITT trap */
766 ** This routine converts from ulaw to 16 bit linear.
768 ** Craig Reese: IDA/Supercomputing Research Center
772 ** 1) CCITT Recommendation G.711 (very difficult to follow)
773 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
774 ** for Analog-to_Digital Conversion Techniques,"
777 ** Input: 8 bit ulaw sample
778 ** Output: signed 16 bit linear sample
781 static int ulaw_to_linear(unsigned char ulawbyte)
783 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
784 int sign, exponent, mantissa, sample;
786 ulawbyte = ~ ulawbyte;
787 sign = ( ulawbyte & 0x80 );
788 exponent = ( ulawbyte >> 4 ) & 0x07;
789 mantissa = ulawbyte & 0x0F;
790 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
796 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
798 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
800 /*===========================================================================*/
802 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
804 void AllocSoundArray(int num)
807 Sound = checked_calloc(num_sounds * sizeof(struct SampleInfo));
810 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
811 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
813 boolean LoadSound(int sound_nr, char *sound_name)
815 struct SampleInfo *snd_info = &Sound[sound_nr];
817 char *sound_ext = "wav";
818 #if !defined(TARGET_SDL)
819 #if !defined(PLATFORM_MSDOS)
820 byte sound_header_buffer[WAV_HEADER_SIZE];
821 char chunk[CHUNK_ID_LEN + 1];
822 int chunk_length, dummy;
828 snd_info->name = sound_name;
830 sprintf(filename, "%s/%s/%s.%s",
831 options.ro_base_directory, SOUNDS_DIRECTORY,
832 snd_info->name, sound_ext);
834 #if defined(TARGET_SDL)
836 snd_info->mix_chunk = Mix_LoadWAV(filename);
837 if (snd_info->mix_chunk == NULL)
839 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
843 #else /* !TARGET_SDL */
845 #if !defined(PLATFORM_MSDOS)
847 if ((file = fopen(filename, MODE_READ)) == NULL)
849 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
853 /* read chunk "RIFF" */
854 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
855 if (strcmp(chunk, "RIFF") != 0)
857 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
862 /* read chunk "WAVE" */
863 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
864 if (strcmp(chunk, "WAVE") != 0)
866 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
871 /* read header information */
872 for (i=0; i<WAV_HEADER_SIZE; i++)
873 sound_header_buffer[i] = fgetc(file);
875 /* read chunk "data" */
876 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
877 if (strcmp(chunk, "data") != 0)
879 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
884 snd_info->data_len = chunk_length;
885 snd_info->data_ptr = checked_malloc(snd_info->data_len);
887 /* read sound data */
888 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
891 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
898 for (i=0; i<snd_info->data_len; i++)
899 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
901 #else /* PLATFORM_MSDOS */
903 snd_info->sample_ptr = load_sample(filename);
904 if (!snd_info->sample_ptr)
906 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
910 #endif /* PLATFORM_MSDOS */
911 #endif /* !TARGET_SDL */
916 void PlayMusic(int nr)
918 if (!audio.music_available)
921 #if defined(TARGET_SDL)
922 if (audio.mods_available)
924 Mix_VolumeMusic(SOUND_MAX_VOLUME);
925 /* start playing module */
927 else /* play music loop */
929 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
930 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
938 void PlaySound(int nr)
940 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
943 void PlaySoundStereo(int nr, int stereo)
945 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
948 void PlaySoundLoop(int nr)
950 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
953 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
955 struct SoundControl snd_ctrl = emptySoundControl;
957 if (!audio.sound_available || !audio.sound_enabled)
960 if (volume<PSND_MIN_VOLUME)
961 volume = PSND_MIN_VOLUME;
962 else if (volume>PSND_MAX_VOLUME)
963 volume = PSND_MAX_VOLUME;
965 if (stereo<PSND_MAX_LEFT)
966 stereo = PSND_MAX_LEFT;
967 else if (stereo>PSND_MAX_RIGHT)
968 stereo = PSND_MAX_RIGHT;
971 snd_ctrl.volume = volume;
972 snd_ctrl.stereo = stereo;
973 snd_ctrl.loop = loop;
974 snd_ctrl.active = TRUE;
975 snd_ctrl.data_ptr = Sound[nr].data_ptr;
976 snd_ctrl.data_len = Sound[nr].data_len;
978 #if defined(TARGET_SDL)
979 Mix_Volume(-1, SOUND_MAX_VOLUME);
980 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
981 #elif defined(PLATFORM_UNIX)
982 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
984 Error(ERR_WARN, "cannot pipe to child process - no sounds");
985 audio.sound_available = audio.sound_enabled = FALSE;
988 #elif defined(PLATFORM_MSDOS)
989 sound_handler(snd_ctrl);
995 #if defined(TARGET_SDL)
996 if (audio.mods_available)
997 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
999 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1001 FadeSound(audio.music_nr);
1005 void FadeSound(int nr)
1007 StopSoundExt(nr, SSND_FADE_SOUND);
1012 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1015 void StopMusic(void)
1017 #if defined(TARGET_SDL)
1018 if (audio.mods_available)
1021 Mix_HaltChannel(audio.music_channel);
1023 StopSound(audio.music_nr);
1027 void StopSound(int nr)
1029 StopSoundExt(nr, SSND_STOP_SOUND);
1034 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1037 void StopSoundExt(int nr, int method)
1039 struct SoundControl snd_ctrl = emptySoundControl;
1041 if (!audio.sound_available)
1044 if (SSND_FADING(method))
1045 snd_ctrl.fade_sound = TRUE;
1047 if (SSND_ALL(method))
1048 snd_ctrl.stop_all_sounds = TRUE;
1052 snd_ctrl.stop_sound = TRUE;
1055 #if defined(TARGET_SDL)
1057 if (SSND_FADING(method))
1061 for (i=0; i<audio.channels; i++)
1062 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1063 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1064 if (snd_ctrl.stop_all_sounds)
1065 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1071 for (i=0; i<audio.channels; i++)
1072 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1074 if (snd_ctrl.stop_all_sounds)
1079 #if !defined(PLATFORM_MSDOS)
1080 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1082 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1083 audio.sound_available = audio.sound_enabled = FALSE;
1087 sound_handler(snd_ctrl);
1092 void FreeSounds(int num_sounds)
1096 if (!audio.sound_available)
1099 for(i=0; i<num_sounds; i++)
1100 #if !defined(PLATFORM_MSDOS)
1101 free(Sound[i].data_ptr);
1103 destroy_sample(Sound[i].sample_ptr);
1107 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/