rnd-20030102-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 #if 0
960 #if DEBUG
961     /* print some debugging information about audio channel usage */
962     for (i=audio.first_sound_channel; i<audio.num_channels; i++)
963     {
964       Error(ERR_RETURN, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
965             i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
966     }
967 #endif
968 #endif
969
970     for (i=audio.first_sound_channel; i<audio.num_channels; i++)
971     {
972       int playing_time = playing_current - mixer[i].playing_starttime;
973       int actual = 1000 * playing_time / mixer[i].data_len;
974
975       if (!IS_LOOP(mixer[i]) && actual > longest)
976       {
977         longest = actual;
978         longest_nr = i;
979       }
980     }
981
982     Mixer_StopChannel(longest_nr);
983   }
984
985   /* add the new sound to the mixer */
986   for(i=audio.first_sound_channel; i<audio.num_channels; i++)
987   {
988 #if 0
989     printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
990 #endif
991
992     if (!mixer[i].active)
993     {
994 #if 0
995       printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
996 #endif
997
998 #if defined(AUDIO_UNIX_NATIVE)
999       if (snd_info->data_len == 0)
1000       {
1001         printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
1002       }
1003 #endif
1004
1005       mixer[i] = snd_ctrl;
1006       Mixer_PlayChannel(i);
1007
1008       break;
1009     }
1010   }
1011 }
1012
1013 static void HandleSoundRequest(SoundControl snd_ctrl)
1014 {
1015   int i;
1016
1017 #if defined(AUDIO_UNIX_NATIVE)
1018   if (IS_PARENT_PROCESS(audio.mixer_pid))
1019   {
1020     SendSoundControlToMixerProcess(&snd_ctrl);
1021     return;
1022   }
1023 #endif
1024
1025   /* deactivate channels that have expired since the last request */
1026   for (i=0; i<audio.num_channels; i++)
1027     if (mixer[i].active && Mixer_ChannelExpired(i))
1028       Mixer_StopChannel(i);
1029
1030   if (IS_RELOADING(snd_ctrl))           /* load new sound or music files */
1031   {
1032     Mixer_StopMusicChannel();
1033     for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1034       Mixer_StopChannel(i);
1035
1036 #if defined(AUDIO_UNIX_NATIVE)
1037     CloseAudioDevice(&audio.device_fd);
1038     ReadReloadInfoFromPipe(&snd_ctrl);
1039 #endif
1040
1041     if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1042       ReloadCustomSounds();
1043     else
1044       ReloadCustomMusic();
1045   }
1046   else if (IS_FADING(snd_ctrl))         /* fade out existing sound or music */
1047   {
1048     if (IS_MUSIC(snd_ctrl))
1049     {
1050       Mixer_FadeMusicChannel();
1051       return;
1052     }
1053
1054     for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1055       if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1056         Mixer_FadeChannel(i);
1057   }
1058   else if (IS_STOPPING(snd_ctrl))       /* stop existing sound or music */
1059   {
1060     if (IS_MUSIC(snd_ctrl))
1061     {
1062       Mixer_StopMusicChannel();
1063       return;
1064     }
1065
1066     for(i=audio.first_sound_channel; i<audio.num_channels; i++)
1067       if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1068         Mixer_StopChannel(i);
1069
1070 #if defined(AUDIO_UNIX_NATIVE)
1071     if (!mixer_active_channels)
1072       CloseAudioDevice(&audio.device_fd);
1073 #endif
1074   }
1075   else if (snd_ctrl.active)             /* add new sound to mixer */
1076   {
1077     Mixer_InsertSound(snd_ctrl);
1078   }
1079 }
1080
1081 void StartMixer(void)
1082 {
1083   int i;
1084
1085 #if 0
1086   SDL_version compile_version;
1087   const SDL_version *link_version;
1088   MIX_VERSION(&compile_version);
1089   printf("compiled with SDL_mixer version: %d.%d.%d\n", 
1090          compile_version.major,
1091          compile_version.minor,
1092          compile_version.patch);
1093   link_version = Mix_Linked_Version();
1094   printf("running with SDL_mixer version: %d.%d.%d\n", 
1095          link_version->major,
1096          link_version->minor,
1097          link_version->patch);
1098 #endif
1099
1100   if (!audio.sound_available)
1101     return;
1102
1103   /* initialize stereo position conversion information */
1104   for(i=0; i<=SOUND_MAX_LEFT2RIGHT; i++)
1105     stereo_volume[i] =
1106       (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1107
1108 #if defined(AUDIO_UNIX_NATIVE)
1109   if (!ForkAudioProcess())
1110     audio.sound_available = FALSE;
1111 #endif
1112 }
1113
1114 #if defined(AUDIO_UNIX_NATIVE)
1115
1116 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1117                                      int sample_pos, int sample_size,
1118                                      short *buffer_ptr)
1119 {
1120   void *sample_ptr = snd_ctrl->data_ptr;
1121   int i;
1122
1123   if (snd_ctrl->format == AUDIO_FORMAT_U8)
1124     for (i=0; i<sample_size; i++)
1125       *buffer_ptr++ =
1126         ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
1127   else  /* AUDIO_FORMAT_S16 */
1128     for (i=0; i<sample_size; i++)
1129       *buffer_ptr++ =
1130         ((short *)sample_ptr)[sample_pos + i];
1131 }
1132
1133 #if defined(AUDIO_STREAMING_DSP)
1134 static void Mixer_Main_DSP()
1135 {
1136   static short premix_first_buffer[SND_BLOCKSIZE];
1137   static short premix_left_buffer[SND_BLOCKSIZE];
1138   static short premix_right_buffer[SND_BLOCKSIZE];
1139   static long premix_last_buffer[SND_BLOCKSIZE];
1140   static byte playing_buffer[SND_BLOCKSIZE];
1141   boolean stereo;
1142   int fragment_size;
1143   int sample_bytes;
1144   int max_sample_size;
1145   int i, j;
1146
1147   if (!mixer_active_channels)
1148     return;
1149
1150   if (audio.device_fd < 0)
1151   {
1152     if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1153       return;
1154
1155     InitAudioDevice(&afmt);
1156   }
1157
1158   stereo = afmt.stereo;
1159   fragment_size = afmt.fragment_size;
1160   sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1161   max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
1162
1163   /* first clear the last premixing buffer */
1164   memset(premix_last_buffer, 0,
1165          max_sample_size * (stereo ? 2 : 1) * sizeof(long));
1166
1167   for(i=0; i<audio.num_channels; i++)
1168   {
1169     void *sample_ptr;
1170     int sample_len;
1171     int sample_pos;
1172     int sample_size;
1173
1174     if (!mixer[i].active)
1175       continue;
1176
1177     if (Mixer_ChannelExpired(i))
1178     {
1179       Mixer_StopChannel(i);
1180       continue;
1181     }
1182
1183     /* pointer, lenght and actual playing position of sound sample */
1184     sample_ptr = mixer[i].data_ptr;
1185     sample_len = mixer[i].data_len;
1186     sample_pos = mixer[i].playing_pos;
1187     sample_size = MIN(max_sample_size, sample_len - sample_pos);
1188     mixer[i].playing_pos += sample_size;
1189
1190     /* copy original sample to first mixing buffer */
1191     CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1192                              premix_first_buffer);
1193
1194     /* are we about to restart a looping sound? */
1195     if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1196     {
1197       while (sample_size < max_sample_size)
1198       {
1199         int restarted_sample_size =
1200           MIN(max_sample_size - sample_size, sample_len);
1201
1202         if (mixer[i].format == AUDIO_FORMAT_U8)
1203           for (j=0; j<restarted_sample_size; j++)
1204             premix_first_buffer[sample_size + j] =
1205               ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
1206         else
1207           for (j=0; j<restarted_sample_size; j++)
1208             premix_first_buffer[sample_size + j] =
1209               ((short *)sample_ptr)[j];
1210
1211         mixer[i].playing_pos = restarted_sample_size;
1212         sample_size += restarted_sample_size;
1213       }
1214     }
1215
1216     /* decrease volume if sound is fading out */
1217     if (IS_FADING(mixer[i]) &&
1218         mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1219       mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1220
1221     /* adjust volume of actual sound sample */
1222     if (mixer[i].volume != SOUND_MAX_VOLUME)
1223       for(j=0; j<sample_size; j++)
1224         premix_first_buffer[j] =
1225           mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1226
1227     /* fill the last mixing buffer with stereo or mono sound */
1228     if (stereo)
1229     {
1230       int left_volume  = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1231       int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1232
1233       for(j=0; j<sample_size; j++)
1234       {
1235         premix_left_buffer[j] =
1236           left_volume  * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1237         premix_right_buffer[j] =
1238           right_volume * premix_first_buffer[j] / SOUND_MAX_LEFT2RIGHT;
1239
1240         premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
1241         premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
1242       }
1243     }
1244     else
1245     {
1246       for(j=0; j<sample_size; j++)
1247         premix_last_buffer[j] += premix_first_buffer[j];
1248     }
1249
1250     /* delete completed sound entries from the mixer */
1251     if (mixer[i].playing_pos >= mixer[i].data_len)
1252     {
1253       if (IS_LOOP(mixer[i]))
1254         mixer[i].playing_pos = 0;
1255       else
1256         Mixer_StopChannel(i);
1257     }
1258     else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1259       Mixer_StopChannel(i);
1260   }
1261
1262   /* prepare final playing buffer according to system audio format */
1263   for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
1264   {
1265     /* cut off at 17 bit value */
1266     if (premix_last_buffer[i] < -65535)
1267       premix_last_buffer[i] = -65535;
1268     else if (premix_last_buffer[i] > 65535)
1269       premix_last_buffer[i] = 65535;
1270
1271     /* shift to 16 bit value */
1272     premix_last_buffer[i] >>= 1;
1273
1274     if (afmt.format & AUDIO_FORMAT_U8)
1275     {
1276       playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1277     }
1278     else if (afmt.format & AUDIO_FORMAT_LE)     /* 16 bit */
1279     {
1280       playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1281       playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1282     }
1283     else                                        /* big endian */
1284     {
1285       playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1286       playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1287     }
1288   }
1289
1290   /* finally play the sound fragment */
1291   write(audio.device_fd, playing_buffer, fragment_size);
1292
1293   if (!mixer_active_channels)
1294     CloseAudioDevice(&audio.device_fd);
1295 }
1296
1297 #else /* !AUDIO_STREAMING_DSP */
1298
1299 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1300 {
1301   static short premix_first_buffer[SND_BLOCKSIZE];
1302   static byte playing_buffer[SND_BLOCKSIZE];
1303   int max_sample_size = SND_BLOCKSIZE;
1304   void *sample_ptr;
1305   int sample_len;
1306   int sample_pos;
1307   int sample_size;
1308   int i, j;
1309
1310   i = 1;
1311
1312   /* pointer, lenght and actual playing position of sound sample */
1313   sample_ptr = mixer[i].data_ptr;
1314   sample_len = mixer[i].data_len;
1315   sample_pos = mixer[i].playing_pos;
1316   sample_size = MIN(max_sample_size, sample_len - sample_pos);
1317   mixer[i].playing_pos += sample_size;
1318
1319   /* copy original sample to first mixing buffer */
1320   CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1321                            premix_first_buffer);
1322
1323   /* adjust volume of actual sound sample */
1324   if (mixer[i].volume != SOUND_MAX_VOLUME)
1325     for(j=0; j<sample_size; j++)
1326       premix_first_buffer[j] =
1327         mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1328
1329   /* might be needed for u-law /dev/audio */
1330 #if 1
1331   for(j=0; j<sample_size; j++)
1332     playing_buffer[j] =
1333       linear_to_ulaw(premix_first_buffer[j]);
1334 #endif
1335
1336   /* delete completed sound entries from the mixer */
1337   if (mixer[i].playing_pos >= mixer[i].data_len)
1338     Mixer_StopChannel(i);
1339
1340   for(i=0; i<sample_size; i++)
1341     playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1342
1343   /* finally play the sound fragment */
1344   write(audio.device_fd, playing_buffer, sample_size);
1345
1346   return sample_size;
1347 }
1348 #endif /* !AUDIO_STREAMING_DSP */
1349
1350 void Mixer_Main()
1351 {
1352   SoundControl snd_ctrl;
1353   fd_set mixer_fdset;
1354
1355   close(audio.mixer_pipe[1]);   /* no writing into pipe needed */
1356
1357   Mixer_InitChannels();
1358
1359 #if defined(PLATFORM_HPUX)
1360   InitAudioDevice(&afmt);
1361 #endif
1362
1363   FD_ZERO(&mixer_fdset); 
1364   FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1365
1366   while(1)      /* wait for sound playing commands from client */
1367   {
1368     struct timeval delay = { 0, 0 };
1369
1370     FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1371     select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1372     if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1373       continue;
1374
1375     ReadSoundControlFromMainProcess(&snd_ctrl);
1376
1377     HandleSoundRequest(snd_ctrl);
1378
1379 #if defined(AUDIO_STREAMING_DSP)
1380
1381     while (mixer_active_channels &&
1382            select(audio.mixer_pipe[0] + 1,
1383                   &mixer_fdset, NULL, NULL, &delay) < 1)
1384     {
1385       FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1386
1387       Mixer_Main_DSP();
1388     }
1389
1390 #else /* !AUDIO_STREAMING_DSP */
1391
1392     if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1393         (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1394       continue;
1395
1396     InitAudioDevice(&afmt);
1397
1398     delay.tv_sec = 0;
1399     delay.tv_usec = 0;
1400
1401     while (mixer_active_channels &&
1402            select(audio.mixer_pipe[0] + 1,
1403                   &mixer_fdset, NULL, NULL, &delay) < 1)
1404     {
1405       int wait_percent = 90;    /* wait 90% of the real playing time */
1406       int sample_size;
1407
1408       FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1409
1410       sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1411
1412       delay.tv_sec = 0;
1413       delay.tv_usec =
1414         ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1415     }
1416
1417     CloseAudioDevice(&audio.device_fd);
1418
1419     Mixer_InitChannels();       /* remove all sounds from mixer */
1420
1421 #endif /* !AUDIO_STREAMING_DSP */
1422   }
1423 }
1424 #endif /* AUDIO_UNIX_NATIVE */
1425
1426
1427 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1428
1429 /* these two are stolen from "sox"... :) */
1430
1431 /*
1432 ** This routine converts from linear to ulaw.
1433 **
1434 ** Craig Reese: IDA/Supercomputing Research Center
1435 ** Joe Campbell: Department of Defense
1436 ** 29 September 1989
1437 **
1438 ** References:
1439 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1440 ** 2) "A New Digital Technique for Implementation of Any
1441 **     Continuous PCM Companding Law," Villeret, Michel,
1442 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1443 **     1973, pg. 11.12-11.17
1444 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1445 **     for Analog-to_Digital Conversion Techniques,"
1446 **     17 February 1987
1447 **
1448 ** Input: Signed 16 bit linear sample
1449 ** Output: 8 bit ulaw sample
1450 */
1451
1452 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
1453 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
1454 #define CLIP 32635
1455
1456 static unsigned char linear_to_ulaw(int sample)
1457 {
1458   static int exp_lut[256] =
1459   {
1460     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1461     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1462     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1463     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1464     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1465     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1466     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1467     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1472     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1473     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1474     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1475     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1476   };
1477
1478   int sign, exponent, mantissa;
1479   unsigned char ulawbyte;
1480
1481   /* Get the sample into sign-magnitude. */
1482   sign = (sample >> 8) & 0x80;          /* set aside the sign */
1483   if (sign != 0)
1484     sample = -sample;                   /* get magnitude */
1485   if (sample > CLIP)
1486     sample = CLIP;                      /* clip the magnitude */
1487
1488   /* Convert from 16 bit linear to ulaw. */
1489   sample = sample + BIAS;
1490   exponent = exp_lut[( sample >> 7 ) & 0xFF];
1491   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1492   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1493 #ifdef ZEROTRAP
1494   if (ulawbyte == 0)
1495     ulawbyte = 0x02;                    /* optional CCITT trap */
1496 #endif
1497
1498   return(ulawbyte);
1499 }
1500
1501 /*
1502 ** This routine converts from ulaw to 16 bit linear.
1503 **
1504 ** Craig Reese: IDA/Supercomputing Research Center
1505 ** 29 September 1989
1506 **
1507 ** References:
1508 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1509 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1510 **     for Analog-to_Digital Conversion Techniques,"
1511 **     17 February 1987
1512 **
1513 ** Input: 8 bit ulaw sample
1514 ** Output: signed 16 bit linear sample
1515 */
1516
1517 static int ulaw_to_linear(unsigned char ulawbyte)
1518 {
1519   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1520   int sign, exponent, mantissa, sample;
1521
1522   ulawbyte = ~ ulawbyte;
1523   sign = ( ulawbyte & 0x80 );
1524   exponent = ( ulawbyte >> 4 ) & 0x07;
1525   mantissa = ulawbyte & 0x0F;
1526   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1527   if (sign != 0)
1528     sample = -sample;
1529
1530   return(sample);
1531 }
1532 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1533
1534
1535 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
1536 /* ========================================================================= */
1537 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
1538
1539 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
1540 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
1541
1542 static void *Load_WAV(char *filename)
1543 {
1544   SoundInfo *snd_info;
1545 #if defined(AUDIO_UNIX_NATIVE)
1546   struct SoundHeader_WAV header;
1547 #if 0
1548   byte sound_header_buffer[WAV_HEADER_SIZE];
1549   int i;
1550 #endif
1551   char chunk_name[CHUNK_ID_LEN + 1];
1552   int chunk_size;
1553   FILE *file;
1554 #endif
1555
1556   if (!audio.sound_available)
1557     return NULL;
1558
1559 #if 0
1560   printf("loading WAV file '%s'\n", filename);
1561 #endif
1562
1563   snd_info = checked_calloc(sizeof(SoundInfo));
1564
1565 #if defined(TARGET_SDL)
1566
1567   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1568   {
1569     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1570     free(snd_info);
1571     return NULL;
1572   }
1573
1574   snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1575
1576 #elif defined(TARGET_ALLEGRO)
1577
1578   if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1579   {
1580     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1581     free(snd_info);
1582     return NULL;
1583   }
1584
1585   snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1586
1587 #else /* AUDIO_UNIX_NATIVE */
1588
1589   if ((file = fopen(filename, MODE_READ)) == NULL)
1590   {
1591     Error(ERR_WARN, "cannot open sound file '%s'", filename);
1592     free(snd_info);
1593     return NULL;
1594   }
1595
1596   /* read chunk id "RIFF" */
1597   getFileChunkLE(file, chunk_name, &chunk_size);
1598   if (strcmp(chunk_name, "RIFF") != 0)
1599   {
1600     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1601     fclose(file);
1602     free(snd_info);
1603     return NULL;
1604   }
1605
1606   /* read "RIFF" type id "WAVE" */
1607   getFileChunkLE(file, chunk_name, NULL);
1608   if (strcmp(chunk_name, "WAVE") != 0)
1609   {
1610     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1611     fclose(file);
1612     free(snd_info);
1613     return NULL;
1614   }
1615
1616   while (getFileChunkLE(file, chunk_name, &chunk_size))
1617   {
1618     if (strcmp(chunk_name, "fmt ") == 0)
1619     {
1620       if (chunk_size < WAV_HEADER_SIZE)
1621       {
1622         Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1623         fclose(file);
1624         free(snd_info);
1625         return NULL;
1626       }
1627
1628       header.compression_code = getFile16BitLE(file);
1629       header.num_channels = getFile16BitLE(file);
1630       header.sample_rate = getFile32BitLE(file);
1631       header.bytes_per_second = getFile32BitLE(file);
1632       header.block_align = getFile16BitLE(file);
1633       header.bits_per_sample = getFile16BitLE(file);
1634
1635       if (chunk_size > WAV_HEADER_SIZE)
1636         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1637
1638       if (header.compression_code != 1)
1639       {
1640         Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1641               filename, header.compression_code);
1642         fclose(file);
1643         free(snd_info);
1644         return NULL;
1645       }
1646
1647       if (header.num_channels != 1 &&
1648           header.num_channels != 2)
1649       {
1650         Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1651               filename, header.num_channels);
1652         fclose(file);
1653         free(snd_info);
1654         return NULL;
1655       }
1656
1657       if (header.bits_per_sample != 8 && header.bits_per_sample != 16)
1658       {
1659         Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1660               filename, header.bits_per_sample);
1661         fclose(file);
1662         free(snd_info);
1663         return NULL;
1664       }
1665
1666       /* warn, but accept wrong sample rate (may be only slightly different) */
1667       if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1668         Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1669               filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1670
1671 #if 0
1672       printf("WAV file: '%s'\n", filename);
1673       printf("  Compression code: %d'\n", header.compression_code);
1674       printf("  Number of channels: %d'\n", header.num_channels);
1675       printf("  Sample rate: %ld'\n", header.sample_rate);
1676       printf("  Average bytes per second: %ld'\n", header.bytes_per_second);
1677       printf("  Block align: %d'\n", header.block_align);
1678       printf("  Significant bits per sample: %d'\n", header.bits_per_sample);
1679 #endif
1680     }
1681     else if (strcmp(chunk_name, "data") == 0)
1682     {
1683       snd_info->data_len = chunk_size;
1684       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1685
1686       /* read sound data */
1687       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1688           snd_info->data_len)
1689       {
1690         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1691         fclose(file);
1692         free(snd_info->data_ptr);
1693         free(snd_info);
1694         return NULL;
1695       }
1696
1697       /* check for odd number of sample bytes (data chunk is word aligned) */
1698       if ((chunk_size % 2) == 1)
1699         ReadUnusedBytesFromFile(file, 1);
1700     }
1701     else        /* unknown chunk -- ignore */
1702       ReadUnusedBytesFromFile(file, chunk_size);
1703   }
1704
1705   fclose(file);
1706
1707   if (snd_info->data_ptr == NULL)
1708   {
1709     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1710     free(snd_info);
1711     return NULL;
1712   }
1713
1714   if (header.bits_per_sample == 8)
1715     snd_info->format = AUDIO_FORMAT_U8;
1716   else                                  /* header.bits_per_sample == 16 */
1717   {
1718     snd_info->format = AUDIO_FORMAT_S16;
1719     snd_info->data_len /= 2;            /* correct number of samples */
1720   }
1721
1722 #endif  /* AUDIO_UNIX_NATIVE */
1723
1724   snd_info->type = SND_TYPE_WAV;
1725   snd_info->source_filename = getStringCopy(filename);
1726
1727   return snd_info;
1728 }
1729
1730 struct FileInfo *getCurrentSoundList()
1731 {
1732   return sound_info->file_list;
1733 }
1734
1735 void InitSoundList(struct ConfigInfo *config_list,
1736                    struct ConfigInfo *config_suffix_list,
1737                    int num_file_list_entries)
1738 {
1739   int i;
1740
1741   sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1742
1743   sound_info->type = ARTWORK_TYPE_SOUNDS;
1744
1745   sound_info->num_file_list_entries = num_file_list_entries;
1746   sound_info->num_suffix_list_entries = 0;
1747   for (i=0; config_suffix_list[i].token != NULL; i++)
1748     sound_info->num_suffix_list_entries++;
1749
1750   sound_info->file_list =
1751     getFileListFromConfigList(config_list, config_suffix_list,
1752                               num_file_list_entries);
1753   sound_info->suffix_list = config_suffix_list;
1754
1755   sound_info->artwork_list =
1756     checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
1757
1758   sound_info->content_list = NULL;
1759
1760   sound_info->load_artwork = Load_WAV;
1761   sound_info->free_artwork = FreeSound;
1762
1763   num_sounds = sound_info->num_file_list_entries;
1764   Sound = (SoundInfo **)sound_info->artwork_list;
1765 }
1766
1767 static MusicInfo *Load_MOD(char *filename)
1768 {
1769 #if defined(TARGET_SDL)
1770   MusicInfo *mod_info;
1771
1772   if (!audio.sound_available)
1773     return NULL;
1774
1775   mod_info = checked_calloc(sizeof(MusicInfo));
1776
1777   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1778   {
1779     Error(ERR_WARN, "cannot read music file '%s'", filename);
1780     free(mod_info);
1781     return NULL;
1782   }
1783
1784   mod_info->type = MUS_TYPE_MOD;
1785   mod_info->source_filename = getStringCopy(filename);
1786
1787   return mod_info;
1788 #else
1789   return NULL;
1790 #endif
1791 }
1792
1793 void LoadCustomMusic(void)
1794 {
1795   static boolean draw_init_text = TRUE;         /* only draw at startup */
1796   static char *last_music_directory = NULL;
1797   char *music_directory = getCustomMusicDirectory();
1798   DIR *dir;
1799   struct dirent *dir_entry;
1800
1801   if (!audio.sound_available)
1802     return;
1803
1804   if (last_music_directory != NULL &&
1805       strcmp(last_music_directory, music_directory) == 0)
1806     return;     /* old and new music directory are the same */
1807
1808   if (last_music_directory != NULL)
1809     free(last_music_directory);
1810   last_music_directory = getStringCopy(music_directory);
1811
1812   FreeAllMusic();
1813
1814   if ((dir = opendir(music_directory)) == NULL)
1815   {
1816     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1817     audio.music_available = FALSE;
1818     return;
1819   }
1820
1821   if (draw_init_text)
1822     DrawInitText("Loading music:", 120, FC_GREEN);
1823
1824   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1825   {
1826     char *basename = dir_entry->d_name;
1827     char *filename = getPath2(music_directory, basename);
1828     MusicInfo *mus_info = NULL;
1829
1830 #if 0
1831     printf("DEBUG: loading music '%s' ...\n", basename);
1832 #endif
1833
1834     if (draw_init_text)
1835       DrawInitText(basename, 150, FC_YELLOW);
1836
1837     if (FileIsSound(basename))
1838       mus_info = Load_WAV(filename);
1839     else if (FileIsMusic(basename))
1840       mus_info = Load_MOD(filename);
1841
1842     free(filename);
1843
1844     if (mus_info)
1845     {
1846       num_music++;
1847       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1848       Music[num_music -1] = mus_info;
1849     }
1850   }
1851
1852   closedir(dir);
1853
1854   draw_init_text = FALSE;
1855
1856   if (num_music == 0)
1857     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1858           music_directory);
1859 }
1860
1861 void PlayMusic(int nr)
1862 {
1863   if (!audio.music_available)
1864     return;
1865
1866   PlaySoundMusic(nr);
1867 }
1868
1869 void PlaySound(int nr)
1870 {
1871   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
1872 }
1873
1874 void PlaySoundStereo(int nr, int stereo_position)
1875 {
1876   PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
1877 }
1878
1879 void PlaySoundLoop(int nr)
1880 {
1881   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
1882 }
1883
1884 void PlaySoundMusic(int nr)
1885 {
1886   PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1887 }
1888
1889 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
1890 {
1891   SoundControl snd_ctrl;
1892
1893   if (!audio.sound_available ||
1894       !audio.sound_enabled ||
1895       audio.sound_deactivated)
1896     return;
1897
1898   if (volume < SOUND_MIN_VOLUME)
1899     volume = SOUND_MIN_VOLUME;
1900   else if (volume > SOUND_MAX_VOLUME)
1901     volume = SOUND_MAX_VOLUME;
1902
1903   if (stereo_position < SOUND_MAX_LEFT)
1904     stereo_position = SOUND_MAX_LEFT;
1905   else if (stereo_position > SOUND_MAX_RIGHT)
1906     stereo_position = SOUND_MAX_RIGHT;
1907
1908   snd_ctrl.active = TRUE;
1909   snd_ctrl.nr = nr;
1910   snd_ctrl.volume = volume;
1911   snd_ctrl.stereo_position = stereo_position;
1912   snd_ctrl.state = state;
1913
1914   HandleSoundRequest(snd_ctrl);
1915 }
1916
1917 void FadeMusic(void)
1918 {
1919   if (!audio.music_available)
1920     return;
1921
1922   StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1923 }
1924
1925 void FadeSound(int nr)
1926 {
1927   StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1928 }
1929
1930 void FadeSounds()
1931 {
1932   FadeMusic();
1933   StopSoundExt(-1, SND_CTRL_FADE_ALL);
1934 }
1935
1936 void StopMusic(void)
1937 {
1938   if (!audio.music_available)
1939     return;
1940
1941   StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1942 }
1943
1944 void StopSound(int nr)
1945 {
1946   StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1947 }
1948
1949 void StopSounds()
1950 {
1951   StopMusic();
1952   StopSoundExt(-1, SND_CTRL_STOP_ALL);
1953 }
1954
1955 void StopSoundExt(int nr, int state)
1956 {
1957   SoundControl snd_ctrl;
1958
1959   if (!audio.sound_available)
1960     return;
1961
1962   snd_ctrl.active = FALSE;
1963   snd_ctrl.nr = nr;
1964   snd_ctrl.state = state;
1965
1966   HandleSoundRequest(snd_ctrl);
1967 }
1968
1969 static void ReloadCustomSounds()
1970 {
1971 #if 0
1972   printf("DEBUG: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
1973 #endif
1974
1975   ReloadCustomArtworkList(sound_info);
1976 }
1977
1978 static void ReloadCustomMusic()
1979 {
1980 #if 0
1981   printf("DEBUG: reloading music '%s' ...\n", artwork.mus_current_identifier);
1982 #endif
1983
1984   LoadCustomMusic();
1985 }
1986
1987 void InitReloadSounds(char *set_identifier)
1988 {
1989   if (!audio.sound_available)
1990     return;
1991
1992 #if defined(AUDIO_UNIX_NATIVE)
1993   WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
1994 #else
1995   ReloadCustomSounds();
1996 #endif
1997 }
1998
1999 void InitReloadMusic(char *set_identifier)
2000 {
2001   if (!audio.music_available)
2002     return;
2003
2004 #if defined(AUDIO_UNIX_NATIVE)
2005   WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2006 #else
2007   ReloadCustomMusic();
2008 #endif
2009 }
2010
2011 void FreeSound(void *ptr)
2012 {
2013   SoundInfo *sound = (SoundInfo *)ptr;
2014
2015   if (sound == NULL)
2016     return;
2017
2018   if (sound->data_ptr)
2019   {
2020 #if defined(TARGET_SDL)
2021     Mix_FreeChunk(sound->data_ptr);
2022 #elif defined(TARGET_ALLEGRO)
2023     destroy_sample(sound->data_ptr);
2024 #else /* AUDIO_UNIX_NATIVE */
2025     free(sound->data_ptr);
2026 #endif
2027   }
2028
2029   if (sound->source_filename)
2030     free(sound->source_filename);
2031
2032   free(sound);
2033 }
2034
2035 void FreeMusic(MusicInfo *music)
2036 {
2037   if (music == NULL)
2038     return;
2039
2040   if (music->data_ptr)
2041   {
2042 #if defined(TARGET_SDL)
2043     if (music->type == MUS_TYPE_MOD)
2044       Mix_FreeMusic(music->data_ptr);
2045     else
2046       Mix_FreeChunk(music->data_ptr);
2047 #elif defined(TARGET_ALLEGRO)
2048     destroy_sample(music->data_ptr);
2049 #else /* AUDIO_UNIX_NATIVE */
2050     free(music->data_ptr);
2051 #endif
2052   }
2053
2054   free(music);
2055 }
2056
2057 void FreeAllSounds()
2058 {
2059   FreeCustomArtworkList(sound_info);
2060 }
2061
2062 void FreeAllMusic()
2063 {
2064   int i;
2065
2066   if (Music == NULL)
2067     return;
2068
2069   for(i=0; i<num_music; i++)
2070     FreeMusic(Music[i]);
2071
2072   free(Music);
2073
2074   Music = NULL;
2075   num_music = 0;
2076 }
2077
2078 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
2079 /* ========================================================================= */