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