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