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