rnd-19990216-1
[rocksndiamonds.git] / src / sound.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  sound.c                                                 *
12 ***********************************************************/
13
14 #include "sound.h"
15 #include "misc.h"
16
17 /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
18
19 static int playing_sounds = 0;
20 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
21 static struct SoundControl emptySoundControl =
22 {
23   -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
24 };
25
26 #ifndef MSDOS
27 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
28 static char premix_first_buffer[SND_BLOCKSIZE];
29 #ifdef VOXWARE
30 static char premix_left_buffer[SND_BLOCKSIZE];
31 static char premix_right_buffer[SND_BLOCKSIZE];
32 static int premix_last_buffer[SND_BLOCKSIZE];
33 #endif /* VOXWARE */
34 static unsigned char playing_buffer[SND_BLOCKSIZE];
35 #endif /* MSDOS */
36
37 /* forward declaration of internal functions */
38 #ifdef VOXWARE
39 static void SoundServer_InsertNewSound(struct SoundControl);
40 #endif
41 #ifndef VOXWARE
42 #ifndef MSDOS
43 static unsigned char linear_to_ulaw(int);
44 static int ulaw_to_linear(unsigned char);
45 #endif
46 #endif
47 #ifdef HPUX_AUDIO
48 static void HPUX_Audio_Control();
49 #endif
50 #ifdef MSDOS
51 static void SoundServer_InsertNewSound(struct SoundControl);
52 static void SoundServer_StopSound(int);
53 static void SoundServer_StopAllSounds();
54 #endif
55
56 void SoundServer()
57 {
58   int i;
59 #ifndef MSDOS
60   struct SoundControl snd_ctrl;
61   fd_set sound_fdset;
62
63   close(sound_pipe[1]);         /* no writing into pipe needed */
64 #endif
65
66   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
67     playlist[i] = emptySoundControl;
68   playing_sounds = 0;
69
70 #ifndef MSDOS
71   stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
72   for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
73     stereo_volume[i] =
74       (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
75
76 #ifdef HPUX_AUDIO
77   HPUX_Audio_Control();
78 #endif
79
80   FD_ZERO(&sound_fdset); 
81   FD_SET(sound_pipe[0], &sound_fdset);
82
83   while(1)      /* wait for sound playing commands from client */
84   {
85     FD_SET(sound_pipe[0], &sound_fdset);
86     select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
87     if (!FD_ISSET(sound_pipe[0], &sound_fdset))
88       continue;
89     if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
90       Error(ERR_EXIT_SOUND_SERVER, "broken pipe - no sounds");
91
92 #ifdef VOXWARE
93
94     if (snd_ctrl.fade_sound)
95     {
96       if (!playing_sounds)
97         continue;
98
99       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
100         if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
101           playlist[i].fade_sound = TRUE;
102     }
103     else if (snd_ctrl.stop_all_sounds)
104     {
105       if (!playing_sounds)
106         continue;
107
108       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
109         playlist[i]=emptySoundControl;
110       playing_sounds=0;
111
112       close(sound_device);
113     }
114     else if (snd_ctrl.stop_sound)
115     {
116       if (!playing_sounds)
117         continue;
118
119       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
120         if (playlist[i].nr == snd_ctrl.nr)
121         {
122           playlist[i]=emptySoundControl;
123           playing_sounds--;
124         }
125
126       if (!playing_sounds)
127         close(sound_device);
128     }
129
130     if (playing_sounds || snd_ctrl.active)
131     {
132       struct timeval delay = { 0, 0 };
133       byte *sample_ptr;
134       long sample_size;
135       static long max_sample_size = 0;
136       static long fragment_size = 0;
137       /* Even if the stereo flag is used as being boolean, it must be
138          defined as an integer, else 'ioctl()' will fail! */
139       int stereo = TRUE;
140       int sample_rate = 8000;
141
142       if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
143       {
144         if (!playing_sounds)    /* we just opened the audio device */
145         {
146           /* 2 buffers / 512 bytes, giving 1/16 second resolution */
147           /* (with stereo the effective buffer size will shrink to 256) */
148           fragment_size = 0x00020009;
149
150           if (ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size) < 0)
151             Error(ERR_EXIT_SOUND_SERVER,
152                   "cannot set fragment size of /dev/dsp - no sounds");
153
154           /* try if we can use stereo sound */
155           if (ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo) < 0)
156           {
157 #ifdef DEBUG
158             static boolean reported = FALSE;
159
160             if (!reported)
161             {
162               Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
163               reported = TRUE;
164             }
165 #endif
166             stereo = FALSE;
167           }
168
169           if (ioctl(sound_device, SNDCTL_DSP_SPEED, &sample_rate) < 0)
170             Error(ERR_EXIT_SOUND_SERVER,
171                   "cannot set sample rate of /dev/dsp - no sounds");
172
173           /* get the real fragmentation size; this should return 512 */
174           if (ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
175             Error(ERR_EXIT_SOUND_SERVER,
176                   "cannot get fragment size of /dev/dsp - no sounds");
177
178           max_sample_size = fragment_size / (stereo ? 2 : 1);
179         }
180
181         if (snd_ctrl.active)    /* new sound has arrived */
182           SoundServer_InsertNewSound(snd_ctrl);
183
184         while(playing_sounds &&
185               select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
186         {       
187           FD_SET(sound_pipe[0], &sound_fdset);
188
189           /* first clear the last premixing buffer */
190           memset(premix_last_buffer,0,fragment_size*sizeof(int));
191
192           for(i=0;i<MAX_SOUNDS_PLAYING;i++)
193           {
194             int j;
195
196             if (!playlist[i].active)
197               continue;
198
199             /* get pointer and size of the actual sound sample */
200             sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
201             sample_size =
202               MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
203             playlist[i].playingpos += sample_size;
204
205             /* fill the first mixing buffer with original sample */
206             memcpy(premix_first_buffer,sample_ptr,sample_size);
207
208             /* are we about to restart a looping sound? */
209             if (playlist[i].loop && sample_size<max_sample_size)
210             {
211               playlist[i].playingpos = max_sample_size-sample_size;
212               memcpy(premix_first_buffer+sample_size,
213                      playlist[i].data_ptr,max_sample_size-sample_size);
214               sample_size = max_sample_size;
215             }
216
217             /* decrease volume if sound is fading out */
218             if (playlist[i].fade_sound &&
219                 playlist[i].volume>=PSND_MAX_VOLUME/10)
220               playlist[i].volume-=PSND_MAX_VOLUME/20;
221
222             /* adjust volume of actual sound sample */
223             if (playlist[i].volume != PSND_MAX_VOLUME)
224               for(j=0;j<sample_size;j++)
225                 premix_first_buffer[j] =
226                   (playlist[i].volume * (int)premix_first_buffer[j])
227                     >> PSND_MAX_VOLUME_BITS;
228
229             /* fill the last mixing buffer with stereo or mono sound */
230             if (stereo)
231             {
232               int middle_pos = PSND_MAX_LEFT2RIGHT/2;
233               int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
234               int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
235
236               for(j=0;j<sample_size;j++)
237               {
238                 premix_left_buffer[j] =
239                   (left_volume * (int)premix_first_buffer[j])
240                     >> PSND_MAX_LEFT2RIGHT_BITS;
241                 premix_right_buffer[j] =
242                   (right_volume * (int)premix_first_buffer[j])
243                     >> PSND_MAX_LEFT2RIGHT_BITS;
244                 premix_last_buffer[2*j+0] += premix_left_buffer[j];
245                 premix_last_buffer[2*j+1] += premix_right_buffer[j];
246               }
247             }
248             else
249             {
250               for(j=0;j<sample_size;j++)
251                 premix_last_buffer[j] += (int)premix_first_buffer[j];
252             }
253
254             /* delete completed sound entries from the playlist */
255             if (playlist[i].playingpos >= playlist[i].data_len)
256             {
257               if (playlist[i].loop)
258                 playlist[i].playingpos = 0;
259               else
260               {
261                 playlist[i] = emptySoundControl;
262                 playing_sounds--;
263               }
264             }
265             else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
266             {
267               playlist[i] = emptySoundControl;
268               playing_sounds--;
269             }
270           }
271
272           /* put last mixing buffer to final playing buffer */
273           for(i=0;i<fragment_size;i++)
274           {
275             if (premix_last_buffer[i]<-255)
276               playing_buffer[i] = 0;
277             else if (premix_last_buffer[i]>255)
278               playing_buffer[i] = 255;
279             else
280               playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
281           }
282
283           /* finally play the sound fragment */
284           write(sound_device,playing_buffer,fragment_size);
285         }
286
287         /* if no sounds playing, free device for other sound programs */
288         if (!playing_sounds)
289           close(sound_device);
290       }
291     }
292
293 #else /* !VOXWARE */
294
295     if (snd_ctrl.active && !snd_ctrl.loop)
296     {
297       struct timeval delay = { 0, 0 };
298       byte *sample_ptr;
299       long sample_size, max_sample_size = SND_BLOCKSIZE;
300       long sample_rate = 8000;  /* standard "/dev/audio" sampling rate */
301       int wait_percent = 90;    /* wait 90% of the real playing time */
302       int i;
303
304       if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
305       {
306         playing_sounds = 1;
307
308         while(playing_sounds &&
309               select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
310         {       
311           FD_SET(sound_pipe[0], &sound_fdset);
312
313           /* get pointer and size of the actual sound sample */
314           sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
315           sample_size =
316             MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
317           snd_ctrl.playingpos += sample_size;
318
319           /* fill the first mixing buffer with original sample */
320           memcpy(premix_first_buffer,sample_ptr,sample_size);
321
322
323           /* adjust volume of actual sound sample */
324           if (snd_ctrl.volume != PSND_MAX_VOLUME)
325             for(i=0;i<sample_size;i++)
326               premix_first_buffer[i] =
327                 (snd_ctrl.volume * (int)premix_first_buffer[i])
328                   >> PSND_MAX_VOLUME_BITS;
329
330           for(i=0;i<sample_size;i++)
331             playing_buffer[i] =
332               linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
333
334           if (snd_ctrl.playingpos >= snd_ctrl.data_len)
335             playing_sounds = 0;
336
337           /* finally play the sound fragment */
338           write(sound_device,playing_buffer,sample_size);
339
340           delay.tv_sec = 0;
341           delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
342         }
343         close(sound_device);
344       }
345     }
346
347 #endif /* !VOXWARE */
348
349   }
350 #endif /* !MSDOS */
351 }
352
353 #ifdef MSDOS
354 static void sound_handler(struct SoundControl snd_ctrl)
355 {
356   int i;
357
358   if (snd_ctrl.fade_sound)
359   {
360     if (!playing_sounds)
361       return;
362
363     for (i=0; i<MAX_SOUNDS_PLAYING; i++)
364       if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
365           !playlist[i].fade_sound)
366       {
367         playlist[i].fade_sound = TRUE;
368         if (voice_check(playlist[i].voice))
369           voice_ramp_volume(playlist[i].voice, 1000, 0);
370         playlist[i].loop = PSND_NO_LOOP;
371       }
372   }
373   else if (snd_ctrl.stop_all_sounds)
374   {
375     if (!playing_sounds)
376       return;
377     SoundServer_StopAllSounds();
378   }
379   else if (snd_ctrl.stop_sound)
380   {
381     if (!playing_sounds)
382       return;
383     SoundServer_StopSound(snd_ctrl.nr);
384   }
385
386   for (i=0; i<MAX_SOUNDS_PLAYING; i++)
387   {
388     if (!playlist[i].active || playlist[i].loop)
389       continue;
390
391     playlist[i].playingpos = voice_get_position(playlist[i].voice);
392     playlist[i].volume = voice_get_volume(playlist[i].voice);
393     if (playlist[i].playingpos == -1 || !playlist[i].volume)
394     {
395       deallocate_voice(playlist[i].voice);
396       playlist[i] = emptySoundControl;
397       playing_sounds--;
398     }
399   }
400
401   if (snd_ctrl.active)
402     SoundServer_InsertNewSound(snd_ctrl);
403 }
404 #endif /* MSDOS */
405
406 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
407 {
408   int i, k;
409
410   /* if playlist is full, remove oldest sound */
411   if (playing_sounds==MAX_SOUNDS_PLAYING)
412   {
413     int longest=0, longest_nr=0;
414
415     for(i=0;i<MAX_SOUNDS_PLAYING;i++)
416     {
417 #ifndef MSDOS
418       int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
419 #else
420       int actual = playlist[i].playingpos;
421 #endif
422
423       if (!playlist[i].loop && actual>longest)
424       {
425         longest=actual;
426         longest_nr=i;
427       }
428     }
429 #ifdef MSDOS
430     voice_set_volume(playlist[longest_nr].voice, 0);
431     deallocate_voice(playlist[longest_nr].voice);
432 #endif
433     playlist[longest_nr] = emptySoundControl;
434     playing_sounds--;
435   }
436
437   /* check if sound is already being played (and how often) */
438   for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
439   {
440     if (playlist[i].nr == snd_ctrl.nr)
441       k++;
442   }
443
444   /* restart loop sounds only if they are just fading out */
445   if (k>=1 && snd_ctrl.loop)
446   {
447     for(i=0;i<MAX_SOUNDS_PLAYING;i++)
448     {
449       if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
450       {
451         playlist[i].fade_sound = FALSE;
452         playlist[i].volume = PSND_MAX_VOLUME;
453 #ifdef MSDOS
454         playlist[i].loop = PSND_LOOP;
455         voice_stop_volumeramp(playlist[i].voice);
456         voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
457 #endif
458       }
459     }
460     return;
461   }
462
463   /* don't play sound more than n times simultaneously (with n == 2 for now) */
464   if (k>=2)
465   {
466     int longest=0, longest_nr=0;
467
468     /* look for oldest equal sound */
469     for(i=0;i<MAX_SOUNDS_PLAYING;i++)
470     {
471       int actual;
472
473       if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
474         continue;
475
476 #ifndef MSDOS
477       actual = 100 * playlist[i].playingpos / playlist[i].data_len;
478 #else
479       actual = playlist[i].playingpos;
480 #endif
481       if (actual>=longest)
482       {
483         longest=actual;
484         longest_nr=i;
485       }
486     }
487 #ifdef MSDOS
488     voice_set_volume(playlist[longest_nr].voice, 0);
489     deallocate_voice(playlist[longest_nr].voice);
490 #endif
491     playlist[longest_nr] = emptySoundControl;
492     playing_sounds--;
493   }
494
495   /* neuen Sound in Liste packen */
496   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
497   {
498     if (!playlist[i].active)
499     {
500       playlist[i] = snd_ctrl;
501       playing_sounds++;
502 #ifdef MSDOS
503       playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
504       if(snd_ctrl.loop)
505         voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
506       voice_set_volume(playlist[i].voice, snd_ctrl.volume);
507       voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
508       voice_start(playlist[i].voice);       
509 #endif
510       break;
511     }
512   }
513 }
514
515 /*
516 void SoundServer_FadeSound(int nr)
517 {
518   int i;
519
520   if (!playing_sounds)
521     return;
522
523   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
524     if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
525       playlist[i].fade_sound = TRUE;
526 }
527 */
528
529 #ifdef MSDOS
530 static void SoundServer_StopSound(int nr)
531 {
532   int i;
533
534   if (!playing_sounds)
535     return;
536
537   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
538     if (playlist[i].nr == nr)
539     {
540 #ifdef MSDOS
541       voice_set_volume(playlist[i].voice, 0);
542       deallocate_voice(playlist[i].voice);
543 #endif
544       playlist[i] = emptySoundControl;
545       playing_sounds--;
546     }
547
548 #ifndef MSDOS
549   if (!playing_sounds)
550     close(sound_device);
551 #endif
552 }
553
554 static void SoundServer_StopAllSounds()
555 {
556   int i;
557
558   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
559   {
560 #ifdef MSDOS
561     voice_set_volume(playlist[i].voice, 0);
562     deallocate_voice(playlist[i].voice);
563 #endif
564     playlist[i]=emptySoundControl;
565   }
566   playing_sounds = 0;
567
568 #ifndef MSDOS
569   close(sound_device);
570 #endif
571 }
572 #endif /* MSDOS */
573
574 #ifdef HPUX_AUDIO
575 static void HPUX_Audio_Control()
576 {
577   struct audio_describe ainfo;
578   int audio_ctl;
579
580   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
581   if (audio_ctl == -1)
582     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl - no sounds");
583
584   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
585     Error(ERR_EXIT_SOUND_SERVER, "no audio info - no sounds");
586
587   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
588     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available - no sounds");
589
590   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
591   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
592
593   close(audio_ctl);
594 }
595 #endif /* HPUX_AUDIO */
596
597 #ifndef VOXWARE
598 #ifndef MSDOS
599 /* these two are stolen from "sox"... :) */
600
601 /*
602 ** This routine converts from linear to ulaw.
603 **
604 ** Craig Reese: IDA/Supercomputing Research Center
605 ** Joe Campbell: Department of Defense
606 ** 29 September 1989
607 **
608 ** References:
609 ** 1) CCITT Recommendation G.711  (very difficult to follow)
610 ** 2) "A New Digital Technique for Implementation of Any
611 **     Continuous PCM Companding Law," Villeret, Michel,
612 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
613 **     1973, pg. 11.12-11.17
614 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
615 **     for Analog-to_Digital Conversion Techniques,"
616 **     17 February 1987
617 **
618 ** Input: Signed 16 bit linear sample
619 ** Output: 8 bit ulaw sample
620 */
621
622 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
623 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
624 #define CLIP 32635
625
626 static unsigned char linear_to_ulaw(int sample)
627 {
628   static int exp_lut[256] =
629   {
630     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
631     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
632     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
633     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
634     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
635     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
636     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
637     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
638     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
639     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
640     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
641     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
642     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
643     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
644     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
645     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
646   };
647
648   int sign, exponent, mantissa;
649   unsigned char ulawbyte;
650
651   /* Get the sample into sign-magnitude. */
652   sign = (sample >> 8) & 0x80;          /* set aside the sign */
653   if (sign != 0)
654     sample = -sample;                   /* get magnitude */
655   if (sample > CLIP)
656     sample = CLIP;                      /* clip the magnitude */
657
658   /* Convert from 16 bit linear to ulaw. */
659   sample = sample + BIAS;
660   exponent = exp_lut[( sample >> 7 ) & 0xFF];
661   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
662   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
663 #ifdef ZEROTRAP
664   if (ulawbyte == 0)
665     ulawbyte = 0x02;                    /* optional CCITT trap */
666 #endif
667
668   return(ulawbyte);
669 }
670
671 /*
672 ** This routine converts from ulaw to 16 bit linear.
673 **
674 ** Craig Reese: IDA/Supercomputing Research Center
675 ** 29 September 1989
676 **
677 ** References:
678 ** 1) CCITT Recommendation G.711  (very difficult to follow)
679 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
680 **     for Analog-to_Digital Conversion Techniques,"
681 **     17 February 1987
682 **
683 ** Input: 8 bit ulaw sample
684 ** Output: signed 16 bit linear sample
685 */
686
687 static int ulaw_to_linear(unsigned char ulawbyte)
688 {
689   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
690   int sign, exponent, mantissa, sample;
691
692   ulawbyte = ~ ulawbyte;
693   sign = ( ulawbyte & 0x80 );
694   exponent = ( ulawbyte >> 4 ) & 0x07;
695   mantissa = ulawbyte & 0x0F;
696   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
697   if (sign != 0)
698     sample = -sample;
699
700   return(sample);
701 }
702 #endif /* !MSDOS */
703 #endif /* !VOXWARE */
704
705 /*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
706
707 /*===========================================================================*/
708
709 /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
710
711 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
712 #define WAV_HEADER_SIZE         20      /* size of WAV file header */
713
714 boolean LoadSound(struct SoundInfo *snd_info)
715 {
716   char filename[256];
717   char *sound_ext = "wav";
718 #ifndef MSDOS
719   byte sound_header_buffer[WAV_HEADER_SIZE];
720   char chunk[CHUNK_ID_LEN + 1];
721   int chunk_length, dummy;
722   FILE *file;
723   int i;
724 #endif
725
726   sprintf(filename, "%s/%s/%s.%s",
727           options.base_directory, SOUNDS_DIRECTORY, snd_info->name, sound_ext);
728
729 #ifndef MSDOS
730
731   if ((file = fopen(filename, "r")) == NULL)
732   {
733     Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename);
734     return FALSE;
735   }
736
737   /* read chunk "RIFF" */
738   getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
739   if (strcmp(chunk, "RIFF") != 0)
740   {
741     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
742     fclose(file);
743     return FALSE;
744   }
745
746   /* read chunk "WAVE" */
747   getFileChunk(file, chunk, &dummy, BYTE_ORDER_LITTLE_ENDIAN);
748   if (strcmp(chunk, "WAVE") != 0)
749   {
750     Error(ERR_WARN, "missing 'WAVE' chunk of sound file '%s'", filename);
751     fclose(file);
752     return FALSE;
753   }
754
755   /* read header information */
756   for (i=0; i<WAV_HEADER_SIZE; i++)
757     sound_header_buffer[i] = fgetc(file);
758
759   /* read chunk "data" */
760   getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_LITTLE_ENDIAN);
761   if (strcmp(chunk, "data") != 0)
762   {
763     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
764     fclose(file);
765     return FALSE;
766   }
767
768   snd_info->data_len = chunk_length;
769   snd_info->data_ptr = checked_malloc(snd_info->data_len);
770
771   /* read sound data */
772   if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
773       snd_info->data_len)
774   {
775     Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
776     fclose(file);
777     return FALSE;
778   }
779
780   fclose(file);
781
782   for (i=0; i<snd_info->data_len; i++)
783     snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
784
785 #else /* MSDOS */
786
787   snd_info->sample_ptr = load_sample(filename);
788   if (!snd_info->sample_ptr)
789   {
790     Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename);
791     return(FALSE);
792   }
793
794 #endif /* MSDOS */
795
796   return(TRUE);
797 }
798
799 void PlaySound(int nr)
800 {
801   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
802 }
803
804 void PlaySoundStereo(int nr, int stereo)
805 {
806   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
807 }
808
809 void PlaySoundLoop(int nr)
810 {
811   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
812 }
813
814 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
815 {
816   struct SoundControl snd_ctrl = emptySoundControl;
817
818   if (sound_status==SOUND_OFF || !setup.sound)
819     return;
820
821   if (volume<PSND_MIN_VOLUME)
822     volume = PSND_MIN_VOLUME;
823   else if (volume>PSND_MAX_VOLUME)
824     volume = PSND_MAX_VOLUME;
825
826   if (stereo<PSND_MAX_LEFT)
827     stereo = PSND_MAX_LEFT;
828   else if (stereo>PSND_MAX_RIGHT)
829     stereo = PSND_MAX_RIGHT;
830
831   snd_ctrl.nr           = nr;
832   snd_ctrl.volume       = volume;
833   snd_ctrl.stereo       = stereo;
834   snd_ctrl.loop         = loop;
835   snd_ctrl.active       = TRUE;
836   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
837   snd_ctrl.data_len     = Sound[nr].data_len;
838
839 #ifndef MSDOS
840   if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
841   {
842     Error(ERR_WARN, "cannot pipe to child process - no sounds");
843     sound_status = SOUND_OFF;
844     return;
845   }
846 #else
847   sound_handler(snd_ctrl);
848 #endif
849 }
850
851 void FadeSound(int nr)
852 {
853   StopSoundExt(nr, SSND_FADE_SOUND);
854 }
855
856 void FadeSounds()
857 {
858   StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
859 }
860
861 void StopSound(int nr)
862 {
863   StopSoundExt(nr, SSND_STOP_SOUND);
864 }
865
866 void StopSounds()
867 {
868   StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
869 }
870
871 void StopSoundExt(int nr, int method)
872 {
873   struct SoundControl snd_ctrl = emptySoundControl;
874
875   if (sound_status==SOUND_OFF)
876     return;
877
878   if (SSND_FADING(method))
879     snd_ctrl.fade_sound = TRUE;
880
881   if (SSND_ALL(method))
882     snd_ctrl.stop_all_sounds = TRUE;
883   else
884   {
885     snd_ctrl.nr = nr;
886     snd_ctrl.stop_sound = TRUE;
887   }
888
889 #ifndef MSDOS
890   if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
891   {
892     Error(ERR_WARN, "cannot pipe to child process - no sounds");
893     sound_status = SOUND_OFF;
894     return;
895   }
896 #else
897   sound_handler(snd_ctrl);
898 #endif
899 }
900
901 void FreeSounds(int num_sounds)
902 {
903   int i;
904
905   if (sound_status == SOUND_OFF)
906     return;
907
908   for(i=0; i<num_sounds; i++)
909 #ifndef MSDOS
910     free(Sound[i].data_ptr);
911 #else
912     destroy_sample(Sound[i].sample_ptr);
913 #endif
914 }
915
916 /*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/