rnd-20020907-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 struct FileInfo *getCurrentSoundList()
1725 {
1726   return sound_info->file_list;
1727 }
1728
1729 void InitSoundList(struct ConfigInfo *config_list, char *config_suffix_list[],
1730                    int num_file_list_entries)
1731 {
1732   int i;
1733
1734   sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1735
1736   sound_info->type = ARTWORK_TYPE_SOUNDS;
1737
1738   sound_info->num_file_list_entries = num_file_list_entries;
1739   sound_info->num_suffix_list_entries = 0;
1740   for (i=0; config_suffix_list[i] != NULL; i++)
1741     sound_info->num_suffix_list_entries++;
1742
1743   sound_info->file_list =
1744     getFileListFromConfigList(config_list, config_suffix_list,
1745                               num_file_list_entries);
1746   sound_info->suffix_list = config_suffix_list;
1747
1748   sound_info->artwork_list =
1749     checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
1750
1751   sound_info->content_list = NULL;
1752
1753   sound_info->load_artwork = Load_WAV;
1754   sound_info->free_artwork = FreeSound;
1755
1756   num_sounds = sound_info->num_file_list_entries;
1757   Sound = (SoundInfo **)sound_info->artwork_list;
1758 }
1759
1760 static MusicInfo *Load_MOD(char *filename)
1761 {
1762 #if defined(TARGET_SDL)
1763   MusicInfo *mod_info;
1764
1765   if (!audio.sound_available)
1766     return NULL;
1767
1768   mod_info = checked_calloc(sizeof(MusicInfo));
1769
1770   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1771   {
1772     Error(ERR_WARN, "cannot read music file '%s'", filename);
1773     free(mod_info);
1774     return NULL;
1775   }
1776
1777   mod_info->type = MUS_TYPE_MOD;
1778   mod_info->source_filename = getStringCopy(filename);
1779
1780   return mod_info;
1781 #else
1782   return NULL;
1783 #endif
1784 }
1785
1786 void LoadCustomMusic(void)
1787 {
1788   static boolean draw_init_text = TRUE;         /* only draw at startup */
1789   static char *last_music_directory = NULL;
1790   char *music_directory = getCustomMusicDirectory();
1791   DIR *dir;
1792   struct dirent *dir_entry;
1793
1794   if (!audio.sound_available)
1795     return;
1796
1797   if (last_music_directory != NULL &&
1798       strcmp(last_music_directory, music_directory) == 0)
1799     return;     /* old and new music directory are the same */
1800
1801   if (last_music_directory != NULL)
1802     free(last_music_directory);
1803   last_music_directory = getStringCopy(music_directory);
1804
1805   FreeAllMusic();
1806
1807   if ((dir = opendir(music_directory)) == NULL)
1808   {
1809     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1810     audio.music_available = FALSE;
1811     return;
1812   }
1813
1814   if (draw_init_text)
1815     DrawInitText("Loading music:", 120, FC_GREEN);
1816
1817   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1818   {
1819     char *basename = dir_entry->d_name;
1820     char *filename = getPath2(music_directory, basename);
1821     MusicInfo *mus_info = NULL;
1822
1823 #if 0
1824     printf("DEBUG: loading music '%s' ...\n", basename);
1825 #endif
1826
1827     if (draw_init_text)
1828       DrawInitText(basename, 150, FC_YELLOW);
1829
1830     if (FileIsSound(basename))
1831       mus_info = Load_WAV(filename);
1832     else if (FileIsMusic(basename))
1833       mus_info = Load_MOD(filename);
1834
1835     free(filename);
1836
1837     if (mus_info)
1838     {
1839       num_music++;
1840       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1841       Music[num_music -1] = mus_info;
1842     }
1843   }
1844
1845   closedir(dir);
1846
1847   draw_init_text = FALSE;
1848
1849   if (num_music == 0)
1850     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1851           music_directory);
1852 }
1853
1854 void PlayMusic(int nr)
1855 {
1856   if (!audio.music_available)
1857     return;
1858
1859   PlaySoundMusic(nr);
1860 }
1861
1862 void PlaySound(int nr)
1863 {
1864   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1865 }
1866
1867 void PlaySoundStereo(int nr, int stereo_position)
1868 {
1869   PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1870 }
1871
1872 void PlaySoundLoop(int nr)
1873 {
1874   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1875 }
1876
1877 void PlaySoundMusic(int nr)
1878 {
1879   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1880 }
1881
1882 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1883 {
1884   SoundControl snd_ctrl;
1885
1886   if (!audio.sound_available ||
1887       !audio.sound_enabled ||
1888       audio.sound_deactivated)
1889     return;
1890
1891   if (volume < SOUND_MIN_VOLUME)
1892     volume = SOUND_MIN_VOLUME;
1893   else if (volume > SOUND_MAX_VOLUME)
1894     volume = SOUND_MAX_VOLUME;
1895
1896   if (stereo_position < SOUND_MAX_LEFT)
1897     stereo_position = SOUND_MAX_LEFT;
1898   else if (stereo_position > SOUND_MAX_RIGHT)
1899     stereo_position = SOUND_MAX_RIGHT;
1900
1901   snd_ctrl.active = TRUE;
1902   snd_ctrl.nr = nr;
1903   snd_ctrl.volume = volume;
1904   snd_ctrl.stereo_position = stereo_position;
1905   snd_ctrl.state = state;
1906
1907   HandleSoundRequest(snd_ctrl);
1908 }
1909
1910 void FadeMusic(void)
1911 {
1912   if (!audio.music_available)
1913     return;
1914
1915   StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1916 }
1917
1918 void FadeSound(int nr)
1919 {
1920   StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1921 }
1922
1923 void FadeSounds()
1924 {
1925   FadeMusic();
1926   StopSoundExt(-1, SND_CTRL_FADE_ALL);
1927 }
1928
1929 void StopMusic(void)
1930 {
1931   if (!audio.music_available)
1932     return;
1933
1934   StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1935 }
1936
1937 void StopSound(int nr)
1938 {
1939   StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1940 }
1941
1942 void StopSounds()
1943 {
1944   StopMusic();
1945   StopSoundExt(-1, SND_CTRL_STOP_ALL);
1946 }
1947
1948 void StopSoundExt(int nr, int state)
1949 {
1950   SoundControl snd_ctrl;
1951
1952   if (!audio.sound_available)
1953     return;
1954
1955   snd_ctrl.active = FALSE;
1956   snd_ctrl.nr = nr;
1957   snd_ctrl.state = state;
1958
1959   HandleSoundRequest(snd_ctrl);
1960 }
1961
1962 static void ReloadCustomSounds()
1963 {
1964 #if 0
1965   printf("DEBUG: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
1966 #endif
1967
1968   ReloadCustomArtworkList(sound_info);
1969 }
1970
1971 static void ReloadCustomMusic()
1972 {
1973 #if 0
1974   printf("DEBUG: reloading music '%s' ...\n", artwork.mus_current_identifier);
1975 #endif
1976
1977   LoadCustomMusic();
1978 }
1979
1980 void InitReloadSounds(char *set_identifier)
1981 {
1982   if (!audio.sound_available)
1983     return;
1984
1985 #if defined(AUDIO_UNIX_NATIVE)
1986   WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
1987 #else
1988   ReloadCustomSounds();
1989 #endif
1990 }
1991
1992 void InitReloadMusic(char *set_identifier)
1993 {
1994   if (!audio.music_available)
1995     return;
1996
1997 #if defined(AUDIO_UNIX_NATIVE)
1998   WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
1999 #else
2000   ReloadCustomMusic();
2001 #endif
2002 }
2003
2004 void FreeSound(void *ptr)
2005 {
2006   SoundInfo *sound = (SoundInfo *)ptr;
2007
2008   if (sound == NULL)
2009     return;
2010
2011   if (sound->data_ptr)
2012   {
2013 #if defined(TARGET_SDL)
2014     Mix_FreeChunk(sound->data_ptr);
2015 #elif defined(TARGET_ALLEGRO)
2016     destroy_sample(sound->data_ptr);
2017 #else /* AUDIO_UNIX_NATIVE */
2018     free(sound->data_ptr);
2019 #endif
2020   }
2021
2022   if (sound->source_filename)
2023     free(sound->source_filename);
2024
2025   free(sound);
2026 }
2027
2028 void FreeMusic(MusicInfo *music)
2029 {
2030   if (music == NULL)
2031     return;
2032
2033   if (music->data_ptr)
2034   {
2035 #if defined(TARGET_SDL)
2036     if (music->type == MUS_TYPE_MOD)
2037       Mix_FreeMusic(music->data_ptr);
2038     else
2039       Mix_FreeChunk(music->data_ptr);
2040 #elif defined(TARGET_ALLEGRO)
2041     destroy_sample(music->data_ptr);
2042 #else /* AUDIO_UNIX_NATIVE */
2043     free(music->data_ptr);
2044 #endif
2045   }
2046
2047   free(music);
2048 }
2049
2050 void FreeAllSounds()
2051 {
2052   FreeCustomArtworkList(sound_info);
2053 }
2054
2055 void FreeAllMusic()
2056 {
2057   int i;
2058
2059   if (Music == NULL)
2060     return;
2061
2062   for(i=0; i<num_music; i++)
2063     FreeMusic(Music[i]);
2064
2065   free(Music);
2066
2067   Music = NULL;
2068   num_music = 0;
2069 }
2070
2071 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
2072 /* ========================================================================= */