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