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