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