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