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