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