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 BOOL LoadSound(struct SoundInfo *snd_info)
570 char *sound_ext = "8svx";
571 struct SoundHeader_8SVX *snd_hdr;
574 sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
576 if (!(file=fopen(filename,"r")))
578 fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
583 if (fseek(file,0,SEEK_END)<0)
585 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
591 snd_info->file_len = ftell(file);
594 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
596 fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
602 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
604 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
612 snd_hdr = (struct SoundHeader_8SVX *)snd_info->file_ptr;
614 if (strncmp(snd_hdr->magic_FORM,"FORM",4) ||
615 snd_info->file_len!=be2long(&snd_hdr->chunk_size)+8 ||
616 strncmp(snd_hdr->magic_8SVX,"8SVX",4))
618 fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
623 ptr = (unsigned char *)snd_info->file_ptr;
625 while(ptr<(unsigned char *)snd_info->file_ptr+snd_info->file_len)
627 if (!strncmp(ptr,"VHDR",4))
629 ptr+=be2long((unsigned long *)(ptr+4));
631 if (!strncmp(ptr,"ANNO",4))
633 ptr+=be2long((unsigned long *)(ptr+4));
635 if (!strncmp(ptr,"CHAN",4))
637 ptr+=be2long((unsigned long *)(ptr+4));
639 if (!strncmp(ptr,"BODY",4))
641 snd_info->data_ptr = ptr+8;
642 snd_info->data_len = be2long((unsigned long *)(ptr+4));
651 void PlaySound(int nr)
653 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
656 void PlaySoundStereo(int nr, int stereo)
658 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
661 void PlaySoundLoop(int nr)
663 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
666 void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
668 struct SoundControl snd_ctrl = emptySoundControl;
670 if (sound_status==SOUND_OFF || !sound_on)
673 if (volume<PSND_MIN_VOLUME)
674 volume = PSND_MIN_VOLUME;
675 else if (volume>PSND_MAX_VOLUME)
676 volume = PSND_MAX_VOLUME;
678 if (stereo<PSND_MAX_LEFT)
679 stereo = PSND_MAX_LEFT;
680 else if (stereo>PSND_MAX_RIGHT)
681 stereo = PSND_MAX_RIGHT;
684 snd_ctrl.volume = volume;
685 snd_ctrl.stereo = stereo;
686 snd_ctrl.loop = loop;
687 snd_ctrl.active = TRUE;
688 snd_ctrl.data_ptr = Sound[nr].data_ptr;
689 snd_ctrl.data_len = Sound[nr].data_len;
691 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
693 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
694 sound_status=SOUND_OFF;
699 void FadeSound(int nr)
701 StopSoundExt(nr, SSND_FADE_SOUND);
706 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
709 void StopSound(int nr)
711 StopSoundExt(nr, SSND_STOP_SOUND);
716 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
719 void StopSoundExt(int nr, int method)
721 struct SoundControl snd_ctrl = emptySoundControl;
723 if (sound_status==SOUND_OFF)
726 if (SSND_FADING(method))
727 snd_ctrl.fade_sound = TRUE;
729 if (SSND_ALL(method))
730 snd_ctrl.stop_all_sounds = TRUE;
734 snd_ctrl.stop_sound = TRUE;
737 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
739 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
740 sound_status=SOUND_OFF;
745 void FreeSounds(int max)
749 if (sound_status==SOUND_OFF)
753 free(Sound[i].file_ptr);
756 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/