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