rnd-20020508-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 struct ListNode
28 {
29   char *key;
30   void *content;
31   struct ListNode *next;
32 };
33 typedef struct ListNode ListNode;
34
35 static ListNode *newListNode(void);
36 static void addNodeToList(ListNode **, char *, void *);
37 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
38 static ListNode *getNodeFromKey(ListNode *, char *);
39 static int getNumNodes(ListNode *);
40
41
42 static struct SoundEffectInfo *sound_effect;
43 static ListNode *SoundFileList = NULL;
44 static SoundInfo **Sound = NULL;
45 static MusicInfo **Music = NULL;
46 static int num_sounds = 0, num_music = 0;
47
48
49 /* ========================================================================= */
50 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
51
52 static struct AudioFormatInfo afmt =
53 {
54   TRUE, 0, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_FRAGMENT_SIZE
55 };
56
57 static int playing_sounds = 0;
58 static struct SoundControl playlist[NUM_MIXER_CHANNELS];
59 static struct SoundControl emptySoundControl =
60 {
61   -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
62 };
63
64 #if defined(PLATFORM_UNIX)
65 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
66 static short premix_first_buffer[SND_BLOCKSIZE];
67 #if defined(AUDIO_STREAMING_DSP)
68 static short premix_left_buffer[SND_BLOCKSIZE];
69 static short premix_right_buffer[SND_BLOCKSIZE];
70 static long premix_last_buffer[SND_BLOCKSIZE];
71 #endif
72 static byte playing_buffer[SND_BLOCKSIZE];
73 #endif
74
75 /* forward declaration of internal functions */
76 #if defined(AUDIO_STREAMING_DSP)
77 static void SoundServer_InsertNewSound(struct SoundControl);
78 static void InitAudioDevice_DSP(struct AudioFormatInfo *);
79 #elif defined(PLATFORM_HPUX)
80 static void InitAudioDevice_HPUX(struct AudioFormatInfo *);
81 #elif defined(PLATFORM_UNIX)
82 static unsigned char linear_to_ulaw(int);
83 static int ulaw_to_linear(unsigned char);
84 #elif defined(PLATFORM_MSDOS)
85 static void SoundServer_InsertNewSound(struct SoundControl);
86 static void SoundServer_StopSound(struct SoundControl);
87 static void SoundServer_StopAllSounds();
88 #endif
89
90 static void ReloadCustomSounds();
91 static void ReloadCustomMusic();
92 static void FreeSound(void *);
93
94 #if defined(PLATFORM_UNIX)
95 static int OpenAudioDevice(char *audio_device_name)
96 {
97   int audio_fd;
98
99   /* check if desired audio device is accessible */
100   if (access(audio_device_name, W_OK) != 0)
101     return -1;
102
103   /* try to open audio device in non-blocking mode */
104   if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
105     return audio_fd;
106
107   /* re-open audio device in blocking mode */
108   close(audio_fd);
109   audio_fd = open(audio_device_name, O_WRONLY);
110
111   return audio_fd;
112 }
113
114 static boolean TestAudioDevices(void)
115 {
116   static char *audio_device_name[] =
117   {
118     DEVICENAME_DSP,
119     DEVICENAME_AUDIO
120   };
121   int audio_fd = -1;
122   int i;
123
124   /* look for available audio devices, starting with preferred ones */
125   for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
126     if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
127       break;
128
129   if (audio_fd < 0)
130   {
131     Error(ERR_WARN, "cannot open audio device -- no sound");
132     return FALSE;
133   }
134
135   close(audio_fd);
136
137   audio.device_name = audio_device_name[i];
138
139   return TRUE;
140 }
141
142 #if !defined(TARGET_SDL)
143 static boolean ForkAudioProcess(void)
144 {
145   if (pipe(audio.soundserver_pipe) < 0)
146   {
147     Error(ERR_WARN, "cannot create pipe -- no sounds");
148     return FALSE;
149   }
150
151   if ((audio.soundserver_pid = fork()) < 0)
152   {       
153     Error(ERR_WARN, "cannot create sound server process -- no sounds");
154     return FALSE;
155   }
156
157   if (audio.soundserver_pid == 0)       /* we are child process */
158   {
159     SoundServer();
160
161     /* never reached */
162     exit(0);
163   }
164   else                                  /* we are parent */
165     close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
166
167   return TRUE;
168 }
169 #endif
170
171 void UnixOpenAudio(void)
172 {
173   if (!TestAudioDevices())
174     return;
175
176   audio.sound_available = TRUE;
177   audio.sound_enabled = TRUE;
178
179 #if defined(AUDIO_STREAMING_DSP)
180   audio.music_available = TRUE;
181   audio.loops_available = TRUE;
182 #endif
183 }
184
185 void UnixCloseAudio(void)
186 {
187   if (audio.device_fd)
188     close(audio.device_fd);
189
190   if (audio.soundserver_pid > 0)        /* we are parent process */
191     kill(audio.soundserver_pid, SIGTERM);
192 }
193 #endif  /* PLATFORM_UNIX */
194
195 void InitPlaylist(void)
196 {
197   int i;
198
199   for(i=0; i<NUM_MIXER_CHANNELS; i++)
200     playlist[i] = emptySoundControl;
201   playing_sounds = 0;
202 }
203
204 #if 0
205 static void HandleSoundRequest(struct SoundControl snd_ctrl)
206 {
207   int i;
208
209   if (snd_ctrl.fade_sound)
210   {
211     if (!playing_sounds)
212       continue;
213
214     if (snd_ctrl.music)
215       playlist[audio.music_channel].fade_sound = TRUE;
216     else
217       for(i=0; i<NUM_MIXER_CHANNELS; i++)
218         if (snd_ctrl.stop_all_sounds ||
219             (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
220           playlist[i].fade_sound = TRUE;
221   }
222   else if (snd_ctrl.stop_all_sounds)
223   {
224     if (!playing_sounds)
225       continue;
226
227     for(i=0; i<NUM_MIXER_CHANNELS; i++)
228       playlist[i] = emptySoundControl;
229     playing_sounds = 0;
230
231     close(audio.device_fd);
232   }
233   else if (snd_ctrl.stop_sound)
234   {
235     if (!playing_sounds)
236       continue;
237
238     if (snd_ctrl.music)
239     {
240       playlist[audio.music_channel] = emptySoundControl;
241       playing_sounds--;
242     }
243
244     for(i=0; i<NUM_MIXER_CHANNELS; i++)
245     {
246       if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
247       {
248         playlist[i] = emptySoundControl;
249         playing_sounds--;
250       }
251     }
252
253     if (!playing_sounds)
254       close(audio.device_fd);
255   }
256 }
257 #endif
258
259 void StartSoundserver(void)
260 {
261   if (!audio.sound_available)
262     return;
263
264 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
265   if (!ForkAudioProcess())
266     audio.sound_available = FALSE;
267 #endif
268 }
269
270 #if defined(PLATFORM_UNIX)
271 void SoundServer(void)
272 {
273   int i;
274
275   struct SoundControl snd_ctrl;
276   fd_set sound_fdset;
277
278   close(audio.soundserver_pipe[1]);     /* no writing into pipe needed */
279
280   InitPlaylist();
281
282   stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
283   for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
284     stereo_volume[i] =
285       (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
286
287 #if defined(PLATFORM_HPUX)
288   InitAudioDevice_HPUX(&afmt);
289 #endif
290
291   FD_ZERO(&sound_fdset); 
292   FD_SET(audio.soundserver_pipe[0], &sound_fdset);
293
294   while(1)      /* wait for sound playing commands from client */
295   {
296     FD_SET(audio.soundserver_pipe[0], &sound_fdset);
297     select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
298     if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
299       continue;
300     if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
301         != sizeof(snd_ctrl))
302       Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
303
304     if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
305     {
306       char *set_name = checked_malloc(snd_ctrl.data_len);
307       TreeInfo **ti_ptr =
308         (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
309       TreeInfo *ti = *ti_ptr;
310       unsigned long str_size1, str_size2, str_size3;
311
312       if (leveldir_current == NULL)
313         leveldir_current = checked_calloc(sizeof(TreeInfo));
314       if (ti == NULL)
315         ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
316       if (leveldir_current->fullpath != NULL)
317         free(leveldir_current->fullpath);
318       if (ti->basepath != NULL)
319         free(ti->basepath);
320       if (ti->fullpath != NULL)
321         free(ti->fullpath);
322
323       if (read(audio.soundserver_pipe[0], set_name,
324                snd_ctrl.data_len) != snd_ctrl.data_len ||
325           read(audio.soundserver_pipe[0], leveldir_current,
326                sizeof(TreeInfo)) != sizeof(TreeInfo) ||
327           read(audio.soundserver_pipe[0], ti,
328                sizeof(TreeInfo)) != sizeof(TreeInfo) ||
329           read(audio.soundserver_pipe[0], &str_size1,
330                sizeof(unsigned long)) != sizeof(unsigned long) ||
331           read(audio.soundserver_pipe[0], &str_size2,
332                sizeof(unsigned long)) != sizeof(unsigned long) ||
333           read(audio.soundserver_pipe[0], &str_size3,
334                sizeof(unsigned long)) != sizeof(unsigned long))
335         Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
336
337       leveldir_current->fullpath = checked_calloc(str_size1);
338       ti->basepath = checked_calloc(str_size2);
339       ti->fullpath = checked_calloc(str_size3);
340
341       if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
342                str_size1) != str_size1 ||
343           read(audio.soundserver_pipe[0], ti->basepath,
344                str_size2) != str_size2 ||
345           read(audio.soundserver_pipe[0], ti->fullpath,
346                str_size3) != str_size3)
347         Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
348
349       InitPlaylist();
350
351       close(audio.device_fd);
352
353       if (snd_ctrl.reload_sounds)
354       {
355         artwork.sounds_set_current = set_name;
356         ReloadCustomSounds();
357       }
358       else
359       {
360         artwork.music_set_current = set_name;
361         ReloadCustomMusic();
362       }
363
364       free(set_name);
365
366       continue;
367     }
368
369 #if defined(AUDIO_STREAMING_DSP)
370
371 #if 0
372     HandleSoundRequest(snd_ctrl);
373 #else
374
375     if (snd_ctrl.fade_sound)
376     {
377       if (!playing_sounds)
378         continue;
379
380       if (snd_ctrl.music)
381         playlist[audio.music_channel].fade_sound = TRUE;
382       else
383         for(i=0; i<NUM_MIXER_CHANNELS; i++)
384           if (snd_ctrl.stop_all_sounds ||
385               (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
386             playlist[i].fade_sound = TRUE;
387     }
388     else if (snd_ctrl.stop_all_sounds)
389     {
390       if (!playing_sounds)
391         continue;
392
393       for(i=0; i<NUM_MIXER_CHANNELS; i++)
394         playlist[i] = emptySoundControl;
395       playing_sounds = 0;
396
397       close(audio.device_fd);
398     }
399     else if (snd_ctrl.stop_sound)
400     {
401       if (!playing_sounds)
402         continue;
403
404       if (snd_ctrl.music)
405       {
406         if (playlist[audio.music_channel].active)
407         {
408           playlist[audio.music_channel] = emptySoundControl;
409           playing_sounds--;
410         }
411       }
412
413       for(i=0; i<NUM_MIXER_CHANNELS; i++)
414       {
415         if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
416         {
417           playlist[i] = emptySoundControl;
418           playing_sounds--;
419         }
420       }
421
422       if (!playing_sounds)
423         close(audio.device_fd);
424     }
425 #endif
426
427     if (playing_sounds || snd_ctrl.active)
428     {
429       if (playing_sounds ||
430           (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
431       {
432         struct timeval delay = { 0, 0 };
433
434         if (!playing_sounds)    /* we just opened the audio device */
435           InitAudioDevice_DSP(&afmt);
436
437         if (snd_ctrl.active)    /* new sound has arrived */
438           SoundServer_InsertNewSound(snd_ctrl);
439
440         while (playing_sounds &&
441                select(audio.soundserver_pipe[0] + 1,
442                       &sound_fdset, NULL, NULL, &delay) < 1)
443         {       
444           int max_sample_size;
445           int fragment_size = afmt.fragment_size;
446           int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
447           boolean stereo = afmt.stereo;
448
449           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
450
451           max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
452
453           /* first clear the last premixing buffer */
454           memset(premix_last_buffer, 0,
455                  max_sample_size * (stereo ? 2 : 1) * sizeof(long));
456
457           for(i=0; i<NUM_MIXER_CHANNELS; i++)
458           {
459             void *sample_ptr;
460             int sample_len;
461             int sample_pos;
462             int sample_size;
463             int j;
464
465             if (!playlist[i].active)
466               continue;
467
468             /* pointer, lenght and actual playing position of sound sample */
469             sample_ptr = playlist[i].data_ptr;
470             sample_len = playlist[i].data_len;
471             sample_pos = playlist[i].playingpos;
472             sample_size = MIN(max_sample_size, sample_len - sample_pos);
473             playlist[i].playingpos += sample_size;
474
475             /* copy original sample to first mixing buffer */
476             if (playlist[i].format == AUDIO_FORMAT_U8)
477               for (j=0; j<sample_size; j++)
478                 premix_first_buffer[j] =
479                   ((short)(((byte *)sample_ptr)[sample_pos + j] ^ 0x80)) << 8;
480             else        /* AUDIO_FORMAT_S16 */
481               for (j=0; j<sample_size; j++)
482                 premix_first_buffer[j] =
483                   ((short *)sample_ptr)[sample_pos + j];
484
485             /* are we about to restart a looping sound? */
486             if (playlist[i].loop && sample_size < max_sample_size)
487             {
488               while (sample_size < max_sample_size)
489               {
490                 int restarted_sample_size =
491                   MIN(max_sample_size - sample_size, sample_len);
492
493                 if (playlist[i].format == AUDIO_FORMAT_U8)
494                   for (j=0; j<restarted_sample_size; j++)
495                     premix_first_buffer[sample_size + j] =
496                       ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
497                 else
498                   for (j=0; j<restarted_sample_size; j++)
499                     premix_first_buffer[sample_size + j] =
500                       ((short *)sample_ptr)[j];
501
502                 playlist[i].playingpos = restarted_sample_size;
503                 sample_size += restarted_sample_size;
504               }
505             }
506
507             /* decrease volume if sound is fading out */
508             if (playlist[i].fade_sound &&
509                 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
510               playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
511
512             /* adjust volume of actual sound sample */
513             if (playlist[i].volume != PSND_MAX_VOLUME)
514               for(j=0; j<sample_size; j++)
515                 premix_first_buffer[j] =
516                   (playlist[i].volume * (long)premix_first_buffer[j])
517                     >> PSND_MAX_VOLUME_BITS;
518
519             /* fill the last mixing buffer with stereo or mono sound */
520             if (stereo)
521             {
522               int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
523               int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
524               int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
525
526               for(j=0; j<sample_size; j++)
527               {
528                 premix_left_buffer[j] =
529                   (left_volume * premix_first_buffer[j])
530                     >> PSND_MAX_LEFT2RIGHT_BITS;
531                 premix_right_buffer[j] =
532                   (right_volume * premix_first_buffer[j])
533                     >> PSND_MAX_LEFT2RIGHT_BITS;
534
535                 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
536                 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
537               }
538             }
539             else
540             {
541               for(j=0; j<sample_size; j++)
542                 premix_last_buffer[j] += premix_first_buffer[j];
543             }
544
545             /* delete completed sound entries from the playlist */
546             if (playlist[i].playingpos >= playlist[i].data_len)
547             {
548               if (playlist[i].loop)
549                 playlist[i].playingpos = 0;
550               else
551               {
552                 playlist[i] = emptySoundControl;
553                 playing_sounds--;
554               }
555             }
556             else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
557             {
558               playlist[i] = emptySoundControl;
559               playing_sounds--;
560             }
561           }
562
563           /* prepare final playing buffer according to system audio format */
564           for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
565           {
566             /* cut off at 17 bit value */
567             if (premix_last_buffer[i] < -65535)
568               premix_last_buffer[i] = -65535;
569             else if (premix_last_buffer[i] > 65535)
570               premix_last_buffer[i] = 65535;
571
572             /* shift to 16 bit value */
573             premix_last_buffer[i] >>= 1;
574
575             if (afmt.format & AUDIO_FORMAT_U8)
576             {
577               playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
578             }
579             else if (afmt.format & AUDIO_FORMAT_LE)     /* 16 bit */
580             {
581               playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
582               playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
583             }
584             else                                        /* big endian */
585             {
586               playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
587               playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
588             }
589           }
590
591           /* finally play the sound fragment */
592           write(audio.device_fd, playing_buffer, fragment_size);
593         }
594
595         /* if no sounds playing, free device for other sound programs */
596         if (!playing_sounds)
597           close(audio.device_fd);
598       }
599     }
600
601 #else /* !AUDIO_STREAMING_DSP */
602
603     if (snd_ctrl.active && !snd_ctrl.loop)
604     {
605       struct timeval delay = { 0, 0 };
606       byte *sample_ptr;
607       long sample_size, max_sample_size = SND_BLOCKSIZE;
608       long sample_rate = 8000;  /* standard "/dev/audio" sampling rate */
609       int wait_percent = 90;    /* wait 90% of the real playing time */
610       int i;
611
612       if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
613       {
614         playing_sounds = 1;
615
616         while (playing_sounds &&
617                select(audio.soundserver_pipe[0] + 1,
618                       &sound_fdset, NULL, NULL, &delay) < 1)
619         {       
620           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
621
622           /* get pointer and size of the actual sound sample */
623           sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
624           sample_size =
625             MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
626           snd_ctrl.playingpos += sample_size;
627
628           /* fill the first mixing buffer with original sample */
629           memcpy(premix_first_buffer,sample_ptr,sample_size);
630
631           /* adjust volume of actual sound sample */
632           if (snd_ctrl.volume != PSND_MAX_VOLUME)
633             for(i=0;i<sample_size;i++)
634               premix_first_buffer[i] =
635                 (snd_ctrl.volume * (int)premix_first_buffer[i])
636                   >> PSND_MAX_VOLUME_BITS;
637
638           for(i=0;i<sample_size;i++)
639             playing_buffer[i] =
640               linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
641
642           if (snd_ctrl.playingpos >= snd_ctrl.data_len)
643             playing_sounds = 0;
644
645           /* finally play the sound fragment */
646           write(audio.device_fd,playing_buffer,sample_size);
647
648           delay.tv_sec = 0;
649           delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
650         }
651         close(audio.device_fd);
652       }
653     }
654 #endif /* !AUDIO_STREAMING_DSP */
655   }
656 }
657 #endif /* PLATFORM_UNIX */
658
659 #if defined(PLATFORM_MSDOS)
660 static void sound_handler(struct SoundControl snd_ctrl)
661 {
662   int i;
663
664   if (snd_ctrl.fade_sound)
665   {
666     if (!playing_sounds)
667       return;
668
669     for (i=0; i<NUM_MIXER_CHANNELS; i++)
670       if ((snd_ctrl.stop_all_sounds ||
671            (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
672            (i == audio.music_channel && snd_ctrl.music)) &&
673           !playlist[i].fade_sound)
674       {
675         playlist[i].fade_sound = TRUE;
676         if (voice_check(playlist[i].voice))
677           voice_ramp_volume(playlist[i].voice, 1000, 0);
678         playlist[i].loop = PSND_NO_LOOP;
679       }
680   }
681   else if (snd_ctrl.stop_all_sounds)
682   {
683     if (!playing_sounds)
684       return;
685     SoundServer_StopAllSounds();
686   }
687   else if (snd_ctrl.stop_sound)
688   {
689     if (!playing_sounds)
690       return;
691     SoundServer_StopSound(snd_ctrl);
692   }
693
694   for (i=0; i<NUM_MIXER_CHANNELS; i++)
695   {
696     if (!playlist[i].active || playlist[i].loop)
697       continue;
698
699     playlist[i].playingpos = voice_get_position(playlist[i].voice);
700     playlist[i].volume = voice_get_volume(playlist[i].voice);
701     if (playlist[i].playingpos == -1 || !playlist[i].volume)
702     {
703       deallocate_voice(playlist[i].voice);
704       playlist[i] = emptySoundControl;
705       playing_sounds--;
706     }
707   }
708
709   if (snd_ctrl.active)
710     SoundServer_InsertNewSound(snd_ctrl);
711 }
712 #endif /* PLATFORM_MSDOS */
713
714 #if 0
715 #if defined(TARGET_SDL)
716 static void sound_handler_SDL(struct SoundControl snd_ctrl)
717 {
718   int i;
719
720   if (snd_ctrl.fade_sound)
721   {
722     if (!playing_sounds)
723       return;
724
725     for (i=0; i<NUM_MIXER_CHANNELS; i++)
726       if ((snd_ctrl.stop_all_sounds ||
727            (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
728            (i == audio.music_channel && snd_ctrl.music)) &&
729           !playlist[i].fade_sound)
730       {
731         playlist[i].fade_sound = TRUE;
732         if (voice_check(playlist[i].voice))
733           voice_ramp_volume(playlist[i].voice, 1000, 0);
734         playlist[i].loop = PSND_NO_LOOP;
735       }
736   }
737   else if (snd_ctrl.stop_all_sounds)
738   {
739     if (!playing_sounds)
740       return;
741     SoundServer_StopAllSounds();
742   }
743   else if (snd_ctrl.stop_sound)
744   {
745     if (!playing_sounds)
746       return;
747     SoundServer_StopSound(snd_ctrl);
748   }
749
750   for (i=0; i<NUM_MIXER_CHANNELS; i++)
751   {
752     if (!playlist[i].active || playlist[i].loop)
753       continue;
754
755     playlist[i].playingpos = voice_get_position(playlist[i].voice);
756     playlist[i].volume = voice_get_volume(playlist[i].voice);
757     if (playlist[i].playingpos == -1 || !playlist[i].volume)
758     {
759       deallocate_voice(playlist[i].voice);
760       playlist[i] = emptySoundControl;
761       playing_sounds--;
762     }
763   }
764
765   if (snd_ctrl.active)
766     SoundServer_InsertNewSound(snd_ctrl);
767 }
768 #endif /* TARGET_SDL */
769 #endif
770
771 #if !defined(PLATFORM_WIN32)
772 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
773 {
774   SoundInfo *snd_info;
775   int i, k;
776
777   if (snd_ctrl.music)
778     snd_ctrl.nr = snd_ctrl.nr % num_music;
779   else if (snd_ctrl.nr >= num_sounds)
780     return;
781
782   snd_info = (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
783   if (snd_info == NULL)
784   {
785 #if 0
786     printf("sound/music %d undefined\n", snd_ctrl.nr);
787 #endif
788     return;
789   }
790
791 #if 0
792   printf("-> %d\n", playing_sounds);
793 #endif
794
795   if (playing_sounds == NUM_MIXER_CHANNELS)
796   {
797     for (i=0; i<NUM_MIXER_CHANNELS; i++)
798     {
799       if (playlist[i].data_ptr == NULL)
800       {
801 #if 1
802         printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
803 #endif
804
805         playlist[i] = emptySoundControl;
806         playing_sounds--;
807       }
808     }
809   }
810
811   /* if playlist is full, remove oldest sound */
812   if (playing_sounds == NUM_MIXER_CHANNELS)
813   {
814     int longest = 0, longest_nr = 0;
815
816     for (i=0; i<NUM_MIXER_CHANNELS; i++)
817     {
818 #if !defined(PLATFORM_MSDOS)
819       int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
820 #else
821       int actual = playlist[i].playingpos;
822 #endif
823
824       if (i != audio.music_channel && !playlist[i].loop && actual > longest)
825       {
826         longest = actual;
827         longest_nr = i;
828       }
829     }
830 #if defined(PLATFORM_MSDOS)
831     voice_set_volume(playlist[longest_nr].voice, 0);
832     deallocate_voice(playlist[longest_nr].voice);
833 #endif
834     playlist[longest_nr] = emptySoundControl;
835     playing_sounds--;
836   }
837
838   /* check if sound is already being played (and how often) */
839   for (k=0,i=0; i<NUM_MIXER_CHANNELS; i++)
840     if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
841       k++;
842
843   /* restart loop sounds only if they are just fading out */
844   if (k >= 1 && snd_ctrl.loop)
845   {
846     for(i=0; i<NUM_MIXER_CHANNELS; i++)
847     {
848       if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
849           playlist[i].fade_sound)
850       {
851         playlist[i].fade_sound = FALSE;
852         playlist[i].volume = PSND_MAX_VOLUME;
853 #if defined(PLATFORM_MSDOS)
854         playlist[i].loop = PSND_LOOP;
855         voice_stop_volumeramp(playlist[i].voice);
856         voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
857 #endif
858       }
859     }
860
861     return;
862   }
863
864   /* don't play sound more than n times simultaneously (with n == 2 for now) */
865   if (k >= 2)
866   {
867     int longest = 0, longest_nr = 0;
868
869     /* look for oldest equal sound */
870     for(i=0; i<NUM_MIXER_CHANNELS; i++)
871     {
872       int actual;
873
874       if (!playlist[i].active ||
875           i == audio.music_channel ||
876           playlist[i].nr != snd_ctrl.nr)
877         continue;
878
879 #if !defined(PLATFORM_MSDOS)
880       actual = 100 * playlist[i].playingpos / playlist[i].data_len;
881 #else
882       actual = playlist[i].playingpos;
883 #endif
884       if (actual >= longest)
885       {
886         longest = actual;
887         longest_nr = i;
888       }
889     }
890
891 #if defined(PLATFORM_MSDOS)
892     voice_set_volume(playlist[longest_nr].voice, 0);
893     deallocate_voice(playlist[longest_nr].voice);
894 #endif
895     playlist[longest_nr] = emptySoundControl;
896     playing_sounds--;
897   }
898
899   /* add new sound to playlist */
900   for(i=0; i<NUM_MIXER_CHANNELS; i++)
901   {
902     if (!playlist[i].active ||
903         (snd_ctrl.music && i == audio.music_channel))
904     {
905       snd_ctrl.data_ptr = snd_info->data_ptr;
906       snd_ctrl.data_len = snd_info->data_len;
907       snd_ctrl.format   = snd_info->format;
908
909 #if 1
910       if (snd_info->data_len == 0)
911       {
912         printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
913       }
914 #endif
915
916 #if 1
917       if (snd_ctrl.music && i == audio.music_channel && playlist[i].active)
918       {
919         printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
920
921 #if 1
922         playlist[i] = emptySoundControl;
923         playing_sounds--;
924 #endif
925       }
926 #endif
927
928       playlist[i] = snd_ctrl;
929       playing_sounds++;
930
931 #if defined(PLATFORM_MSDOS)
932       playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
933
934       if (snd_ctrl.loop)
935         voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
936
937       voice_set_volume(playlist[i].voice, snd_ctrl.volume);
938       voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
939       voice_start(playlist[i].voice);       
940 #endif
941       break;
942     }
943   }
944 }
945 #endif /* !PLATFORM_WIN32 */
946
947 /*
948 void SoundServer_FadeSound(int nr)
949 {
950   int i;
951
952   if (!playing_sounds)
953     return;
954
955   for(i=0;i<NUM_MIXER_CHANNELS;i++)
956     if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
957       playlist[i].fade_sound = TRUE;
958 }
959 */
960
961 #if !defined(PLATFORM_WIN32)
962 #if defined(PLATFORM_MSDOS)
963 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
964 {
965   int nr = snd_ctrl.nr;
966   int i;
967
968   if (!playing_sounds)
969     return;
970
971   for(i=0; i<NUM_MIXER_CHANNELS; i++)
972   {
973     if ((i == audio.music_channel && snd_ctrl.music) ||
974         (i != audio.music_channel && playlist[i].nr == nr))
975     {
976 #if defined(PLATFORM_MSDOS)
977       voice_set_volume(playlist[i].voice, 0);
978       deallocate_voice(playlist[i].voice);
979 #endif
980       playlist[i] = emptySoundControl;
981       playing_sounds--;
982     }
983   }
984
985 #if !defined(PLATFORM_MSDOS)
986   if (!playing_sounds)
987     close(audio.device_fd);
988 #endif
989 }
990
991 static void SoundServer_StopAllSounds()
992 {
993   int i;
994
995   for(i=0; i<NUM_MIXER_CHANNELS; i++)
996   {
997 #if defined(PLATFORM_MSDOS)
998     voice_set_volume(playlist[i].voice, 0);
999     deallocate_voice(playlist[i].voice);
1000 #endif
1001     playlist[i] = emptySoundControl;
1002   }
1003   playing_sounds = 0;
1004
1005 #if !defined(PLATFORM_MSDOS)
1006   close(audio.device_fd);
1007 #endif
1008 }
1009 #endif /* PLATFORM_MSDOS */
1010 #endif /* !PLATFORM_WIN32 */
1011
1012
1013 /* ------------------------------------------------------------------------- */
1014 /* platform dependant audio initialization code                              */
1015 /* ------------------------------------------------------------------------- */
1016
1017 #if defined(AUDIO_LINUX_IOCTL)
1018 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
1019 {
1020   /* "ioctl()" expects pointer to 'int' value for stereo flag
1021      (boolean is defined as 'char', which will not work here) */
1022   unsigned int fragment_spec = 0;
1023   int fragment_size_query;
1024   int stereo = TRUE;
1025   struct
1026   {
1027     int format_ioctl;
1028     int format_result;
1029   }
1030   formats[] =
1031   {
1032     /* supported audio format in preferred order */
1033     { AFMT_S16_LE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
1034     { AFMT_S16_BE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
1035     { AFMT_U8,          AUDIO_FORMAT_U8                    },
1036     { -1,               -1 }
1037   };
1038   int i;
1039
1040   /* determine logarithm (log2) of the fragment size */
1041   while ((1 << fragment_spec) < afmt->fragment_size)
1042     fragment_spec++;
1043
1044   /* use two fragments (play one fragment, prepare the other);
1045      one fragment would result in interrupted audio output, more
1046      than two fragments would raise audio output latency to much */
1047   fragment_spec |= 0x00020000;
1048
1049   /* Example for fragment specification:
1050      - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1051      - (with stereo the effective buffer size will shrink to 256)
1052      => fragment_size = 0x00020009 */
1053
1054   if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1055     Error(ERR_EXIT_SOUND_SERVER,
1056           "cannot set fragment size of /dev/dsp -- no sounds");
1057
1058   i = 0;
1059   afmt->format = 0;
1060   while (formats[i].format_result != -1)
1061   {
1062     unsigned int audio_format = formats[i].format_ioctl;
1063     if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1064     {
1065       afmt->format = formats[i].format_result;
1066       break;
1067     }
1068   }
1069
1070   if (afmt->format == 0)        /* no supported audio format found */
1071     Error(ERR_EXIT_SOUND_SERVER,
1072           "cannot set audio format of /dev/dsp -- no sounds");
1073
1074   /* try if we can use stereo sound */
1075   afmt->stereo = TRUE;
1076   if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1077     afmt->stereo = FALSE;
1078
1079   if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1080     Error(ERR_EXIT_SOUND_SERVER,
1081           "cannot set sample rate of /dev/dsp -- no sounds");
1082
1083   /* get the real fragmentation size; this should return 512 */
1084   if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1085     Error(ERR_EXIT_SOUND_SERVER,
1086           "cannot get fragment size of /dev/dsp -- no sounds");
1087   if (fragment_size_query != afmt->fragment_size)
1088     Error(ERR_EXIT_SOUND_SERVER,
1089           "cannot set fragment size of /dev/dsp -- no sounds");
1090 }
1091 #endif  /* AUDIO_LINUX_IOCTL */
1092
1093 #if defined(PLATFORM_NETBSD)
1094 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1095 {
1096   audio_info_t a_info;
1097   boolean stereo = TRUE;
1098
1099   AUDIO_INITINFO(&a_info);
1100   a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1101   a_info.play.precision = 8;
1102   a_info.play.channels = 2;
1103   a_info.play.sample_rate = sample_rate;
1104   a_info.blocksize = fragment_size;
1105
1106   afmt->format = AUDIO_FORMAT_U8;
1107   afmt->stereo = TRUE;
1108
1109   if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1110   {
1111     /* try to disable stereo */
1112     a_info.play.channels = 1;
1113
1114     afmt->stereo = FALSE;
1115
1116     if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1117       Error(ERR_EXIT_SOUND_SERVER,
1118             "cannot set sample rate of /dev/audio -- no sounds");
1119   }
1120 }
1121 #endif /* PLATFORM_NETBSD */
1122
1123 #if defined(PLATFORM_HPUX)
1124 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1125 {
1126   struct audio_describe ainfo;
1127   int audio_ctl;
1128
1129   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1130   if (audio_ctl == -1)
1131     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1132
1133   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1134     Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1135
1136   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1137     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1138
1139   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1140   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1141
1142   afmt->format = AUDIO_FORMAT_U8;
1143   afmt->stereo = FALSE;
1144   afmt->sample_rate = 8000;
1145
1146   close(audio_ctl);
1147 }
1148 #endif /* PLATFORM_HPUX */
1149
1150 #if defined(PLATFORM_UNIX)
1151 static void InitAudioDevice_DSP(struct AudioFormatInfo *afmt)
1152 {
1153 #if defined(AUDIO_LINUX_IOCTL)
1154   InitAudioDevice_Linux(afmt);
1155 #elif defined(PLATFORM_NETBSD)
1156   InitAudioDevice_NetBSD(afmt);
1157 #elif defined(PLATFORM_HPUX)
1158   InitAudioDevice_HPUX(afmt);
1159 #endif
1160 }
1161 #endif /* PLATFORM_UNIX */
1162
1163 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1164
1165 /* these two are stolen from "sox"... :) */
1166
1167 /*
1168 ** This routine converts from linear to ulaw.
1169 **
1170 ** Craig Reese: IDA/Supercomputing Research Center
1171 ** Joe Campbell: Department of Defense
1172 ** 29 September 1989
1173 **
1174 ** References:
1175 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1176 ** 2) "A New Digital Technique for Implementation of Any
1177 **     Continuous PCM Companding Law," Villeret, Michel,
1178 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1179 **     1973, pg. 11.12-11.17
1180 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1181 **     for Analog-to_Digital Conversion Techniques,"
1182 **     17 February 1987
1183 **
1184 ** Input: Signed 16 bit linear sample
1185 ** Output: 8 bit ulaw sample
1186 */
1187
1188 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
1189 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
1190 #define CLIP 32635
1191
1192 static unsigned char linear_to_ulaw(int sample)
1193 {
1194   static int exp_lut[256] =
1195   {
1196     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1197     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1198     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1199     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1200     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1201     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1202     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1203     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1204     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1205     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1206     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1207     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1208     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1209     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1210     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1211     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1212   };
1213
1214   int sign, exponent, mantissa;
1215   unsigned char ulawbyte;
1216
1217   /* Get the sample into sign-magnitude. */
1218   sign = (sample >> 8) & 0x80;          /* set aside the sign */
1219   if (sign != 0)
1220     sample = -sample;                   /* get magnitude */
1221   if (sample > CLIP)
1222     sample = CLIP;                      /* clip the magnitude */
1223
1224   /* Convert from 16 bit linear to ulaw. */
1225   sample = sample + BIAS;
1226   exponent = exp_lut[( sample >> 7 ) & 0xFF];
1227   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1228   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1229 #ifdef ZEROTRAP
1230   if (ulawbyte == 0)
1231     ulawbyte = 0x02;                    /* optional CCITT trap */
1232 #endif
1233
1234   return(ulawbyte);
1235 }
1236
1237 /*
1238 ** This routine converts from ulaw to 16 bit linear.
1239 **
1240 ** Craig Reese: IDA/Supercomputing Research Center
1241 ** 29 September 1989
1242 **
1243 ** References:
1244 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1245 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1246 **     for Analog-to_Digital Conversion Techniques,"
1247 **     17 February 1987
1248 **
1249 ** Input: 8 bit ulaw sample
1250 ** Output: signed 16 bit linear sample
1251 */
1252
1253 static int ulaw_to_linear(unsigned char ulawbyte)
1254 {
1255   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1256   int sign, exponent, mantissa, sample;
1257
1258   ulawbyte = ~ ulawbyte;
1259   sign = ( ulawbyte & 0x80 );
1260   exponent = ( ulawbyte >> 4 ) & 0x07;
1261   mantissa = ulawbyte & 0x0F;
1262   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1263   if (sign != 0)
1264     sample = -sample;
1265
1266   return(sample);
1267 }
1268 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1269
1270
1271 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
1272 /* ========================================================================= */
1273 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
1274
1275 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
1276 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
1277
1278 static SoundInfo *Load_WAV(char *filename)
1279 {
1280   SoundInfo *snd_info;
1281 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1282   byte sound_header_buffer[WAV_HEADER_SIZE];
1283   char chunk_name[CHUNK_ID_LEN + 1];
1284   int chunk_size;
1285   FILE *file;
1286   int i;
1287 #endif
1288
1289   if (!audio.sound_available)
1290     return NULL;
1291
1292 #if 0
1293   printf("loading WAV file '%s'\n", filename);
1294 #endif
1295
1296   snd_info = checked_calloc(sizeof(SoundInfo));
1297
1298 #if defined(TARGET_SDL)
1299
1300   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1301   {
1302     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1303     free(snd_info);
1304     return NULL;
1305   }
1306
1307 #elif defined(TARGET_ALLEGRO)
1308
1309   if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1310   {
1311     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1312     free(snd_info);
1313     return NULL;
1314   }
1315
1316 #else   /* PLATFORM_UNIX */
1317
1318   if ((file = fopen(filename, MODE_READ)) == NULL)
1319   {
1320     Error(ERR_WARN, "cannot open sound file '%s'", filename);
1321     free(snd_info);
1322     return NULL;
1323   }
1324
1325   /* read chunk id "RIFF" */
1326   getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1327   if (strcmp(chunk_name, "RIFF") != 0)
1328   {
1329     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1330     fclose(file);
1331     free(snd_info);
1332     return NULL;
1333   }
1334
1335   /* read "RIFF" type id "WAVE" */
1336   getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1337   if (strcmp(chunk_name, "WAVE") != 0)
1338   {
1339     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1340     fclose(file);
1341     free(snd_info);
1342     return NULL;
1343   }
1344
1345   while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1346   {
1347     if (strcmp(chunk_name, "fmt ") == 0)
1348     {
1349       /* read header information */
1350       for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1351         sound_header_buffer[i] = fgetc(file);
1352
1353       if (chunk_size > WAV_HEADER_SIZE)
1354         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1355     }
1356     else if (strcmp(chunk_name, "data") == 0)
1357     {
1358       snd_info->data_len = chunk_size;
1359       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1360
1361       /* read sound data */
1362       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1363           snd_info->data_len)
1364       {
1365         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1366         fclose(file);
1367         free(snd_info->data_ptr);
1368         free(snd_info);
1369         return NULL;
1370       }
1371
1372       /* check for odd number of sample bytes (data chunk is word aligned) */
1373       if ((chunk_size % 2) == 1)
1374         ReadUnusedBytesFromFile(file, 1);
1375     }
1376     else        /* unknown chunk -- ignore */
1377       ReadUnusedBytesFromFile(file, chunk_size);
1378   }
1379
1380   fclose(file);
1381
1382   if (snd_info->data_ptr == NULL)
1383   {
1384     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1385     free(snd_info);
1386     return NULL;
1387   }
1388
1389   snd_info->format = AUDIO_FORMAT_U8;
1390
1391 #endif  /* PLATFORM_UNIX */
1392
1393   snd_info->type = SND_TYPE_WAV;
1394   snd_info->source_filename = getStringCopy(filename);
1395
1396   return snd_info;
1397 }
1398
1399 static void deleteSoundEntry(SoundInfo **snd_info)
1400 {
1401   if (*snd_info)
1402   {
1403     char *filename = (*snd_info)->source_filename;
1404
1405 #if 0
1406     printf("[decrementing reference counter of sound '%s']\n", filename);
1407 #endif
1408
1409     if (--(*snd_info)->num_references <= 0)
1410     {
1411 #if 0
1412       printf("[deleting sound '%s']\n", filename);
1413 #endif
1414
1415       /*
1416       FreeSound(*snd_info);
1417       */
1418       deleteNodeFromList(&SoundFileList, filename, FreeSound);
1419     }
1420
1421     *snd_info = NULL;
1422   }
1423 }
1424
1425 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1426 {
1427   ListNode *node;
1428
1429   /* check if the old and the new sound file are the same */
1430   if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1431   {
1432     /* The old and new sound are the same (have the same filename and path).
1433        This usually means that this sound does not exist in this sound set
1434        and a fallback to the existing sound is done. */
1435
1436 #if 0
1437     printf("[sound '%s' already exists (same list entry)]\n", filename);
1438 #endif
1439
1440     return;
1441   }
1442
1443   /* delete existing sound file entry */
1444   deleteSoundEntry(snd_info);
1445
1446   /* check if the new sound file already exists in the list of sounds */
1447   if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1448   {
1449 #if 0
1450       printf("[sound '%s' already exists (other list entry)]\n", filename);
1451 #endif
1452
1453       *snd_info = (SoundInfo *)node->content;
1454       (*snd_info)->num_references++;
1455   }
1456   else if ((*snd_info = Load_WAV(filename)) != NULL)    /* load new sound */
1457   {
1458     (*snd_info)->num_references = 1;
1459     addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1460   }
1461 }
1462
1463 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1464 {
1465   char *filename = getCustomSoundFilename(basename);
1466
1467   if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1468   {
1469     deleteSoundEntry(snd_info);
1470     return;
1471   }
1472
1473   if (filename == NULL)
1474   {
1475     Error(ERR_WARN, "cannot find sound file '%s'", basename);
1476     return;
1477   }
1478
1479   replaceSoundEntry(snd_info, filename);
1480 }
1481
1482 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1483 {
1484   if (Sound == NULL)
1485     Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1486
1487   sound_effect = sounds_list;
1488   num_sounds = num_list_entries;
1489 }
1490
1491 void LoadSoundToList(char *basename, int list_pos)
1492 {
1493   if (Sound == NULL || list_pos >= num_sounds)
1494     return;
1495
1496 #if 0
1497   printf("loading sound '%s' ...  [%d]\n",
1498          basename, getNumNodes(SoundFileList));
1499 #endif
1500
1501   LoadCustomSound(&Sound[list_pos], basename);
1502
1503 #if 0
1504   printf("loading sound '%s' done [%d]\n",
1505          basename, getNumNodes(SoundFileList));
1506 #endif
1507 }
1508
1509 static MusicInfo *Load_MOD(char *filename)
1510 {
1511 #if defined(TARGET_SDL)
1512   MusicInfo *mod_info;
1513
1514   if (!audio.sound_available)
1515     return NULL;
1516
1517   mod_info = checked_calloc(sizeof(MusicInfo));
1518
1519   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1520   {
1521     Error(ERR_WARN, "cannot read music file '%s'", filename);
1522     free(mod_info);
1523     return NULL;
1524   }
1525
1526   mod_info->type = MUS_TYPE_MOD;
1527   mod_info->source_filename = getStringCopy(filename);
1528
1529   return mod_info;
1530 #else
1531   return NULL;
1532 #endif
1533 }
1534
1535 void LoadCustomMusic(void)
1536 {
1537   char *music_directory = getCustomMusicDirectory();
1538   DIR *dir;
1539   struct dirent *dir_entry;
1540
1541   if (!audio.sound_available)
1542     return;
1543
1544   if ((dir = opendir(music_directory)) == NULL)
1545   {
1546     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1547     audio.music_available = FALSE;
1548     return;
1549   }
1550
1551   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1552   {
1553     char *basename = dir_entry->d_name;
1554     char *filename = getPath2(music_directory, basename);
1555     MusicInfo *mus_info = NULL;
1556
1557     if (FileIsSound(basename))
1558       mus_info = Load_WAV(filename);
1559     else if (FileIsMusic(basename))
1560       mus_info = Load_MOD(filename);
1561
1562     free(filename);
1563
1564     if (mus_info)
1565     {
1566       num_music++;
1567       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1568       Music[num_music -1] = mus_info;
1569     }
1570   }
1571
1572   closedir(dir);
1573
1574   if (num_music == 0)
1575     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1576           music_directory);
1577 }
1578
1579 void PlayMusic(int nr)
1580 {
1581   if (!audio.music_available)
1582     return;
1583
1584 #if defined(TARGET_SDL)
1585
1586   nr = nr % num_music;
1587
1588   if (Music[nr]->type == MUS_TYPE_MOD)
1589   {
1590     Mix_PlayMusic(Music[nr]->data_ptr, -1);
1591     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1592   }
1593   else                          /* play WAV music loop */
1594   {
1595     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1596     Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1597   }
1598
1599 #else
1600
1601   PlaySoundMusic(nr);
1602
1603 #endif
1604 }
1605
1606 void PlaySound(int nr)
1607 {
1608   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1609 }
1610
1611 void PlaySoundStereo(int nr, int stereo)
1612 {
1613   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1614 }
1615
1616 void PlaySoundLoop(int nr)
1617 {
1618   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1619 }
1620
1621 void PlaySoundMusic(int nr)
1622 {
1623   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1624 }
1625
1626 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1627 {
1628   struct SoundControl snd_ctrl = emptySoundControl;
1629
1630   if (!audio.sound_available ||
1631       !audio.sound_enabled ||
1632       audio.sound_deactivated)
1633     return;
1634
1635   if (volume < PSND_MIN_VOLUME)
1636     volume = PSND_MIN_VOLUME;
1637   else if (volume > PSND_MAX_VOLUME)
1638     volume = PSND_MAX_VOLUME;
1639
1640   if (stereo < PSND_MAX_LEFT)
1641     stereo = PSND_MAX_LEFT;
1642   else if (stereo > PSND_MAX_RIGHT)
1643     stereo = PSND_MAX_RIGHT;
1644
1645   snd_ctrl.nr           = nr;
1646   snd_ctrl.volume       = volume;
1647   snd_ctrl.stereo       = stereo;
1648   snd_ctrl.loop         = (loop_type != PSND_NO_LOOP);
1649   snd_ctrl.music        = (loop_type == PSND_MUSIC);
1650   snd_ctrl.active       = TRUE;
1651
1652 #if 0
1653   /* now only used internally in sound server child process */
1654   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
1655   snd_ctrl.data_len     = Sound[nr].data_len;
1656 #endif
1657
1658 #if defined(TARGET_SDL)
1659   if (Sound[nr])
1660   {
1661     Mix_Volume(-1, SOUND_MAX_VOLUME);
1662     Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1663   }
1664 #elif defined(PLATFORM_UNIX)
1665   if (audio.soundserver_pid == 0)       /* we are child process */
1666     return;
1667
1668   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1669   {
1670     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1671     audio.sound_available = audio.sound_enabled = FALSE;
1672     return;
1673   }
1674 #elif defined(PLATFORM_MSDOS)
1675   sound_handler(snd_ctrl);
1676 #endif
1677 }
1678
1679 void FadeMusic(void)
1680 {
1681   if (!audio.sound_available)
1682     return;
1683
1684 #if defined(TARGET_SDL)
1685   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1686   Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1687 #else
1688   StopSoundExt(-1, SSND_FADE_MUSIC);
1689 #endif
1690 }
1691
1692 void FadeSound(int nr)
1693 {
1694   StopSoundExt(nr, SSND_FADE_SOUND);
1695 }
1696
1697 void FadeSounds()
1698 {
1699   FadeMusic();
1700   StopSoundExt(-1, SSND_FADE_ALL);
1701 }
1702
1703 void StopMusic(void)
1704 {
1705 #if defined(TARGET_SDL)
1706   if (!audio.sound_available)
1707     return;
1708
1709   Mix_HaltMusic();
1710   Mix_HaltChannel(audio.music_channel);
1711 #else
1712   StopSoundExt(-1, SSND_STOP_MUSIC);
1713 #endif
1714 }
1715
1716 void StopSound(int nr)
1717 {
1718   StopSoundExt(nr, SSND_STOP_SOUND);
1719 }
1720
1721 void StopSounds()
1722 {
1723   StopSoundExt(-1, SSND_STOP_ALL);
1724 }
1725
1726 void StopSoundExt(int nr, int method)
1727 {
1728   struct SoundControl snd_ctrl = emptySoundControl;
1729
1730   if (!audio.sound_available)
1731     return;
1732
1733   if (method & SSND_FADING)
1734     snd_ctrl.fade_sound = TRUE;
1735
1736   if (method & SSND_ALL)
1737     snd_ctrl.stop_all_sounds = TRUE;
1738   else
1739   {
1740     snd_ctrl.stop_sound = TRUE;
1741     snd_ctrl.nr = nr;
1742   }
1743
1744   if (method & SSND_MUSIC)
1745     snd_ctrl.music = TRUE;
1746
1747 #if defined(TARGET_SDL)
1748
1749   if (method & SSND_FADING)
1750   {
1751     int i;
1752
1753     for (i=0; i<audio.channels; i++)
1754       if (i != audio.music_channel || snd_ctrl.music)
1755         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1756     if (snd_ctrl.music)
1757       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1758   }
1759   else
1760   {
1761     int i;
1762
1763     for (i=0; i<audio.channels; i++)
1764       if (i != audio.music_channel || snd_ctrl.music)
1765         Mix_HaltChannel(i);
1766     if (snd_ctrl.music)
1767       Mix_HaltMusic();
1768   }
1769
1770 #elif !defined(PLATFORM_MSDOS)
1771
1772   if (audio.soundserver_pid == 0)       /* we are child process */
1773     return;
1774
1775   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1776   {
1777     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1778     audio.sound_available = audio.sound_enabled = FALSE;
1779     return;
1780   }
1781 #else /* PLATFORM_MSDOS */
1782   sound_handler(snd_ctrl);
1783 #endif
1784 }
1785
1786 ListNode *newListNode()
1787 {
1788   return checked_calloc(sizeof(ListNode));
1789 }
1790
1791 void addNodeToList(ListNode **node_first, char *key, void *content)
1792 {
1793   ListNode *node_new = newListNode();
1794
1795 #if 0
1796   printf("LIST: adding node with key '%s'\n", key);
1797 #endif
1798
1799   node_new->key = getStringCopy(key);
1800   node_new->content = content;
1801   node_new->next = *node_first;
1802   *node_first = node_new;
1803 }
1804
1805 void deleteNodeFromList(ListNode **node_first, char *key,
1806                         void (*destructor_function)(void *))
1807 {
1808   if (node_first == NULL || *node_first == NULL)
1809     return;
1810
1811 #if 0
1812   printf("[CHECKING LIST KEY '%s' == '%s']\n",
1813          (*node_first)->key, key);
1814 #endif
1815
1816   if (strcmp((*node_first)->key, key) == 0)
1817   {
1818 #if 0
1819     printf("[DELETING LIST ENTRY]\n");
1820 #endif
1821
1822     free((*node_first)->key);
1823     if (destructor_function)
1824       destructor_function((*node_first)->content);
1825     *node_first = (*node_first)->next;
1826   }
1827   else
1828     deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1829 }
1830
1831 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1832 {
1833   if (node_first == NULL)
1834     return NULL;
1835
1836   if (strcmp(node_first->key, key) == 0)
1837     return node_first;
1838   else
1839     return getNodeFromKey(node_first->next, key);
1840 }
1841
1842 int getNumNodes(ListNode *node_first)
1843 {
1844   return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1845 }
1846
1847 void dumpList(ListNode *node_first)
1848 {
1849   ListNode *node = node_first;
1850
1851   while (node)
1852   {
1853     printf("['%s' (%d)]\n", node->key,
1854            ((SoundInfo *)node->content)->num_references);
1855     node = node->next;
1856   }
1857
1858   printf("[%d nodes]\n", getNumNodes(node_first));
1859 }
1860
1861 static void LoadSoundsInfo()
1862 {
1863   char *filename = getCustomSoundConfigFilename();
1864   struct SetupFileList *setup_file_list;
1865   int i;
1866
1867   /* always start with reliable default values */
1868   for (i=0; i<num_sounds; i++)
1869     sound_effect[i].filename = NULL;
1870
1871   if (filename == NULL)
1872     return;
1873
1874   if ((setup_file_list = loadSetupFileList(filename)))
1875   {
1876     for (i=0; i<num_sounds; i++)
1877       sound_effect[i].filename =
1878         getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1879
1880     freeSetupFileList(setup_file_list);
1881
1882 #if 1
1883     for (i=0; i<num_sounds; i++)
1884     {
1885       printf("'%s' ", sound_effect[i].text);
1886       if (sound_effect[i].filename)
1887         printf("-> '%s'\n", sound_effect[i].filename);
1888       else
1889         printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1890     }
1891 #endif
1892   }
1893 }
1894
1895 static void ReloadCustomSounds()
1896 {
1897   int i;
1898
1899 #if 0
1900   printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1901 #endif
1902
1903   LoadSoundsInfo();
1904
1905   for(i=0; i<num_sounds; i++)
1906   {
1907     if (sound_effect[i].filename)
1908       LoadSoundToList(sound_effect[i].filename, i);
1909     else
1910       LoadSoundToList(sound_effect[i].default_filename, i);
1911   }
1912
1913   /*
1914   printf("list size == %d\n", getNumNodes(SoundFileList));
1915   */
1916
1917 #if 0
1918   dumpList(SoundFileList);
1919 #endif
1920 }
1921
1922 static void ReloadCustomMusic()
1923 {
1924 #if 0
1925   printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1926 #endif
1927
1928   FreeAllMusic();
1929
1930   LoadCustomMusic();
1931 }
1932
1933 static void InitReloadSoundsOrMusic(char *set_name, int type)
1934 {
1935 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1936   struct SoundControl snd_ctrl = emptySoundControl;
1937   TreeInfo *ti =
1938     (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1939   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1940   unsigned long str_size2 = strlen(ti->basepath) + 1;
1941   unsigned long str_size3 = strlen(ti->fullpath) + 1;
1942 #endif
1943
1944   if (!audio.sound_available)
1945     return;
1946
1947 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1948   if (type == SND_RELOAD_SOUNDS)
1949     ReloadCustomSounds();
1950   else
1951     ReloadCustomMusic();
1952 #elif defined(PLATFORM_UNIX)
1953   if (audio.soundserver_pid == 0)       /* we are child process */
1954     return;
1955
1956   if (leveldir_current == NULL)         /* should never happen */
1957     Error(ERR_EXIT, "leveldir_current == NULL");
1958
1959   snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1960   snd_ctrl.reload_music  = (type == SND_RELOAD_MUSIC);
1961   snd_ctrl.data_len = strlen(set_name) + 1;
1962
1963   if (write(audio.soundserver_pipe[1], &snd_ctrl,
1964             sizeof(snd_ctrl)) < 0 ||
1965       write(audio.soundserver_pipe[1], set_name,
1966             snd_ctrl.data_len) < 0 ||
1967       write(audio.soundserver_pipe[1], leveldir_current,
1968             sizeof(TreeInfo)) < 0 ||
1969       write(audio.soundserver_pipe[1], ti,
1970             sizeof(TreeInfo)) < 0 ||
1971       write(audio.soundserver_pipe[1], &str_size1,
1972             sizeof(unsigned long)) < 0 ||
1973       write(audio.soundserver_pipe[1], &str_size2,
1974             sizeof(unsigned long)) < 0 ||
1975       write(audio.soundserver_pipe[1], &str_size3,
1976             sizeof(unsigned long)) < 0 ||
1977       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1978             str_size1) < 0 ||
1979       write(audio.soundserver_pipe[1], ti->basepath,
1980             str_size2) < 0 ||
1981       write(audio.soundserver_pipe[1], ti->fullpath,
1982             str_size3) < 0)
1983   {
1984     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1985     audio.sound_available = audio.sound_enabled = FALSE;
1986     return;
1987   }
1988 #endif
1989 }
1990
1991 void InitReloadSounds(char *set_name)
1992 {
1993   InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1994 }
1995
1996 void InitReloadMusic(char *set_name)
1997 {
1998   InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1999 }
2000
2001 void FreeSound(void *ptr)
2002 {
2003   SoundInfo *sound = (SoundInfo *)ptr;
2004
2005   if (sound == NULL)
2006     return;
2007
2008   if (sound->data_ptr)
2009   {
2010 #if defined(TARGET_SDL)
2011     Mix_FreeChunk(sound->data_ptr);
2012 #elif defined(TARGET_ALLEGRO)
2013     destroy_sample(sound->data_ptr);
2014 #else   /* PLATFORM_UNIX */
2015     free(sound->data_ptr);
2016 #endif
2017   }
2018
2019   if (sound->source_filename)
2020     free(sound->source_filename);
2021
2022   free(sound);
2023 }
2024
2025 void FreeMusic(MusicInfo *music)
2026 {
2027   if (music == NULL)
2028     return;
2029
2030   if (music->data_ptr)
2031   {
2032 #if defined(TARGET_SDL)
2033     if (music->type == MUS_TYPE_MOD)
2034       Mix_FreeMusic(music->data_ptr);
2035     else
2036       Mix_FreeChunk(music->data_ptr);
2037 #elif defined(TARGET_ALLEGRO)
2038     destroy_sample(music->data_ptr);
2039 #else   /* PLATFORM_UNIX */
2040     free(music->data_ptr);
2041 #endif
2042   }
2043
2044   free(music);
2045 }
2046
2047 void FreeAllSounds()
2048 {
2049   int i;
2050
2051   if (Sound == NULL)
2052     return;
2053
2054   printf("%s: FREEING SOUNDS ...\n",
2055          audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2056
2057   for(i=0; i<num_sounds; i++)
2058     deleteSoundEntry(&Sound[i]);
2059   /*
2060     FreeSound(Sound[i]);
2061   */
2062
2063   printf("%s: FREEING SOUNDS -- DONE\n",
2064          audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2065
2066   free(Sound);
2067
2068   Sound = NULL;
2069   num_sounds = 0;
2070 }
2071
2072 void FreeAllMusic()
2073 {
2074   int i;
2075
2076   if (Music == NULL)
2077     return;
2078
2079   for(i=0; i<num_music; i++)
2080     FreeMusic(Music[i]);
2081
2082   free(Music);
2083
2084   Music = NULL;
2085   num_music = 0;
2086 }
2087
2088 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
2089 /* ========================================================================= */