rnd-20020421-1-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 static int num_sounds = 0, num_music = 0;
28 static struct SampleInfo *Sound = NULL;
29 #if defined(TARGET_SDL)
30 static int num_mods = 0;
31 static struct SampleInfo *Mod = NULL;
32 #endif
33
34
35 /* ========================================================================= */
36 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
37
38 static int playing_sounds = 0;
39 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
40 static struct SoundControl emptySoundControl =
41 {
42   -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
43 };
44
45 #if defined(PLATFORM_UNIX)
46 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
47 static char premix_first_buffer[SND_BLOCKSIZE];
48 #if defined(AUDIO_STREAMING_DSP)
49 static char premix_left_buffer[SND_BLOCKSIZE];
50 static char premix_right_buffer[SND_BLOCKSIZE];
51 static int premix_last_buffer[SND_BLOCKSIZE];
52 #endif
53 static unsigned char playing_buffer[SND_BLOCKSIZE];
54 #endif
55
56 /* forward declaration of internal functions */
57 #if defined(AUDIO_STREAMING_DSP)
58 static void SoundServer_InsertNewSound(struct SoundControl);
59 #elif defined(PLATFORM_UNIX)
60 static unsigned char linear_to_ulaw(int);
61 static int ulaw_to_linear(unsigned char);
62 #endif
63
64 #if defined(AUDIO_LINUX_IOCTL)
65 static boolean InitAudioDevice_Linux();
66 #elif defined(PLATFORM_NETBSD)
67 static boolean InitAudioDevice_NetBSD();
68 #elif defined(PLATFORM_HPUX)
69 static boolean InitAudioDevice_HPUX();
70 #elif defined(PLATFORM_MSDOS)
71 static void SoundServer_InsertNewSound(struct SoundControl);
72 static void SoundServer_StopSound(int);
73 static void SoundServer_StopAllSounds();
74 #endif
75
76 #if defined(PLATFORM_UNIX)
77 static int OpenAudioDevice(char *audio_device_name)
78 {
79   int audio_fd;
80
81   /* check if desired audio device is accessible */
82   if (access(audio_device_name, W_OK) != 0)
83     return -1;
84
85   /* try to open audio device in non-blocking mode */
86   if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
87     return audio_fd;
88
89   /* re-open audio device in blocking mode */
90   close(audio_fd);
91   audio_fd = open(audio_device_name, O_WRONLY);
92
93   return audio_fd;
94 }
95
96 static boolean TestAudioDevices(void)
97 {
98   static char *audio_device_name[] =
99   {
100     DEVICENAME_DSP,
101     DEVICENAME_AUDIO
102   };
103   int audio_fd = -1;
104   int i;
105
106   /* look for available audio devices, starting with preferred ones */
107   for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
108     if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
109       break;
110
111   if (audio_fd < 0)
112   {
113     Error(ERR_WARN, "cannot open audio device -- no sound");
114     return FALSE;
115   }
116
117   close(audio_fd);
118
119   audio.device_name = audio_device_name[i];
120
121   return TRUE;
122 }
123
124 #if !defined(TARGET_SDL)
125 static boolean ForkAudioProcess(void)
126 {
127   if (pipe(audio.soundserver_pipe) < 0)
128   {
129     Error(ERR_WARN, "cannot create pipe -- no sounds");
130     return FALSE;
131   }
132
133   if ((audio.soundserver_pid = fork()) < 0)
134   {       
135     Error(ERR_WARN, "cannot create sound server process -- no sounds");
136     return FALSE;
137   }
138
139   if (audio.soundserver_pid == 0)       /* we are child process */
140   {
141     SoundServer();
142
143     /* never reached */
144     exit(0);
145   }
146   else                                  /* we are parent */
147     close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
148
149   return TRUE;
150 }
151 #endif
152
153 void UnixOpenAudio(void)
154 {
155   if (!TestAudioDevices())
156     return;
157
158   audio.sound_available = TRUE;
159   audio.sound_enabled = TRUE;
160
161 #if defined(AUDIO_STREAMING_DSP)
162   audio.music_available = TRUE;
163   audio.loops_available = TRUE;
164 #endif
165 }
166
167 void UnixCloseAudio(void)
168 {
169   if (audio.device_fd)
170     close(audio.device_fd);
171
172   if (audio.soundserver_pid > 0)        /* we are parent process */
173     kill(audio.soundserver_pid, SIGTERM);
174 }
175 #endif  /* PLATFORM_UNIX */
176
177 void InitPlaylist(void)
178 {
179   int i;
180
181   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
182     playlist[i] = emptySoundControl;
183   playing_sounds = 0;
184 }
185
186 void StartSoundserver(void)
187 {
188   if (!audio.sound_available)
189     return;
190
191 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
192   if (!ForkAudioProcess())
193     audio.sound_available = FALSE;
194 #endif
195 }
196
197 #if defined(PLATFORM_UNIX)
198 void SoundServer(void)
199 {
200   int i;
201
202   struct SoundControl snd_ctrl;
203   fd_set sound_fdset;
204
205   close(audio.soundserver_pipe[1]);     /* no writing into pipe needed */
206
207   InitPlaylist();
208
209   stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
210   for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
211     stereo_volume[i] =
212       (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
213
214 #if defined(PLATFORM_HPUX)
215   InitAudioDevice_HPUX();
216 #endif
217
218   FD_ZERO(&sound_fdset); 
219   FD_SET(audio.soundserver_pipe[0], &sound_fdset);
220
221   while(1)      /* wait for sound playing commands from client */
222   {
223     FD_SET(audio.soundserver_pipe[0], &sound_fdset);
224     select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
225     if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
226       continue;
227     if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
228         != sizeof(snd_ctrl))
229       Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
230
231     if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
232     {
233       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
234         playlist[i] = emptySoundControl;
235       playing_sounds = 0;
236
237       close(audio.device_fd);
238
239       if (snd_ctrl.reload_sounds)
240         ReloadSounds();
241       else
242         ReloadMusic();
243
244       continue;
245     }
246
247 #if defined(AUDIO_STREAMING_DSP)
248
249     if (snd_ctrl.fade_sound)
250     {
251       if (!playing_sounds)
252         continue;
253
254       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
255         if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
256           playlist[i].fade_sound = TRUE;
257     }
258     else if (snd_ctrl.stop_all_sounds)
259     {
260       if (!playing_sounds)
261         continue;
262
263       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
264         playlist[i] = emptySoundControl;
265       playing_sounds = 0;
266
267       close(audio.device_fd);
268     }
269     else if (snd_ctrl.stop_sound)
270     {
271       if (!playing_sounds)
272         continue;
273
274       for(i=0;i<MAX_SOUNDS_PLAYING;i++)
275         if (playlist[i].nr == snd_ctrl.nr)
276         {
277           playlist[i] = emptySoundControl;
278           playing_sounds--;
279         }
280
281       if (!playing_sounds)
282         close(audio.device_fd);
283     }
284
285     if (playing_sounds || snd_ctrl.active)
286     {
287       struct timeval delay = { 0, 0 };
288       byte *sample_ptr;
289       long sample_size;
290       static long max_sample_size = 0;
291       static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
292       int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
293       static boolean stereo = TRUE;
294
295       if (playing_sounds ||
296           (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
297       {
298         if (!playing_sounds)    /* we just opened the audio device */
299         {
300 #if defined(AUDIO_LINUX_IOCTL)
301           stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
302 #elif defined(PLATFORM_NETBSD)
303           stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
304 #endif
305           max_sample_size = fragment_size / (stereo ? 2 : 1);
306         }
307
308         if (snd_ctrl.active)    /* new sound has arrived */
309           SoundServer_InsertNewSound(snd_ctrl);
310
311         while(playing_sounds &&
312               select(audio.soundserver_pipe[0] + 1,
313                      &sound_fdset, NULL, NULL, &delay) < 1)
314         {       
315           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
316
317           /* first clear the last premixing buffer */
318           memset(premix_last_buffer, 0, fragment_size * sizeof(int));
319
320           for(i=0;i<MAX_SOUNDS_PLAYING;i++)
321           {
322             int j;
323
324             if (!playlist[i].active)
325               continue;
326
327             /* get pointer and size of the actual sound sample */
328             sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
329             sample_size =
330               MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
331             playlist[i].playingpos += sample_size;
332
333             /* fill the first mixing buffer with original sample */
334             memcpy(premix_first_buffer,sample_ptr,sample_size);
335
336             /* are we about to restart a looping sound? */
337             if (playlist[i].loop && sample_size<max_sample_size)
338             {
339               playlist[i].playingpos = max_sample_size-sample_size;
340               memcpy(premix_first_buffer+sample_size,
341                      playlist[i].data_ptr,max_sample_size-sample_size);
342               sample_size = max_sample_size;
343             }
344
345             /* decrease volume if sound is fading out */
346             if (playlist[i].fade_sound &&
347                 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
348               playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
349
350             /* adjust volume of actual sound sample */
351             if (playlist[i].volume != PSND_MAX_VOLUME)
352               for(j=0;j<sample_size;j++)
353                 premix_first_buffer[j] =
354                   (playlist[i].volume * (int)premix_first_buffer[j])
355                     >> PSND_MAX_VOLUME_BITS;
356
357             /* fill the last mixing buffer with stereo or mono sound */
358             if (stereo)
359             {
360               int middle_pos = PSND_MAX_LEFT2RIGHT/2;
361               int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
362               int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
363
364               for(j=0;j<sample_size;j++)
365               {
366                 premix_left_buffer[j] =
367                   (left_volume * (int)premix_first_buffer[j])
368                     >> PSND_MAX_LEFT2RIGHT_BITS;
369                 premix_right_buffer[j] =
370                   (right_volume * (int)premix_first_buffer[j])
371                     >> PSND_MAX_LEFT2RIGHT_BITS;
372                 premix_last_buffer[2*j+0] += premix_left_buffer[j];
373                 premix_last_buffer[2*j+1] += premix_right_buffer[j];
374               }
375             }
376             else
377             {
378               for(j=0;j<sample_size;j++)
379                 premix_last_buffer[j] += (int)premix_first_buffer[j];
380             }
381
382             /* delete completed sound entries from the playlist */
383             if (playlist[i].playingpos >= playlist[i].data_len)
384             {
385               if (playlist[i].loop)
386                 playlist[i].playingpos = 0;
387               else
388               {
389                 playlist[i] = emptySoundControl;
390                 playing_sounds--;
391               }
392             }
393             else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
394             {
395               playlist[i] = emptySoundControl;
396               playing_sounds--;
397             }
398           }
399
400           /* put last mixing buffer to final playing buffer */
401           for(i=0; i<fragment_size; i++)
402           {
403             if (premix_last_buffer[i]<-255)
404               playing_buffer[i] = 0;
405             else if (premix_last_buffer[i]>255)
406               playing_buffer[i] = 255;
407             else
408               playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
409           }
410
411           /* finally play the sound fragment */
412           write(audio.device_fd, playing_buffer, fragment_size);
413         }
414
415         /* if no sounds playing, free device for other sound programs */
416         if (!playing_sounds)
417           close(audio.device_fd);
418       }
419     }
420
421 #else /* !AUDIO_STREAMING_DSP */
422
423     if (snd_ctrl.active && !snd_ctrl.loop)
424     {
425       struct timeval delay = { 0, 0 };
426       byte *sample_ptr;
427       long sample_size, max_sample_size = SND_BLOCKSIZE;
428       long sample_rate = 8000;  /* standard "/dev/audio" sampling rate */
429       int wait_percent = 90;    /* wait 90% of the real playing time */
430       int i;
431
432       if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
433       {
434         playing_sounds = 1;
435
436         while(playing_sounds &&
437               select(audio.soundserver_pipe[0] + 1,
438                      &sound_fdset, NULL, NULL, &delay) < 1)
439         {       
440           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
441
442           /* get pointer and size of the actual sound sample */
443           sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
444           sample_size =
445             MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
446           snd_ctrl.playingpos += sample_size;
447
448           /* fill the first mixing buffer with original sample */
449           memcpy(premix_first_buffer,sample_ptr,sample_size);
450
451           /* adjust volume of actual sound sample */
452           if (snd_ctrl.volume != PSND_MAX_VOLUME)
453             for(i=0;i<sample_size;i++)
454               premix_first_buffer[i] =
455                 (snd_ctrl.volume * (int)premix_first_buffer[i])
456                   >> PSND_MAX_VOLUME_BITS;
457
458           for(i=0;i<sample_size;i++)
459             playing_buffer[i] =
460               linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
461
462           if (snd_ctrl.playingpos >= snd_ctrl.data_len)
463             playing_sounds = 0;
464
465           /* finally play the sound fragment */
466           write(audio.device_fd,playing_buffer,sample_size);
467
468           delay.tv_sec = 0;
469           delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
470         }
471         close(audio.device_fd);
472       }
473     }
474 #endif /* !AUDIO_STREAMING_DSP */
475   }
476 }
477 #endif /* PLATFORM_UNIX */
478
479 #if defined(PLATFORM_MSDOS)
480 static void sound_handler(struct SoundControl snd_ctrl)
481 {
482   int i;
483
484   if (snd_ctrl.fade_sound)
485   {
486     if (!playing_sounds)
487       return;
488
489     for (i=0; i<MAX_SOUNDS_PLAYING; i++)
490       if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
491           !playlist[i].fade_sound)
492       {
493         playlist[i].fade_sound = TRUE;
494         if (voice_check(playlist[i].voice))
495           voice_ramp_volume(playlist[i].voice, 1000, 0);
496         playlist[i].loop = PSND_NO_LOOP;
497       }
498   }
499   else if (snd_ctrl.stop_all_sounds)
500   {
501     if (!playing_sounds)
502       return;
503     SoundServer_StopAllSounds();
504   }
505   else if (snd_ctrl.stop_sound)
506   {
507     if (!playing_sounds)
508       return;
509     SoundServer_StopSound(snd_ctrl.nr);
510   }
511
512   for (i=0; i<MAX_SOUNDS_PLAYING; i++)
513   {
514     if (!playlist[i].active || playlist[i].loop)
515       continue;
516
517     playlist[i].playingpos = voice_get_position(playlist[i].voice);
518     playlist[i].volume = voice_get_volume(playlist[i].voice);
519     if (playlist[i].playingpos == -1 || !playlist[i].volume)
520     {
521       deallocate_voice(playlist[i].voice);
522       playlist[i] = emptySoundControl;
523       playing_sounds--;
524     }
525   }
526
527   if (snd_ctrl.active)
528     SoundServer_InsertNewSound(snd_ctrl);
529 }
530 #endif /* PLATFORM_MSDOS */
531
532 #if !defined(PLATFORM_WIN32)
533 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
534 {
535   int i, k;
536
537   /* if playlist is full, remove oldest sound */
538   if (playing_sounds==MAX_SOUNDS_PLAYING)
539   {
540     int longest=0, longest_nr=0;
541
542     for(i=0;i<MAX_SOUNDS_PLAYING;i++)
543     {
544 #if !defined(PLATFORM_MSDOS)
545       int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
546 #else
547       int actual = playlist[i].playingpos;
548 #endif
549
550       if (!playlist[i].loop && actual>longest)
551       {
552         longest=actual;
553         longest_nr=i;
554       }
555     }
556 #if defined(PLATFORM_MSDOS)
557     voice_set_volume(playlist[longest_nr].voice, 0);
558     deallocate_voice(playlist[longest_nr].voice);
559 #endif
560     playlist[longest_nr] = emptySoundControl;
561     playing_sounds--;
562   }
563
564   /* check if sound is already being played (and how often) */
565   for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
566   {
567     if (playlist[i].nr == snd_ctrl.nr)
568       k++;
569   }
570
571   /* restart loop sounds only if they are just fading out */
572   if (k>=1 && snd_ctrl.loop)
573   {
574     for(i=0;i<MAX_SOUNDS_PLAYING;i++)
575     {
576       if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
577       {
578         playlist[i].fade_sound = FALSE;
579         playlist[i].volume = PSND_MAX_VOLUME;
580 #if defined(PLATFORM_MSDOS)
581         playlist[i].loop = PSND_LOOP;
582         voice_stop_volumeramp(playlist[i].voice);
583         voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
584 #endif
585       }
586     }
587     return;
588   }
589
590   /* don't play sound more than n times simultaneously (with n == 2 for now) */
591   if (k>=2)
592   {
593     int longest=0, longest_nr=0;
594
595     /* look for oldest equal sound */
596     for(i=0;i<MAX_SOUNDS_PLAYING;i++)
597     {
598       int actual;
599
600       if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
601         continue;
602
603 #if !defined(PLATFORM_MSDOS)
604       actual = 100 * playlist[i].playingpos / playlist[i].data_len;
605 #else
606       actual = playlist[i].playingpos;
607 #endif
608       if (actual>=longest)
609       {
610         longest=actual;
611         longest_nr=i;
612       }
613     }
614
615 #if defined(PLATFORM_MSDOS)
616     voice_set_volume(playlist[longest_nr].voice, 0);
617     deallocate_voice(playlist[longest_nr].voice);
618 #endif
619     playlist[longest_nr] = emptySoundControl;
620     playing_sounds--;
621   }
622
623   /* neuen Sound in Liste packen */
624   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
625   {
626     if (!playlist[i].active)
627     {
628       playlist[i] = snd_ctrl;
629       playing_sounds++;
630
631 #if defined(PLATFORM_MSDOS)
632       playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr);
633       if(snd_ctrl.loop)
634         voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
635       voice_set_volume(playlist[i].voice, snd_ctrl.volume);
636       voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
637       voice_start(playlist[i].voice);       
638 #endif
639       break;
640     }
641   }
642 }
643 #endif /* !PLATFORM_WIN32 */
644
645 /*
646 void SoundServer_FadeSound(int nr)
647 {
648   int i;
649
650   if (!playing_sounds)
651     return;
652
653   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
654     if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
655       playlist[i].fade_sound = TRUE;
656 }
657 */
658
659 #if !defined(PLATFORM_WIN32)
660 #if defined(PLATFORM_MSDOS)
661 static void SoundServer_StopSound(int nr)
662 {
663   int i;
664
665   if (!playing_sounds)
666     return;
667
668   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
669     if (playlist[i].nr == nr)
670     {
671 #if defined(PLATFORM_MSDOS)
672       voice_set_volume(playlist[i].voice, 0);
673       deallocate_voice(playlist[i].voice);
674 #endif
675       playlist[i] = emptySoundControl;
676       playing_sounds--;
677     }
678
679 #if !defined(PLATFORM_MSDOS)
680   if (!playing_sounds)
681     close(audio.device_fd);
682 #endif
683 }
684
685 static void SoundServer_StopAllSounds()
686 {
687   int i;
688
689   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
690   {
691 #if defined(PLATFORM_MSDOS)
692     voice_set_volume(playlist[i].voice, 0);
693     deallocate_voice(playlist[i].voice);
694 #endif
695     playlist[i]=emptySoundControl;
696   }
697   playing_sounds = 0;
698
699 #if !defined(PLATFORM_MSDOS)
700   close(audio.device_fd);
701 #endif
702 }
703 #endif /* PLATFORM_MSDOS */
704 #endif /* !PLATFORM_WIN32 */
705
706
707 /* ------------------------------------------------------------------------- */
708 /* platform dependant audio initialization code                              */
709 /* ------------------------------------------------------------------------- */
710
711 #if defined(AUDIO_LINUX_IOCTL)
712 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
713 {
714   /* "ioctl()" expects pointer to 'int' value for stereo flag
715      (boolean is defined as 'char', which will not work here) */
716   int stereo = TRUE;
717   unsigned long fragment_spec = 0;
718
719   /* determine logarithm (log2) of the fragment size */
720   for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
721        fragment_spec++);
722
723   /* use two fragments (play one fragment, prepare the other);
724      one fragment would result in interrupted audio output, more
725      than two fragments would raise audio output latency to much */
726   fragment_spec |= 0x00020000;
727
728   /* Example for fragment specification:
729      - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
730      - (with stereo the effective buffer size will shrink to 256)
731      => fragment_size = 0x00020009 */
732
733   if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
734     Error(ERR_EXIT_SOUND_SERVER,
735           "cannot set fragment size of /dev/dsp -- no sounds");
736
737   /* try if we can use stereo sound */
738   if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
739   {
740 #ifdef DEBUG
741     static boolean reported = FALSE;
742
743     if (!reported)
744     {
745       Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
746       reported = TRUE;
747     }
748 #endif
749     stereo = FALSE;
750   }
751
752   if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
753     Error(ERR_EXIT_SOUND_SERVER,
754           "cannot set sample rate of /dev/dsp -- no sounds");
755
756   /* get the real fragmentation size; this should return 512 */
757   if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
758     Error(ERR_EXIT_SOUND_SERVER,
759           "cannot get fragment size of /dev/dsp -- no sounds");
760
761   return (boolean)stereo;
762 }
763 #endif  /* AUDIO_LINUX_IOCTL */
764
765 #if defined(PLATFORM_NETBSD)
766 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
767 {
768   audio_info_t a_info;
769   boolean stereo = TRUE;
770
771   AUDIO_INITINFO(&a_info);
772   a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
773   a_info.play.precision = 8;
774   a_info.play.channels = 2;
775   a_info.play.sample_rate = sample_rate;
776   a_info.blocksize = fragment_size;
777
778   if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
779   {
780     /* try to disable stereo */
781     a_info.play.channels = 1;
782     stereo = FALSE;
783
784     if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
785       Error(ERR_EXIT_SOUND_SERVER,
786             "cannot set sample rate of /dev/audio -- no sounds");
787   }
788
789   return stereo;
790 }
791 #endif /* PLATFORM_NETBSD */
792
793 #if defined(PLATFORM_HPUX)
794 static boolean InitAudioDevice_HPUX()
795 {
796   struct audio_describe ainfo;
797   int audio_ctl;
798
799   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
800   if (audio_ctl == -1)
801     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
802
803   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
804     Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
805
806   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
807     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
808
809   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
810   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
811
812   close(audio_ctl);
813
814   return TRUE;  /* to provide common interface for InitAudioDevice_...() */
815 }
816 #endif /* PLATFORM_HPUX */
817
818 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
819
820 /* these two are stolen from "sox"... :) */
821
822 /*
823 ** This routine converts from linear to ulaw.
824 **
825 ** Craig Reese: IDA/Supercomputing Research Center
826 ** Joe Campbell: Department of Defense
827 ** 29 September 1989
828 **
829 ** References:
830 ** 1) CCITT Recommendation G.711  (very difficult to follow)
831 ** 2) "A New Digital Technique for Implementation of Any
832 **     Continuous PCM Companding Law," Villeret, Michel,
833 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
834 **     1973, pg. 11.12-11.17
835 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
836 **     for Analog-to_Digital Conversion Techniques,"
837 **     17 February 1987
838 **
839 ** Input: Signed 16 bit linear sample
840 ** Output: 8 bit ulaw sample
841 */
842
843 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
844 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
845 #define CLIP 32635
846
847 static unsigned char linear_to_ulaw(int sample)
848 {
849   static int exp_lut[256] =
850   {
851     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
852     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
853     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
854     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
855     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
856     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
857     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
858     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
859     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
860     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
861     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
862     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
863     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
864     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
865     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
866     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
867   };
868
869   int sign, exponent, mantissa;
870   unsigned char ulawbyte;
871
872   /* Get the sample into sign-magnitude. */
873   sign = (sample >> 8) & 0x80;          /* set aside the sign */
874   if (sign != 0)
875     sample = -sample;                   /* get magnitude */
876   if (sample > CLIP)
877     sample = CLIP;                      /* clip the magnitude */
878
879   /* Convert from 16 bit linear to ulaw. */
880   sample = sample + BIAS;
881   exponent = exp_lut[( sample >> 7 ) & 0xFF];
882   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
883   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
884 #ifdef ZEROTRAP
885   if (ulawbyte == 0)
886     ulawbyte = 0x02;                    /* optional CCITT trap */
887 #endif
888
889   return(ulawbyte);
890 }
891
892 /*
893 ** This routine converts from ulaw to 16 bit linear.
894 **
895 ** Craig Reese: IDA/Supercomputing Research Center
896 ** 29 September 1989
897 **
898 ** References:
899 ** 1) CCITT Recommendation G.711  (very difficult to follow)
900 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
901 **     for Analog-to_Digital Conversion Techniques,"
902 **     17 February 1987
903 **
904 ** Input: 8 bit ulaw sample
905 ** Output: signed 16 bit linear sample
906 */
907
908 static int ulaw_to_linear(unsigned char ulawbyte)
909 {
910   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
911   int sign, exponent, mantissa, sample;
912
913   ulawbyte = ~ ulawbyte;
914   sign = ( ulawbyte & 0x80 );
915   exponent = ( ulawbyte >> 4 ) & 0x07;
916   mantissa = ulawbyte & 0x0F;
917   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
918   if (sign != 0)
919     sample = -sample;
920
921   return(sample);
922 }
923 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
924
925
926 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
927 /* ========================================================================= */
928 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
929
930 void ReloadSounds()
931 {
932   printf("reloading sounds ...\n");
933 }
934
935 void ReloadMusic()
936 {
937   printf("reloading music ...\n");
938 }
939
940 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
941 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
942
943 static boolean LoadSoundExt(char *sound_name, boolean is_music)
944 {
945   struct SampleInfo *snd_info;
946   char *filename;
947 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
948   byte sound_header_buffer[WAV_HEADER_SIZE];
949   char chunk_name[CHUNK_ID_LEN + 1];
950   int chunk_size;
951   FILE *file;
952   int i;
953 #endif
954
955   if (!audio.sound_available)
956     return FALSE;
957
958   num_sounds++;
959   Sound = checked_realloc(Sound, num_sounds * sizeof(struct SampleInfo));
960
961   snd_info = &Sound[num_sounds - 1];
962   snd_info->data_len = 0;
963   snd_info->data_ptr = NULL;
964 #if 0
965   snd_info->name = sound_name;
966 #endif
967
968   if (is_music)
969     filename = getPath2(options.music_directory, sound_name);
970   else
971     filename = getStringCopy(sound_name);
972
973 #if defined(TARGET_SDL)
974
975   if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL)
976   {
977     Error(ERR_WARN, "cannot read sound file '%s'", filename);
978     free(filename);
979     return FALSE;
980   }
981
982 #elif defined(PLATFORM_UNIX)
983
984   if ((file = fopen(filename, MODE_READ)) == NULL)
985   {
986     Error(ERR_WARN, "cannot open sound file '%s'", filename);
987     free(filename);
988     return FALSE;
989   }
990
991   /* read chunk id "RIFF" */
992   getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
993   if (strcmp(chunk_name, "RIFF") != 0)
994   {
995     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
996     fclose(file);
997     free(filename);
998     return FALSE;
999   }
1000
1001   /* read "RIFF" type id "WAVE" */
1002   getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1003   if (strcmp(chunk_name, "WAVE") != 0)
1004   {
1005     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1006     fclose(file);
1007     free(filename);
1008     return FALSE;
1009   }
1010
1011   while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1012   {
1013 #if 0
1014     printf("DEBUG: file '%s', chunk id '%s', chunk size '%d' [%d]\n",
1015            filename, chunk_name, chunk_size, feof(file));
1016 #endif
1017
1018     if (strcmp(chunk_name, "fmt ") == 0)
1019     {
1020       /* read header information */
1021       for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1022         sound_header_buffer[i] = fgetc(file);
1023
1024       if (chunk_size > WAV_HEADER_SIZE)
1025         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1026     }
1027     else if (strcmp(chunk_name, "data") == 0)
1028     {
1029       snd_info->data_len = chunk_size;
1030       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1031
1032       /* read sound data */
1033       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1034           snd_info->data_len)
1035       {
1036         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1037         fclose(file);
1038         free(filename);
1039         return FALSE;
1040       }
1041
1042       /* check for odd number of sample bytes (data chunk is word aligned) */
1043       if ((chunk_size % 2) == 1)
1044         ReadUnusedBytesFromFile(file, 1);
1045     }
1046     else        /* unknown chunk -- ignore */
1047       ReadUnusedBytesFromFile(file, chunk_size);
1048   }
1049
1050   fclose(file);
1051
1052   if (snd_info->data_ptr == NULL)
1053   {
1054     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1055     free(filename);
1056     return FALSE;
1057   }
1058
1059   for (i=0; i<snd_info->data_len; i++)
1060     snd_info->data_ptr[i] = snd_info->data_ptr[i] ^ 0x80;
1061
1062 #else /* PLATFORM_MSDOS */
1063
1064   snd_info->sample_ptr = load_sample(filename);
1065   if (!snd_info->sample_ptr)
1066   {
1067     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1068     return FALSE;
1069   }
1070
1071 #endif
1072
1073   free(filename);
1074
1075   return TRUE;
1076 }
1077
1078 boolean LoadSound(char *sound_name)
1079 {
1080   return LoadSoundExt(sound_name, FALSE);
1081 }
1082
1083 boolean LoadCustomSound(char *basename)
1084 {
1085   char *filename = getCustomSoundFilename(basename);
1086
1087   if (filename == NULL)
1088   {
1089     Error(ERR_WARN, "cannot find sound file '%s' -- no sounds", filename);
1090     return FALSE;
1091   }
1092
1093   return LoadSound(filename);
1094 }
1095
1096 boolean LoadMod(char *mod_name)
1097 {
1098 #if defined(TARGET_SDL)
1099   struct SampleInfo *mod_info;
1100   char *filename;
1101
1102   num_mods++;
1103   Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo));
1104
1105   mod_info = &Mod[num_mods - 1];
1106   mod_info->name = mod_name;
1107
1108   filename = getPath2(options.music_directory, mod_info->name);
1109
1110   if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL)
1111   {
1112     Error(ERR_WARN, "cannot read music file '%s' -- no music", filename);
1113     free(filename);
1114     return FALSE;
1115   }
1116
1117   free(filename);
1118
1119   return TRUE;
1120 #else
1121   return FALSE;
1122 #endif
1123 }
1124
1125 int LoadMusic(void)
1126 {
1127   DIR *dir;
1128   struct dirent *dir_entry;
1129   int num_wav_music = 0;
1130   int num_mod_music = 0;
1131
1132   if (!audio.sound_available)
1133     return 0;
1134
1135   if ((dir = opendir(options.music_directory)) == NULL)
1136   {
1137     Error(ERR_WARN, "cannot read music directory '%s'",
1138           options.music_directory);
1139     audio.music_available = FALSE;
1140     return 0;
1141   }
1142
1143   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1144   {
1145     char *filename = dir_entry->d_name;
1146
1147     if (FileIsSound(filename) && LoadSoundExt(filename, TRUE))
1148       num_wav_music++;
1149     else if (FileIsMusic(filename) && LoadMod(filename))
1150       num_mod_music++;
1151   }
1152
1153   closedir(dir);
1154
1155   if (num_wav_music == 0 && num_mod_music == 0)
1156     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1157           options.music_directory);
1158
1159   num_music = (num_mod_music > 0 ? num_mod_music : num_wav_music);
1160
1161   audio.mods_available = (num_mod_music > 0);
1162   audio.music_available = (num_music > 0);
1163
1164   return num_music;
1165 }
1166
1167 void PlayMusic(int nr)
1168 {
1169   if (!audio.music_available)
1170     return;
1171
1172   if (!audio.mods_available)
1173     nr = num_sounds - num_music + nr;
1174
1175 #if defined(TARGET_SDL)
1176   if (audio.mods_available)     /* play MOD music */
1177   {
1178     Mix_PlayMusic(Mod[nr].mix_music, -1);
1179     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1180   }
1181   else                          /* play WAV music loop */
1182   {
1183     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1184     Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1);
1185   }
1186 #else
1187   audio.music_nr = nr;
1188   PlaySoundLoop(nr);
1189 #endif
1190 }
1191
1192 void PlaySound(int nr)
1193 {
1194   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1195 }
1196
1197 void PlaySoundStereo(int nr, int stereo)
1198 {
1199   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1200 }
1201
1202 void PlaySoundLoop(int nr)
1203 {
1204   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1205 }
1206
1207 void PlaySoundExt(int nr, int volume, int stereo, boolean loop)
1208 {
1209   struct SoundControl snd_ctrl = emptySoundControl;
1210
1211   if (!audio.sound_available ||
1212       !audio.sound_enabled ||
1213       audio.sound_deactivated)
1214     return;
1215
1216   if (volume<PSND_MIN_VOLUME)
1217     volume = PSND_MIN_VOLUME;
1218   else if (volume>PSND_MAX_VOLUME)
1219     volume = PSND_MAX_VOLUME;
1220
1221   if (stereo<PSND_MAX_LEFT)
1222     stereo = PSND_MAX_LEFT;
1223   else if (stereo>PSND_MAX_RIGHT)
1224     stereo = PSND_MAX_RIGHT;
1225
1226   snd_ctrl.nr           = nr;
1227   snd_ctrl.volume       = volume;
1228   snd_ctrl.stereo       = stereo;
1229   snd_ctrl.loop         = loop;
1230   snd_ctrl.active       = TRUE;
1231   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
1232   snd_ctrl.data_len     = Sound[nr].data_len;
1233
1234 #if defined(TARGET_SDL)
1235   Mix_Volume(-1, SOUND_MAX_VOLUME);
1236   Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0));
1237 #elif defined(PLATFORM_UNIX)
1238   if (audio.soundserver_pid == 0)       /* we are child process */
1239     return;
1240
1241   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1242   {
1243     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1244     audio.sound_available = audio.sound_enabled = FALSE;
1245     return;
1246   }
1247 #elif defined(PLATFORM_MSDOS)
1248   sound_handler(snd_ctrl);
1249 #endif
1250 }
1251
1252 void FadeMusic(void)
1253 {
1254 #if defined(TARGET_SDL)
1255   if (!audio.sound_available)
1256     return;
1257
1258   if (audio.mods_available)
1259     Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1260   else
1261     Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1262 #else
1263   FadeSound(audio.music_nr);
1264 #endif
1265 }
1266
1267 void FadeSound(int nr)
1268 {
1269   StopSoundExt(nr, SSND_FADE_SOUND);
1270 }
1271
1272 void FadeSounds()
1273 {
1274   FadeMusic();
1275   StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
1276 }
1277
1278 void StopMusic(void)
1279 {
1280 #if defined(TARGET_SDL)
1281   if (!audio.sound_available)
1282     return;
1283
1284   if (audio.mods_available)
1285     Mix_HaltMusic();
1286   else
1287     Mix_HaltChannel(audio.music_channel);
1288 #else
1289   StopSound(audio.music_nr);
1290 #endif
1291 }
1292
1293 void StopSound(int nr)
1294 {
1295   StopSoundExt(nr, SSND_STOP_SOUND);
1296 }
1297
1298 void StopSounds()
1299 {
1300   StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
1301 }
1302
1303 void StopSoundExt(int nr, int method)
1304 {
1305   struct SoundControl snd_ctrl = emptySoundControl;
1306
1307   if (!audio.sound_available)
1308     return;
1309
1310   if (SSND_FADING(method))
1311     snd_ctrl.fade_sound = TRUE;
1312
1313   if (SSND_ALL(method))
1314     snd_ctrl.stop_all_sounds = TRUE;
1315   else
1316   {
1317     snd_ctrl.nr = nr;
1318     snd_ctrl.stop_sound = TRUE;
1319   }
1320
1321 #if defined(TARGET_SDL)
1322
1323   if (SSND_FADING(method))
1324   {
1325     int i;
1326
1327     for (i=0; i<audio.channels; i++)
1328       if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1329         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1330     if (snd_ctrl.stop_all_sounds)
1331       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1332   }
1333   else
1334   {
1335     int i;
1336
1337     for (i=0; i<audio.channels; i++)
1338       if (i != audio.music_channel || snd_ctrl.stop_all_sounds)
1339         Mix_HaltChannel(i);
1340     if (snd_ctrl.stop_all_sounds)
1341       Mix_HaltMusic();
1342   }
1343
1344 #else
1345 #if !defined(PLATFORM_MSDOS)
1346   if (audio.soundserver_pid == 0)       /* we are child process */
1347     return;
1348
1349   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1350   {
1351     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1352     audio.sound_available = audio.sound_enabled = FALSE;
1353     return;
1354   }
1355 #else
1356   sound_handler(snd_ctrl);
1357 #endif
1358 #endif
1359 }
1360
1361 void InitReloadSounds(char *set_name)
1362 {
1363   struct SoundControl snd_ctrl = emptySoundControl;
1364
1365   if (!audio.sound_available)
1366     return;
1367
1368   snd_ctrl.reload_sounds = TRUE;
1369
1370 #if defined(TARGET_SDL)
1371   ReloadSounds();
1372 #elif defined(PLATFORM_UNIX)
1373   if (audio.soundserver_pid == 0)       /* we are child process */
1374     return;
1375
1376   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1377   {
1378     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1379     audio.sound_available = audio.sound_enabled = FALSE;
1380     return;
1381   }
1382 #elif defined(PLATFORM_MSDOS)
1383   sound_handler(snd_ctrl);
1384 #endif
1385 }
1386
1387 void InitReloadMusic(char *set_name)
1388 {
1389   struct SoundControl snd_ctrl = emptySoundControl;
1390
1391   if (!audio.sound_available)
1392     return;
1393
1394   snd_ctrl.reload_music = TRUE;
1395
1396 #if defined(TARGET_SDL)
1397   ReloadMusic();
1398 #elif defined(PLATFORM_UNIX)
1399   if (audio.soundserver_pid == 0)       /* we are child process */
1400     return;
1401
1402   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1403   {
1404     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1405     audio.sound_available = audio.sound_enabled = FALSE;
1406     return;
1407   }
1408 #elif defined(PLATFORM_MSDOS)
1409   sound_handler(snd_ctrl);
1410 #endif
1411 }
1412
1413 void FreeSounds(int num_sounds)
1414 {
1415   int i;
1416
1417   if (!audio.sound_available)
1418     return;
1419
1420   for(i=0; i<num_sounds; i++)
1421 #if defined(TARGET_SDL)
1422     free(Sound[i].mix_chunk);
1423 #elif !defined(PLATFORM_MSDOS)
1424     free(Sound[i].data_ptr);
1425 #else
1426     destroy_sample(Sound[i].sample_ptr);
1427 #endif
1428 }
1429
1430 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
1431 /* ========================================================================= */