private void Apply3D(Vector3 listenerForward, Vector3 listenerUp, Vector3 listenerPosition, Vector3 listenerVelocity, Vector3 emitterForward, Vector3 emitterUp, Vector3 emitterPosition, Vector3 emitterVelocity)
        {
            if (!Effect.AudioManager.IsSpatialAudioEnabled)
            {
                throw new InvalidOperationException("Spatial audio must be enabled first.");
            }

            if (emitter == null)
            {
                emitter = new Emitter();
            }

            emitter.OrientFront         = emitterForward;
            emitter.OrientTop           = emitterUp;
            emitter.Position            = emitterPosition;
            emitter.Velocity            = emitterVelocity;
            emitter.DopplerScaler       = SoundEffect.DopplerScale;
            emitter.CurveDistanceScaler = SoundEffect.DistanceScale;
            emitter.ChannelCount        = Effect.Format.Channels;

            //TODO: work out what ChannelAzimuths is supposed to be.
            if (emitter.ChannelCount > 1)
            {
                emitter.ChannelAzimuths = new float[emitter.ChannelCount];
            }

            if (listener == null)
            {
                listener = new Listener();
            }

            listener.OrientFront = listenerForward;
            listener.OrientTop   = listenerUp;
            listener.Position    = listenerPosition;
            listener.Velocity    = listenerVelocity;

            if (dspSettings == null)
            {
                dspSettings = new DspSettings(Effect.Format.Channels, Effect.AudioManager.MasteringVoice.VoiceDetails.InputChannelCount);
            }

            CalculateFlags flags = CalculateFlags.Matrix | CalculateFlags.Doppler | CalculateFlags.LpfDirect;

            if ((Effect.AudioManager.Speakers & Speakers.LowFrequency) > 0)
            {
                // On devices with an LFE channel, allow the mono source data to be routed to the LFE destination channel.
                flags |= CalculateFlags.RedirectToLfe;
            }

            if (Effect.AudioManager.IsReverbEffectEnabled)
            {
                flags |= CalculateFlags.Reverb | CalculateFlags.LpfReverb;

                if (!isReverbSubmixEnabled)
                {
                    VoiceSendFlags        sendFlags    = Effect.AudioManager.IsReverbFilterEnabled ? VoiceSendFlags.UseFilter : VoiceSendFlags.None;
                    VoiceSendDescriptor[] outputVoices = new VoiceSendDescriptor[]
                    {
                        new VoiceSendDescriptor {
                            OutputVoice = Effect.AudioManager.MasteringVoice, Flags = sendFlags
                        },
                        new VoiceSendDescriptor {
                            OutputVoice = Effect.AudioManager.ReverbVoice, Flags = sendFlags
                        }
                    };

                    voice.SetOutputVoices(outputVoices);
                    isReverbSubmixEnabled = true;
                }
            }

            Effect.AudioManager.Calculate3D(listener, emitter, flags, dspSettings);

            voice.SetFrequencyRatio(dspSettings.DopplerFactor);
            voice.SetOutputMatrix(Effect.AudioManager.MasteringVoice, dspSettings.SourceChannelCount, dspSettings.DestinationChannelCount, dspSettings.MatrixCoefficients);

            if (Effect.AudioManager.IsReverbEffectEnabled)
            {
                if (reverbLevels == null || reverbLevels.Length != Effect.Format.Channels)
                {
                    reverbLevels = new float[Effect.Format.Channels];
                }

                for (int i = 0; i < reverbLevels.Length; i++)
                {
                    reverbLevels[i] = dspSettings.ReverbLevel;
                }

                voice.SetOutputMatrix(Effect.AudioManager.ReverbVoice, Effect.Format.Channels, 1, reverbLevels);
            }

            if (Effect.AudioManager.IsReverbFilterEnabled)
            {
                FilterParameters filterDirect = new FilterParameters
                {
                    Type = FilterType.LowPassFilter,
                    // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here
                    Frequency = 2.0f * (float)Math.Sin(X3DAudio.PI / 6.0f * dspSettings.LpfDirectCoefficient),
                    OneOverQ  = 1.0f
                };

                voice.SetOutputFilterParameters(Effect.AudioManager.MasteringVoice, filterDirect);

                if (Effect.AudioManager.IsReverbEffectEnabled)
                {
                    FilterParameters filterReverb = new FilterParameters
                    {
                        Type = FilterType.LowPassFilter,
                        // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here
                        Frequency = 2.0f * (float)Math.Sin(X3DAudio.PI / 6.0f * dspSettings.LpfReverbCoefficient),
                        OneOverQ  = 1.0f
                    };

                    voice.SetOutputFilterParameters(Effect.AudioManager.ReverbVoice, filterReverb);
                }
            }
        }
        /// <summary>
        /// Applies the 3D effect to the current sound effect instance.
        /// </summary>
        /// <param name="listenerAgent">Listener</param>
        /// <param name="emitterAgent">Emitter</param>
        private void Apply3D()
        {
            UpdateListener(Listener);
            UpdateEmitter(Emitter);

            var flags = Calculate3DFlags();

            if (dspSettings == null)
            {
                dspSettings = new DspSettings(
                    this.Effect.WaveFormat.Channels,
                    this.Effect.GameAudio.MasteringVoice.VoiceDetails.InputChannelCount);
            }

            this.Effect.GameAudio.Calculate3D(listener, emitter, flags, dspSettings);

            voice.SetFrequencyRatio(dspSettings.DopplerFactor);

            voice.SetOutputMatrix(
                this.Effect.GameAudio.MasteringVoice,
                dspSettings.SourceChannelCount,
                dspSettings.DestinationChannelCount,
                dspSettings.MatrixCoefficients);

            if (!this.Effect.GameAudio.UseReverb)
            {
                return;
            }

            if (reverbLevels?.Length != this.Effect.WaveFormat.Channels)
            {
                reverbLevels = new float[this.Effect.WaveFormat.Channels];
            }

            for (int i = 0; i < reverbLevels.Length; i++)
            {
                reverbLevels[i] = dspSettings.ReverbLevel;
            }

            voice.SetOutputMatrix(this.Effect.GameAudio.ReverbVoice, this.Effect.WaveFormat.Channels, 1, reverbLevels);

            if (!this.Effect.GameAudio.UseReverbFilter)
            {
                return;
            }

            var filterDirect = new FilterParameters
            {
                Type      = FilterType.LowPassFilter,
                Frequency = 2.0f * (float)Math.Sin(MathUtil.Pi / 6.0f * dspSettings.LpfDirectCoefficient),
                OneOverQ  = 1.0f
            };

            voice.SetOutputFilterParameters(this.Effect.GameAudio.MasteringVoice, filterDirect);

            var filterReverb = new FilterParameters
            {
                Type      = FilterType.LowPassFilter,
                Frequency = 2.0f * (float)Math.Sin(MathUtil.Pi / 6.0f * dspSettings.LpfReverbCoefficient),
                OneOverQ  = 1.0f
            };

            voice.SetOutputFilterParameters(this.Effect.GameAudio.ReverbVoice, filterReverb);
        }