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