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 ***********************************************************/
25 static int num_sounds = 0, num_music = 0, num_mods = 0;
26 static struct SampleInfo *Sound = NULL;
27 static struct SampleInfo *Mod = NULL;
30 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
32 static int playing_sounds = 0;
33 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
34 static struct SoundControl emptySoundControl =
36 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
39 #if defined(PLATFORM_UNIX)
40 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
41 static char premix_first_buffer[SND_BLOCKSIZE];
42 #if defined(AUDIO_STREAMING_DSP)
43 static char premix_left_buffer[SND_BLOCKSIZE];
44 static char premix_right_buffer[SND_BLOCKSIZE];
45 static int premix_last_buffer[SND_BLOCKSIZE];
47 static unsigned char playing_buffer[SND_BLOCKSIZE];
50 /* forward declaration of internal functions */
51 #if defined(AUDIO_STREAMING_DSP)
52 static void SoundServer_InsertNewSound(struct SoundControl);
53 #elif defined(PLATFORM_UNIX)
54 static unsigned char linear_to_ulaw(int);
55 static int ulaw_to_linear(unsigned char);
58 #if defined(PLATFORM_HPUX)
59 static void HPUX_Audio_Control();
62 #if defined(PLATFORM_MSDOS)
63 static void SoundServer_InsertNewSound(struct SoundControl);
64 static void SoundServer_StopSound(int);
65 static void SoundServer_StopAllSounds();
68 #if defined(PLATFORM_UNIX)
69 int OpenAudioDevice(char *audio_device_name)
73 /* check if desired audio device is accessible */
74 if (access(audio_device_name, W_OK) != 0)
77 /* try to open audio device in non-blocking mode */
78 if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
81 /* re-open audio device in blocking mode */
83 audio_fd = open(audio_device_name, O_WRONLY);
88 void UnixOpenAudio(void)
90 static char *audio_device_name[] =
98 /* look for available audio devices, starting with preferred ones */
99 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
100 if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
105 Error(ERR_WARN, "cannot open audio device - no sound");
111 audio.device_name = audio_device_name[i];
112 audio.sound_available = TRUE;
113 audio.sound_enabled = TRUE;
115 #if defined(AUDIO_STREAMING_DSP)
116 audio.music_available = TRUE;
117 audio.loops_available = TRUE;
121 void UnixCloseAudio(void)
124 close(audio.device_fd);
127 #endif /* PLATFORM_UNIX */
132 #if defined(PLATFORM_UNIX)
133 struct SoundControl snd_ctrl;
136 close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
139 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
140 playlist[i] = emptySoundControl;
143 #if defined(PLATFORM_UNIX)
144 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
145 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
147 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
149 #if defined(PLATFORM_HPUX)
150 HPUX_Audio_Control();
153 FD_ZERO(&sound_fdset);
154 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
156 while(1) /* wait for sound playing commands from client */
158 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
159 select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
160 if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
162 if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
164 Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
166 #if defined(AUDIO_STREAMING_DSP)
168 if (snd_ctrl.fade_sound)
173 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
174 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
175 playlist[i].fade_sound = TRUE;
177 else if (snd_ctrl.stop_all_sounds)
182 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
183 playlist[i]=emptySoundControl;
186 close(audio.device_fd);
188 else if (snd_ctrl.stop_sound)
193 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
194 if (playlist[i].nr == snd_ctrl.nr)
196 playlist[i]=emptySoundControl;
201 close(audio.device_fd);
204 if (playing_sounds || snd_ctrl.active)
206 struct timeval delay = { 0, 0 };
209 static long max_sample_size = 0;
210 static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
211 int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
213 /* 'ioctl()' expects pointer to integer value for stereo flag
214 (boolean is defined as 'char', which will not work here) */
216 if (playing_sounds ||
217 (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
219 if (!playing_sounds) /* we just opened the audio device */
221 unsigned long fragment_spec = 0;
223 /* determine logarithm (log2) of the fragment size */
224 for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
227 /* use two fragments (play one fragment, prepare the other);
228 one fragment would result in interrupted audio output, more
229 than two fragments would raise audio output latency to much */
230 fragment_spec |= 0x00020000;
232 /* Example for fragment specification:
233 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
234 - (with stereo the effective buffer size will shrink to 256)
235 => fragment_size = 0x00020009 */
237 if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0)
238 Error(ERR_EXIT_SOUND_SERVER,
239 "cannot set fragment size of /dev/dsp - no sounds");
241 /* try if we can use stereo sound */
242 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
245 static boolean reported = FALSE;
249 Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
256 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
257 Error(ERR_EXIT_SOUND_SERVER,
258 "cannot set sample rate of /dev/dsp - no sounds");
260 /* get the real fragmentation size; this should return 512 */
261 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE,&fragment_size) < 0)
262 Error(ERR_EXIT_SOUND_SERVER,
263 "cannot get fragment size of /dev/dsp - no sounds");
265 max_sample_size = fragment_size / (stereo ? 2 : 1);
268 if (snd_ctrl.active) /* new sound has arrived */
269 SoundServer_InsertNewSound(snd_ctrl);
271 while(playing_sounds &&
272 select(audio.soundserver_pipe[0] + 1,
273 &sound_fdset, NULL, NULL, &delay) < 1)
275 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
277 /* first clear the last premixing buffer */
278 memset(premix_last_buffer, 0, fragment_size * sizeof(int));
280 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
284 if (!playlist[i].active)
287 /* get pointer and size of the actual sound sample */
288 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
290 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
291 playlist[i].playingpos += sample_size;
293 /* fill the first mixing buffer with original sample */
294 memcpy(premix_first_buffer,sample_ptr,sample_size);
296 /* are we about to restart a looping sound? */
297 if (playlist[i].loop && sample_size<max_sample_size)
299 playlist[i].playingpos = max_sample_size-sample_size;
300 memcpy(premix_first_buffer+sample_size,
301 playlist[i].data_ptr,max_sample_size-sample_size);
302 sample_size = max_sample_size;
305 /* decrease volume if sound is fading out */
306 if (playlist[i].fade_sound &&
307 playlist[i].volume>=PSND_MAX_VOLUME/10)
308 playlist[i].volume-=PSND_MAX_VOLUME/20;
310 /* adjust volume of actual sound sample */
311 if (playlist[i].volume != PSND_MAX_VOLUME)
312 for(j=0;j<sample_size;j++)
313 premix_first_buffer[j] =
314 (playlist[i].volume * (int)premix_first_buffer[j])
315 >> PSND_MAX_VOLUME_BITS;
317 /* fill the last mixing buffer with stereo or mono sound */
320 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
321 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
322 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
324 for(j=0;j<sample_size;j++)
326 premix_left_buffer[j] =
327 (left_volume * (int)premix_first_buffer[j])
328 >> PSND_MAX_LEFT2RIGHT_BITS;
329 premix_right_buffer[j] =
330 (right_volume * (int)premix_first_buffer[j])
331 >> PSND_MAX_LEFT2RIGHT_BITS;
332 premix_last_buffer[2*j+0] += premix_left_buffer[j];
333 premix_last_buffer[2*j+1] += premix_right_buffer[j];
338 for(j=0;j<sample_size;j++)
339 premix_last_buffer[j] += (int)premix_first_buffer[j];
342 /* delete completed sound entries from the playlist */
343 if (playlist[i].playingpos >= playlist[i].data_len)
345 if (playlist[i].loop)
346 playlist[i].playingpos = 0;
349 playlist[i] = emptySoundControl;
353 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
355 playlist[i] = emptySoundControl;
360 /* put last mixing buffer to final playing buffer */
361 for(i=0; i<fragment_size; i++)
363 if (premix_last_buffer[i]<-255)
364 playing_buffer[i] = 0;
365 else if (premix_last_buffer[i]>255)
366 playing_buffer[i] = 255;
368 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
371 /* finally play the sound fragment */
372 write(audio.device_fd, playing_buffer, fragment_size);
375 /* if no sounds playing, free device for other sound programs */
377 close(audio.device_fd);
381 #else /* !AUDIO_STREAMING_DSP */
383 if (snd_ctrl.active && !snd_ctrl.loop)
385 struct timeval delay = { 0, 0 };
387 long sample_size, max_sample_size = SND_BLOCKSIZE;
388 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
389 int wait_percent = 90; /* wait 90% of the real playing time */
392 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
396 while(playing_sounds &&
397 select(audio.soundserver_pipe[0] + 1,
398 &sound_fdset, NULL, NULL, &delay) < 1)
400 FD_SET(audio.soundserver_pipe[0], &sound_fdset);
402 /* get pointer and size of the actual sound sample */
403 sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
405 MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
406 snd_ctrl.playingpos += sample_size;
408 /* fill the first mixing buffer with original sample */
409 memcpy(premix_first_buffer,sample_ptr,sample_size);
412 /* adjust volume of actual sound sample */
413 if (snd_ctrl.volume != PSND_MAX_VOLUME)
414 for(i=0;i<sample_size;i++)
415 premix_first_buffer[i] =
416 (snd_ctrl.volume * (int)premix_first_buffer[i])
417 >> PSND_MAX_VOLUME_BITS;
419 for(i=0;i<sample_size;i++)
421 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
423 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
426 /* finally play the sound fragment */
427 write(audio.device_fd,playing_buffer,sample_size);
430 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
432 close(audio.device_fd);
436 #endif /* !AUDIO_STREAMING_DSP */
440 #endif /* PLATFORM_UNIX */
444 #if defined(PLATFORM_MSDOS)
445 static void sound_handler(struct SoundControl snd_ctrl)
449 if (snd_ctrl.fade_sound)
454 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
455 if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
456 !playlist[i].fade_sound)
458 playlist[i].fade_sound = TRUE;
459 if (voice_check(playlist[i].voice))
460 voice_ramp_volume(playlist[i].voice, 1000, 0);
461 playlist[i].loop = PSND_NO_LOOP;
464 else if (snd_ctrl.stop_all_sounds)
468 SoundServer_StopAllSounds();
470 else if (snd_ctrl.stop_sound)
474 SoundServer_StopSound(snd_ctrl.nr);
477 for (i=0; i<MAX_SOUNDS_PLAYING; i++)
479 if (!playlist[i].active || playlist[i].loop)
482 playlist[i].playingpos = voice_get_position(playlist[i].voice);
483 playlist[i].volume = voice_get_volume(playlist[i].voice);
484 if (playlist[i].playingpos == -1 || !playlist[i].volume)
486 deallocate_voice(playlist[i].voice);
487 playlist[i] = emptySoundControl;
493 SoundServer_InsertNewSound(snd_ctrl);
495 #endif /* PLATFORM_MSDOS */
497 #if !defined(PLATFORM_WIN32)
498 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
502 /* if playlist is full, remove oldest sound */
503 if (playing_sounds==MAX_SOUNDS_PLAYING)
505 int longest=0, longest_nr=0;
507 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
509 #if !defined(PLATFORM_MSDOS)
510 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
512 int actual = playlist[i].playingpos;
515 if (!playlist[i].loop && actual>longest)
521 #if defined(PLATFORM_MSDOS)
522 voice_set_volume(playlist[longest_nr].voice, 0);
523 deallocate_voice(playlist[longest_nr].voice);
525 playlist[longest_nr] = emptySoundControl;
529 /* check if sound is already being played (and how often) */
530 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
532 if (playlist[i].nr == snd_ctrl.nr)
536 /* restart loop sounds only if they are just fading out */
537 if (k>=1 && snd_ctrl.loop)
539 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
541 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
543 playlist[i].fade_sound = FALSE;
544 playlist[i].volume = PSND_MAX_VOLUME;
545 #if defined(PLATFORM_MSDOS)
546 playlist[i].loop = PSND_LOOP;
547 voice_stop_volumeramp(playlist[i].voice);
548 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
555 /* don't play sound more than n times simultaneously (with n == 2 for now) */
558 int longest=0, longest_nr=0;
560 /* look for oldest equal sound */
561 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
565 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
568 #if !defined(PLATFORM_MSDOS)
569 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
571 actual = playlist[i].playingpos;
580 #if defined(PLATFORM_MSDOS)
581 voice_set_volume(playlist[longest_nr].voice, 0);
582 deallocate_voice(playlist[longest_nr].voice);
584 playlist[longest_nr] = emptySoundControl;
588 /* neuen Sound in Liste packen */
589 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
591 if (!playlist[i].active)
593 playlist[i] = snd_ctrl;
596 #if defined(PLATFORM_MSDOS)
597 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
599 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
600 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
601 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
602 voice_start(playlist[i].voice);
608 #endif /* !PLATFORM_WIN32 */
611 void SoundServer_FadeSound(int nr)
618 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
619 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
620 playlist[i].fade_sound = TRUE;
624 #if !defined(PLATFORM_WIN32)
625 #if defined(PLATFORM_MSDOS)
626 static void SoundServer_StopSound(int nr)
633 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
634 if (playlist[i].nr == nr)
636 #if defined(PLATFORM_MSDOS)
637 voice_set_volume(playlist[i].voice, 0);
638 deallocate_voice(playlist[i].voice);
640 playlist[i] = emptySoundControl;
644 #if !defined(PLATFORM_MSDOS)
646 close(audio.device_fd);
650 static void SoundServer_StopAllSounds()
654 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
656 #if defined(PLATFORM_MSDOS)
657 voice_set_volume(playlist[i].voice, 0);
658 deallocate_voice(playlist[i].voice);
660 playlist[i]=emptySoundControl;
664 #if !defined(PLATFORM_MSDOS)
665 close(audio.device_fd);
668 #endif /* PLATFORM_MSDOS */
669 #endif /* !PLATFORM_WIN32 */
671 #if defined(PLATFORM_HPUX)
672 static void HPUX_Audio_Control()
674 struct audio_describe ainfo;
677 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
679 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
681 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
682 Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
684 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
685 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
687 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
688 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
692 #endif /* PLATFORM_HPUX */
694 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
696 /* these two are stolen from "sox"... :) */
699 ** This routine converts from linear to ulaw.
701 ** Craig Reese: IDA/Supercomputing Research Center
702 ** Joe Campbell: Department of Defense
706 ** 1) CCITT Recommendation G.711 (very difficult to follow)
707 ** 2) "A New Digital Technique for Implementation of Any
708 ** Continuous PCM Companding Law," Villeret, Michel,
709 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
710 ** 1973, pg. 11.12-11.17
711 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
712 ** for Analog-to_Digital Conversion Techniques,"
715 ** Input: Signed 16 bit linear sample
716 ** Output: 8 bit ulaw sample
719 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
720 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
723 static unsigned char linear_to_ulaw(int sample)
725 static int exp_lut[256] =
727 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
728 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
729 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
730 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
731 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
732 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
733 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
734 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
740 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
741 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
742 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
745 int sign, exponent, mantissa;
746 unsigned char ulawbyte;
748 /* Get the sample into sign-magnitude. */
749 sign = (sample >> 8) & 0x80; /* set aside the sign */
751 sample = -sample; /* get magnitude */
753 sample = CLIP; /* clip the magnitude */
755 /* Convert from 16 bit linear to ulaw. */
756 sample = sample + BIAS;
757 exponent = exp_lut[( sample >> 7 ) & 0xFF];
758 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
759 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
762 ulawbyte = 0x02; /* optional CCITT trap */
769 ** This routine converts from ulaw to 16 bit linear.
771 ** Craig Reese: IDA/Supercomputing Research Center
775 ** 1) CCITT Recommendation G.711 (very difficult to follow)
776 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
777 ** for Analog-to_Digital Conversion Techniques,"
780 ** Input: 8 bit ulaw sample
781 ** Output: signed 16 bit linear sample
784 static int ulaw_to_linear(unsigned char ulawbyte)
786 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
787 int sign, exponent, mantissa, sample;
789 ulawbyte = ~ ulawbyte;
790 sign = ( ulawbyte & 0x80 );
791 exponent = ( ulawbyte >> 4 ) & 0x07;
792 mantissa = ulawbyte & 0x0F;
793 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
799 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
801 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
803 /*===========================================================================*/
805 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
807 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
808 #define WAV_HEADER_SIZE 20 /* size of WAV file header */
810 static boolean LoadSoundExt(char *sound_name, boolean is_music)
812 struct SampleInfo *snd_info;
814 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
815 byte sound_header_buffer[WAV_HEADER_SIZE];
816 char chunk[CHUNK_ID_LEN + 1];
817 int chunk_length, dummy;
823 Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
825 snd_info = &Sound[num_sounds - 1];
826 snd_info->name = sound_name;
828 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
829 (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name);
831 #if defined(TARGET_SDL)
833 if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
835 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
839 #elif defined(PLATFORM_UNIX)
841 if ((file = fopen(filename, MODE_READ)) == NULL)
843 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
847 /* read chunk "RIFF" */
848 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
849 if (strcmp(chunk, "RIFF") != 0)
851 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
856 /* read chunk "WAVE" */
857 getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
858 if (strcmp(chunk, "WAVE") != 0)
860 Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
865 /* read header information */
866 for (i=0; i<WAV_HEADER_SIZE; i++)
867 sound_header_buffer[i] = fgetc(file);
869 /* read chunk "data" */
870 getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
871 if (strcmp(chunk, "data") != 0)
873 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
878 snd_info->data_len = chunk_length;
879 snd_info->data_ptr = checked_malloc(snd_info->data_len);
881 /* read sound data */
882 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
885 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
892 for (i=0; i<snd_info->data_len; i++)
893 snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
895 #else /* PLATFORM_MSDOS */
897 snd_info->sample_ptr = load_sample(filename);
898 if (!snd_info->sample_ptr)
900 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
909 boolean LoadSound(char *sound_name)
911 return LoadSoundExt(sound_name, FALSE);
914 boolean LoadMod(char *mod_name)
916 struct SampleInfo *mod_info;
920 Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
922 mod_info = &Mod[num_mods - 1];
923 mod_info->name = mod_name;
925 sprintf(filename, "%s/%s/%s", options.ro_base_directory,
926 MUSIC_DIRECTORY, mod_info->name);
928 #if defined(TARGET_SDL)
929 if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
931 Error(ERR_WARN, "cannot read music file '%s' - no sounds", filename);
936 audio.mods_available = TRUE;
944 struct dirent *dir_entry;
945 char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
949 if ((dir = opendir(music_directory)) == NULL)
951 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
952 audio.music_available = FALSE;
953 free(music_directory);
957 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
959 char *filename = dir_entry->d_name;
961 if (strlen(filename) > 4 &&
962 strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
964 if (!LoadSoundExt(filename, TRUE))
966 audio.music_available = FALSE;
967 free(music_directory);
973 else if (strlen(filename) > 4 &&
974 (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
975 strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
976 strncmp(filename, "mod.", 4) == 0 ||
977 strncmp(filename, "MOD.", 4) == 0))
979 if (!LoadMod(filename))
981 audio.music_available = FALSE;
982 free(music_directory);
993 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
996 free(music_directory);
999 num_music = num_mods;
1004 void PlayMusic(int nr)
1006 if (!audio.music_available)
1010 nr = num_sounds - num_music + nr;
1012 #if defined(TARGET_SDL)
1013 if (audio.mods_available)
1015 Mix_VolumeMusic(SOUND_MAX_VOLUME);
1016 Mix_PlayMusic(Mod[nr].mix_music, -1);
1018 else /* play music loop */
1020 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1021 Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1024 audio.music_nr = nr;
1029 void PlaySound(int nr)
1031 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1034 void PlaySoundStereo(int nr, int stereo)
1036 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1039 void PlaySoundLoop(int nr)
1041 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1044 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1046 struct SoundControl snd_ctrl = emptySoundControl;
1048 if (!audio.sound_available || !audio.sound_enabled)
1051 if (volume<PSND_MIN_VOLUME)
1052 volume = PSND_MIN_VOLUME;
1053 else if (volume>PSND_MAX_VOLUME)
1054 volume = PSND_MAX_VOLUME;
1056 if (stereo<PSND_MAX_LEFT)
1057 stereo = PSND_MAX_LEFT;
1058 else if (stereo>PSND_MAX_RIGHT)
1059 stereo = PSND_MAX_RIGHT;
1062 snd_ctrl.volume = volume;
1063 snd_ctrl.stereo = stereo;
1064 snd_ctrl.loop = loop;
1065 snd_ctrl.active = TRUE;
1066 snd_ctrl.data_ptr = Sound[nr].data_ptr;
1067 snd_ctrl.data_len = Sound[nr].data_len;
1069 #if defined(TARGET_SDL)
1070 Mix_Volume(-1, SOUND_MAX_VOLUME);
1071 Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1072 #elif defined(PLATFORM_UNIX)
1073 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1075 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1076 audio.sound_available = audio.sound_enabled = FALSE;
1079 #elif defined(PLATFORM_MSDOS)
1080 sound_handler(snd_ctrl);
1084 void FadeMusic(void)
1086 #if defined(TARGET_SDL)
1087 if (audio.mods_available)
1088 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1090 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1092 FadeSound(audio.music_nr);
1096 void FadeSound(int nr)
1098 StopSoundExt(nr, SSND_FADE_SOUND);
1103 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1106 void StopMusic(void)
1108 #if defined(TARGET_SDL)
1109 if (audio.mods_available)
1112 Mix_HaltChannel(audio.music_channel);
1114 StopSound(audio.music_nr);
1118 void StopSound(int nr)
1120 StopSoundExt(nr, SSND_STOP_SOUND);
1125 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1128 void StopSoundExt(int nr, int method)
1130 struct SoundControl snd_ctrl = emptySoundControl;
1132 if (!audio.sound_available)
1135 if (SSND_FADING(method))
1136 snd_ctrl.fade_sound = TRUE;
1138 if (SSND_ALL(method))
1139 snd_ctrl.stop_all_sounds = TRUE;
1143 snd_ctrl.stop_sound = TRUE;
1146 #if defined(TARGET_SDL)
1148 if (SSND_FADING(method))
1152 for (i=0; i<audio.channels; i++)
1153 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1154 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1155 if (snd_ctrl.stop_all_sounds)
1156 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1162 for (i=0; i<audio.channels; i++)
1163 if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1165 if (snd_ctrl.stop_all_sounds)
1170 #if !defined(PLATFORM_MSDOS)
1171 if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1173 Error(ERR_WARN, "cannot pipe to child process - no sounds");
1174 audio.sound_available = audio.sound_enabled = FALSE;
1178 sound_handler(snd_ctrl);
1183 void FreeSounds(int num_sounds)
1187 if (!audio.sound_available)
1190 for(i=0; i<num_sounds; i++)
1191 #if defined(TARGET_SDL)
1192 free(Sound[i].mix_chunk);
1193 #elif !defined(PLATFORM_MSDOS)
1194 free(Sound[i].data_ptr);
1196 destroy_sample(Sound[i].sample_ptr);
1200 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/