rnd-20020510-8-src
[rocksndiamonds.git] / src / libgame / sound.c
index 00019c6e3e5cc12a1c10e4c3be03ef2c6e692bb2..d451e6ecf58616a0f5403a815059974bcb917a98 100644 (file)
@@ -24,6 +24,9 @@
 #include "setup.h"
 
 
+#define IS_PARENT_PROCESS(pid)         ((pid) > 0)
+#define IS_CHILD_PROCESS(pid)          ((pid) == 0)
+
 struct ListNode
 {
   char *key;
@@ -54,20 +57,13 @@ static struct SoundControl mixer[NUM_MIXER_CHANNELS];
 static int mixer_active_channels = 0;
 
 /* forward declaration of internal functions */
-static void Mixer_Main(void);
-static void Mixer_InsertNewSound(struct SoundControl);
 static void InitAudioDevice(struct AudioFormatInfo *);
+static void Mixer_Main(void);
 
-#if defined(PLATFORM_UNIX)
-#if !defined(AUDIO_STREAMING_DSP)
+#if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
 static unsigned char linear_to_ulaw(int);
 static int ulaw_to_linear(unsigned char);
 #endif
-#elif defined(PLATFORM_MSDOS)
-static void Mixer_InsertNewSound(struct SoundControl);
-static void Mixer_StopSound(struct SoundControl);
-static void Mixer_StopAllSounds();
-#endif
 
 static void ReloadCustomSounds();
 static void ReloadCustomMusic();
@@ -145,15 +141,10 @@ static boolean ForkAudioProcess(void)
     return FALSE;
   }
 
-  if (audio.mixer_pid == 0)            /* we are child process */
-  {
-    Mixer_Main();
-
-    /* never reached */
-    exit(0);
-  }
-  else                                 /* we are parent */
-    close(audio.mixer_pipe[0]);        /* no reading from pipe needed */
+  if (IS_CHILD_PROCESS(audio.mixer_pid))
+    Mixer_Main();                      /* this function never returns */
+  else
+    close(audio.mixer_pipe[0]);                /* no reading from pipe needed */
 
   return TRUE;
 }
@@ -182,20 +173,43 @@ void UnixCloseAudio(void)
   if (audio.device_fd)
     close(audio.device_fd);
 
-  if (audio.mixer_pid > 0)             /* we are parent process */
+  if (IS_PARENT_PROCESS(audio.mixer_pid))
     kill(audio.mixer_pid, SIGTERM);
 }
 
+static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
+{
+  if (IS_CHILD_PROCESS(audio.mixer_pid))
+    return;
+
+  if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
+  {
+    Error(ERR_WARN, "cannot pipe to child process -- no sounds");
+    audio.sound_available = audio.sound_enabled = FALSE;
+    return;
+  }
+}
+
+static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
+{
+  if (IS_PARENT_PROCESS(audio.mixer_pid))
+    return;
+
+  if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
+      != sizeof(SoundControl))
+    Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
+}
+
 static void WriteReloadInfoToPipe(char *set_name, int type)
 {
-  struct SoundControl snd_ctrl;
+  SoundControl snd_ctrl;
   TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
                  artwork.mus_current);
   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
   unsigned long str_size2 = strlen(ti->basepath) + 1;
   unsigned long str_size3 = strlen(ti->fullpath) + 1;
 
-  if (audio.mixer_pid == 0)            /* we are child process */
+  if (IS_CHILD_PROCESS(audio.mixer_pid))
     return;
 
   if (leveldir_current == NULL)                /* should never happen */
@@ -232,9 +246,9 @@ static void WriteReloadInfoToPipe(char *set_name, int type)
   }
 }
 
-static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
+static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
 {
-  TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
+  TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
                       &artwork.snd_current : &artwork.mus_current);
   TreeInfo *ti = *ti_ptr;
   unsigned long str_size1, str_size2, str_size3;
@@ -243,7 +257,7 @@ static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
   if (set_name)
     free(set_name);
 
-  set_name = checked_malloc(snd_ctrl.data_len);
+  set_name = checked_malloc(snd_ctrl->data_len);
 
   if (leveldir_current == NULL)
     leveldir_current = checked_calloc(sizeof(TreeInfo));
@@ -257,7 +271,7 @@ static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
     free(ti->fullpath);
 
   if (read(audio.mixer_pipe[0], set_name,
-          snd_ctrl.data_len) != snd_ctrl.data_len ||
+          snd_ctrl->data_len) != snd_ctrl->data_len ||
       read(audio.mixer_pipe[0], leveldir_current,
           sizeof(TreeInfo)) != sizeof(TreeInfo) ||
       read(audio.mixer_pipe[0], ti,
@@ -282,7 +296,7 @@ static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
           str_size3) != str_size3)
     Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
 
-  if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
+  if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
     artwork.sounds_set_current = set_name;
   else
     artwork.music_set_current = set_name;
@@ -298,25 +312,101 @@ void Mixer_InitChannels()
   mixer_active_channels = 0;
 }
 
-static void Mixer_FadeSound(int channel)
+static void Mixer_PlayChannel(int channel)
 {
-  mixer[channel].state |= SND_CTRL_FADE;
+  /* start with inactive channel in case something goes wrong */
+  mixer[channel].active = FALSE;
+
+  if (IS_MUSIC_MODULE(mixer[channel]))
+    return;
+
+  mixer[channel].playingpos = 0;
+  mixer[channel].playingtime = 0;
+
+#if defined(TARGET_SDL)
+  Mix_Volume(channel, SOUND_MAX_VOLUME);
+  Mix_PlayChannel(channel, mixer[channel].data_ptr,
+                 IS_LOOP(mixer[channel]) ? -1 : 0);
+#elif defined(PLATFORM_MSDOS)
+  mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
+  if (mixer[channel].voice < 0)
+    return;
+
+  if (IS_LOOP(mixer[channel]))
+    voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
+
+  voice_set_volume(mixer[channel].voice, mixer[channel].volume);
+  voice_set_pan(mixer[channel].voice, mixer[channel].stereo);
+  voice_start(mixer[channel].voice);       
+#endif
+
+  mixer[channel].active = TRUE;
+  mixer_active_channels++;
+}
+
+static void Mixer_PlayMusicChannel()
+{
+  Mixer_PlayChannel(audio.music_channel);
+
+#if defined(TARGET_SDL)
+  if (IS_MUSIC_MODULE(mixer[audio.music_channel]))
+  {
+    /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
+       this looks like a bug in the SDL_mixer library */
+    Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
+    Mix_VolumeMusic(SOUND_MAX_VOLUME);
+  }
+#endif
 }
 
-static void Mixer_RemoveSound(int channel)
+static void Mixer_StopChannel(int channel)
 {
   if (!mixer_active_channels || !mixer[channel].active)
     return;
 
-#if 0
-  printf("REMOVING MIXER SOUND %d\n", channel);
+#if defined(TARGET_SDL)
+  Mix_HaltChannel(channel);
+#elif defined(PLATFORM_MSDOS)
+  voice_set_volume(mixer[channel].voice, 0);
+  deallocate_voice(mixer[channel].voice);
 #endif
 
   mixer[channel].active = FALSE;
   mixer_active_channels--;
 }
 
-static void Mixer_InsertSound(struct SoundControl snd_ctrl)
+static void Mixer_StopMusicChannel()
+{
+  Mixer_StopChannel(audio.music_channel);
+
+#if defined(TARGET_SDL)
+  Mix_HaltMusic();
+#endif
+}
+
+static void Mixer_FadeChannel(int channel)
+{
+  mixer[channel].state |= SND_CTRL_FADE;
+
+#if defined(TARGET_SDL)
+  Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
+#elif defined(PLATFORM_MSDOS)
+  if (voice_check(mixer[channel].voice))
+    voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
+  mixer[channel].state &= ~SND_CTRL_IS_LOOP;
+#endif
+}
+
+static void Mixer_FadeMusicChannel()
+{
+  Mixer_FadeChannel(audio.music_channel);
+
+#if defined(TARGET_SDL)
+  Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
+#endif
+}
+
+static void Mixer_InsertSound(SoundControl snd_ctrl)
 {
   SoundInfo *snd_info;
   int i, k;
@@ -332,10 +422,19 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl)
 
   snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
   if (snd_info == NULL)
+    return;
+
+  /* copy sound sample and format information */
+  snd_ctrl.data_ptr = snd_info->data_ptr;
+  snd_ctrl.data_len = snd_info->data_len;
+  snd_ctrl.format   = snd_info->format;
+
+  if (IS_MUSIC(snd_ctrl))
   {
-#if 0
-    printf("sound/music %d undefined\n", snd_ctrl.nr);
-#endif
+    mixer[audio.music_channel] = snd_ctrl;
+
+    Mixer_PlayChannel(audio.music_channel);
+
     return;
   }
 
@@ -353,7 +452,7 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl)
        printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
 #endif
 
-       Mixer_RemoveSound(i);
+       Mixer_StopChannel(i);
       }
     }
   }
@@ -377,11 +476,8 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl)
        longest_nr = i;
       }
     }
-#if defined(PLATFORM_MSDOS)
-    voice_set_volume(mixer[longest_nr].voice, 0);
-    deallocate_voice(mixer[longest_nr].voice);
-#endif
-    Mixer_RemoveSound(longest_nr);
+
+    Mixer_StopChannel(longest_nr);
   }
 
   /* check if sound is already being played (and how often) */
@@ -434,11 +530,7 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl)
       }
     }
 
-#if defined(PLATFORM_MSDOS)
-    voice_set_volume(mixer[longest_nr].voice, 0);
-    deallocate_voice(mixer[longest_nr].voice);
-#endif
-    Mixer_RemoveSound(longest_nr);
+    Mixer_StopChannel(longest_nr);
   }
 
   /* add new sound to mixer */
@@ -455,12 +547,9 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl)
     if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
        (i != audio.music_channel && !mixer[i].active))
     {
-      snd_ctrl.data_ptr = snd_info->data_ptr;
-      snd_ctrl.data_len = snd_info->data_len;
-      snd_ctrl.format   = snd_info->format;
-
-      snd_ctrl.playingpos = 0;
-      snd_ctrl.playingtime = 0;
+#if 0
+      printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr);
+#endif
 
 #if 1
       if (snd_info->data_len == 0)
@@ -475,40 +564,53 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl)
        printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
 
 #if 1
-       Mixer_RemoveSound(i);
+       Mixer_StopChannel(i);
 #endif
       }
 #endif
 
-      mixer[i] = snd_ctrl;
-      mixer_active_channels++;
-
 #if 0
-      printf("NEW SOUND %d ADDED TO MIXER\n", snd_ctrl.nr);
+      snd_ctrl.data_ptr = snd_info->data_ptr;
+      snd_ctrl.data_len = snd_info->data_len;
+      snd_ctrl.format   = snd_info->format;
 #endif
 
-#if defined(PLATFORM_MSDOS)
-      mixer[i].voice = allocate_voice((SAMPLE *)mixer[i].data_ptr);
+      mixer[i] = snd_ctrl;
 
-      if (snd_ctrl.loop)
-        voice_set_playmode(mixer[i].voice, PLAYMODE_LOOP);
+      Mixer_PlayChannel(i);
 
-      voice_set_volume(mixer[i].voice, snd_ctrl.volume);
-      voice_set_pan(mixer[i].voice, snd_ctrl.stereo);
-      voice_start(mixer[i].voice);       
-#endif
       break;
     }
   }
 }
 
-static void HandleSoundRequest(struct SoundControl snd_ctrl)
+static void HandleSoundRequest(SoundControl snd_ctrl)
 {
   int i;
 
+#if defined(AUDIO_UNIX_NATIVE)
+  if (IS_PARENT_PROCESS(audio.mixer_pid))
+  {
+    SendSoundControlToMixerProcess(&snd_ctrl);
+    return;
+  }
+#elif defined(TARGET_ALLEGRO)
+  for (i=0; i<audio.num_channels; i++)
+  {
+    if (!mixer[i].active || IS_LOOP(mixer[i]))
+      continue;
+
+    mixer[i].playingpos = voice_get_position(mixer[i].voice);
+    mixer[i].volume = voice_get_volume(mixer[i].voice);
+
+    if (mixer[i].playingpos == -1 || mixer[i].volume == 0)
+      Mixer_StopChannel(i);
+  }
+#endif /* TARGET_ALLEGRO */
+
   if (IS_RELOADING(snd_ctrl))          /* load new sound or music files */
   {
-    ReadReloadInfoFromPipe(snd_ctrl);
+    ReadReloadInfoFromPipe(&snd_ctrl);
     Mixer_InitChannels();
     CloseAudioDevice(&audio.device_fd);
 
@@ -524,13 +626,13 @@ static void HandleSoundRequest(struct SoundControl snd_ctrl)
 
     if (IS_MUSIC(snd_ctrl))
     {
-      mixer[audio.music_channel].state |= SND_CTRL_FADE;
+      Mixer_FadeChannel(audio.music_channel);
       return;
     }
 
     for(i=audio.first_sound_channel; i<audio.num_channels; i++)
       if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
-       mixer[i].state |= SND_CTRL_FADE;
+       Mixer_FadeChannel(i);
   }
   else if (IS_STOPPING(snd_ctrl))      /* stop existing sound or music */
   {
@@ -539,20 +641,20 @@ static void HandleSoundRequest(struct SoundControl snd_ctrl)
 
     if (IS_MUSIC(snd_ctrl))
     {
-      Mixer_RemoveSound(audio.music_channel);
+      Mixer_StopChannel(audio.music_channel);
       return;
     }
 
     for(i=audio.first_sound_channel; i<audio.num_channels; i++)
       if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
-       Mixer_RemoveSound(i);
+       Mixer_StopChannel(i);
 
     if (!mixer_active_channels)
       CloseAudioDevice(&audio.device_fd);
   }
   else if (snd_ctrl.active)            /* add new sound to mixer */
   {
-    Mixer_InsertNewSound(snd_ctrl);
+    Mixer_InsertSound(snd_ctrl);
   }
 }
 
@@ -569,7 +671,7 @@ void StartMixer(void)
 
 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
 
-static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
+static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
                                     int sample_pos, int sample_size,
                                     short *buffer_ptr)
 {
@@ -718,10 +820,10 @@ static void Mixer_Main_DSP()
       if (IS_LOOP(mixer[i]))
        mixer[i].playingpos = 0;
       else
-       Mixer_RemoveSound(i);
+       Mixer_StopChannel(i);
     }
     else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
-      Mixer_RemoveSound(i);
+      Mixer_StopChannel(i);
   }
 
   /* prepare final playing buffer according to system audio format */
@@ -761,7 +863,7 @@ static void Mixer_Main_DSP()
 
 #else /* !AUDIO_STREAMING_DSP */
 
-static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
+static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
 {
   static short premix_first_buffer[SND_BLOCKSIZE];
   static byte playing_buffer[SND_BLOCKSIZE];
@@ -801,7 +903,7 @@ static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
 
   /* delete completed sound entries from the mixer */
   if (mixer[i].playingpos >= mixer[i].data_len)
-    Mixer_RemoveSound(i);
+    Mixer_StopChannel(i);
 
   for(i=0; i<sample_size; i++)
     playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
@@ -815,7 +917,7 @@ static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
 
 void Mixer_Main()
 {
-  struct SoundControl snd_ctrl;
+  SoundControl snd_ctrl;
   fd_set mixer_fdset;
 
   close(audio.mixer_pipe[1]);  /* no writing into pipe needed */
@@ -837,9 +939,8 @@ void Mixer_Main()
     select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
     if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
       continue;
-    if (read(audio.mixer_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
-       != sizeof(snd_ctrl))
-      Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
+
+    ReadSoundControlFromMainProcess(&snd_ctrl);
 
     HandleSoundRequest(snd_ctrl);
 
@@ -890,140 +991,6 @@ void Mixer_Main()
 }
 #endif /* PLATFORM_UNIX */
 
-#if defined(PLATFORM_MSDOS)
-static void sound_handler(struct SoundControl snd_ctrl)
-{
-  int i;
-
-  if (snd_ctrl.fade_sound)
-  {
-    if (!mixer_active_channels)
-      return;
-
-    for (i=0; i<audio.num_channels; i++)
-      if ((snd_ctrl.stop_all_sounds ||
-          (i != audio.music_channel && mixer[i].nr == snd_ctrl.nr) ||
-          (i == audio.music_channel && snd_ctrl.music)) &&
-         !mixer[i].fade_sound)
-      {
-       mixer[i].fade_sound = TRUE;
-       if (voice_check(mixer[i].voice))
-         voice_ramp_volume(mixer[i].voice, 1000, 0);
-       mixer[i].state &= ~SND_CTRL_IS_LOOP;
-      }
-  }
-  else if (snd_ctrl.stop_all_sounds)
-  {
-    if (!mixer_active_channels)
-      return;
-    Mixer_StopAllSounds();
-  }
-  else if (snd_ctrl.stop_sound)
-  {
-    if (!mixer_active_channels)
-      return;
-    Mixer_StopSound(snd_ctrl);
-  }
-
-  for (i=0; i<audio.num_channels; i++)
-  {
-    if (!mixer[i].active || mixer[i].loop)
-      continue;
-
-    mixer[i].playingpos = voice_get_position(mixer[i].voice);
-    mixer[i].volume = voice_get_volume(mixer[i].voice);
-    if (mixer[i].playingpos == -1 || !mixer[i].volume)
-    {
-      deallocate_voice(mixer[i].voice);
-      Mixer_RemoveSound(i);
-    }
-  }
-
-  if (snd_ctrl.active)
-    Mixer_InsertNewSound(snd_ctrl);
-}
-#endif /* PLATFORM_MSDOS */
-
-#if 0
-#if defined(TARGET_SDL)
-static void sound_handler_SDL(struct SoundControl snd_ctrl)
-{
-  /* copy sound_handler() here ... */
-}
-#endif /* TARGET_SDL */
-#endif
-
-#if !defined(PLATFORM_WIN32)
-static void Mixer_InsertNewSound(struct SoundControl snd_ctrl)
-{
-  Mixer_InsertSound(snd_ctrl);
-}
-#endif /* !PLATFORM_WIN32 */
-
-/*
-void Mixer_FadeSound(int nr)
-{
-  int i;
-
-  if (!mixer_active_channels)
-    return;
-
-  for(i=0;i<audio.num_channels;i++)
-    if (snd_ctrl.stop_all_sounds || mixer[i].nr == snd_ctrl.nr)
-      mixer[i].fade_sound = TRUE;
-}
-*/
-
-#if !defined(PLATFORM_WIN32)
-#if defined(PLATFORM_MSDOS)
-static void Mixer_StopSound(struct SoundControl snd_ctrl)
-{
-  int nr = snd_ctrl.nr;
-  int i;
-
-  if (!mixer_active_channels)
-    return;
-
-  for(i=0; i<audio.num_channels; i++)
-  {
-    if ((i == audio.music_channel && snd_ctrl.music) ||
-       (i != audio.music_channel && mixer[i].nr == nr))
-    {
-#if defined(PLATFORM_MSDOS)
-      voice_set_volume(mixer[i].voice, 0);
-      deallocate_voice(mixer[i].voice);
-#endif
-      Mixer_RemoveSound(i);
-    }
-  }
-
-#if !defined(PLATFORM_MSDOS)
-  if (!mixer_active_channels)
-    close(audio.device_fd);
-#endif
-}
-
-static void Mixer_StopAllSounds()
-{
-  int i;
-
-  for(i=0; i<audio.num_channels; i++)
-  {
-#if defined(PLATFORM_MSDOS)
-    voice_set_volume(mixer[i].voice, 0);
-    deallocate_voice(mixer[i].voice);
-#endif
-    Mixer_RemoveSound(i);
-  }
-  mixer_active_channels = 0;
-
-#if !defined(PLATFORM_MSDOS)
-  close(audio.device_fd);
-#endif
-}
-#endif /* PLATFORM_MSDOS */
-#endif /* !PLATFORM_WIN32 */
-
 
 /* ------------------------------------------------------------------------- */
 /* platform dependant audio initialization code                              */
@@ -1647,7 +1614,7 @@ void PlaySoundMusic(int nr)
 
 void PlaySoundExt(int nr, int volume, int stereo, int state)
 {
-  struct SoundControl snd_ctrl;
+  SoundControl snd_ctrl;
 
   if (!audio.sound_available ||
       !audio.sound_enabled ||
@@ -1670,25 +1637,7 @@ void PlaySoundExt(int nr, int volume, int stereo, int state)
   snd_ctrl.stereo = stereo;
   snd_ctrl.state  = state;
 
-#if defined(TARGET_SDL)
-  if (Sound[nr])
-  {
-    Mix_Volume(-1, SOUND_MAX_VOLUME);
-    Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
-  }
-#elif defined(PLATFORM_UNIX)
-  if (audio.mixer_pid == 0)            /* we are child process */
-    return;
-
-  if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
-  {
-    Error(ERR_WARN, "cannot pipe to child process -- no sounds");
-    audio.sound_available = audio.sound_enabled = FALSE;
-    return;
-  }
-#elif defined(PLATFORM_MSDOS)
-  sound_handler(snd_ctrl);
-#endif
+  HandleSoundRequest(snd_ctrl);
 }
 
 void FadeMusic(void)
@@ -1741,7 +1690,7 @@ void StopSounds()
 
 void StopSoundExt(int nr, int state)
 {
-  struct SoundControl snd_ctrl;
+  SoundControl snd_ctrl;
 
   if (!audio.sound_available)
     return;
@@ -1750,47 +1699,7 @@ void StopSoundExt(int nr, int state)
   snd_ctrl.nr     = nr;
   snd_ctrl.state  = state;
 
-#if defined(TARGET_SDL)
-
-  if (state & SND_CTRL_FADE)
-  {
-    int i;
-
-    /*
-    for (i=audio.first_sound_channel; i<audio.num_channels; i++)
-    */
-
-    for (i=0; i<audio.channels; i++)
-      if (i != audio.music_channel || snd_ctrl.music)
-       Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
-    if (state & SND_CTRL_MUSIC)
-      Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
-  }
-  else
-  {
-    int i;
-
-    for (i=0; i<audio.channels; i++)
-      if (i != audio.music_channel || snd_ctrl.music)
-       Mix_HaltChannel(i);
-    if (state & SND_CTRL_MUSIC)
-      Mix_HaltMusic();
-  }
-
-#elif !defined(PLATFORM_MSDOS)
-
-  if (audio.mixer_pid == 0)            /* we are child process */
-    return;
-
-  if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
-  {
-    Error(ERR_WARN, "cannot pipe to child process -- no sounds");
-    audio.sound_available = audio.sound_enabled = FALSE;
-    return;
-  }
-#else /* PLATFORM_MSDOS */
-  sound_handler(snd_ctrl);
-#endif
+  HandleSoundRequest(snd_ctrl);
 }
 
 ListNode *newListNode()
@@ -2022,7 +1931,7 @@ void FreeAllSounds()
     return;
 
   printf("%s: FREEING SOUNDS ...\n",
-        audio.mixer_pid == 0 ? "CHILD" : "PARENT");
+        IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
 
   for(i=0; i<num_sounds; i++)
     deleteSoundEntry(&Sound[i]);
@@ -2031,7 +1940,7 @@ void FreeAllSounds()
   */
 
   printf("%s: FREEING SOUNDS -- DONE\n",
-        audio.mixer_pid == 0 ? "CHILD" : "PARENT");
+        IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
 
   free(Sound);