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 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
19 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
20 static struct SoundControl emptySoundControl =
22 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
24 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
25 static char premix_first_buffer[SND_BLOCKSIZE];
26 static char premix_left_buffer[SND_BLOCKSIZE];
27 static char premix_right_buffer[SND_BLOCKSIZE];
28 static int premix_last_buffer[SND_BLOCKSIZE];
29 static unsigned char playing_buffer[SND_BLOCKSIZE];
30 static int playing_sounds = 0;
34 struct SoundControl snd_ctrl;
38 close(sound_pipe[1]); /* no writing into pipe needed */
40 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
41 playlist[i] = emptySoundControl;
43 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
44 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
46 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
52 FD_ZERO(&sound_fdset);
53 FD_SET(sound_pipe[0], &sound_fdset);
55 for(;;) /* wait for calls from PlaySound(), StopSound(), ... */
57 FD_SET(sound_pipe[0], &sound_fdset);
58 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
59 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
61 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
63 fprintf(stderr,"%s: broken pipe - no sounds\n",progname);
69 if (snd_ctrl.fade_sound)
74 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
75 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
76 playlist[i].fade_sound = TRUE;
78 else if (snd_ctrl.stop_all_sounds)
83 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
84 playlist[i]=emptySoundControl;
89 else if (snd_ctrl.stop_sound)
94 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
95 if (playlist[i].nr == snd_ctrl.nr)
97 playlist[i]=emptySoundControl;
105 if (playing_sounds || snd_ctrl.active)
107 struct timeval delay = { 0, 0 };
109 long sample_size, max_sample_size;
113 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
115 if (!playing_sounds) /* we just opened the audio device */
117 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
118 /* (with stereo the effective buffer size will shrink to 256) */
119 fragment_size = 0x00020009;
120 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
121 /* try if we can use stereo sound */
123 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
124 /* get the real fragmentation size; this should return 512 */
125 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
126 max_sample_size = fragment_size / (stereo ? 2 : 1);
129 if (snd_ctrl.active) /* new sound has arrived */
130 SoundServer_InsertNewSound(snd_ctrl);
132 while(playing_sounds &&
133 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
135 FD_SET(sound_pipe[0], &sound_fdset);
137 /* first clear the last premixing buffer */
138 memset(premix_last_buffer,0,fragment_size*sizeof(int));
140 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
144 if (!playlist[i].active)
147 /* get pointer and size of the actual sound sample */
148 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
150 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
151 playlist[i].playingpos += sample_size;
153 /* fill the first mixing buffer with original sample */
154 memcpy(premix_first_buffer,sample_ptr,sample_size);
156 /* are we about to restart a looping sound? */
157 if (playlist[i].loop && sample_size<max_sample_size)
159 playlist[i].playingpos = max_sample_size-sample_size;
160 memcpy(premix_first_buffer+sample_size,
161 playlist[i].data_ptr,max_sample_size-sample_size);
162 sample_size = max_sample_size;
165 /* decrease volume if sound is fading out */
166 if (playlist[i].fade_sound &&
167 playlist[i].volume>=PSND_MAX_VOLUME/10)
168 playlist[i].volume-=PSND_MAX_VOLUME/20;
170 /* adjust volume of actual sound sample */
171 if (playlist[i].volume != PSND_MAX_VOLUME)
172 for(j=0;j<sample_size;j++)
173 premix_first_buffer[j] =
174 (playlist[i].volume * (int)premix_first_buffer[j])
175 >> PSND_MAX_VOLUME_BITS;
177 /* fill the last mixing buffer with stereo or mono sound */
180 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
181 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
182 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
184 for(j=0;j<sample_size;j++)
186 premix_left_buffer[j] =
187 (left_volume * (int)premix_first_buffer[j])
188 >> PSND_MAX_LEFT2RIGHT_BITS;
189 premix_right_buffer[j] =
190 (right_volume * (int)premix_first_buffer[j])
191 >> PSND_MAX_LEFT2RIGHT_BITS;
192 premix_last_buffer[2*j+0] += premix_left_buffer[j];
193 premix_last_buffer[2*j+1] += premix_right_buffer[j];
198 for(j=0;j<sample_size;j++)
199 premix_last_buffer[j] += (int)premix_first_buffer[j];
202 /* delete completed sound entries from the playlist */
203 if (playlist[i].playingpos >= playlist[i].data_len)
205 if (playlist[i].loop)
206 playlist[i].playingpos = 0;
209 playlist[i] = emptySoundControl;
213 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
215 playlist[i] = emptySoundControl;
220 /* put last mixing buffer to final playing buffer */
221 for(i=0;i<fragment_size;i++)
223 if (premix_last_buffer[i]<-255)
224 playing_buffer[i] = 0;
225 else if (premix_last_buffer[i]>255)
226 playing_buffer[i] = 255;
228 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
231 /* finally play the sound fragment */
232 write(sound_device,playing_buffer,fragment_size);
235 /* if no sounds playing, free device for other sound programs */
241 #else /* von '#ifdef VOXWARE' */
243 if (snd_ctrl.active && !snd_ctrl.loop)
245 struct timeval delay = { 0, 0 };
247 long sample_size, max_sample_size = SND_BLOCKSIZE;
248 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
249 int wait_percent = 90; /* wait 90% of the real playing time */
252 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
256 while(playing_sounds &&
257 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
259 FD_SET(sound_pipe[0], &sound_fdset);
261 /* get pointer and size of the actual sound sample */
262 sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
264 MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
265 snd_ctrl.playingpos += sample_size;
267 /* fill the first mixing buffer with original sample */
268 memcpy(premix_first_buffer,sample_ptr,sample_size);
271 /* adjust volume of actual sound sample */
272 if (snd_ctrl.volume != PSND_MAX_VOLUME)
273 for(i=0;i<sample_size;i++)
274 premix_first_buffer[i] =
275 (snd_ctrl.volume * (int)premix_first_buffer[i])
276 >> PSND_MAX_VOLUME_BITS;
278 for(i=0;i<sample_size;i++)
280 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
282 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
285 /* finally play the sound fragment */
286 write(sound_device,playing_buffer,sample_size);
289 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
295 #endif /* von '#ifdef VOXWARE' */
300 void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
304 /* wenn voll, ältesten Sound 'rauswerfen */
305 if (playing_sounds==MAX_SOUNDS_PLAYING)
307 int longest=0, longest_nr=0;
309 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
312 100 * playlist[i].playingpos / playlist[i].data_len;
314 if (!playlist[i].loop && actual>longest)
320 playlist[longest_nr] = emptySoundControl;
324 /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
325 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
327 if (playlist[i].nr == snd_ctrl.nr)
331 /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
332 if (k>=1 && snd_ctrl.loop)
334 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
336 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
338 playlist[i].fade_sound = FALSE;
339 playlist[i].volume = PSND_MAX_VOLUME;
345 /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
348 int longest=0, longest_nr=0;
350 /* den bereits am längsten gespielten (gleichen) Sound suchen */
351 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
355 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
358 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
365 playlist[longest_nr] = emptySoundControl;
369 /* neuen Sound in Liste packen */
370 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
372 if (!playlist[i].active)
374 playlist[i] = snd_ctrl;
382 void SoundServer_FadeSound(int nr)
389 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
390 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
391 playlist[i].fade_sound = TRUE;
395 void SoundServer_StopSound(int nr)
402 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
403 if (playlist[i].nr == nr)
405 playlist[i] = emptySoundControl;
413 void SoundServer_StopAllSounds()
417 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
418 playlist[i]=emptySoundControl;
425 void HPUX_Audio_Control()
427 struct audio_describe ainfo;
430 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
433 fprintf(stderr,"%s: cannot open /dev/audioCtl - no sounds\n",progname);
437 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
439 fprintf(stderr,"%s: no audio info - no sounds\n",progname);
443 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
445 fprintf(stderr,"%s: ulaw audio not available - no sounds\n",progname);
449 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
450 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
454 #endif /* HPUX_AUDIO */
456 /* these two are stolen from "sox"... :) */
459 ** This routine converts from linear to ulaw.
461 ** Craig Reese: IDA/Supercomputing Research Center
462 ** Joe Campbell: Department of Defense
466 ** 1) CCITT Recommendation G.711 (very difficult to follow)
467 ** 2) "A New Digital Technique for Implementation of Any
468 ** Continuous PCM Companding Law," Villeret, Michel,
469 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
470 ** 1973, pg. 11.12-11.17
471 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
472 ** for Analog-to_Digital Conversion Techniques,"
475 ** Input: Signed 16 bit linear sample
476 ** Output: 8 bit ulaw sample
479 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
480 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
483 unsigned char linear_to_ulaw(int sample)
485 static int exp_lut[256] =
487 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
488 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
489 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
490 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
491 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
492 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
496 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
505 int sign, exponent, mantissa;
506 unsigned char ulawbyte;
508 /* Get the sample into sign-magnitude. */
509 sign = (sample >> 8) & 0x80; /* set aside the sign */
511 sample = -sample; /* get magnitude */
513 sample = CLIP; /* clip the magnitude */
515 /* Convert from 16 bit linear to ulaw. */
516 sample = sample + BIAS;
517 exponent = exp_lut[( sample >> 7 ) & 0xFF];
518 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
519 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
522 ulawbyte = 0x02; /* optional CCITT trap */
529 ** This routine converts from ulaw to 16 bit linear.
531 ** Craig Reese: IDA/Supercomputing Research Center
535 ** 1) CCITT Recommendation G.711 (very difficult to follow)
536 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
537 ** for Analog-to_Digital Conversion Techniques,"
540 ** Input: 8 bit ulaw sample
541 ** Output: signed 16 bit linear sample
544 int ulaw_to_linear(unsigned char ulawbyte)
546 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
547 int sign, exponent, mantissa, sample;
549 ulawbyte = ~ ulawbyte;
550 sign = ( ulawbyte & 0x80 );
551 exponent = ( ulawbyte >> 4 ) & 0x07;
552 mantissa = ulawbyte & 0x0F;
553 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
560 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
562 /*===========================================================================*/
564 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
566 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
568 unsigned char *ptr = (unsigned char *)be;
570 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
573 BOOL LoadSound(struct SoundInfo *snd_info)
577 char *sound_ext = "8svx";
578 struct SoundHeader_8SVX *sound_header;
581 sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
583 if (!(file=fopen(filename,"r")))
585 fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
590 if (fseek(file,0,SEEK_END)<0)
592 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
598 snd_info->file_len = ftell(file);
601 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
603 fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
609 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
611 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
619 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
621 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
622 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
623 strncmp(sound_header->magic_8SVX,"8SVX",4))
625 fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
630 ptr = snd_info->file_ptr + 12;
632 while(ptr < (unsigned char *)(snd_info->file_ptr + snd_info->file_len))
634 if (!strncmp(ptr,"VHDR",4))
636 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
639 else if (!strncmp(ptr,"ANNO",4))
641 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
644 else if (!strncmp(ptr,"CHAN",4))
646 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
649 else if (!strncmp(ptr,"BODY",4))
651 snd_info->data_ptr = ptr + 8;
652 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
657 /* other chunk not recognized here */
658 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
666 void PlaySound(int nr)
668 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
671 void PlaySoundStereo(int nr, int stereo)
673 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
676 void PlaySoundLoop(int nr)
678 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
681 void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
683 struct SoundControl snd_ctrl = emptySoundControl;
685 if (sound_status==SOUND_OFF || !sound_on)
688 if (volume<PSND_MIN_VOLUME)
689 volume = PSND_MIN_VOLUME;
690 else if (volume>PSND_MAX_VOLUME)
691 volume = PSND_MAX_VOLUME;
693 if (stereo<PSND_MAX_LEFT)
694 stereo = PSND_MAX_LEFT;
695 else if (stereo>PSND_MAX_RIGHT)
696 stereo = PSND_MAX_RIGHT;
699 snd_ctrl.volume = volume;
700 snd_ctrl.stereo = stereo;
701 snd_ctrl.loop = loop;
702 snd_ctrl.active = TRUE;
703 snd_ctrl.data_ptr = Sound[nr].data_ptr;
704 snd_ctrl.data_len = Sound[nr].data_len;
706 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
708 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
709 sound_status=SOUND_OFF;
714 void FadeSound(int nr)
716 StopSoundExt(nr, SSND_FADE_SOUND);
721 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
724 void StopSound(int nr)
726 StopSoundExt(nr, SSND_STOP_SOUND);
731 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
734 void StopSoundExt(int nr, int method)
736 struct SoundControl snd_ctrl = emptySoundControl;
738 if (sound_status==SOUND_OFF)
741 if (SSND_FADING(method))
742 snd_ctrl.fade_sound = TRUE;
744 if (SSND_ALL(method))
745 snd_ctrl.stop_all_sounds = TRUE;
749 snd_ctrl.stop_sound = TRUE;
752 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
754 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
755 sound_status=SOUND_OFF;
760 void FreeSounds(int max)
764 if (sound_status==SOUND_OFF)
768 free(Sound[i].file_ptr);
771 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/