+static boolean Mixer_ChannelExpired(int channel)
+{
+ if (!mixer[channel].active)
+ return TRUE;
+
+ if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
+ DelayReached(&mixer[channel].playing_starttime,
+ SOUND_LOOP_EXPIRATION_TIME))
+ return TRUE;
+
+#if defined(TARGET_SDL)
+
+ if (!Mix_Playing(channel))
+ return TRUE;
+
+#elif defined(TARGET_ALLEGRO)
+
+ mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
+ mixer[channel].volume = voice_get_volume(mixer[channel].voice);
+
+ /* sound sample has completed playing or was completely faded out */
+ if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
+ return TRUE;
+
+#endif /* TARGET_ALLEGRO */
+
+ return FALSE;
+}
+
+static void Mixer_PlayChannel(int channel)
+{
+ /* start with inactive channel in case something goes wrong */
+ mixer[channel].active = FALSE;
+
+ if (mixer[channel].type != MUS_TYPE_WAV)
+ return;
+
+#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_position);
+ voice_start(mixer[channel].voice);
+#endif
+
+ Mixer_ResetChannelExpiration(channel);
+
+ mixer[channel].playing_pos = 0;
+ mixer[channel].active = TRUE;
+ mixer_active_channels++;
+}
+
+static void Mixer_PlayMusicChannel()
+{
+ Mixer_PlayChannel(audio.music_channel);
+
+#if defined(TARGET_SDL)
+ if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
+ {
+ /* 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_StopChannel(int channel)
+{
+ if (!mixer[channel].active)
+ return;
+
+#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_StopMusicChannel()
+{
+ Mixer_StopChannel(audio.music_channel);
+
+#if defined(TARGET_SDL)
+ Mix_HaltMusic();
+#endif
+}
+
+static void Mixer_FadeChannel(int channel)
+{
+ if (!mixer[channel].active)
+ return;
+
+ 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);
+#endif
+}
+
+static void Mixer_FadeMusicChannel()
+{
+ Mixer_FadeChannel(audio.music_channel);
+
+#if defined(TARGET_SDL)
+ Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
+#endif
+}
+
+static void Mixer_UnFadeChannel(int channel)
+{
+ if (!mixer[channel].active || !IS_FADING(mixer[channel]))
+ return;
+
+ mixer[channel].state &= ~SND_CTRL_FADE;
+ mixer[channel].volume = PSND_MAX_VOLUME;
+
+#if defined(TARGET_SDL)
+ Mix_ExpireChannel(channel, -1);
+ Mix_Volume(channel, SOUND_MAX_VOLUME);
+#elif defined(TARGET_ALLEGRO)
+ voice_stop_volumeramp(mixer[channel].voice);
+ voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
+ mixer[channel].volume);
+#endif
+}
+
+static void Mixer_InsertSound(SoundControl snd_ctrl)
+{
+ SoundInfo *snd_info;
+ int i, k;
+
+#if 0
+ printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);