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