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