Example #1
0
        /// <summary>Gets a cue-instance variable value based on its friendly name.</summary>
        /// <param name="name">Friendly name of the variable.</param>
        /// <returns>Value of the variable.</returns>
        /// <remarks>
        /// <para>Cue-instance variables are useful when multiple instantiations of a single cue (and its associated sounds) are required (for example, a "car" cue where there may be more than one car at any given time). While a global variable allows multiple audio elements to be controlled in unison, a cue instance variable grants discrete control of each instance of a cue, even for each copy of the same cue.</para>
        /// <para>The friendly name is a value set from the designer.</para>
        /// </remarks>
        public float GetVariable(string name)
        {
            if (name == "Volume")
            {
                return(volume);
            }

            return(engine.GetGlobalVariable(name));
        }
Example #2
0
 public float GetVariable(string name)
 {
     if (name == "Volume")
     {
         return(volume);
     }
     else if (curSound != null && curSound.rpcVariables.ContainsKey(name))
     {
         return(curSound.rpcVariables[name]);
     }
     else
     {
         return(engine.GetGlobalVariable(name));
     }
 }
Example #3
0
File: Cue.cs Project: raizam/FNA
        internal bool INTERNAL_update()
        {
            // If we're not running, save some instructions...
            if (!INTERNAL_timer.IsRunning)
            {
                return(true);
            }
            elapsedFrames += 1;

            // Play events when the timestamp has been hit.
            for (int i = 0; i < INTERNAL_eventList.Count; i += 1)
            {
                if (!INTERNAL_eventPlayed[i] &&
                    INTERNAL_timer.ElapsedMilliseconds > INTERNAL_eventList[i].Timestamp)
                {
                    uint type = INTERNAL_eventList[i].Type;
                    if (type == 1)
                    {
                        PlayWave((PlayWaveEvent)INTERNAL_eventList[i]);
                    }
                    else if (type == 2)
                    {
                        eventVolume = ((SetVolumeEvent)INTERNAL_eventList[i]).GetVolume();
                    }
                    else if (type == 3)
                    {
                        eventPitch = ((SetPitchEvent)INTERNAL_eventList[i]).GetPitch();
                    }
                    else
                    {
                        throw new NotImplementedException("Unhandled XACTEvent type!");
                    }
                    INTERNAL_eventPlayed[i] = true;
                }
            }

            // Clear out sound effect instances as they finish
            for (int i = 0; i < INTERNAL_instancePool.Count; i += 1)
            {
                if (INTERNAL_instancePool[i].State == SoundState.Stopped)
                {
                    // Get the event that spawned this instance...
                    PlayWaveEvent evt        = (PlayWaveEvent)INTERNAL_waveEventSounds[INTERNAL_instancePool[i]];
                    float         prevVolume = INTERNAL_instanceVolumes[i];
                    float         prevPitch  = INTERNAL_instancePitches[i];

                    // Then delete all the guff
                    INTERNAL_waveEventSounds.Remove(INTERNAL_instancePool[i]);
                    INTERNAL_instancePool[i].Dispose();
                    INTERNAL_instancePool.RemoveAt(i);
                    INTERNAL_instanceVolumes.RemoveAt(i);
                    INTERNAL_instancePitches.RemoveAt(i);
                    INTERNAL_rpcTrackVolumes.RemoveAt(i);
                    INTERNAL_rpcTrackPitches.RemoveAt(i);

                    // Increment the loop counter, try to get another loop
                    INTERNAL_eventLoops[evt] += 1;
                    PlayWave(evt, prevVolume, prevPitch);

                    // Removed a wave, have to step back...
                    i -= 1;
                }
            }

            // Fade in/out
            float fadePerc = 1.0f;

            if (INTERNAL_fadeMode != FadeMode.None)
            {
                if (INTERNAL_fadeMode == FadeMode.FadeOut)
                {
                    if (INTERNAL_category.crossfadeType == CrossfadeType.Linear)
                    {
                        fadePerc = (INTERNAL_fadeEnd - (INTERNAL_timer.ElapsedMilliseconds - INTERNAL_fadeStart)) / (float)INTERNAL_fadeEnd;
                    }
                    else
                    {
                        throw new NotImplementedException("Unhandled CrossfadeType!");
                    }
                    if (fadePerc <= 0.0f)
                    {
                        Stop(AudioStopOptions.Immediate);
                        INTERNAL_fadeMode = FadeMode.None;
                        return(false);
                    }
                }
                else
                {
                    if (INTERNAL_category.crossfadeType == CrossfadeType.Linear)
                    {
                        fadePerc = INTERNAL_timer.ElapsedMilliseconds / (float)INTERNAL_fadeEnd;
                    }
                    else
                    {
                        throw new NotImplementedException("Unhandled CrossfadeType!");
                    }
                    if (fadePerc > 1.0f)
                    {
                        fadePerc          = 1.0f;
                        INTERNAL_fadeMode = FadeMode.None;
                    }
                }
            }

            // User control updates
            if (INTERNAL_data.IsUserControlled)
            {
                string varName = INTERNAL_data.UserControlVariable;
                if (INTERNAL_userControlledPlaying &&
                    (INTERNAL_baseEngine.INTERNAL_isGlobalVariable(varName) ?
                     !MathHelper.WithinEpsilon(INTERNAL_controlledValue, INTERNAL_baseEngine.GetGlobalVariable(varName)) :
                     !MathHelper.WithinEpsilon(INTERNAL_controlledValue, GetVariable(INTERNAL_data.UserControlVariable))))
                {
                    // TODO: Crossfading
                    foreach (SoundEffectInstance sfi in INTERNAL_instancePool)
                    {
                        sfi.Stop();
                        sfi.Dispose();
                    }
                    INTERNAL_instancePool.Clear();
                    INTERNAL_instanceVolumes.Clear();
                    INTERNAL_instancePitches.Clear();
                    INTERNAL_rpcTrackVolumes.Clear();
                    INTERNAL_rpcTrackPitches.Clear();
                    if (!INTERNAL_calculateNextSound())
                    {
                        // Nothing to play, bail.
                        return(true);
                    }
                    INTERNAL_activeSound.GatherEvents(INTERNAL_eventList);
                    foreach (XACTEvent evt in INTERNAL_eventList)
                    {
                        INTERNAL_eventPlayed.Add(false);
                        INTERNAL_eventLoops.Add(evt, 0);
                    }
                    INTERNAL_timer.Stop();
                    INTERNAL_timer.Reset();
                    INTERNAL_timer.Start();
                }

                if (INTERNAL_activeSound == null)
                {
                    return(INTERNAL_userControlledPlaying);
                }
            }

            // If everything has been played and finished, we're done here.
            if (INTERNAL_instancePool.Count == 0)
            {
                bool allPlayed = true;
                foreach (bool played in INTERNAL_eventPlayed)
                {
                    if (!played)
                    {
                        allPlayed = false;
                        break;
                    }
                }
                if (allPlayed)
                {
                    // If this is managed, we're done completely.
                    if (INTERNAL_isManaged)
                    {
                        Dispose();
                    }
                    else
                    {
                        INTERNAL_timer.Stop();
                        INTERNAL_timer.Reset();
                        INTERNAL_category.INTERNAL_removeActiveCue(this);
                    }
                    return(INTERNAL_userControlledPlaying);
                }
            }

            // RPC updates
            float rpcVolume = 1.0f;
            float rpcPitch  = 0.0f;
            float hfGain    = 1.0f;
            float lfGain    = 1.0f;

            for (int i = 0; i < INTERNAL_activeSound.RPCCodes.Count; i += 1)
            {
                if (i > INTERNAL_instancePool.Count)
                {
                    break;
                }
                if (i > 0)
                {
                    INTERNAL_rpcTrackVolumes[i - 1] = 1.0f;
                    INTERNAL_rpcTrackPitches[i - 1] = 0.0f;
                }
                foreach (uint curCode in INTERNAL_activeSound.RPCCodes[i])
                {
                    RPC   curRPC = INTERNAL_baseEngine.INTERNAL_getRPC(curCode);
                    float result;
                    if (!INTERNAL_baseEngine.INTERNAL_isGlobalVariable(curRPC.Variable))
                    {
                        result = curRPC.CalculateRPC(GetVariable(curRPC.Variable));
                    }
                    else
                    {
                        // It's a global variable we're looking for!
                        result = curRPC.CalculateRPC(
                            INTERNAL_baseEngine.GetGlobalVariable(
                                curRPC.Variable
                                )
                            );
                    }
                    if (curRPC.Parameter == RPCParameter.Volume)
                    {
                        float vol = XACTCalculator.CalculateAmplitudeRatio(result / 100.0);
                        if (i == 0)
                        {
                            rpcVolume *= vol;
                        }
                        else
                        {
                            INTERNAL_rpcTrackVolumes[i - 1] *= vol;
                        }
                    }
                    else if (curRPC.Parameter == RPCParameter.Pitch)
                    {
                        float pitch = result / 1000.0f;
                        if (i == 0)
                        {
                            rpcPitch += pitch;
                        }
                        else
                        {
                            INTERNAL_rpcTrackPitches[i - 1] += pitch;
                        }
                    }
                    else if (curRPC.Parameter == RPCParameter.FilterFrequency)
                    {
                        // FIXME: Just listening to the last RPC!
                        float hf = result / 20000.0f;
                        float lf = 1.0f - hf;
                        if (i == 0)
                        {
                            hfGain = hf;
                            lfGain = lf;
                        }
                        else
                        {
                            throw new NotImplementedException("Per-track filter RPCs!");
                        }
                    }
                    else
                    {
                        throw new NotImplementedException("RPC Parameter Type: " + curRPC.Parameter.ToString());
                    }
                }
            }

            // Sound effect instance updates
            for (int i = 0; i < INTERNAL_instancePool.Count; i += 1)
            {
                /* The final volume should be the combination of the
                 * authored volume, category volume, RPC/Event volumes, and fade.
                 */
                INTERNAL_instancePool[i].Volume = (
                    INTERNAL_instanceVolumes[i] *
                    INTERNAL_category.INTERNAL_volume.Value *
                    rpcVolume *
                    INTERNAL_rpcTrackVolumes[i] *
                    eventVolume *
                    fadePerc
                    );

                /* The final pitch should be the combination of the
                 * authored pitch and RPC/Event pitch results.
                 */
                INTERNAL_instancePool[i].Pitch = (
                    INTERNAL_instancePitches[i] +
                    rpcPitch +
                    eventPitch +
                    INTERNAL_rpcTrackPitches[i]
                    );

                /* The final filter is determined by the instance's filter type,
                 * in addition to our calculation of the HF/LF gain values.
                 */
                byte fType = INTERNAL_instancePool[i].FilterType;
                if (fType == 0xFF)
                {
                    // No-op, no filter!
                }
                else if (fType == 0)
                {
                    INTERNAL_instancePool[i].INTERNAL_applyLowPassFilter(hfGain);
                }
                else if (fType == 1)
                {
                    INTERNAL_instancePool[i].INTERNAL_applyHighPassFilter(lfGain);
                }
                else if (fType == 2)
                {
                    INTERNAL_instancePool[i].INTERNAL_applyBandPassFilter(hfGain, lfGain);
                }
                else
                {
                    throw new InvalidOperationException("Unhandled filter type!");
                }

                // Update 3D position, if applicable
                if (INTERNAL_isPositional)
                {
                    INTERNAL_instancePool[i].Apply3D(
                        INTERNAL_listener,
                        INTERNAL_emitter
                        );
                }
            }

            return(true);
        }
Example #4
0
        internal bool INTERNAL_update()
        {
            // If this is our first update, time to play!
            if (INTERNAL_queuedPlayback)
            {
                INTERNAL_queuedPlayback = false;
                foreach (SoundEffectInstance sfi in INTERNAL_instancePool)
                {
                    sfi.Play();
                    if (INTERNAL_queuedPaused)
                    {
                        sfi.Pause();
                    }
                }
                INTERNAL_queuedPaused = false;
            }

            for (int i = 0; i < INTERNAL_instancePool.Count; i += 1)
            {
                if (INTERNAL_instancePool[i].INTERNAL_timer.ElapsedMilliseconds > INTERNAL_instancePool[i].INTERNAL_delayMS)
                {
                    // Okay, play this NOW!
                    INTERNAL_instancePool[i].Play();
                    if (IsPaused)
                    {
                        INTERNAL_instancePool[i].Pause();
                    }
                }
                if (INTERNAL_instancePool[i].State == SoundState.Stopped)
                {
                    INTERNAL_instancePool[i].Dispose();
                    INTERNAL_instancePool.RemoveAt(i);
                    INTERNAL_instanceVolumes.RemoveAt(i);
                    INTERNAL_instancePitches.RemoveAt(i);
                    i -= 1;
                }
            }

            // User control updates
            if (INTERNAL_data.IsUserControlled)
            {
                if (INTERNAL_userControlledPlaying &&
                    INTERNAL_controlledValue != GetVariable(INTERNAL_data.UserControlVariable))
                {
                    // TODO: Crossfading
                    foreach (SoundEffectInstance sfi in INTERNAL_instancePool)
                    {
                        sfi.Stop();
                        sfi.Dispose();
                    }
                    INTERNAL_instancePool.Clear();
                    INTERNAL_instanceVolumes.Clear();
                    INTERNAL_instancePitches.Clear();
                    if (!INTERNAL_calculateNextSound())
                    {
                        // Nothing to play, bail.
                        return(true);
                    }
                    INTERNAL_setupSounds();
                    foreach (SoundEffectInstance sfi in INTERNAL_instancePool)
                    {
                        sfi.Play();
                    }
                }

                if (INTERNAL_activeSound == null)
                {
                    return(INTERNAL_userControlledPlaying);
                }
            }

            if (INTERNAL_isPositional)
            {
                foreach (SoundEffectInstance sfi in INTERNAL_instancePool)
                {
                    sfi.Apply3D(
                        INTERNAL_listener,
                        INTERNAL_emitter
                        );
                }
            }

            float rpcVolume = 1.0f;
            float rpcPitch  = 0.0f;

            foreach (uint curCode in INTERNAL_activeSound.RPCCodes)
            {
                RPC   curRPC = INTERNAL_baseEngine.INTERNAL_getRPC(curCode);
                float result;
                if (!INTERNAL_baseEngine.INTERNAL_isGlobalVariable(curRPC.Variable))
                {
                    result = curRPC.CalculateRPC(GetVariable(curRPC.Variable));
                }
                else
                {
                    // It's a global variable we're looking for!
                    result = curRPC.CalculateRPC(
                        INTERNAL_baseEngine.GetGlobalVariable(
                            curRPC.Variable
                            )
                        );
                }
                if (curRPC.Parameter == RPCParameter.Volume)
                {
                    rpcVolume *= XACTCalculator.CalculateAmplitudeRatio(result / 100.0);
                }
                else if (curRPC.Parameter == RPCParameter.Pitch)
                {
                    rpcPitch += result / 1000.0f;
                }
                else if (curRPC.Parameter == RPCParameter.FilterFrequency)
                {
                    // TODO: Filters?
                }
                else
                {
                    throw new Exception("RPC Parameter Type: " + curRPC.Parameter.ToString());
                }
            }
            for (int i = 0; i < INTERNAL_instancePool.Count; i += 1)
            {
                /* The final volume should be the combination of the
                 * authored volume, Volume variable and RPC volume results.
                 */
                INTERNAL_instancePool[i].Volume = INTERNAL_instanceVolumes[i] * GetVariable("Volume") * rpcVolume;

                /* The final pitch should be the combination of the
                 * authored pitch and RPC pitch results.
                 */
                INTERNAL_instancePool[i].Pitch = INTERNAL_instancePitches[i] + rpcPitch;
            }

            // Finally, check if we're still active.
            if (IsStopped && !INTERNAL_queuedPlayback && !INTERNAL_userControlledPlaying)
            {
                // If this is managed, we're done here.
                if (INTERNAL_isManaged)
                {
                    Dispose();
                }
                return(false);
            }
            return(true);
        }
Example #5
0
        private float UpdateRpcCurves()
        {
            var volume = 1.0f;

            // Evaluate the runtime parameter controls.
            var rpcCurves = _curSound.RpcCurves;

            if (rpcCurves.Length > 0)
            {
                var   pitch           = 0.0f;
                var   reverbMix       = 1.0f;
                float?filterFrequency = null;
                float?filterQFactor   = null;

                for (var i = 0; i < rpcCurves.Length; i++)
                {
                    var rpcCurve = _engine.RpcCurves[rpcCurves[i]];

                    // Some curves are driven by global variables and others by cue instance variables.
                    float value;
                    if (rpcCurve.IsGlobal)
                    {
                        value = rpcCurve.Evaluate(_engine.GetGlobalVariable(rpcCurve.Variable));
                    }
                    else
                    {
                        value = rpcCurve.Evaluate(_variables[rpcCurve.Variable].Value);
                    }

                    // Process the final curve value based on the parameter type it is.
                    switch (rpcCurve.Parameter)
                    {
                    case RpcParameter.Volume:
                        volume *= XactHelpers.ParseVolumeFromDecibels(value / 100.0f);
                        break;

                    case RpcParameter.Pitch:
                        pitch += value / 1000.0f;
                        break;

                    case RpcParameter.ReverbSend:
                        reverbMix *= XactHelpers.ParseVolumeFromDecibels(value / 100.0f);
                        break;

                    case RpcParameter.FilterFrequency:
                        filterFrequency = value;
                        break;

                    case RpcParameter.FilterQFactor:
                        filterQFactor = value;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("rpcCurve.Parameter");
                    }
                }

                pitch = MathHelper.Clamp(pitch, -1.0f, 1.0f);
                if (volume < 0.0f)
                {
                    volume = 0.0f;
                }

                _curSound.UpdateState(_engine, volume, pitch, reverbMix, filterFrequency, filterQFactor);
            }

            return(volume);
        }
Example #6
0
        internal bool INTERNAL_update()
        {
            // If we're not running, save some instructions...
            if (!INTERNAL_timer.IsRunning)
            {
                return(true);
            }
            elapsedFrames += 1;

            // User control updates
            if (INTERNAL_data.IsUserControlled)
            {
                string varName = INTERNAL_data.UserControlVariable;
                if (INTERNAL_userControlledPlaying &&
                    (INTERNAL_baseEngine.INTERNAL_isGlobalVariable(varName) ?
                     !MathHelper.WithinEpsilon(INTERNAL_controlledValue, INTERNAL_baseEngine.GetGlobalVariable(varName)) :
                     !MathHelper.WithinEpsilon(INTERNAL_controlledValue, GetVariable(INTERNAL_data.UserControlVariable))))
                {
                    // TODO: Crossfading
                    foreach (SoundEffectInstance sfi in INTERNAL_instancePool)
                    {
                        sfi.Stop();
                        sfi.Dispose();
                    }
                    INTERNAL_instancePool.Clear();
                    INTERNAL_instanceVolumes.Clear();
                    INTERNAL_instancePitches.Clear();
                    INTERNAL_rpcTrackVolumes.Clear();
                    INTERNAL_rpcTrackPitches.Clear();
                    if (!INTERNAL_calculateNextSound())
                    {
                        // Nothing to play, bail.
                        return(true);
                    }
                    INTERNAL_activeSound.InitializeClips();
                    INTERNAL_timer.Stop();
                    INTERNAL_timer.Reset();
                    INTERNAL_timer.Start();
                }

                if (INTERNAL_activeSound == null)
                {
                    return(INTERNAL_userControlledPlaying);
                }
            }

            // Trigger events for each track
            foreach (XACTClipInstance clip in INTERNAL_activeSound.Clips)
            {
                // Play events when the timestamp has been hit.
                for (int i = 0; i < clip.Events.Count; i += 1)
                {
                    EventInstance evt = clip.Events[i];

                    if (!evt.Played &&
                        INTERNAL_timer.ElapsedMilliseconds > evt.Timestamp)
                    {
                        evt.Apply(
                            this,
                            null,
                            INTERNAL_timer.ElapsedMilliseconds / 1000.0f
                            );
                    }
                }
            }


            // Clear out sound effect instances as they finish
            for (int i = 0; i < INTERNAL_instancePool.Count; i += 1)
            {
                if (INTERNAL_instancePool[i].State == SoundState.Stopped)
                {
                    // Get the event that spawned this instance...
                    PlayWaveEventInstance evtInstance =
                        INTERNAL_playWaveEventBySound[INTERNAL_instancePool[i]];
                    double prevVolume = INTERNAL_instanceVolumes[i];
                    short  prevPitch  = INTERNAL_instancePitches[i];

                    // Then delete all the guff
                    INTERNAL_playWaveEventBySound.Remove(INTERNAL_instancePool[i]);
                    INTERNAL_instancePool[i].Dispose();
                    INTERNAL_instancePool.RemoveAt(i);
                    INTERNAL_instanceVolumes.RemoveAt(i);
                    INTERNAL_instancePitches.RemoveAt(i);
                    INTERNAL_rpcTrackVolumes.RemoveAt(i);
                    INTERNAL_rpcTrackPitches.RemoveAt(i);

                    // Increment the loop counter, try to get another loop
                    evtInstance.LoopCount += 1;
                    PlayWave(evtInstance, prevVolume, prevPitch);

                    // Removed a wave, have to step back...
                    i -= 1;
                }
            }

            // Fade in/out
            float fadePerc = 1.0f;

            if (INTERNAL_fadeMode != FadeMode.None)
            {
                if (INTERNAL_fadeMode == FadeMode.FadeOut)
                {
                    if (INTERNAL_category.crossfadeType == CrossfadeType.Linear)
                    {
                        fadePerc = (
                            INTERNAL_fadeEnd -
                            (
                                INTERNAL_timer.ElapsedMilliseconds -
                                INTERNAL_fadeStart
                            )
                            ) / (float)INTERNAL_fadeEnd;
                    }
                    else
                    {
                        throw new NotImplementedException("Unhandled CrossfadeType!");
                    }
                    if (fadePerc <= 0.0f)
                    {
                        Stop(AudioStopOptions.Immediate);
                        INTERNAL_fadeMode = FadeMode.None;
                        return(false);
                    }
                }
                else if (INTERNAL_fadeMode == FadeMode.FadeIn)
                {
                    if (INTERNAL_category.crossfadeType == CrossfadeType.Linear)
                    {
                        fadePerc = INTERNAL_timer.ElapsedMilliseconds / (float)INTERNAL_fadeEnd;
                    }
                    else
                    {
                        throw new NotImplementedException("Unhandled CrossfadeType!");
                    }
                    if (fadePerc > 1.0f)
                    {
                        fadePerc          = 1.0f;
                        INTERNAL_fadeMode = FadeMode.None;
                    }
                }
                else if (INTERNAL_fadeMode == FadeMode.ReleaseRpc)
                {
                    float releasePerc = (
                        INTERNAL_timer.ElapsedMilliseconds -
                        INTERNAL_fadeStart
                        ) / (float)INTERNAL_maxRpcReleaseTime;
                    if (releasePerc > 1.0f)
                    {
                        Stop(AudioStopOptions.Immediate);
                        INTERNAL_fadeMode = FadeMode.None;
                        return(false);
                    }
                }
                else
                {
                    throw new NotImplementedException("Unsupported FadeMode!");
                }
            }

            // If everything has been played and finished, we're done here.
            if (INTERNAL_instancePool.Count == 0)
            {
                bool allPlayed = true;
                foreach (XACTClipInstance clipInstance in INTERNAL_activeSound.Clips)
                {
                    foreach (EventInstance evt in clipInstance.Events)
                    {
                        if (!evt.Played)
                        {
                            allPlayed = false;
                            break;
                        }
                    }
                }
                if (allPlayed)
                {
                    // If this is managed, we're done completely.
                    if (INTERNAL_isManaged)
                    {
                        Dispose();
                    }
                    else
                    {
                        KillCue();
                    }
                    if (INTERNAL_userControlledPlaying)
                    {
                        // We're "still" "playing" right now...
                        return(true);
                    }
                    IsStopped = true;
                    return(false);
                }
            }

            // RPC updates
            float rpcVolume = 0.0f;
            float rpcPitch  = 0.0f;
            float hfGain    = 1.0f;
            float lfGain    = 1.0f;

            for (int i = 0; i < INTERNAL_activeSound.Sound.RPCCodes.Count; i += 1)
            {
                // Are we processing an RPC targeting the sound itself rather than a track?
                bool isSoundRpc = i == 0 && INTERNAL_activeSound.Sound.HasSoundRpcs;

                // If there is an RPC targeting the sound instance itself, it is handled in rpcVolume/rpcPitch, and the first track is at i-1.
                int trackRpcIndex = INTERNAL_activeSound.Sound.HasSoundRpcs ? i - 1 : i;

                // If this RPC Code is for a track that is not active yet, we have nothing to do.
                if (trackRpcIndex >= INTERNAL_instancePool.Count)
                {
                    // FIXME: This presumes that tracks start in order, which doesn't have to be true.
                    break;
                }
                if (!isSoundRpc)
                {
                    INTERNAL_rpcTrackVolumes[trackRpcIndex] = 0.0f;
                    INTERNAL_rpcTrackPitches[trackRpcIndex] = 0.0f;
                }

                foreach (uint curCode in INTERNAL_activeSound.Sound.RPCCodes[i])
                {
                    RPC   curRPC = INTERNAL_baseEngine.INTERNAL_getRPC(curCode);
                    float result;
                    if (!INTERNAL_baseEngine.INTERNAL_isGlobalVariable(curRPC.Variable))
                    {
                        float variableValue;

                        if (curRPC.Variable.Equals("AttackTime"))
                        {
                            PlayWaveEvent playWaveEvent =
                                (PlayWaveEvent)INTERNAL_activeSound.Sound.INTERNAL_clips[trackRpcIndex].Events[0];

                            long elapsedFromPlay = INTERNAL_timer.ElapsedMilliseconds
                                                   - playWaveEvent.Timestamp;
                            variableValue = elapsedFromPlay;
                        }
                        else if (curRPC.Variable.Equals("ReleaseTime"))
                        {
                            if (INTERNAL_fadeMode == FadeMode.ReleaseRpc)
                            {
                                long elapsedFromStop = INTERNAL_timer.ElapsedMilliseconds - INTERNAL_fadeStart;
                                variableValue = elapsedFromStop;
                            }
                            else
                            {
                                variableValue = 0.0f;
                            }
                        }
                        else
                        {
                            variableValue = GetVariable(curRPC.Variable);
                        }

                        result = curRPC.CalculateRPC(variableValue);
                    }
                    else
                    {
                        // It's a global variable we're looking for!
                        result = curRPC.CalculateRPC(
                            INTERNAL_baseEngine.GetGlobalVariable(
                                curRPC.Variable
                                )
                            );
                    }
                    if (curRPC.Parameter == RPCParameter.Volume)
                    {
                        // If this RPC targets the sound instance itself then apply to the dedicated variable.
                        if (isSoundRpc)
                        {
                            rpcVolume += result;
                        }
                        else
                        {
                            INTERNAL_rpcTrackVolumes[trackRpcIndex] += result;
                        }
                    }
                    else if (curRPC.Parameter == RPCParameter.Pitch)
                    {
                        float pitch = result;
                        if (isSoundRpc)
                        {
                            rpcPitch += pitch;
                        }
                        else
                        {
                            INTERNAL_rpcTrackPitches[trackRpcIndex] += pitch;
                        }
                    }
                    else if (curRPC.Parameter == RPCParameter.FilterFrequency)
                    {
                        // FIXME: Just listening to the last RPC!
                        float hf = result / 20000.0f;
                        float lf = 1.0f - hf;
                        if (isSoundRpc)
                        {
                            hfGain = hf;
                            lfGain = lf;
                        }
                        else
                        {
                            throw new NotImplementedException("Per-track filter RPCs!");
                        }
                    }
                    else
                    {
                        throw new NotImplementedException(
                                  "RPC Parameter Type: " + curRPC.Parameter.ToString()
                                  );
                    }
                }
            }

            // Sound effect instance updates
            for (int i = 0; i < INTERNAL_instancePool.Count; i += 1)
            {
                /* The final volume should be the combination of the
                 * authored volume, category volume, RPC sound/track
                 * volumes, event volumes, and fade.
                 */
                INTERNAL_instancePool[i].Volume = XACTCalculator.CalculateAmplitudeRatio(
                    INTERNAL_instanceVolumes[i] +
                    rpcVolume +
                    INTERNAL_rpcTrackVolumes[i] +
                    eventVolume
                    ) * INTERNAL_category.INTERNAL_volume.Value * fadePerc;

                /* The final pitch should be the combination of the
                 * authored pitch, RPC sound/track pitches, and event
                 * pitch.
                 *
                 * XACT uses -1200 to 1200 (+/- 12 semitones),
                 * XNA uses -1.0f to 1.0f (+/- 1 octave).
                 */
                INTERNAL_instancePool[i].Pitch = (
                    INTERNAL_instancePitches[i] +
                    rpcPitch +
                    INTERNAL_rpcTrackPitches[i] +
                    eventPitch
                    ) / 1200.0f;

                /* The final filter is determined by the instance's filter type,
                 * in addition to our calculation of the HF/LF gain values.
                 */
                byte fType = INTERNAL_instancePool[i].FilterType;
                if (fType == 0xFF)
                {
                    // No-op, no filter!
                }
                else if (fType == 0)
                {
                    INTERNAL_instancePool[i].INTERNAL_applyLowPassFilter(hfGain);
                }
                else if (fType == 1)
                {
                    INTERNAL_instancePool[i].INTERNAL_applyHighPassFilter(lfGain);
                }
                else if (fType == 2)
                {
                    INTERNAL_instancePool[i].INTERNAL_applyBandPassFilter(hfGain, lfGain);
                }
                else
                {
                    throw new InvalidOperationException("Unhandled filter type!");
                }

                // Update 3D position, if applicable
                if (INTERNAL_isPositional)
                {
                    INTERNAL_instancePool[i].Apply3D(
                        INTERNAL_listener,
                        INTERNAL_emitter
                        );
                }
            }

            return(true);
        }