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