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