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