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 *----------------------------------------------------------*
14 * Letzte Aenderung: 15.06.1995 *
15 ***********************************************************/
19 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
21 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
22 static struct SoundControl emptySoundControl =
24 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
26 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
27 static char premix_first_buffer[SND_BLOCKSIZE];
28 static char premix_left_buffer[SND_BLOCKSIZE];
29 static char premix_right_buffer[SND_BLOCKSIZE];
30 static int premix_last_buffer[SND_BLOCKSIZE];
31 static unsigned char playing_buffer[SND_BLOCKSIZE];
32 static int playing_sounds = 0;
36 struct SoundControl snd_ctrl;
40 close(sound_pipe[1]); /* no writing into pipe needed */
42 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
43 playlist[i] = emptySoundControl;
45 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
46 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
48 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
54 FD_ZERO(&sound_fdset);
55 FD_SET(sound_pipe[0], &sound_fdset);
57 for(;;) /* wait for calls from PlaySound(), StopSound(), ... */
59 FD_SET(sound_pipe[0], &sound_fdset);
60 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
61 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
63 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
65 fprintf(stderr,"%s: broken pipe - no sounds\n",progname);
71 if (snd_ctrl.fade_sound)
76 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
77 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
78 playlist[i].fade_sound = TRUE;
80 else if (snd_ctrl.stop_all_sounds)
85 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
86 playlist[i]=emptySoundControl;
91 else if (snd_ctrl.stop_sound)
96 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
97 if (playlist[i].nr == snd_ctrl.nr)
99 playlist[i]=emptySoundControl;
107 if (playing_sounds || snd_ctrl.active)
109 struct timeval delay = { 0, 0 };
111 long sample_size, max_sample_size;
115 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
117 if (!playing_sounds) /* we just opened the audio device */
119 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
120 /* (with stereo the effective buffer size will shrink to 256) */
121 fragment_size = 0x00020009;
122 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
123 /* try if we can use stereo sound */
125 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
126 /* get the real fragmentation size; this should return 512 */
127 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
128 max_sample_size = fragment_size / (stereo ? 2 : 1);
131 if (snd_ctrl.active) /* new sound has arrived */
132 SoundServer_InsertNewSound(snd_ctrl);
134 while(playing_sounds &&
135 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
137 FD_SET(sound_pipe[0], &sound_fdset);
139 /* first clear the last premixing buffer */
140 memset(premix_last_buffer,0,fragment_size*sizeof(int));
142 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
146 if (!playlist[i].active)
149 /* get pointer and size of the actual sound sample */
150 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
152 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
153 playlist[i].playingpos += sample_size;
155 /* fill the first mixing buffer with original sample */
156 memcpy(premix_first_buffer,sample_ptr,sample_size);
158 /* are we about to restart a looping sound? */
159 if (playlist[i].loop && sample_size<max_sample_size)
161 playlist[i].playingpos = max_sample_size-sample_size;
162 memcpy(premix_first_buffer+sample_size,
163 playlist[i].data_ptr,max_sample_size-sample_size);
164 sample_size = max_sample_size;
167 /* decrease volume if sound is fading out */
168 if (playlist[i].fade_sound &&
169 playlist[i].volume>=PSND_MAX_VOLUME/10)
170 playlist[i].volume-=PSND_MAX_VOLUME/20;
172 /* adjust volume of actual sound sample */
173 if (playlist[i].volume != PSND_MAX_VOLUME)
174 for(j=0;j<sample_size;j++)
175 premix_first_buffer[j] =
176 (playlist[i].volume * (int)premix_first_buffer[j])
177 >> PSND_MAX_VOLUME_BITS;
179 /* fill the last mixing buffer with stereo or mono sound */
182 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
183 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
184 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
186 for(j=0;j<sample_size;j++)
188 premix_left_buffer[j] =
189 (left_volume * (int)premix_first_buffer[j])
190 >> PSND_MAX_LEFT2RIGHT_BITS;
191 premix_right_buffer[j] =
192 (right_volume * (int)premix_first_buffer[j])
193 >> PSND_MAX_LEFT2RIGHT_BITS;
194 premix_last_buffer[2*j+0] += premix_left_buffer[j];
195 premix_last_buffer[2*j+1] += premix_right_buffer[j];
200 for(j=0;j<sample_size;j++)
201 premix_last_buffer[j] += (int)premix_first_buffer[j];
204 /* delete completed sound entries from the playlist */
205 if (playlist[i].playingpos >= playlist[i].data_len)
207 if (playlist[i].loop)
208 playlist[i].playingpos = 0;
211 playlist[i] = emptySoundControl;
215 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
217 playlist[i] = emptySoundControl;
222 /* put last mixing buffer to final playing buffer */
223 for(i=0;i<fragment_size;i++)
225 if (premix_last_buffer[i]<-255)
226 playing_buffer[i] = 0;
227 else if (premix_last_buffer[i]>255)
228 playing_buffer[i] = 255;
230 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
233 /* finally play the sound fragment */
234 write(sound_device,playing_buffer,fragment_size);
237 /* if no sounds playing, free device for other sound programs */
243 #else /* von '#ifdef VOXWARE' */
245 if (snd_ctrl.active && !snd_ctrl.loop)
247 struct timeval delay = { 0, 0 };
249 long sample_size, max_sample_size = SND_BLOCKSIZE;
250 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
251 int wait_percent = 90; /* wait 90% of the real playing time */
254 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
258 while(playing_sounds &&
259 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
261 FD_SET(sound_pipe[0], &sound_fdset);
263 /* get pointer and size of the actual sound sample */
264 sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
266 MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
267 snd_ctrl.playingpos += sample_size;
269 /* fill the first mixing buffer with original sample */
270 memcpy(premix_first_buffer,sample_ptr,sample_size);
273 /* adjust volume of actual sound sample */
274 if (snd_ctrl.volume != PSND_MAX_VOLUME)
275 for(i=0;i<sample_size;i++)
276 premix_first_buffer[i] =
277 (snd_ctrl.volume * (int)premix_first_buffer[i])
278 >> PSND_MAX_VOLUME_BITS;
280 for(i=0;i<sample_size;i++)
282 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
284 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
287 /* finally play the sound fragment */
288 write(sound_device,playing_buffer,sample_size);
291 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
297 #endif /* von '#ifdef VOXWARE' */
302 void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
306 /* wenn voll, ältesten Sound 'rauswerfen */
307 if (playing_sounds==MAX_SOUNDS_PLAYING)
309 int longest=0, longest_nr=0;
311 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
314 100 * playlist[i].playingpos / playlist[i].data_len;
316 if (!playlist[i].loop && actual>longest)
322 playlist[longest_nr] = emptySoundControl;
326 /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
327 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
329 if (playlist[i].nr == snd_ctrl.nr)
333 /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
334 if (k>=1 && snd_ctrl.loop)
336 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
338 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
340 playlist[i].fade_sound = FALSE;
341 playlist[i].volume = PSND_MAX_VOLUME;
347 /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
350 int longest=0, longest_nr=0;
352 /* den bereits am längsten gespielten (gleichen) Sound suchen */
353 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
357 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
360 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
367 playlist[longest_nr] = emptySoundControl;
371 /* neuen Sound in Liste packen */
372 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
374 if (!playlist[i].active)
376 playlist[i] = snd_ctrl;
384 void SoundServer_FadeSound(int nr)
391 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
392 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
393 playlist[i].fade_sound = TRUE;
397 void SoundServer_StopSound(int nr)
404 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
405 if (playlist[i].nr == nr)
407 playlist[i] = emptySoundControl;
415 void SoundServer_StopAllSounds()
419 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
420 playlist[i]=emptySoundControl;
427 void HPUX_Audio_Control()
429 struct audio_describe ainfo;
432 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
435 fprintf(stderr,"%s: cannot open /dev/audioCtl - no sounds\n",progname);
439 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
441 fprintf(stderr,"%s: no audio info - no sounds\n",progname);
445 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
447 fprintf(stderr,"%s: ulaw audio not available - no sounds\n",progname);
451 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
452 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
456 #endif /* HPUX_AUDIO */
458 /* these two are stolen from "sox"... :) */
461 ** This routine converts from linear to ulaw.
463 ** Craig Reese: IDA/Supercomputing Research Center
464 ** Joe Campbell: Department of Defense
468 ** 1) CCITT Recommendation G.711 (very difficult to follow)
469 ** 2) "A New Digital Technique for Implementation of Any
470 ** Continuous PCM Companding Law," Villeret, Michel,
471 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
472 ** 1973, pg. 11.12-11.17
473 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
474 ** for Analog-to_Digital Conversion Techniques,"
477 ** Input: Signed 16 bit linear sample
478 ** Output: 8 bit ulaw sample
481 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
482 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
485 unsigned char linear_to_ulaw(int sample)
487 static int exp_lut[256] =
489 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
490 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
491 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
492 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
493 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
494 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
495 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
496 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
497 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
498 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
499 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
500 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
501 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
502 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
503 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
504 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
507 int sign, exponent, mantissa;
508 unsigned char ulawbyte;
510 /* Get the sample into sign-magnitude. */
511 sign = (sample >> 8) & 0x80; /* set aside the sign */
513 sample = -sample; /* get magnitude */
515 sample = CLIP; /* clip the magnitude */
517 /* Convert from 16 bit linear to ulaw. */
518 sample = sample + BIAS;
519 exponent = exp_lut[( sample >> 7 ) & 0xFF];
520 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
521 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
524 ulawbyte = 0x02; /* optional CCITT trap */
531 ** This routine converts from ulaw to 16 bit linear.
533 ** Craig Reese: IDA/Supercomputing Research Center
537 ** 1) CCITT Recommendation G.711 (very difficult to follow)
538 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
539 ** for Analog-to_Digital Conversion Techniques,"
542 ** Input: 8 bit ulaw sample
543 ** Output: signed 16 bit linear sample
546 int ulaw_to_linear(unsigned char ulawbyte)
548 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
549 int sign, exponent, mantissa, sample;
551 ulawbyte = ~ ulawbyte;
552 sign = ( ulawbyte & 0x80 );
553 exponent = ( ulawbyte >> 4 ) & 0x07;
554 mantissa = ulawbyte & 0x0F;
555 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
562 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
564 /*===========================================================================*/
566 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
568 BOOL LoadSound(struct SoundInfo *snd_info)
572 char *sound_ext = "8svx";
573 struct SoundHeader_8SVX *snd_hdr;
576 sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
578 if (!(file=fopen(filename,"r")))
580 fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
585 if (fseek(file,0,SEEK_END)<0)
587 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
593 snd_info->file_len = ftell(file);
596 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
598 fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
604 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
606 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
614 snd_hdr = (struct SoundHeader_8SVX *)snd_info->file_ptr;
616 if (strncmp(snd_hdr->magic_FORM,"FORM",4) ||
617 snd_info->file_len!=be2long(&snd_hdr->chunk_size)+8 ||
618 strncmp(snd_hdr->magic_8SVX,"8SVX",4))
620 fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
625 ptr = (unsigned char *)snd_info->file_ptr;
627 while(ptr<(unsigned char *)snd_info->file_ptr+snd_info->file_len)
629 if (!strncmp(ptr,"VHDR",4))
631 ptr+=be2long((unsigned long *)(ptr+4));
633 if (!strncmp(ptr,"ANNO",4))
635 ptr+=be2long((unsigned long *)(ptr+4));
637 if (!strncmp(ptr,"CHAN",4))
639 ptr+=be2long((unsigned long *)(ptr+4));
641 if (!strncmp(ptr,"BODY",4))
643 snd_info->data_ptr = ptr+8;
644 snd_info->data_len = be2long((unsigned long *)(ptr+4));
653 void PlaySound(int nr)
655 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
658 void PlaySoundStereo(int nr, int stereo)
660 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
663 void PlaySoundLoop(int nr)
665 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
668 void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
670 struct SoundControl snd_ctrl = emptySoundControl;
672 if (sound_status==SOUND_OFF || !sound_on)
675 if (volume<PSND_MIN_VOLUME)
676 volume = PSND_MIN_VOLUME;
677 else if (volume>PSND_MAX_VOLUME)
678 volume = PSND_MAX_VOLUME;
680 if (stereo<PSND_MAX_LEFT)
681 stereo = PSND_MAX_LEFT;
682 else if (stereo>PSND_MAX_RIGHT)
683 stereo = PSND_MAX_RIGHT;
686 snd_ctrl.volume = volume;
687 snd_ctrl.stereo = stereo;
688 snd_ctrl.loop = loop;
689 snd_ctrl.active = TRUE;
690 snd_ctrl.data_ptr = Sound[nr].data_ptr;
691 snd_ctrl.data_len = Sound[nr].data_len;
693 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
695 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
696 sound_status=SOUND_OFF;
701 void FadeSound(int nr)
703 StopSoundExt(nr, SSND_FADE_SOUND);
708 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
711 void StopSound(int nr)
713 StopSoundExt(nr, SSND_STOP_SOUND);
718 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
721 void StopSoundExt(int nr, int method)
723 struct SoundControl snd_ctrl = emptySoundControl;
725 if (sound_status==SOUND_OFF)
728 if (SSND_FADING(method))
729 snd_ctrl.fade_sound = TRUE;
731 if (SSND_ALL(method))
732 snd_ctrl.stop_all_sounds = TRUE;
736 snd_ctrl.stop_sound = TRUE;
739 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
741 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
742 sound_status=SOUND_OFF;
747 void FreeSounds(int max)
751 if (sound_status==SOUND_OFF)
755 free(Sound[i].file_ptr);
758 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/