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 ***********************************************************/
18 extern void sound_handler(struct SoundControl);
21 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
24 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
25 static struct SoundControl emptySoundControl =
27 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
29 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
30 static char premix_first_buffer[SND_BLOCKSIZE];
31 static char premix_left_buffer[SND_BLOCKSIZE];
32 static char premix_right_buffer[SND_BLOCKSIZE];
33 static int premix_last_buffer[SND_BLOCKSIZE];
34 static unsigned char playing_buffer[SND_BLOCKSIZE];
35 static int playing_sounds = 0;
37 struct SoundControl playlist[MAX_SOUNDS_PLAYING];
38 struct SoundControl emptySoundControl;
46 struct SoundControl snd_ctrl;
49 close(sound_pipe[1]); /* no writing into pipe needed */
52 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
53 playlist[i] = emptySoundControl;
57 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
58 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
60 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
66 FD_ZERO(&sound_fdset);
67 FD_SET(sound_pipe[0], &sound_fdset);
69 for(;;) /* wait for calls from PlaySound(), StopSound(), ... */
71 FD_SET(sound_pipe[0], &sound_fdset);
72 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
73 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
75 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
76 Error(ERR_EXIT_SOUNDSERVER, "broken pipe - no sounds");
80 if (snd_ctrl.fade_sound)
85 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
86 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
87 playlist[i].fade_sound = TRUE;
89 else if (snd_ctrl.stop_all_sounds)
94 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
95 playlist[i]=emptySoundControl;
100 else if (snd_ctrl.stop_sound)
105 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
106 if (playlist[i].nr == snd_ctrl.nr)
108 playlist[i]=emptySoundControl;
116 if (playing_sounds || snd_ctrl.active)
118 struct timeval delay = { 0, 0 };
120 long sample_size, max_sample_size;
124 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
126 if (!playing_sounds) /* we just opened the audio device */
128 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
129 /* (with stereo the effective buffer size will shrink to 256) */
130 fragment_size = 0x00020009;
131 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
132 /* try if we can use stereo sound */
134 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
135 /* get the real fragmentation size; this should return 512 */
136 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
137 max_sample_size = fragment_size / (stereo ? 2 : 1);
140 if (snd_ctrl.active) /* new sound has arrived */
141 SoundServer_InsertNewSound(snd_ctrl);
143 while(playing_sounds &&
144 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
146 FD_SET(sound_pipe[0], &sound_fdset);
148 /* first clear the last premixing buffer */
149 memset(premix_last_buffer,0,fragment_size*sizeof(int));
151 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
155 if (!playlist[i].active)
158 /* get pointer and size of the actual sound sample */
159 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
161 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
162 playlist[i].playingpos += sample_size;
164 /* fill the first mixing buffer with original sample */
165 memcpy(premix_first_buffer,sample_ptr,sample_size);
167 /* are we about to restart a looping sound? */
168 if (playlist[i].loop && sample_size<max_sample_size)
170 playlist[i].playingpos = max_sample_size-sample_size;
171 memcpy(premix_first_buffer+sample_size,
172 playlist[i].data_ptr,max_sample_size-sample_size);
173 sample_size = max_sample_size;
176 /* decrease volume if sound is fading out */
177 if (playlist[i].fade_sound &&
178 playlist[i].volume>=PSND_MAX_VOLUME/10)
179 playlist[i].volume-=PSND_MAX_VOLUME/20;
181 /* adjust volume of actual sound sample */
182 if (playlist[i].volume != PSND_MAX_VOLUME)
183 for(j=0;j<sample_size;j++)
184 premix_first_buffer[j] =
185 (playlist[i].volume * (int)premix_first_buffer[j])
186 >> PSND_MAX_VOLUME_BITS;
188 /* fill the last mixing buffer with stereo or mono sound */
191 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
192 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
193 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
195 for(j=0;j<sample_size;j++)
197 premix_left_buffer[j] =
198 (left_volume * (int)premix_first_buffer[j])
199 >> PSND_MAX_LEFT2RIGHT_BITS;
200 premix_right_buffer[j] =
201 (right_volume * (int)premix_first_buffer[j])
202 >> PSND_MAX_LEFT2RIGHT_BITS;
203 premix_last_buffer[2*j+0] += premix_left_buffer[j];
204 premix_last_buffer[2*j+1] += premix_right_buffer[j];
209 for(j=0;j<sample_size;j++)
210 premix_last_buffer[j] += (int)premix_first_buffer[j];
213 /* delete completed sound entries from the playlist */
214 if (playlist[i].playingpos >= playlist[i].data_len)
216 if (playlist[i].loop)
217 playlist[i].playingpos = 0;
220 playlist[i] = emptySoundControl;
224 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
226 playlist[i] = emptySoundControl;
231 /* put last mixing buffer to final playing buffer */
232 for(i=0;i<fragment_size;i++)
234 if (premix_last_buffer[i]<-255)
235 playing_buffer[i] = 0;
236 else if (premix_last_buffer[i]>255)
237 playing_buffer[i] = 255;
239 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
242 /* finally play the sound fragment */
243 write(sound_device,playing_buffer,fragment_size);
246 /* if no sounds playing, free device for other sound programs */
252 #else /* von '#ifdef VOXWARE' */
254 if (snd_ctrl.active && !snd_ctrl.loop)
256 struct timeval delay = { 0, 0 };
258 long sample_size, max_sample_size = SND_BLOCKSIZE;
259 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
260 int wait_percent = 90; /* wait 90% of the real playing time */
263 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
267 while(playing_sounds &&
268 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
270 FD_SET(sound_pipe[0], &sound_fdset);
272 /* get pointer and size of the actual sound sample */
273 sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
275 MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
276 snd_ctrl.playingpos += sample_size;
278 /* fill the first mixing buffer with original sample */
279 memcpy(premix_first_buffer,sample_ptr,sample_size);
282 /* adjust volume of actual sound sample */
283 if (snd_ctrl.volume != PSND_MAX_VOLUME)
284 for(i=0;i<sample_size;i++)
285 premix_first_buffer[i] =
286 (snd_ctrl.volume * (int)premix_first_buffer[i])
287 >> PSND_MAX_VOLUME_BITS;
289 for(i=0;i<sample_size;i++)
291 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
293 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
296 /* finally play the sound fragment */
297 write(sound_device,playing_buffer,sample_size);
300 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
306 #endif /* von '#ifdef VOXWARE' */
312 void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
316 /* wenn voll, ältesten Sound 'rauswerfen */
317 if (playing_sounds==MAX_SOUNDS_PLAYING)
319 int longest=0, longest_nr=0;
321 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
324 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
326 int actual = playlist[i].playingpos;
329 if (!playlist[i].loop && actual>longest)
336 voice_set_volume(playlist[longest_nr].voice, 0);
337 deallocate_voice(playlist[longest_nr].voice);
339 playlist[longest_nr] = emptySoundControl;
343 /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
344 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
346 if (playlist[i].nr == snd_ctrl.nr)
350 /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
351 if (k>=1 && snd_ctrl.loop)
353 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
355 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
357 playlist[i].fade_sound = FALSE;
358 playlist[i].volume = PSND_MAX_VOLUME;
360 playlist[i].loop = PSND_LOOP;
361 voice_stop_volumeramp(playlist[i].voice);
362 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
369 /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
372 int longest=0, longest_nr=0;
374 /* den bereits am längsten gespielten (gleichen) Sound suchen */
375 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
379 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
383 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
385 actual = playlist[i].playingpos;
394 voice_set_volume(playlist[longest_nr].voice, 0);
395 deallocate_voice(playlist[longest_nr].voice);
397 playlist[longest_nr] = emptySoundControl;
401 /* neuen Sound in Liste packen */
402 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
404 if (!playlist[i].active)
406 playlist[i] = snd_ctrl;
409 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
411 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
412 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
413 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
414 voice_start(playlist[i].voice);
422 void SoundServer_FadeSound(int nr)
429 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
430 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
431 playlist[i].fade_sound = TRUE;
435 void SoundServer_StopSound(int nr)
442 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
443 if (playlist[i].nr == nr)
446 voice_set_volume(playlist[i].voice, 0);
447 deallocate_voice(playlist[i].voice);
449 playlist[i] = emptySoundControl;
459 void SoundServer_StopAllSounds()
463 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
466 voice_set_volume(playlist[i].voice, 0);
467 deallocate_voice(playlist[i].voice);
469 playlist[i]=emptySoundControl;
479 void HPUX_Audio_Control()
481 struct audio_describe ainfo;
484 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
486 Error(ERR_EXIT_SOUNDSERVER, "cannot open /dev/audioCtl - no sounds");
488 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
489 Error(ERR_EXIT_SOUNDSERVER, "no audio info - no sounds");
491 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
492 Error(ERR_EXIT_SOUNDSERVER, "ulaw audio not available - no sounds");
494 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
495 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
499 #endif /* HPUX_AUDIO */
501 /* these two are stolen from "sox"... :) */
504 ** This routine converts from linear to ulaw.
506 ** Craig Reese: IDA/Supercomputing Research Center
507 ** Joe Campbell: Department of Defense
511 ** 1) CCITT Recommendation G.711 (very difficult to follow)
512 ** 2) "A New Digital Technique for Implementation of Any
513 ** Continuous PCM Companding Law," Villeret, Michel,
514 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
515 ** 1973, pg. 11.12-11.17
516 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
517 ** for Analog-to_Digital Conversion Techniques,"
520 ** Input: Signed 16 bit linear sample
521 ** Output: 8 bit ulaw sample
524 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
525 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
528 unsigned char linear_to_ulaw(int sample)
530 static int exp_lut[256] =
532 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
533 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
534 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
535 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
536 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
537 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
538 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
539 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
540 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
541 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
542 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
543 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
544 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
545 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
546 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
547 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
550 int sign, exponent, mantissa;
551 unsigned char ulawbyte;
553 /* Get the sample into sign-magnitude. */
554 sign = (sample >> 8) & 0x80; /* set aside the sign */
556 sample = -sample; /* get magnitude */
558 sample = CLIP; /* clip the magnitude */
560 /* Convert from 16 bit linear to ulaw. */
561 sample = sample + BIAS;
562 exponent = exp_lut[( sample >> 7 ) & 0xFF];
563 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
564 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
567 ulawbyte = 0x02; /* optional CCITT trap */
574 ** This routine converts from ulaw to 16 bit linear.
576 ** Craig Reese: IDA/Supercomputing Research Center
580 ** 1) CCITT Recommendation G.711 (very difficult to follow)
581 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
582 ** for Analog-to_Digital Conversion Techniques,"
585 ** Input: 8 bit ulaw sample
586 ** Output: signed 16 bit linear sample
589 int ulaw_to_linear(unsigned char ulawbyte)
591 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
592 int sign, exponent, mantissa, sample;
594 ulawbyte = ~ ulawbyte;
595 sign = ( ulawbyte & 0x80 );
596 exponent = ( ulawbyte >> 4 ) & 0x07;
597 mantissa = ulawbyte & 0x0F;
598 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
605 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
607 /*===========================================================================*/
609 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
611 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
613 unsigned char *ptr = (unsigned char *)be;
615 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
618 boolean LoadSound(struct SoundInfo *snd_info)
623 char *sound_ext = "8svx";
625 char *sound_ext = "wav";
627 struct SoundHeader_8SVX *sound_header;
630 sprintf(filename, "%s/%s/%s.%s",
631 options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
634 if (!(file=fopen(filename,"r")))
636 Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
640 if (fseek(file,0,SEEK_END)<0)
642 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
647 snd_info->file_len = ftell(file);
650 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
652 Error(ERR_WARN, "out of memory (this shouldn't happen :) - no sounds");
657 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
659 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
666 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
668 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
669 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
670 strncmp(sound_header->magic_8SVX,"8SVX",4))
672 Error(ERR_WARN, "'%s' is not an IFF/8SVX file or broken - no sounds",
677 ptr = snd_info->file_ptr + 12;
679 while(ptr < (unsigned char *)(snd_info->file_ptr + snd_info->file_len))
681 if (!strncmp(ptr,"VHDR",4))
683 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
686 else if (!strncmp(ptr,"ANNO",4))
688 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
691 else if (!strncmp(ptr,"CHAN",4))
693 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
696 else if (!strncmp(ptr,"BODY",4))
698 snd_info->data_ptr = ptr + 8;
699 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
704 /* other chunk not recognized here */
705 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
712 snd_info->sample_ptr = load_sample(filename);
713 if(!snd_info->sample_ptr)
715 Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
720 #endif // von #ifndef MSDOS
723 void PlaySound(int nr)
725 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
728 void PlaySoundStereo(int nr, int stereo)
730 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
733 void PlaySoundLoop(int nr)
735 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
738 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
740 struct SoundControl snd_ctrl = emptySoundControl;
742 if (sound_status==SOUND_OFF || !setup.sound)
745 if (volume<PSND_MIN_VOLUME)
746 volume = PSND_MIN_VOLUME;
747 else if (volume>PSND_MAX_VOLUME)
748 volume = PSND_MAX_VOLUME;
750 if (stereo<PSND_MAX_LEFT)
751 stereo = PSND_MAX_LEFT;
752 else if (stereo>PSND_MAX_RIGHT)
753 stereo = PSND_MAX_RIGHT;
756 snd_ctrl.volume = volume;
757 snd_ctrl.stereo = stereo;
758 snd_ctrl.loop = loop;
759 snd_ctrl.active = TRUE;
760 snd_ctrl.data_ptr = Sound[nr].data_ptr;
761 snd_ctrl.data_len = Sound[nr].data_len;
764 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
766 Error(ERR_WARN, "cannot pipe to child process - no sounds");
767 sound_status = SOUND_OFF;
771 sound_handler(snd_ctrl);
775 void FadeSound(int nr)
777 StopSoundExt(nr, SSND_FADE_SOUND);
782 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
785 void StopSound(int nr)
787 StopSoundExt(nr, SSND_STOP_SOUND);
792 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
795 void StopSoundExt(int nr, int method)
797 struct SoundControl snd_ctrl = emptySoundControl;
799 if (sound_status==SOUND_OFF)
802 if (SSND_FADING(method))
803 snd_ctrl.fade_sound = TRUE;
805 if (SSND_ALL(method))
806 snd_ctrl.stop_all_sounds = TRUE;
810 snd_ctrl.stop_sound = TRUE;
814 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
816 Error(ERR_WARN, "cannot pipe to child process - no sounds");
817 sound_status = SOUND_OFF;
821 sound_handler(snd_ctrl);
825 void FreeSounds(int max)
829 if (sound_status==SOUND_OFF)
834 free(Sound[i].file_ptr);
836 destroy_sample(Sound[i].sample_ptr);
840 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/