1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * ©1995 Artsoft Development *
6 * 33659 Bielefeld-Senne *
7 * Telefon: (0521) 493245 *
8 * eMail: aeglos@valinor.owl.de *
9 * aeglos@uni-paderborn.de *
10 * q99492@pbhrzx.uni-paderborn.de *
11 *----------------------------------------------------------*
13 ***********************************************************/
17 extern void sound_handler(struct SoundControl);
20 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
23 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
24 static struct SoundControl emptySoundControl =
26 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
28 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
29 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];
33 static unsigned char playing_buffer[SND_BLOCKSIZE];
34 static int playing_sounds = 0;
36 struct SoundControl playlist[MAX_SOUNDS_PLAYING];
37 struct SoundControl emptySoundControl;
45 struct SoundControl snd_ctrl;
48 close(sound_pipe[1]); /* no writing into pipe needed */
51 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
52 playlist[i] = emptySoundControl;
56 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
57 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
59 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
65 FD_ZERO(&sound_fdset);
66 FD_SET(sound_pipe[0], &sound_fdset);
68 for(;;) /* wait for calls from PlaySound(), StopSound(), ... */
70 FD_SET(sound_pipe[0], &sound_fdset);
71 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
72 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
74 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
76 fprintf(stderr,"%s: broken pipe - no sounds\n",progname);
82 if (snd_ctrl.fade_sound)
87 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
88 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
89 playlist[i].fade_sound = TRUE;
91 else if (snd_ctrl.stop_all_sounds)
96 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
97 playlist[i]=emptySoundControl;
102 else if (snd_ctrl.stop_sound)
107 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
108 if (playlist[i].nr == snd_ctrl.nr)
110 playlist[i]=emptySoundControl;
118 if (playing_sounds || snd_ctrl.active)
120 struct timeval delay = { 0, 0 };
122 long sample_size, max_sample_size;
126 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
128 if (!playing_sounds) /* we just opened the audio device */
130 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
131 /* (with stereo the effective buffer size will shrink to 256) */
132 fragment_size = 0x00020009;
133 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
134 /* try if we can use stereo sound */
136 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
137 /* get the real fragmentation size; this should return 512 */
138 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
139 max_sample_size = fragment_size / (stereo ? 2 : 1);
142 if (snd_ctrl.active) /* new sound has arrived */
143 SoundServer_InsertNewSound(snd_ctrl);
145 while(playing_sounds &&
146 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
148 FD_SET(sound_pipe[0], &sound_fdset);
150 /* first clear the last premixing buffer */
151 memset(premix_last_buffer,0,fragment_size*sizeof(int));
153 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
157 if (!playlist[i].active)
160 /* get pointer and size of the actual sound sample */
161 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
163 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
164 playlist[i].playingpos += sample_size;
166 /* fill the first mixing buffer with original sample */
167 memcpy(premix_first_buffer,sample_ptr,sample_size);
169 /* are we about to restart a looping sound? */
170 if (playlist[i].loop && sample_size<max_sample_size)
172 playlist[i].playingpos = max_sample_size-sample_size;
173 memcpy(premix_first_buffer+sample_size,
174 playlist[i].data_ptr,max_sample_size-sample_size);
175 sample_size = max_sample_size;
178 /* decrease volume if sound is fading out */
179 if (playlist[i].fade_sound &&
180 playlist[i].volume>=PSND_MAX_VOLUME/10)
181 playlist[i].volume-=PSND_MAX_VOLUME/20;
183 /* adjust volume of actual sound sample */
184 if (playlist[i].volume != PSND_MAX_VOLUME)
185 for(j=0;j<sample_size;j++)
186 premix_first_buffer[j] =
187 (playlist[i].volume * (int)premix_first_buffer[j])
188 >> PSND_MAX_VOLUME_BITS;
190 /* fill the last mixing buffer with stereo or mono sound */
193 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
194 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
195 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
197 for(j=0;j<sample_size;j++)
199 premix_left_buffer[j] =
200 (left_volume * (int)premix_first_buffer[j])
201 >> PSND_MAX_LEFT2RIGHT_BITS;
202 premix_right_buffer[j] =
203 (right_volume * (int)premix_first_buffer[j])
204 >> PSND_MAX_LEFT2RIGHT_BITS;
205 premix_last_buffer[2*j+0] += premix_left_buffer[j];
206 premix_last_buffer[2*j+1] += premix_right_buffer[j];
211 for(j=0;j<sample_size;j++)
212 premix_last_buffer[j] += (int)premix_first_buffer[j];
215 /* delete completed sound entries from the playlist */
216 if (playlist[i].playingpos >= playlist[i].data_len)
218 if (playlist[i].loop)
219 playlist[i].playingpos = 0;
222 playlist[i] = emptySoundControl;
226 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
228 playlist[i] = emptySoundControl;
233 /* put last mixing buffer to final playing buffer */
234 for(i=0;i<fragment_size;i++)
236 if (premix_last_buffer[i]<-255)
237 playing_buffer[i] = 0;
238 else if (premix_last_buffer[i]>255)
239 playing_buffer[i] = 255;
241 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
244 /* finally play the sound fragment */
245 write(sound_device,playing_buffer,fragment_size);
248 /* if no sounds playing, free device for other sound programs */
254 #else /* von '#ifdef VOXWARE' */
256 if (snd_ctrl.active && !snd_ctrl.loop)
258 struct timeval delay = { 0, 0 };
260 long sample_size, max_sample_size = SND_BLOCKSIZE;
261 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
262 int wait_percent = 90; /* wait 90% of the real playing time */
265 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
269 while(playing_sounds &&
270 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
272 FD_SET(sound_pipe[0], &sound_fdset);
274 /* get pointer and size of the actual sound sample */
275 sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
277 MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
278 snd_ctrl.playingpos += sample_size;
280 /* fill the first mixing buffer with original sample */
281 memcpy(premix_first_buffer,sample_ptr,sample_size);
284 /* adjust volume of actual sound sample */
285 if (snd_ctrl.volume != PSND_MAX_VOLUME)
286 for(i=0;i<sample_size;i++)
287 premix_first_buffer[i] =
288 (snd_ctrl.volume * (int)premix_first_buffer[i])
289 >> PSND_MAX_VOLUME_BITS;
291 for(i=0;i<sample_size;i++)
293 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
295 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
298 /* finally play the sound fragment */
299 write(sound_device,playing_buffer,sample_size);
302 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
308 #endif /* von '#ifdef VOXWARE' */
314 void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
318 /* wenn voll, ältesten Sound 'rauswerfen */
319 if (playing_sounds==MAX_SOUNDS_PLAYING)
321 int longest=0, longest_nr=0;
323 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
326 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
328 int actual = playlist[i].playingpos;
331 if (!playlist[i].loop && actual>longest)
338 voice_set_volume(playlist[longest_nr].voice, 0);
339 deallocate_voice(playlist[longest_nr].voice);
341 playlist[longest_nr] = emptySoundControl;
345 /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
346 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
348 if (playlist[i].nr == snd_ctrl.nr)
352 /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
353 if (k>=1 && snd_ctrl.loop)
355 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
357 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
359 playlist[i].fade_sound = FALSE;
360 playlist[i].volume = PSND_MAX_VOLUME;
362 playlist[i].loop = PSND_LOOP;
363 voice_stop_volumeramp(playlist[i].voice);
364 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
371 /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
374 int longest=0, longest_nr=0;
376 /* den bereits am längsten gespielten (gleichen) Sound suchen */
377 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
381 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
385 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
387 actual = playlist[i].playingpos;
396 voice_set_volume(playlist[longest_nr].voice, 0);
397 deallocate_voice(playlist[longest_nr].voice);
399 playlist[longest_nr] = emptySoundControl;
403 /* neuen Sound in Liste packen */
404 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
406 if (!playlist[i].active)
408 playlist[i] = snd_ctrl;
411 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
413 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
414 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
415 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
416 voice_start(playlist[i].voice);
424 void SoundServer_FadeSound(int nr)
431 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
432 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
433 playlist[i].fade_sound = TRUE;
437 void SoundServer_StopSound(int nr)
444 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
445 if (playlist[i].nr == nr)
448 voice_set_volume(playlist[i].voice, 0);
449 deallocate_voice(playlist[i].voice);
451 playlist[i] = emptySoundControl;
461 void SoundServer_StopAllSounds()
465 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
468 voice_set_volume(playlist[i].voice, 0);
469 deallocate_voice(playlist[i].voice);
471 playlist[i]=emptySoundControl;
481 void HPUX_Audio_Control()
483 struct audio_describe ainfo;
486 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
489 fprintf(stderr,"%s: cannot open /dev/audioCtl - no sounds\n",progname);
493 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
495 fprintf(stderr,"%s: no audio info - no sounds\n",progname);
499 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
501 fprintf(stderr,"%s: ulaw audio not available - no sounds\n",progname);
505 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
506 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
510 #endif /* HPUX_AUDIO */
512 /* these two are stolen from "sox"... :) */
515 ** This routine converts from linear to ulaw.
517 ** Craig Reese: IDA/Supercomputing Research Center
518 ** Joe Campbell: Department of Defense
522 ** 1) CCITT Recommendation G.711 (very difficult to follow)
523 ** 2) "A New Digital Technique for Implementation of Any
524 ** Continuous PCM Companding Law," Villeret, Michel,
525 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
526 ** 1973, pg. 11.12-11.17
527 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
528 ** for Analog-to_Digital Conversion Techniques,"
531 ** Input: Signed 16 bit linear sample
532 ** Output: 8 bit ulaw sample
535 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
536 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
539 unsigned char linear_to_ulaw(int sample)
541 static int exp_lut[256] =
543 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
544 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
545 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
546 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
547 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
548 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
549 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
550 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
551 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
552 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
553 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
554 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
555 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
556 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
557 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
558 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
561 int sign, exponent, mantissa;
562 unsigned char ulawbyte;
564 /* Get the sample into sign-magnitude. */
565 sign = (sample >> 8) & 0x80; /* set aside the sign */
567 sample = -sample; /* get magnitude */
569 sample = CLIP; /* clip the magnitude */
571 /* Convert from 16 bit linear to ulaw. */
572 sample = sample + BIAS;
573 exponent = exp_lut[( sample >> 7 ) & 0xFF];
574 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
575 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
578 ulawbyte = 0x02; /* optional CCITT trap */
585 ** This routine converts from ulaw to 16 bit linear.
587 ** Craig Reese: IDA/Supercomputing Research Center
591 ** 1) CCITT Recommendation G.711 (very difficult to follow)
592 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
593 ** for Analog-to_Digital Conversion Techniques,"
596 ** Input: 8 bit ulaw sample
597 ** Output: signed 16 bit linear sample
600 int ulaw_to_linear(unsigned char ulawbyte)
602 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
603 int sign, exponent, mantissa, sample;
605 ulawbyte = ~ ulawbyte;
606 sign = ( ulawbyte & 0x80 );
607 exponent = ( ulawbyte >> 4 ) & 0x07;
608 mantissa = ulawbyte & 0x0F;
609 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
616 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
618 /*===========================================================================*/
620 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
622 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
624 unsigned char *ptr = (unsigned char *)be;
626 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
629 BOOL LoadSound(struct SoundInfo *snd_info)
634 char *sound_ext = "8svx";
636 char *sound_ext = "wav";
638 struct SoundHeader_8SVX *sound_header;
641 sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
644 if (!(file=fopen(filename,"r")))
646 fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
651 if (fseek(file,0,SEEK_END)<0)
653 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
659 snd_info->file_len = ftell(file);
662 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
664 fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
670 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
672 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
680 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
682 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
683 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
684 strncmp(sound_header->magic_8SVX,"8SVX",4))
686 fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
691 ptr = snd_info->file_ptr + 12;
693 while(ptr < (unsigned char *)(snd_info->file_ptr + snd_info->file_len))
695 if (!strncmp(ptr,"VHDR",4))
697 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
700 else if (!strncmp(ptr,"ANNO",4))
702 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
705 else if (!strncmp(ptr,"CHAN",4))
707 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
710 else if (!strncmp(ptr,"BODY",4))
712 snd_info->data_ptr = ptr + 8;
713 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
718 /* other chunk not recognized here */
719 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
726 snd_info->sample_ptr = load_sample(filename);
727 if(!snd_info->sample_ptr)
729 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
735 #endif // von #ifndef MSDOS
738 void PlaySound(int nr)
740 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
743 void PlaySoundStereo(int nr, int stereo)
745 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
748 void PlaySoundLoop(int nr)
750 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
753 void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
755 struct SoundControl snd_ctrl = emptySoundControl;
757 if (sound_status==SOUND_OFF || !sound_on)
760 if (volume<PSND_MIN_VOLUME)
761 volume = PSND_MIN_VOLUME;
762 else if (volume>PSND_MAX_VOLUME)
763 volume = PSND_MAX_VOLUME;
765 if (stereo<PSND_MAX_LEFT)
766 stereo = PSND_MAX_LEFT;
767 else if (stereo>PSND_MAX_RIGHT)
768 stereo = PSND_MAX_RIGHT;
771 snd_ctrl.volume = volume;
772 snd_ctrl.stereo = stereo;
773 snd_ctrl.loop = loop;
774 snd_ctrl.active = TRUE;
775 snd_ctrl.data_ptr = Sound[nr].data_ptr;
776 snd_ctrl.data_len = Sound[nr].data_len;
779 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
781 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
782 sound_status=SOUND_OFF;
786 sound_handler(snd_ctrl);
790 void FadeSound(int nr)
792 StopSoundExt(nr, SSND_FADE_SOUND);
797 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
800 void StopSound(int nr)
802 StopSoundExt(nr, SSND_STOP_SOUND);
807 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
810 void StopSoundExt(int nr, int method)
812 struct SoundControl snd_ctrl = emptySoundControl;
814 if (sound_status==SOUND_OFF)
817 if (SSND_FADING(method))
818 snd_ctrl.fade_sound = TRUE;
820 if (SSND_ALL(method))
821 snd_ctrl.stop_all_sounds = TRUE;
825 snd_ctrl.stop_sound = TRUE;
829 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
831 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
832 sound_status=SOUND_OFF;
836 sound_handler(snd_ctrl);
840 void FreeSounds(int max)
844 if (sound_status==SOUND_OFF)
849 free(Sound[i].file_ptr);
851 destroy_sample(Sound[i].sample_ptr);
855 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/