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 int sample_size, max_sample_size;
116 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
118 if (!playing_sounds) /* we just opened the audio device */
120 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
121 /* (with stereo the effective buffer size will shrink to 256) */
122 fragment_size = 0x00020009;
123 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
124 /* try if we can use stereo sound */
126 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
127 /* get the real fragmentation size; this should return 512 */
128 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
129 max_sample_size = fragment_size / (stereo ? 2 : 1);
132 if (snd_ctrl.active) /* new sound has arrived */
133 SoundServer_InsertNewSound(snd_ctrl);
135 while(playing_sounds &&
136 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
138 FD_SET(sound_pipe[0], &sound_fdset);
140 /* first clear the last premixing buffer */
141 memset(premix_last_buffer,0,fragment_size*sizeof(int));
143 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
147 if (!playlist[i].active)
150 /* get pointer and size of the actual sound sample */
151 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
153 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
154 playlist[i].playingpos += sample_size;
156 /* fill the first mixing buffer with original sample */
157 memcpy(premix_first_buffer,sample_ptr,sample_size);
159 /* are we about to restart a looping sound? */
160 if (playlist[i].loop && sample_size<max_sample_size)
162 playlist[i].playingpos = max_sample_size-sample_size;
163 memcpy(premix_first_buffer+sample_size,
164 playlist[i].data_ptr,max_sample_size-sample_size);
165 sample_size = max_sample_size;
168 /* decrease volume if sound is fading out */
169 if (playlist[i].fade_sound &&
170 playlist[i].volume>=PSND_MAX_VOLUME/10)
171 playlist[i].volume-=PSND_MAX_VOLUME/20;
173 /* adjust volume of actual sound sample */
174 if (playlist[i].volume != PSND_MAX_VOLUME)
175 for(j=0;j<sample_size;j++)
176 premix_first_buffer[j] =
177 (playlist[i].volume * (int)premix_first_buffer[j])
178 >> PSND_MAX_VOLUME_BITS;
180 /* fill the last mixing buffer with stereo or mono sound */
183 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
184 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
185 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
187 for(j=0;j<sample_size;j++)
189 premix_left_buffer[j] =
190 (left_volume * (int)premix_first_buffer[j])
191 >> PSND_MAX_LEFT2RIGHT_BITS;
192 premix_right_buffer[j] =
193 (right_volume * (int)premix_first_buffer[j])
194 >> PSND_MAX_LEFT2RIGHT_BITS;
195 premix_last_buffer[2*j+0] += premix_left_buffer[j];
196 premix_last_buffer[2*j+1] += premix_right_buffer[j];
201 for(j=0;j<sample_size;j++)
202 premix_last_buffer[j] += (int)premix_first_buffer[j];
205 /* delete completed sound entries from the playlist */
206 if (playlist[i].playingpos >= playlist[i].data_len)
208 if (playlist[i].loop)
209 playlist[i].playingpos = 0;
212 playlist[i] = emptySoundControl;
216 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
218 playlist[i] = emptySoundControl;
223 /* put last mixing buffer to final playing buffer */
224 for(i=0;i<fragment_size;i++)
226 if (premix_last_buffer[i]<-255)
227 playing_buffer[i] = 0;
228 else if (premix_last_buffer[i]>255)
229 playing_buffer[i] = 255;
231 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
234 /* finally play the sound fragment */
235 ignored = write(sound_device,playing_buffer,fragment_size);
238 /* if no sounds playing, free device for other sound programs */
244 #else /* von '#ifdef VOXWARE' */
246 if (snd_ctrl.active && !snd_ctrl.loop)
248 struct timeval delay = { 0, 0 };
250 int sample_size, max_sample_size = SND_BLOCKSIZE;
251 int sample_rate = 8000; /* standard "/dev/audio" sampling rate */
252 int wait_percent = 90; /* wait 90% of the real playing time */
255 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
259 while(playing_sounds &&
260 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
262 FD_SET(sound_pipe[0], &sound_fdset);
264 /* get pointer and size of the actual sound sample */
265 sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
267 MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
268 snd_ctrl.playingpos += sample_size;
270 /* fill the first mixing buffer with original sample */
271 memcpy(premix_first_buffer,sample_ptr,sample_size);
274 /* adjust volume of actual sound sample */
275 if (snd_ctrl.volume != PSND_MAX_VOLUME)
276 for(i=0;i<sample_size;i++)
277 premix_first_buffer[i] =
278 (snd_ctrl.volume * (int)premix_first_buffer[i])
279 >> PSND_MAX_VOLUME_BITS;
281 for(i=0;i<sample_size;i++)
283 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
285 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
288 /* finally play the sound fragment */
289 write(sound_device,playing_buffer,sample_size);
292 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
298 #endif /* von '#ifdef VOXWARE' */
303 void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
307 /* wenn voll, ältesten Sound 'rauswerfen */
308 if (playing_sounds==MAX_SOUNDS_PLAYING)
310 int longest=0, longest_nr=0;
312 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
315 100 * playlist[i].playingpos / playlist[i].data_len;
317 if (!playlist[i].loop && actual>longest)
323 playlist[longest_nr] = emptySoundControl;
327 /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
328 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
330 if (playlist[i].nr == snd_ctrl.nr)
334 /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
335 if (k>=1 && snd_ctrl.loop)
337 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
339 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
341 playlist[i].fade_sound = FALSE;
342 playlist[i].volume = PSND_MAX_VOLUME;
348 /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
351 int longest=0, longest_nr=0;
353 /* den bereits am längsten gespielten (gleichen) Sound suchen */
354 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
358 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
361 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
368 playlist[longest_nr] = emptySoundControl;
372 /* neuen Sound in Liste packen */
373 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
375 if (!playlist[i].active)
377 playlist[i] = snd_ctrl;
385 void SoundServer_FadeSound(int nr)
392 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
393 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
394 playlist[i].fade_sound = TRUE;
398 void SoundServer_StopSound(int nr)
405 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
406 if (playlist[i].nr == nr)
408 playlist[i] = emptySoundControl;
416 void SoundServer_StopAllSounds()
420 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
421 playlist[i]=emptySoundControl;
428 void HPUX_Audio_Control()
430 struct audio_describe ainfo;
433 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
436 fprintf(stderr,"%s: cannot open /dev/audioCtl - no sounds\n",progname);
440 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
442 fprintf(stderr,"%s: no audio info - no sounds\n",progname);
446 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
448 fprintf(stderr,"%s: ulaw audio not available - no sounds\n",progname);
452 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
453 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
457 #endif /* HPUX_AUDIO */
459 /* these two are stolen from "sox"... :) */
462 ** This routine converts from linear to ulaw.
464 ** Craig Reese: IDA/Supercomputing Research Center
465 ** Joe Campbell: Department of Defense
469 ** 1) CCITT Recommendation G.711 (very difficult to follow)
470 ** 2) "A New Digital Technique for Implementation of Any
471 ** Continuous PCM Companding Law," Villeret, Michel,
472 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
473 ** 1973, pg. 11.12-11.17
474 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
475 ** for Analog-to_Digital Conversion Techniques,"
478 ** Input: Signed 16 bit linear sample
479 ** Output: 8 bit ulaw sample
482 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
483 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
486 unsigned char linear_to_ulaw(int sample)
488 static int exp_lut[256] =
490 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
491 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
492 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
493 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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,
505 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
508 int sign, exponent, mantissa;
509 unsigned char ulawbyte;
511 /* Get the sample into sign-magnitude. */
512 sign = (sample >> 8) & 0x80; /* set aside the sign */
514 sample = -sample; /* get magnitude */
516 sample = CLIP; /* clip the magnitude */
518 /* Convert from 16 bit linear to ulaw. */
519 sample = sample + BIAS;
520 exponent = exp_lut[( sample >> 7 ) & 0xFF];
521 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
522 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
525 ulawbyte = 0x02; /* optional CCITT trap */
532 ** This routine converts from ulaw to 16 bit linear.
534 ** Craig Reese: IDA/Supercomputing Research Center
538 ** 1) CCITT Recommendation G.711 (very difficult to follow)
539 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
540 ** for Analog-to_Digital Conversion Techniques,"
543 ** Input: 8 bit ulaw sample
544 ** Output: signed 16 bit linear sample
547 int ulaw_to_linear(unsigned char ulawbyte)
549 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
550 int sign, exponent, mantissa, sample;
552 ulawbyte = ~ ulawbyte;
553 sign = ( ulawbyte & 0x80 );
554 exponent = ( ulawbyte >> 4 ) & 0x07;
555 mantissa = ulawbyte & 0x0F;
556 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
563 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
565 /*===========================================================================*/
567 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
569 BOOL LoadSound(struct SoundInfo *snd_info)
573 char *sound_ext = "8svx";
574 struct SoundHeader_8SVX *snd_hdr;
577 sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
579 if (!(file=fopen(filename,"r")))
581 fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
586 if (fseek(file,0,SEEK_END)<0)
588 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
594 snd_info->file_len = ftell(file);
597 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
599 fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
605 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
607 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
615 snd_hdr = (struct SoundHeader_8SVX *)snd_info->file_ptr;
617 if (strncmp(snd_hdr->magic_FORM,"FORM",4) ||
618 snd_info->file_len!=be2int(&snd_hdr->chunk_size)+8 ||
619 strncmp(snd_hdr->magic_8SVX,"8SVX",4))
621 fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
626 ptr = (unsigned char *)snd_info->file_ptr;
628 while(ptr<(unsigned char *)snd_info->file_ptr+snd_info->file_len)
630 if (!strncmp(ptr,"VHDR",4))
632 ptr+=be2int((unsigned int *)(ptr+4));
634 if (!strncmp(ptr,"ANNO",4))
636 ptr+=be2int((unsigned int *)(ptr+4));
638 if (!strncmp(ptr,"CHAN",4))
640 ptr+=be2int((unsigned int *)(ptr+4));
642 if (!strncmp(ptr,"BODY",4))
644 snd_info->data_ptr = ptr+8;
645 snd_info->data_len = be2int((unsigned int *)(ptr+4));
654 void PlaySound(int nr)
656 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
659 void PlaySoundStereo(int nr, int stereo)
661 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
664 void PlaySoundLoop(int nr)
666 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
669 void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
671 struct SoundControl snd_ctrl = emptySoundControl;
673 if (sound_status==SOUND_OFF || !sound_on)
676 if (volume<PSND_MIN_VOLUME)
677 volume = PSND_MIN_VOLUME;
678 else if (volume>PSND_MAX_VOLUME)
679 volume = PSND_MAX_VOLUME;
681 if (stereo<PSND_MAX_LEFT)
682 stereo = PSND_MAX_LEFT;
683 else if (stereo>PSND_MAX_RIGHT)
684 stereo = PSND_MAX_RIGHT;
687 snd_ctrl.volume = volume;
688 snd_ctrl.stereo = stereo;
689 snd_ctrl.loop = loop;
690 snd_ctrl.active = TRUE;
691 snd_ctrl.data_ptr = Sound[nr].data_ptr;
692 snd_ctrl.data_len = Sound[nr].data_len;
694 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
696 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
697 sound_status=SOUND_OFF;
702 void FadeSound(int nr)
704 StopSoundExt(nr, SSND_FADE_SOUND);
709 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
712 void StopSound(int nr)
714 StopSoundExt(nr, SSND_STOP_SOUND);
719 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
722 void StopSoundExt(int nr, int method)
724 struct SoundControl snd_ctrl = emptySoundControl;
726 if (sound_status==SOUND_OFF)
729 if (SSND_FADING(method))
730 snd_ctrl.fade_sound = TRUE;
732 if (SSND_ALL(method))
733 snd_ctrl.stop_all_sounds = TRUE;
737 snd_ctrl.stop_sound = TRUE;
740 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
742 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
743 sound_status=SOUND_OFF;
748 void FreeSounds(int max)
752 if (sound_status==SOUND_OFF)
756 free(Sound[i].file_ptr);
759 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/