+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 boolean Mixer_AllocateChannel(int channel)
+{
+#if defined(TARGET_ALLEGRO)
+ mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
+ if (mixer[channel].voice < 0)
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static void Mixer_SetChannelProperties(int channel)
+{
+#if defined(TARGET_SDL)
+ Mix_Volume(channel, mixer[channel].volume);
+ Mix_SetPanning(channel,
+ SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
+ SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
+#elif defined(TARGET_ALLEGRO)
+ voice_set_volume(mixer[channel].voice, mixer[channel].volume);
+ voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
+#endif
+}
+
+static void Mixer_StartChannel(int channel)
+{
+#if defined(TARGET_SDL)
+ Mix_PlayChannel(channel, mixer[channel].data_ptr,
+ IS_LOOP(mixer[channel]) ? -1 : 0);
+#elif defined(TARGET_ALLEGRO)
+ if (IS_LOOP(mixer[channel]))
+ voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
+
+ voice_start(mixer[channel].voice);
+#endif
+}
+
+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 (!Mixer_AllocateChannel(channel))
+ return;
+
+ Mixer_SetChannelProperties(channel);
+ Mixer_StartChannel(channel);
+
+ 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(TARGET_ALLEGRO)
+ 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(TARGET_ALLEGRO)
+ 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 = SOUND_MAX_VOLUME;
+
+#if defined(TARGET_SDL)
+ Mix_ExpireChannel(channel, -1);
+ Mix_Volume(channel, mixer[channel].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;
+ int num_sounds = getSoundListSize();
+
+#if 0
+ printf("NEW SOUND %d ARRIVED [%d] [%d ACTIVE CHANNELS]\n",
+ snd_ctrl.nr, num_sounds, mixer_active_channels);
+#endif
+
+ if (IS_MUSIC(snd_ctrl))
+ {
+ if (num_music == 0)
+ return;
+
+ snd_ctrl.nr = snd_ctrl.nr % num_music;
+ }
+ else if (snd_ctrl.nr >= num_sounds)
+ return;
+
+#if 0
+ snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
+#else
+ snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] :
+ getSoundInfoEntryFromSoundID(snd_ctrl.nr));