1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
16 extern void sound_handler(struct SoundControl);
19 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
22 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
23 static struct SoundControl emptySoundControl =
25 -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
27 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
28 static char premix_first_buffer[SND_BLOCKSIZE];
29 static char premix_left_buffer[SND_BLOCKSIZE];
30 static char premix_right_buffer[SND_BLOCKSIZE];
31 static int premix_last_buffer[SND_BLOCKSIZE];
32 static unsigned char playing_buffer[SND_BLOCKSIZE];
33 static int playing_sounds = 0;
35 struct SoundControl playlist[MAX_SOUNDS_PLAYING];
36 struct SoundControl emptySoundControl;
44 struct SoundControl snd_ctrl;
47 close(sound_pipe[1]); /* no writing into pipe needed */
50 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
51 playlist[i] = emptySoundControl;
55 stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
56 for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
58 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
64 FD_ZERO(&sound_fdset);
65 FD_SET(sound_pipe[0], &sound_fdset);
67 for(;;) /* wait for calls from PlaySound(), StopSound(), ... */
69 FD_SET(sound_pipe[0], &sound_fdset);
70 select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
71 if (!FD_ISSET(sound_pipe[0], &sound_fdset))
73 if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
75 fprintf(stderr,"%s: broken pipe - no sounds\n",progname);
81 if (snd_ctrl.fade_sound)
86 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
87 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
88 playlist[i].fade_sound = TRUE;
90 else if (snd_ctrl.stop_all_sounds)
95 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
96 playlist[i]=emptySoundControl;
101 else if (snd_ctrl.stop_sound)
106 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
107 if (playlist[i].nr == snd_ctrl.nr)
109 playlist[i]=emptySoundControl;
117 if (playing_sounds || snd_ctrl.active)
119 struct timeval delay = { 0, 0 };
121 long sample_size, max_sample_size;
125 if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
127 if (!playing_sounds) /* we just opened the audio device */
129 /* 2 buffers / 512 bytes, giving 1/16 second resolution */
130 /* (with stereo the effective buffer size will shrink to 256) */
131 fragment_size = 0x00020009;
132 ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
133 /* try if we can use stereo sound */
135 ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
136 /* get the real fragmentation size; this should return 512 */
137 ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
138 max_sample_size = fragment_size / (stereo ? 2 : 1);
141 if (snd_ctrl.active) /* new sound has arrived */
142 SoundServer_InsertNewSound(snd_ctrl);
144 while(playing_sounds &&
145 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
147 FD_SET(sound_pipe[0], &sound_fdset);
149 /* first clear the last premixing buffer */
150 memset(premix_last_buffer,0,fragment_size*sizeof(int));
152 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
156 if (!playlist[i].active)
159 /* get pointer and size of the actual sound sample */
160 sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
162 MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
163 playlist[i].playingpos += sample_size;
165 /* fill the first mixing buffer with original sample */
166 memcpy(premix_first_buffer,sample_ptr,sample_size);
168 /* are we about to restart a looping sound? */
169 if (playlist[i].loop && sample_size<max_sample_size)
171 playlist[i].playingpos = max_sample_size-sample_size;
172 memcpy(premix_first_buffer+sample_size,
173 playlist[i].data_ptr,max_sample_size-sample_size);
174 sample_size = max_sample_size;
177 /* decrease volume if sound is fading out */
178 if (playlist[i].fade_sound &&
179 playlist[i].volume>=PSND_MAX_VOLUME/10)
180 playlist[i].volume-=PSND_MAX_VOLUME/20;
182 /* adjust volume of actual sound sample */
183 if (playlist[i].volume != PSND_MAX_VOLUME)
184 for(j=0;j<sample_size;j++)
185 premix_first_buffer[j] =
186 (playlist[i].volume * (int)premix_first_buffer[j])
187 >> PSND_MAX_VOLUME_BITS;
189 /* fill the last mixing buffer with stereo or mono sound */
192 int middle_pos = PSND_MAX_LEFT2RIGHT/2;
193 int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
194 int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
196 for(j=0;j<sample_size;j++)
198 premix_left_buffer[j] =
199 (left_volume * (int)premix_first_buffer[j])
200 >> PSND_MAX_LEFT2RIGHT_BITS;
201 premix_right_buffer[j] =
202 (right_volume * (int)premix_first_buffer[j])
203 >> PSND_MAX_LEFT2RIGHT_BITS;
204 premix_last_buffer[2*j+0] += premix_left_buffer[j];
205 premix_last_buffer[2*j+1] += premix_right_buffer[j];
210 for(j=0;j<sample_size;j++)
211 premix_last_buffer[j] += (int)premix_first_buffer[j];
214 /* delete completed sound entries from the playlist */
215 if (playlist[i].playingpos >= playlist[i].data_len)
217 if (playlist[i].loop)
218 playlist[i].playingpos = 0;
221 playlist[i] = emptySoundControl;
225 else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
227 playlist[i] = emptySoundControl;
232 /* put last mixing buffer to final playing buffer */
233 for(i=0;i<fragment_size;i++)
235 if (premix_last_buffer[i]<-255)
236 playing_buffer[i] = 0;
237 else if (premix_last_buffer[i]>255)
238 playing_buffer[i] = 255;
240 playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
243 /* finally play the sound fragment */
244 write(sound_device,playing_buffer,fragment_size);
247 /* if no sounds playing, free device for other sound programs */
253 #else /* von '#ifdef VOXWARE' */
255 if (snd_ctrl.active && !snd_ctrl.loop)
257 struct timeval delay = { 0, 0 };
259 long sample_size, max_sample_size = SND_BLOCKSIZE;
260 long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
261 int wait_percent = 90; /* wait 90% of the real playing time */
264 if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
268 while(playing_sounds &&
269 select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
271 FD_SET(sound_pipe[0], &sound_fdset);
273 /* get pointer and size of the actual sound sample */
274 sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
276 MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
277 snd_ctrl.playingpos += sample_size;
279 /* fill the first mixing buffer with original sample */
280 memcpy(premix_first_buffer,sample_ptr,sample_size);
283 /* adjust volume of actual sound sample */
284 if (snd_ctrl.volume != PSND_MAX_VOLUME)
285 for(i=0;i<sample_size;i++)
286 premix_first_buffer[i] =
287 (snd_ctrl.volume * (int)premix_first_buffer[i])
288 >> PSND_MAX_VOLUME_BITS;
290 for(i=0;i<sample_size;i++)
292 linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
294 if (snd_ctrl.playingpos >= snd_ctrl.data_len)
297 /* finally play the sound fragment */
298 write(sound_device,playing_buffer,sample_size);
301 delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
307 #endif /* von '#ifdef VOXWARE' */
313 void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
317 /* wenn voll, ältesten Sound 'rauswerfen */
318 if (playing_sounds==MAX_SOUNDS_PLAYING)
320 int longest=0, longest_nr=0;
322 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
325 int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
327 int actual = playlist[i].playingpos;
330 if (!playlist[i].loop && actual>longest)
337 voice_set_volume(playlist[longest_nr].voice, 0);
338 deallocate_voice(playlist[longest_nr].voice);
340 playlist[longest_nr] = emptySoundControl;
344 /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
345 for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
347 if (playlist[i].nr == snd_ctrl.nr)
351 /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
352 if (k>=1 && snd_ctrl.loop)
354 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
356 if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
358 playlist[i].fade_sound = FALSE;
359 playlist[i].volume = PSND_MAX_VOLUME;
361 playlist[i].loop = PSND_LOOP;
362 voice_stop_volumeramp(playlist[i].voice);
363 voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
370 /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
373 int longest=0, longest_nr=0;
375 /* den bereits am längsten gespielten (gleichen) Sound suchen */
376 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
380 if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
384 actual = 100 * playlist[i].playingpos / playlist[i].data_len;
386 actual = playlist[i].playingpos;
395 voice_set_volume(playlist[longest_nr].voice, 0);
396 deallocate_voice(playlist[longest_nr].voice);
398 playlist[longest_nr] = emptySoundControl;
402 /* neuen Sound in Liste packen */
403 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
405 if (!playlist[i].active)
407 playlist[i] = snd_ctrl;
410 playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
412 voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
413 voice_set_volume(playlist[i].voice, snd_ctrl.volume);
414 voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
415 voice_start(playlist[i].voice);
423 void SoundServer_FadeSound(int nr)
430 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
431 if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
432 playlist[i].fade_sound = TRUE;
436 void SoundServer_StopSound(int nr)
443 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
444 if (playlist[i].nr == nr)
447 voice_set_volume(playlist[i].voice, 0);
448 deallocate_voice(playlist[i].voice);
450 playlist[i] = emptySoundControl;
460 void SoundServer_StopAllSounds()
464 for(i=0;i<MAX_SOUNDS_PLAYING;i++)
467 voice_set_volume(playlist[i].voice, 0);
468 deallocate_voice(playlist[i].voice);
470 playlist[i]=emptySoundControl;
480 void HPUX_Audio_Control()
482 struct audio_describe ainfo;
485 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
488 fprintf(stderr,"%s: cannot open /dev/audioCtl - no sounds\n",progname);
492 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
494 fprintf(stderr,"%s: no audio info - no sounds\n",progname);
498 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
500 fprintf(stderr,"%s: ulaw audio not available - no sounds\n",progname);
504 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
505 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
509 #endif /* HPUX_AUDIO */
511 /* these two are stolen from "sox"... :) */
514 ** This routine converts from linear to ulaw.
516 ** Craig Reese: IDA/Supercomputing Research Center
517 ** Joe Campbell: Department of Defense
521 ** 1) CCITT Recommendation G.711 (very difficult to follow)
522 ** 2) "A New Digital Technique for Implementation of Any
523 ** Continuous PCM Companding Law," Villeret, Michel,
524 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
525 ** 1973, pg. 11.12-11.17
526 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
527 ** for Analog-to_Digital Conversion Techniques,"
530 ** Input: Signed 16 bit linear sample
531 ** Output: 8 bit ulaw sample
534 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
535 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
538 unsigned char linear_to_ulaw(int sample)
540 static int exp_lut[256] =
542 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
543 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
544 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
545 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
546 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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
560 int sign, exponent, mantissa;
561 unsigned char ulawbyte;
563 /* Get the sample into sign-magnitude. */
564 sign = (sample >> 8) & 0x80; /* set aside the sign */
566 sample = -sample; /* get magnitude */
568 sample = CLIP; /* clip the magnitude */
570 /* Convert from 16 bit linear to ulaw. */
571 sample = sample + BIAS;
572 exponent = exp_lut[( sample >> 7 ) & 0xFF];
573 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
574 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
577 ulawbyte = 0x02; /* optional CCITT trap */
584 ** This routine converts from ulaw to 16 bit linear.
586 ** Craig Reese: IDA/Supercomputing Research Center
590 ** 1) CCITT Recommendation G.711 (very difficult to follow)
591 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
592 ** for Analog-to_Digital Conversion Techniques,"
595 ** Input: 8 bit ulaw sample
596 ** Output: signed 16 bit linear sample
599 int ulaw_to_linear(unsigned char ulawbyte)
601 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
602 int sign, exponent, mantissa, sample;
604 ulawbyte = ~ ulawbyte;
605 sign = ( ulawbyte & 0x80 );
606 exponent = ( ulawbyte >> 4 ) & 0x07;
607 mantissa = ulawbyte & 0x0F;
608 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
615 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
617 /*===========================================================================*/
619 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
621 static unsigned long be2long(unsigned long *be) /* big-endian -> longword */
623 unsigned char *ptr = (unsigned char *)be;
625 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
628 BOOL LoadSound(struct SoundInfo *snd_info)
633 char *sound_ext = "8svx";
635 char *sound_ext = "wav";
637 struct SoundHeader_8SVX *sound_header;
640 sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
643 if (!(file=fopen(filename,"r")))
645 fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
650 if (fseek(file,0,SEEK_END)<0)
652 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
658 snd_info->file_len = ftell(file);
661 if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
663 fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
669 if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
671 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
679 sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr;
681 if (strncmp(sound_header->magic_FORM,"FORM",4) ||
682 snd_info->file_len != be2long(&sound_header->chunk_size)+8 ||
683 strncmp(sound_header->magic_8SVX,"8SVX",4))
685 fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
690 ptr = snd_info->file_ptr + 12;
692 while(ptr < (unsigned char *)(snd_info->file_ptr + snd_info->file_len))
694 if (!strncmp(ptr,"VHDR",4))
696 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
699 else if (!strncmp(ptr,"ANNO",4))
701 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
704 else if (!strncmp(ptr,"CHAN",4))
706 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
709 else if (!strncmp(ptr,"BODY",4))
711 snd_info->data_ptr = ptr + 8;
712 snd_info->data_len = be2long((unsigned long *)(ptr + 4));
717 /* other chunk not recognized here */
718 ptr += be2long((unsigned long *)(ptr + 4)) + 8;
725 snd_info->sample_ptr = load_sample(filename);
726 if(!snd_info->sample_ptr)
728 fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
734 #endif // von #ifndef MSDOS
737 void PlaySound(int nr)
739 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
742 void PlaySoundStereo(int nr, int stereo)
744 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
747 void PlaySoundLoop(int nr)
749 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
752 void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
754 struct SoundControl snd_ctrl = emptySoundControl;
756 if (sound_status==SOUND_OFF || !sound_on)
759 if (volume<PSND_MIN_VOLUME)
760 volume = PSND_MIN_VOLUME;
761 else if (volume>PSND_MAX_VOLUME)
762 volume = PSND_MAX_VOLUME;
764 if (stereo<PSND_MAX_LEFT)
765 stereo = PSND_MAX_LEFT;
766 else if (stereo>PSND_MAX_RIGHT)
767 stereo = PSND_MAX_RIGHT;
770 snd_ctrl.volume = volume;
771 snd_ctrl.stereo = stereo;
772 snd_ctrl.loop = loop;
773 snd_ctrl.active = TRUE;
774 snd_ctrl.data_ptr = Sound[nr].data_ptr;
775 snd_ctrl.data_len = Sound[nr].data_len;
778 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
780 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
781 sound_status=SOUND_OFF;
785 sound_handler(snd_ctrl);
789 void FadeSound(int nr)
791 StopSoundExt(nr, SSND_FADE_SOUND);
796 StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
799 void StopSound(int nr)
801 StopSoundExt(nr, SSND_STOP_SOUND);
806 StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
809 void StopSoundExt(int nr, int method)
811 struct SoundControl snd_ctrl = emptySoundControl;
813 if (sound_status==SOUND_OFF)
816 if (SSND_FADING(method))
817 snd_ctrl.fade_sound = TRUE;
819 if (SSND_ALL(method))
820 snd_ctrl.stop_all_sounds = TRUE;
824 snd_ctrl.stop_sound = TRUE;
828 if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
830 fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
831 sound_status=SOUND_OFF;
835 sound_handler(snd_ctrl);
839 void FreeSounds(int max)
843 if (sound_status==SOUND_OFF)
848 free(Sound[i].file_ptr);
850 destroy_sample(Sound[i].sample_ptr);
854 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/