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