예제 #1
0
    /// <summary>
    /// Calculates DSP settings for the specified listener and emitter.
    /// </summary>
    /// <param name="listener">The <see cref="Listener"/>.</param>
    /// <param name="emitter">The <see cref="Emitter"/>.</param>
    /// <param name="flags">The <see cref="CalculateFlags"/>.</param>
    /// <param name="sourceChannelCount">The source channel count.</param>
    /// <param name="destinationChannelCount">The destination channel count.</param>
    /// <returns>An instance of <see cref="DspSettings"/> class.</returns>
    public DspSettings Calculate(Listener listener, Emitter emitter, CalculateFlags flags, int sourceChannelCount, int destinationChannelCount)
    {
        var settings = new DspSettings(sourceChannelCount, destinationChannelCount);

        Calculate(listener, emitter, flags, settings);
        return(settings);
    }
예제 #2
0
        public override void Play(AudioBuffer buffer)
        {
            _xa2Buffer            = (XAudio2AudioBuffer)buffer;
            _channelCount         = GetChannelCount(_xa2Buffer.Format);
            _emitter.ChannelCount = _channelCount;
            if ((_channelCount > 1 && !_stereoState) || (_channelCount == 1 && _stereoState))
            {
                float volume = _sourceVoice.Volume;
                _sourceVoice.DestroyVoice();
                _sourceVoice.Dispose();
                WaveFormat waveFormat = new WaveFormat(_xa2Buffer.Frequency, GetChannelCount(_xa2Buffer.Format));
                _sourceVoice = new SourceVoice(_engine.XAudio2, waveFormat, VoiceFlags.None, maxFrequencyRatio: 2.0f);
                _sourceVoice.SetVolume(volume);
                _emitter.ChannelAzimuths = new[] { 0.0f };
                _dspSettings             = new DspSettings(_channelCount, 2);
                UpdateSourcePosition();
                _stereoState = _channelCount == 2;
            }

            if (_sourcePositionDirty)
            {
                UpdateSourcePosition();
                _sourcePositionDirty = false;
            }

            _audioBuffer.Stream     = _xa2Buffer.DataStream;
            _audioBuffer.AudioBytes = _xa2Buffer.SizeInBytes;
            _audioBuffer.Flags      = BufferFlags.EndOfStream;
            _sourceVoice.Stop();
            _sourceVoice.FlushSourceBuffers();
            _sourceVoice.SubmitSourceBuffer(_audioBuffer, null);
            _sourceVoice.Start();
        }
예제 #3
0
    /// <summary>
    /// Calculates DSP settings for the specified listener and emitter. See remarks.
    /// </summary>
    /// <param name="listener">The <see cref="Listener"/>.</param>
    /// <param name="emitter">The <see cref="Emitter"/>.</param>
    /// <param name="flags">The <see cref="CalculateFlags"/>.</param>
    /// <param name="settings">The <see cref="DspSettings"/>.</param>
    /// <remarks>The source and destination channel count must be set on <see cref="DspSettings" /> before calling this method.</remarks>
    public void Calculate(Listener listener, Emitter emitter, CalculateFlags flags, DspSettings settings)
    {
        if (settings == null)
        {
            throw new ArgumentNullException(nameof(settings));
        }

        DspSettings.__Native settingsNative;
        settingsNative.SrcChannelCount = settings.SourceChannelCount;
        settingsNative.DstChannelCount = settings.DestinationChannelCount;

        unsafe
        {
            fixed(void *pMatrix = settings.MatrixCoefficients)
            {
                fixed(void *pDelays = settings.DelayTimes)
                {
                    settingsNative.MatrixCoefficientsPointer = (IntPtr)pMatrix;
                    settingsNative.DelayTimesPointer         = (IntPtr)pDelays;

                    XAudio2Native.X3DAudioCalculate(ref _handle, listener, emitter, flags, new IntPtr(&settingsNative));
                }
            }
        }

        settings.__MarshalFrom(ref settingsNative);
    }
예제 #4
0
 /// <summary>
 /// Applies 3-D settings represented by the supplied settings object to the sound.
 /// </summary>
 /// <param name="settings">The DspSettings object that represents changes that should be made to this sound.</param>
 /// <param name="sourceChannels">The source channel count.</param>
 /// <param name="destinationChannels">The destination channel count.</param>
 /// <param name="flags">The 3D flags to calculate. The default will calculate volume and doppler shift. This parameter is useful if it is not desirable for XAudio2 to calculate doppler on sounds that modify their own frequencies as an example; in this case, the flags should omit doppler.</param>
 public void apply3D(DspSettings settings, int sourceChannels, int destinationChannels, CalculateFlags flags)
 {
     voice.SetOutputMatrix(sourceChannels, destinationChannels, settings.MatrixCoefficients);
     if ((flags & CalculateFlags.Doppler) == CalculateFlags.Doppler)
     {
         voice.GetFrequencyRatio(out float freq);
         voice.SetFrequencyRatio(settings.DopplerFactor * freq);
     }
 }
예제 #5
0
        private void SetEmitterPosition(Vector3 vector3)
        {
            DspSettings dspSettings = new DspSettings(_sourceChannels, _destinationChannels);

            _emitter.Position = vector3;

            //just calculate the matrix... no doppler or anything else.
            _x3daudio.X3DAudioCalculate(_listener, _emitter, CalculateFlags.Matrix, dspSettings);

            _streamingSourceVoice.SetOutputMatrix(_masteringVoice, _sourceChannels, _destinationChannels, dspSettings.MatrixCoefficients);
        }
예제 #6
0
        public object CalculateDspSettingsDebug(IMy3DSoundEmitter source)
        {
            MySoundData cue = m_cueBank.GetCue(source.SoundId);

            m_helperEmitter.UpdateValuesOmni(source.SourcePosition, source.Velocity, cue, m_deviceDetails.OutputFormat.Channels, source.CustomMaxDistance);
            DspSettingsRef result   = new DspSettingsRef(1, m_deviceDetails.OutputFormat.Channels);
            DspSettings    settings = result.DspSettings;

            unsafe
            {
                m_x3dAudio.Calculate(m_listener, m_helperEmitter, m_calculateFlags, &settings);
            }
            return(result);
        }
예제 #7
0
        private void Refresh3DVoiceData()
        {
            //Change output speakers parameter to simulate 3D sound
            DspSettings settings3D = _soundEngine.X3DAudio.Calculate(_soundEngine.Listener, Emitter, CalculateFlags.Matrix, PlayingDataSource.WaveFormat.Channels, _soundEngine.DeviceDetail.OutputFormat.Channels);

            _voice.SetOutputMatrix(PlayingDataSource.WaveFormat.Channels, _soundEngine.DeviceDetail.OutputFormat.Channels, settings3D.MatrixCoefficients);

            //Set global input sound volume based on distance VS object
            float soundVolume = _voiceVolume *
                                (1.0f - (Math.Max(0.0f, Math.Min(1.0f, settings3D.EmitterToListenerDistance / _playingDataSource.Power)))) *
                                (_playingDataSource.Category == SourceCategory.Music ? _soundEngine.GlobalMusicVolume : _soundEngine.GlobalFXVolume);

            _voice.SetVolume(soundVolume, XAudio2.CommitNow);
        }
예제 #8
0
        /// <summary>
        /// Positions a sound in 3-D space
        /// </summary>
        /// <param name="sound">The ExtendedAudioBuffer to play.</param>
        /// <param name="stop">If true, will stop the sound and return its position to 0 before playing it. Passing false will have the effect of resuming the sound from the last position it was stopped at.</param>
        /// <param name="loop">Whether or not to loop the sound.</param>
        /// <param name="x">The x coordinate of the source.</param>
        /// <param name="y">The y coordinate of the source.</param>
        /// <param name="z">The z coordinate of the source.</param>
        /// <param name="vx">The x component of the velocity vector.</param>
        /// <param name="vy">The y component of the velocity  vector.</param>
        /// <param name="vz">The z component of the velocity vector.</param>
        /// <param name="flags">The 3D flags to calculate. The default will calculate volume and doppler shift. This parameter is useful if it is not desirable for XAudio2 to calculate doppler on sounds that modify their own frequencies as an example; in this case, the flags should omit doppler.</param>
        public static void PlaySound3d(ExtendedAudioBuffer sound, bool stop, bool loop, float x, float y, float z, float vx = 0, float vy = 0, float vz = 0, CalculateFlags flags = CalculateFlags.Matrix | CalculateFlags.Doppler)
        {
            Emitter emitter = new Emitter {
                ChannelCount        = 1,
                CurveDistanceScaler = 1.0f,
                OrientFront         = new Vector3(0, 0, 1),
                OrientTop           = new Vector3(0, 1, 0),
                Position            = new Vector3(x, y, z),
                Velocity            = new Vector3(vx, vy, vz)
            };

            sound.play(stop, loop);
            DspSettings dspSettings = x3DAudio.Calculate(listener, emitter, flags, sound.getVoiceDetails().InputChannelCount, mainMasteringVoice.VoiceDetails.InputChannelCount);

            sound.apply3D(dspSettings, sound.getVoiceDetails().InputChannelCount, mainMasteringVoice.VoiceDetails.InputChannelCount, flags);
        }
예제 #9
0
 private void RecalculateFxSounds()
 {
     foreach (LinkedSoundList.Sound sound in _fxLinkedSoundList)
     {
         DspSettings settings = _x3DAudio.Calculate(
             _listener,
             sound.Emitter,
             CalculateFlags.Matrix | CalculateFlags.Doppler,
             sound.SourceVoice.VoiceDetails.InputChannelCount,
             _inputChannelCount);
         sound.SourceVoice.SetOutputMatrix(
             sound.SourceVoice.VoiceDetails.InputChannelCount, _inputChannelCount,
             settings.MatrixCoefficients);
         sound.SourceVoice.SetFrequencyRatio(settings.DopplerFactor);
     }
 }
예제 #10
0
        internal void Apply3DImpl(AudioListener listener, AudioEmitter emitter)
        {
            //////////////////////////////////////////////////////////////
            // 1. First let's calculate the parameters to set to the voice
            var inputChannels  = soundEffect.WaveFormat.Channels;
            var outputChannels = MasterVoice.VoiceDetails.InputChannelCount;

            if (inputChannels != 1 || outputChannels != 2)
            {
                throw new AudioSystemInternalException("Error in Apply3DImpl only mono sounds are supposed to be localizable");
            }

            var list = new Listener
            {
                Position    = listener.Position.ToSharpDX(),
                Velocity    = listener.Velocity.ToSharpDX(),
                OrientFront = listener.Forward.ToSharpDX(),
                OrientTop   = listener.Up.ToSharpDX()
            };
            var emit = new Emitter
            {
                Position            = emitter.Position.ToSharpDX(),
                Velocity            = emitter.Velocity.ToSharpDX(),
                DopplerScaler       = emitter.DopplerScale,
                CurveDistanceScaler = emitter.DistanceScale,
                ChannelRadius       = 0f, // Multi-channels localizable sound are considered as source of multiple sounds coming from the same location.
                ChannelCount        = inputChannels
            };

            var dspSettings = new DspSettings(inputChannels, outputChannels);

            AudioEngine.X3DAudio.Calculate(list, emit, CalculateFlags.Matrix | CalculateFlags.LpfDirect, dspSettings);

            /////////////////////////////////////////////////////////////
            // 2. Now let's set the voice parameters to simulate a 3D voice.

            // 2.1 The Doppler effect due to the difference of speed between the emitter and listener
            ComputeDopplerFactor(listener, emitter);
            UpdatePitch();

            // 2.2 The channel attenuations due to the source localization.
            localizationChannelVolumes = new[] { dspSettings.MatrixCoefficients[0], dspSettings.MatrixCoefficients[1] };    // only mono sound can be localized so matrix should be 2*1
            UpdateStereoVolumes();
        }
예제 #11
0
        private void PlaySound(int soundID,
                               Emitter emitter,
                               float volume,
                               LinkedSoundList list,
                               ref VoiceSendDescriptor voiceSendDescriptor,
                               Action <IntPtr>?onFxEnd = null)
        {
            if (!_soundBuffer.TryGetValue(soundID, out SoundBuffer buffer))
            {
                return;
            }

            SourceVoice sourceVoice = new SourceVoice(_xAudio2, buffer.Format, VoiceFlags.None, true);

            sourceVoice.SetVolume(volume);
            sourceVoice.SubmitSourceBuffer(buffer.AudioBuffer, buffer.DecodedPacketsInfo);
            sourceVoice.SetOutputVoices(voiceSendDescriptor);

            LinkedSoundList.Sound sound = new LinkedSoundList.Sound(emitter, sourceVoice);
            list.Add(sound);

            sourceVoice.BufferEnd += _ =>
            {
                list.Remove(sound);
                sourceVoice.DestroyVoice();
            };

            if (onFxEnd != null)
            {
                sourceVoice.BufferEnd += onFxEnd;
            }
            sourceVoice.Start();

            DspSettings settings = _x3DAudio.Calculate(
                _listener,
                sound.Emitter,
                CalculateFlags.Matrix | CalculateFlags.Doppler,
                buffer.Format.Channels,
                _inputChannelCount);

            sound.SourceVoice.SetOutputMatrix(buffer.Format.Channels, _inputChannelCount, settings.MatrixCoefficients);
            sound.SourceVoice.SetFrequencyRatio(settings.DopplerFactor);
        }
예제 #12
0
        public override void SetSourcePosition(AudioSource source, Vector3 position)
        {
            XA2Source xa2Source = (XA2Source)source;

            if (!_x3DEmitters.TryGetValue(source, out var emitter))
            {
                emitter = new Emitter();
                emitter.CurveDistanceScaler = float.MinValue;
                emitter.OrientTop           = new RawVector3(0, 0, 1);
                emitter.OrientFront         = new RawVector3(0, 1, 0);

                _x3DEmitters.Add(source, emitter);
            }

            emitter.ChannelCount = xa2Source.SourceVoice.VoiceDetails.InputChannelCount;
            emitter.Position     = new RawVector3(position.X, position.Y, position.Z);

            var outChannels = _engine.MasterVoice.VoiceDetails.InputChannelCount;

            DspSettings dspSettings = new DspSettings(1, outChannels);

            _x3DAudio.Calculate(_x3DListener, emitter, CalculateFlags.Matrix, dspSettings);
            xa2Source.SourceVoice.SetOutputMatrix(_engine.MasterVoice, 1, outChannels, dspSettings.MatrixCoefficients);
        }
예제 #13
0
        /// <summary>
        /// Calculate 3D Audio parameters.
        /// </summary>
        /// <param name="listener">The 3D audio listener definition.</param>
        /// <param name="emitter">The 3D audio emitter definition.</param>
        /// <param name="flags">The 3D audio calculate flags.</param>
        /// <param name="dspSettings">The DSP settings.</param>
        internal void Calculate3D(Listener listener, Emitter emitter, CalculateFlags flags, DspSettings dspSettings)
        {
            DisposeGuard();

            x3DAudio.Calculate(listener, emitter, flags, dspSettings);
        }
        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);
        }
예제 #16
0
 public MyX3DAudio(AudioEngine engine)
 {
     m_x3dAudio = new X3DAudio(engine.FinalMixFormat.ChannelMask);
     m_dsp      = new DspSettings(1, engine.FinalMixFormat.Channels);
 }
예제 #17
0
        static void Main()
        {
            var initError = EVRInitError.None;

            system = OpenVR.Init(ref initError);

            if (initError != EVRInitError.None)
            {
                return;
            }

            compositor = OpenVR.Compositor;

            compositor.CompositorBringToFront();
            compositor.FadeGrid(5.0f, false);

            count = OpenVR.k_unMaxTrackedDeviceCount;

            currentPoses = new TrackedDevicePose_t[count];
            nextPoses    = new TrackedDevicePose_t[count];

            controllers                    = new List <uint>();
            controllerModels               = new RenderModel_t[count];
            controllerTextures             = new RenderModel_TextureMap_t[count];
            controllerTextureViews         = new ShaderResourceView[count];
            controllerVertexBuffers        = new SharpDX.Direct3D11.Buffer[count];
            controllerIndexBuffers         = new SharpDX.Direct3D11.Buffer[count];
            controllerVertexBufferBindings = new VertexBufferBinding[count];
            controllerEmitters             = new Emitter[count];
            controllerVoices               = new SourceVoice[count];

            for (uint device = 0; device < count; device++)
            {
                var deviceClass = system.GetTrackedDeviceClass(device);

                switch (deviceClass)
                {
                case ETrackedDeviceClass.HMD:
                    headset = device;
                    break;

                case ETrackedDeviceClass.Controller:
                    controllers.Add(device);
                    break;
                }
            }

            uint width  = 0;
            uint height = 0;

            system.GetRecommendedRenderTargetSize(ref width, ref height);

            headsetSize = new Size((int)width, (int)height);
            windowSize  = new Size(960, 540);

            var leftEyeProjection  = Convert(system.GetProjectionMatrix(EVREye.Eye_Left, 0.01f, 1000.0f));
            var rightEyeProjection = Convert(system.GetProjectionMatrix(EVREye.Eye_Right, 0.01f, 1000.0f));

            var leftEyeView  = Convert(system.GetEyeToHeadTransform(EVREye.Eye_Left));
            var rightEyeView = Convert(system.GetEyeToHeadTransform(EVREye.Eye_Right));

            foreach (var controller in controllers)
            {
                var modelName     = new StringBuilder(255, 255);
                var propertyError = ETrackedPropertyError.TrackedProp_Success;

                var length = system.GetStringTrackedDeviceProperty(controller, ETrackedDeviceProperty.Prop_RenderModelName_String, modelName, 255, ref propertyError);

                if (propertyError == ETrackedPropertyError.TrackedProp_Success)
                {
                    var modelName2 = modelName.ToString();

                    while (true)
                    {
                        var pointer    = IntPtr.Zero;
                        var modelError = EVRRenderModelError.None;

                        modelError = OpenVR.RenderModels.LoadRenderModel_Async(modelName2, ref pointer);

                        if (modelError == EVRRenderModelError.Loading)
                        {
                            continue;
                        }

                        if (modelError == EVRRenderModelError.None)
                        {
                            var renderModel = System.Runtime.InteropServices.Marshal.PtrToStructure <RenderModel_t>(pointer);

                            controllerModels[controller] = renderModel;
                            break;
                        }
                    }

                    while (true)
                    {
                        var pointer      = IntPtr.Zero;
                        var textureError = EVRRenderModelError.None;

                        textureError = OpenVR.RenderModels.LoadTexture_Async(controllerModels[controller].diffuseTextureId, ref pointer);

                        if (textureError == EVRRenderModelError.Loading)
                        {
                            continue;
                        }

                        if (textureError == EVRRenderModelError.None)
                        {
                            var texture = System.Runtime.InteropServices.Marshal.PtrToStructure <RenderModel_TextureMap_t>(pointer);

                            controllerTextures[controller] = texture;
                            break;
                        }
                    }
                }
            }

            int adapterIndex = 0;

            system.GetDXGIOutputInfo(ref adapterIndex);

            using (var form = new Form())
                using (var factory = new Factory4())
                {
                    form.ClientSize = windowSize;

                    var adapter = factory.GetAdapter(adapterIndex);

                    var swapChainDescription = new SwapChainDescription
                    {
                        BufferCount     = 1,
                        Flags           = SwapChainFlags.None,
                        IsWindowed      = true,
                        ModeDescription = new ModeDescription
                        {
                            Format      = Format.B8G8R8A8_UNorm,
                            Width       = form.ClientSize.Width,
                            Height      = form.ClientSize.Height,
                            RefreshRate = new Rational(60, 1)
                        },
                        OutputHandle      = form.Handle,
                        SampleDescription = new SampleDescription(1, 0),
                        SwapEffect        = SwapEffect.Discard,
                        Usage             = Usage.RenderTargetOutput
                    };

                    SharpDX.Direct3D11.Device.CreateWithSwapChain(adapter, DeviceCreationFlags.None, swapChainDescription, out device, out swapChain);

                    factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.None);

                    context = device.ImmediateContext;

                    using (var backBuffer = swapChain.GetBackBuffer <Texture2D>(0))
                        backBufferView = new RenderTargetView(device, backBuffer);

                    var depthBufferDescription = new Texture2DDescription
                    {
                        Format            = Format.D16_UNorm,
                        ArraySize         = 1,
                        MipLevels         = 1,
                        Width             = form.ClientSize.Width,
                        Height            = form.ClientSize.Height,
                        SampleDescription = new SampleDescription(1, 0),
                        Usage             = ResourceUsage.Default,
                        BindFlags         = BindFlags.DepthStencil,
                        CpuAccessFlags    = CpuAccessFlags.None,
                        OptionFlags       = ResourceOptionFlags.None
                    };

                    using (var depthBuffer = new Texture2D(device, depthBufferDescription))
                        depthStencilView = new DepthStencilView(device, depthBuffer);

                    // Create Eye Textures
                    var eyeTextureDescription = new Texture2DDescription
                    {
                        ArraySize         = 1,
                        BindFlags         = BindFlags.RenderTarget,
                        CpuAccessFlags    = CpuAccessFlags.None,
                        Format            = Format.B8G8R8A8_UNorm,
                        Width             = headsetSize.Width,
                        Height            = headsetSize.Height,
                        MipLevels         = 1,
                        OptionFlags       = ResourceOptionFlags.None,
                        SampleDescription = new SampleDescription(1, 0),
                        Usage             = ResourceUsage.Default
                    };

                    var leftEyeTexture  = new Texture2D(device, eyeTextureDescription);
                    var rightEyeTexture = new Texture2D(device, eyeTextureDescription);

                    var leftEyeTextureView  = new RenderTargetView(device, leftEyeTexture);
                    var rightEyeTextureView = new RenderTargetView(device, rightEyeTexture);

                    // Create Eye Depth Buffer
                    eyeTextureDescription.BindFlags = BindFlags.DepthStencil;
                    eyeTextureDescription.Format    = Format.D32_Float;

                    var eyeDepth     = new Texture2D(device, eyeTextureDescription);
                    var eyeDepthView = new DepthStencilView(device, eyeDepth);

                    Shapes.Cube.Load(device);
                    Shapes.Sphere.Load(device);
                    Shaders.Load(device);

                    // Load Controller Models
                    foreach (var controller in controllers)
                    {
                        var model = controllerModels[controller];

                        controllerVertexBuffers[controller] = new SharpDX.Direct3D11.Buffer(device, model.rVertexData, new BufferDescription
                        {
                            BindFlags   = BindFlags.VertexBuffer,
                            SizeInBytes = (int)model.unVertexCount * 32
                        });

                        controllerVertexBufferBindings[controller] = new VertexBufferBinding(controllerVertexBuffers[controller], 32, 0);

                        controllerIndexBuffers[controller] = new SharpDX.Direct3D11.Buffer(device, model.rIndexData, new BufferDescription
                        {
                            BindFlags   = BindFlags.IndexBuffer,
                            SizeInBytes = (int)model.unTriangleCount * 3 * 2
                        });

                        var texture = controllerTextures[controller];

                        using (var texture2d = new Texture2D(device, new Texture2DDescription
                        {
                            ArraySize = 1,
                            BindFlags = BindFlags.ShaderResource,
                            Format = Format.R8G8B8A8_UNorm,
                            Width = texture.unWidth,
                            Height = texture.unHeight,
                            MipLevels = 1,
                            SampleDescription = new SampleDescription(1, 0)
                        }, new DataRectangle(texture.rubTextureMapData, texture.unWidth * 4)))
                            controllerTextureViews[controller] = new ShaderResourceView(device, texture2d);
                    }

                    var controllerVertexShaderByteCode = SharpDX.D3DCompiler.ShaderBytecode.Compile(Properties.Resources.NormalTextureShader, "VS", "vs_5_0");
                    controllerVertexShader = new VertexShader(device, controllerVertexShaderByteCode);
                    controllerPixelShader  = new PixelShader(device, SharpDX.D3DCompiler.ShaderBytecode.Compile(Properties.Resources.NormalTextureShader, "PS", "ps_5_0"));

                    var controllerLayout = new InputLayout(device, SharpDX.D3DCompiler.ShaderSignature.GetInputSignature(controllerVertexShaderByteCode), new InputElement[]
                    {
                        new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0),
                        new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0),
                        new InputElement("TEXCOORD", 0, Format.R32G32_Float, 24, 0)
                    });

                    worldViewProjectionBuffer = new SharpDX.Direct3D11.Buffer(device, Utilities.SizeOf <Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

                    var rasterizerStateDescription = RasterizerStateDescription.Default();
                    //rasterizerStateDescription.FillMode = FillMode.Wireframe;
                    rasterizerStateDescription.IsFrontCounterClockwise = true;
                    //rasterizerStateDescription.CullMode = CullMode.None;

                    rasterizerState = new RasterizerState(device, rasterizerStateDescription);

                    var blendStateDescription = BlendStateDescription.Default();

                    blendStateDescription.RenderTarget[0].BlendOperation   = BlendOperation.Add;
                    blendStateDescription.RenderTarget[0].SourceBlend      = BlendOption.SourceAlpha;
                    blendStateDescription.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;

                    blendStateDescription.RenderTarget[0].IsBlendEnabled = false;

                    blendState = new BlendState(device, blendStateDescription);

                    var depthStateDescription = DepthStencilStateDescription.Default();

                    depthStateDescription.DepthComparison  = Comparison.LessEqual;
                    depthStateDescription.IsDepthEnabled   = true;
                    depthStateDescription.IsStencilEnabled = false;

                    depthStencilState = new DepthStencilState(device, depthStateDescription);

                    var samplerStateDescription = SamplerStateDescription.Default();

                    samplerStateDescription.Filter   = Filter.MinMagMipLinear;
                    samplerStateDescription.AddressU = TextureAddressMode.Wrap;
                    samplerStateDescription.AddressV = TextureAddressMode.Wrap;

                    samplerState = new SamplerState(device, samplerStateDescription);

                    startTime  = DateTime.Now;
                    frame      = 0;
                    windowSize = form.ClientSize;

                    backgroundColor = new RawColor4(0.1f, 0.1f, 0.1f, 1);

                    var vrEvent   = new VREvent_t();
                    var eventSize = (uint)Utilities.SizeOf <VREvent_t>();

                    head = Matrix.Identity;

                    // Initialize Audio
                    audio = new XAudio2();
                    var voice = new MasteringVoice(audio);
                    audio3d = new X3DAudio(Speakers.Stereo);

                    foreach (var controller in controllers)
                    {
                        controllerEmitters[controller] = new Emitter
                        {
                            ChannelCount        = 1,
                            CurveDistanceScaler = 0.15f,
                            OrientFront         = Vector3.ForwardLH,
                            OrientTop           = Vector3.Up,
                            Position            = new Vector3(0, 0, 1000),
                            //Velocity = Vector3.Zero
                        };
                    }

                    listener = new Listener
                    {
                        OrientFront = Vector3.ForwardLH,
                        OrientTop   = Vector3.Up,
                        Position    = new Vector3(0, 0, 1000)
                    };

                    var audioFormat = new WaveFormat(44100, 32, 1);
                    //var audioSource = new SourceVoice(audio, audioFormat);
                    var audioBufferSize = audioFormat.ConvertLatencyToByteSize(1000);
                    var audioStream     = new DataStream(audioBufferSize, true, true);
                    var audioSamples    = audioBufferSize / audioFormat.BlockAlign;

                    var random = new Random();

                    for (var sample = 0; sample < audioSamples; sample++)
                    {
                        audioStream.Write((float)random.NextFloat(-1, 1));
                    }

                    audioStream.Position = 0;

                    var audioBuffer = new AudioBuffer
                    {
                        Stream     = audioStream,
                        AudioBytes = audioBufferSize,
                        LoopCount  = 255
                    };

                    var audioSettings = new DspSettings(1, 2);

                    foreach (var controller in controllers)
                    {
                        var audioSource = new SourceVoice(audio, audioFormat);

                        audioSource.SubmitSourceBuffer(audioBuffer, null);

                        audio3d.Calculate(listener, controllerEmitters[controller], CalculateFlags.Matrix, audioSettings);

                        audioSource.SetOutputMatrix(1, 2, audioSettings.MatrixCoefficients);

                        audioSource.Start();

                        controllerVoices[controller] = audioSource;
                    }

                    RenderLoop.Run(form, () =>
                    {
                        while (system.PollNextEvent(ref vrEvent, eventSize))
                        {
                            switch ((EVREventType)vrEvent.eventType)
                            {
                            case EVREventType.VREvent_TrackedDeviceActivated:
                                var controller = vrEvent.trackedDeviceIndex;

                                controllers.Add(controller);

                                var modelName     = new StringBuilder(255, 255);
                                var propertyError = ETrackedPropertyError.TrackedProp_Success;

                                var length = system.GetStringTrackedDeviceProperty(controller, ETrackedDeviceProperty.Prop_RenderModelName_String, modelName, 255, ref propertyError);

                                if (propertyError == ETrackedPropertyError.TrackedProp_Success)
                                {
                                    var modelName2 = modelName.ToString();

                                    while (true)
                                    {
                                        var pointer    = IntPtr.Zero;
                                        var modelError = EVRRenderModelError.None;

                                        modelError = OpenVR.RenderModels.LoadRenderModel_Async(modelName2, ref pointer);

                                        if (modelError == EVRRenderModelError.Loading)
                                        {
                                            continue;
                                        }

                                        if (modelError == EVRRenderModelError.None)
                                        {
                                            var renderModel = System.Runtime.InteropServices.Marshal.PtrToStructure <RenderModel_t>(pointer);

                                            controllerModels[controller] = renderModel;

                                            // Load Controller Model
                                            var model = controllerModels[controller];

                                            controllerVertexBuffers[controller] = new SharpDX.Direct3D11.Buffer(device, model.rVertexData, new BufferDescription
                                            {
                                                BindFlags   = BindFlags.VertexBuffer,
                                                SizeInBytes = (int)model.unVertexCount * 32
                                            });

                                            controllerVertexBufferBindings[controller] = new VertexBufferBinding(controllerVertexBuffers[controller], 32, 0);

                                            controllerIndexBuffers[controller] = new SharpDX.Direct3D11.Buffer(device, model.rIndexData, new BufferDescription
                                            {
                                                BindFlags   = BindFlags.IndexBuffer,
                                                SizeInBytes = (int)model.unTriangleCount * 3 * 2
                                            });

                                            break;
                                        }
                                    }

                                    while (true)
                                    {
                                        var pointer      = IntPtr.Zero;
                                        var textureError = EVRRenderModelError.None;

                                        textureError = OpenVR.RenderModels.LoadTexture_Async(controllerModels[controller].diffuseTextureId, ref pointer);

                                        if (textureError == EVRRenderModelError.Loading)
                                        {
                                            continue;
                                        }

                                        if (textureError == EVRRenderModelError.None)
                                        {
                                            var textureMap = System.Runtime.InteropServices.Marshal.PtrToStructure <RenderModel_TextureMap_t>(pointer);

                                            controllerTextures[controller] = textureMap;

                                            using (var texture2d = new Texture2D(device, new Texture2DDescription
                                            {
                                                ArraySize = 1,
                                                BindFlags = BindFlags.ShaderResource,
                                                Format = Format.R8G8B8A8_UNorm,
                                                Width = textureMap.unWidth,
                                                Height = textureMap.unHeight,
                                                MipLevels = 1,
                                                SampleDescription = new SampleDescription(1, 0)
                                            }, new DataRectangle(textureMap.rubTextureMapData, textureMap.unWidth * 4)))
                                                controllerTextureViews[controller] = new ShaderResourceView(device, texture2d);

                                            break;
                                        }
                                    }

                                    controllerEmitters[controller] = new Emitter
                                    {
                                        ChannelCount        = 1,
                                        CurveDistanceScaler = 0.15f,
                                        OrientFront         = Vector3.ForwardLH,
                                        OrientTop           = Vector3.Up,
                                        Position            = new Vector3(0, 0, 1000),
                                        //Velocity = Vector3.Zero
                                    };

                                    var audioSource = new SourceVoice(audio, audioFormat);

                                    audioSource.SubmitSourceBuffer(audioBuffer, null);

                                    audio3d.Calculate(listener, controllerEmitters[controller], CalculateFlags.Matrix, audioSettings);

                                    audioSource.SetOutputMatrix(1, 2, audioSettings.MatrixCoefficients);

                                    audioSource.Start();

                                    controllerVoices[controller] = audioSource;
                                }
                                break;

                            case EVREventType.VREvent_TrackedDeviceDeactivated:
                                controllers.RemoveAll(c => c == vrEvent.trackedDeviceIndex);
                                break;

                            default:
                                System.Diagnostics.Debug.WriteLine((EVREventType)vrEvent.eventType);
                                break;
                            }
                        }

                        if (form.ClientSize != windowSize)
                        {
                            Utilities.Dispose(ref backBufferView);

                            if (form.ClientSize.Width != 0 && form.ClientSize.Height != 0)
                            {
                                swapChain.ResizeBuffers(1, form.ClientSize.Width, form.ClientSize.Height, Format.B8G8R8A8_UNorm, SwapChainFlags.None);

                                using (var backBuffer = swapChain.GetBackBuffer <Texture2D>(0))
                                    backBufferView = new RenderTargetView(device, backBuffer);
                            }

                            windowSize = form.ClientSize;
                        }

                        // Update Device Tracking
                        compositor.WaitGetPoses(currentPoses, nextPoses);

                        if (currentPoses[headset].bPoseIsValid)
                        {
                            Convert(ref currentPoses[headset].mDeviceToAbsoluteTracking, ref head);

                            // Update Audio Listener
                            listener.Position    = head.TranslationVector * new Vector3(1, 1, -1);
                            listener.OrientFront = head.Forward * new Vector3(1, 1, -1);
                            listener.OrientTop   = head.Up * new Vector3(1, 1, -1);
                        }

                        foreach (var controller in controllers)
                        {
                            var controllerMatrix = Matrix.Identity;

                            Convert(ref currentPoses[controller].mDeviceToAbsoluteTracking, ref controllerMatrix);

                            var position = controllerMatrix.TranslationVector * new Vector3(1, 1, -1);

                            controllerEmitters[controller].Position = position;

                            audio3d.Calculate(listener, controllerEmitters[controller], CalculateFlags.Matrix, audioSettings);

                            controllerVoices[controller].SetOutputMatrix(1, 2, audioSettings.MatrixCoefficients);
                        }

                        // Render Left Eye
                        context.Rasterizer.SetViewport(0, 0, headsetSize.Width, headsetSize.Height);
                        context.OutputMerger.SetTargets(eyeDepthView, leftEyeTextureView);
                        context.OutputMerger.SetDepthStencilState(depthStencilState);

                        context.ClearRenderTargetView(leftEyeTextureView, backgroundColor);
                        context.ClearDepthStencilView(eyeDepthView, DepthStencilClearFlags.Depth, 1.0f, 0);

                        Shaders.Apply(context);

                        context.Rasterizer.State = rasterizerState;

                        context.OutputMerger.SetBlendState(blendState);
                        context.OutputMerger.SetDepthStencilState(depthStencilState);

                        context.PixelShader.SetSampler(0, samplerState);

                        var ratio = (float)headsetSize.Width / (float)headsetSize.Height;

                        var projection = leftEyeProjection;
                        var view       = Matrix.Invert(leftEyeView * head);
                        var world      = Matrix.Scaling(0.5f) * Matrix.Translation(0, 1.0f, 0);

                        worldViewProjection = world * view * projection;

                        context.UpdateSubresource(ref worldViewProjection, worldViewProjectionBuffer);

                        context.VertexShader.SetConstantBuffer(0, worldViewProjectionBuffer);

                        //Shapes.Cube.Begin(context);
                        //Shapes.Cube.Draw(context);

                        Shapes.Sphere.Begin(context);
                        Shapes.Sphere.Draw(context);

                        // Draw Controllers
                        context.InputAssembler.InputLayout       = controllerLayout;
                        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;

                        context.VertexShader.Set(controllerVertexShader);
                        context.PixelShader.Set(controllerPixelShader);
                        context.GeometryShader.Set(null);
                        context.DomainShader.Set(null);
                        context.HullShader.Set(null);

                        context.PixelShader.SetSampler(0, samplerState);

                        foreach (var controller in controllers)
                        {
                            context.InputAssembler.SetVertexBuffers(0, controllerVertexBufferBindings[controller]);
                            context.InputAssembler.SetIndexBuffer(controllerIndexBuffers[controller], Format.R16_UInt, 0);

                            context.PixelShader.SetShaderResource(0, controllerTextureViews[controller]);

                            Convert(ref currentPoses[controller].mDeviceToAbsoluteTracking, ref world);

                            worldViewProjection = world * view * projection;

                            context.UpdateSubresource(ref worldViewProjection, worldViewProjectionBuffer);

                            context.VertexShader.SetConstantBuffer(0, worldViewProjectionBuffer);

                            context.DrawIndexed((int)controllerModels[controller].unTriangleCount * 3 * 4, 0, 0);
                        }

                        var texture = new Texture_t
                        {
                            eType       = ETextureType.DirectX,
                            eColorSpace = EColorSpace.Gamma,
                            handle      = leftEyeTextureView.Resource.NativePointer
                        };

                        var bounds = new VRTextureBounds_t
                        {
                            uMin = 0.0f,
                            uMax = 1.0f,
                            vMin = 0.0f,
                            vMax = 1.0f,
                        };

                        var submitError = compositor.Submit(EVREye.Eye_Left, ref texture, ref bounds, EVRSubmitFlags.Submit_Default);

                        if (submitError != EVRCompositorError.None)
                        {
                            System.Diagnostics.Debug.WriteLine(submitError);
                        }

                        // Render Right Eye
                        context.Rasterizer.SetViewport(0, 0, headsetSize.Width, headsetSize.Height);
                        context.OutputMerger.SetTargets(eyeDepthView, rightEyeTextureView);
                        context.OutputMerger.SetDepthStencilState(depthStencilState);

                        context.ClearRenderTargetView(rightEyeTextureView, backgroundColor);
                        context.ClearDepthStencilView(eyeDepthView, DepthStencilClearFlags.Depth, 1.0f, 0);

                        Shaders.Apply(context);

                        context.Rasterizer.State = rasterizerState;

                        context.OutputMerger.SetBlendState(blendState);
                        context.OutputMerger.SetDepthStencilState(depthStencilState);

                        context.PixelShader.SetSampler(0, samplerState);

                        projection = rightEyeProjection;
                        view       = Matrix.Invert(rightEyeView * head);
                        world      = Matrix.Scaling(0.5f) * Matrix.Translation(0, 1.0f, 0);

                        worldViewProjection = world * view * projection;

                        context.UpdateSubresource(ref worldViewProjection, worldViewProjectionBuffer);

                        context.VertexShader.SetConstantBuffer(0, worldViewProjectionBuffer);

                        //Shapes.Cube.Begin(context);
                        //Shapes.Cube.Draw(context);

                        Shapes.Sphere.Begin(context);
                        Shapes.Sphere.Draw(context);

                        // Draw Controllers
                        context.InputAssembler.InputLayout       = controllerLayout;
                        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;

                        context.VertexShader.Set(controllerVertexShader);
                        context.PixelShader.Set(controllerPixelShader);
                        context.GeometryShader.Set(null);
                        context.DomainShader.Set(null);
                        context.HullShader.Set(null);

                        context.PixelShader.SetSampler(0, samplerState);

                        foreach (var controller in controllers)
                        {
                            context.InputAssembler.SetVertexBuffers(0, controllerVertexBufferBindings[controller]);
                            context.InputAssembler.SetIndexBuffer(controllerIndexBuffers[controller], Format.R16_UInt, 0);

                            context.PixelShader.SetShaderResource(0, controllerTextureViews[controller]);

                            Convert(ref currentPoses[controller].mDeviceToAbsoluteTracking, ref world);

                            worldViewProjection = world * view * projection;

                            context.UpdateSubresource(ref worldViewProjection, worldViewProjectionBuffer);

                            context.VertexShader.SetConstantBuffer(0, worldViewProjectionBuffer);

                            context.DrawIndexed((int)controllerModels[controller].unTriangleCount * 3 * 4, 0, 0);
                        }

                        texture.handle = rightEyeTextureView.Resource.NativePointer;

                        submitError = compositor.Submit(EVREye.Eye_Right, ref texture, ref bounds, EVRSubmitFlags.Submit_Default);

                        if (submitError != EVRCompositorError.None)
                        {
                            System.Diagnostics.Debug.WriteLine(submitError);
                        }

                        // Render Window
                        context.Rasterizer.SetViewport(0, 0, windowSize.Width, windowSize.Height);

                        context.OutputMerger.SetTargets(depthStencilView, backBufferView);
                        context.OutputMerger.SetDepthStencilState(depthStencilState);

                        context.ClearRenderTargetView(backBufferView, backgroundColor);
                        context.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);

                        Shaders.Apply(context);

                        context.Rasterizer.State = rasterizerState;

                        context.OutputMerger.SetBlendState(blendState);
                        context.OutputMerger.SetDepthStencilState(depthStencilState);

                        context.PixelShader.SetSampler(0, samplerState);

                        ratio = (float)form.ClientSize.Width / (float)form.ClientSize.Height;

                        projection = Matrix.PerspectiveFovRH(3.14F / 3.0F, ratio, 0.01f, 1000);
                        view       = Matrix.Invert(head);
                        world      = Matrix.Scaling(0.5f) * Matrix.Translation(0, 1.0f, 0);

                        worldViewProjection = world * view * projection;

                        context.UpdateSubresource(ref worldViewProjection, worldViewProjectionBuffer);

                        context.VertexShader.SetConstantBuffer(0, worldViewProjectionBuffer);

                        //Shapes.Cube.Begin(context);
                        //Shapes.Cube.Draw(context);

                        Shapes.Sphere.Begin(context);
                        Shapes.Sphere.Draw(context);

                        // Draw Controllers
                        context.InputAssembler.InputLayout       = controllerLayout;
                        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;

                        context.VertexShader.Set(controllerVertexShader);
                        context.PixelShader.Set(controllerPixelShader);
                        context.GeometryShader.Set(null);
                        context.DomainShader.Set(null);
                        context.HullShader.Set(null);

                        context.PixelShader.SetSampler(0, samplerState);

                        foreach (var controller in controllers)
                        {
                            context.InputAssembler.SetVertexBuffers(0, controllerVertexBufferBindings[controller]);
                            context.InputAssembler.SetIndexBuffer(controllerIndexBuffers[controller], Format.R16_UInt, 0);

                            Convert(ref currentPoses[controller].mDeviceToAbsoluteTracking, ref world);

                            worldViewProjection = world * view * projection;

                            context.UpdateSubresource(ref worldViewProjection, worldViewProjectionBuffer);

                            context.VertexShader.SetConstantBuffer(0, worldViewProjectionBuffer);

                            context.DrawIndexed((int)controllerModels[controller].unTriangleCount * 3 * 4, 0, 0);
                        }

                        // Show Backbuffer
                        swapChain.Present(0, PresentFlags.None);
                    });

                    audio.Dispose();
                }
        }
예제 #18
0
        public void Initialize(CameraSettingsActivatedEventArgs args)
        {
            videoDevController = (VideoDeviceController)args.VideoDeviceController;

            if (args.VideoDeviceExtension != null)
            {
                lcWrapper = new WinRTComponent();
                lcWrapper.Initialize(args.VideoDeviceExtension);
            }

            bool   bAuto = false;
            double value = 0.0;

            if (videoDevController.Brightness.Capabilities.Step != 0)
            {
                slBrt.Minimum       = videoDevController.Brightness.Capabilities.Min;
                slBrt.Maximum       = videoDevController.Brightness.Capabilities.Max;
                slBrt.StepFrequency = videoDevController.Brightness.Capabilities.Step;
                videoDevController.Brightness.TryGetValue(out value);
                slBrt.Value = value;
            }
            else
            {
                slBrt.IsEnabled = false;
            }
            if (videoDevController.Brightness.Capabilities.AutoModeSupported)
            {
                videoDevController.Brightness.TryGetAuto(out bAuto);
                tsBrtAuto.IsOn = bAuto;
            }
            else
            {
                tsBrtAuto.IsOn      = false;
                tsBrtAuto.IsEnabled = false;
            }

            if (videoDevController.Contrast.Capabilities.Step != 0)
            {
                slCrt.Minimum       = videoDevController.Contrast.Capabilities.Min;
                slCrt.Maximum       = videoDevController.Contrast.Capabilities.Max;
                slCrt.StepFrequency = videoDevController.Contrast.Capabilities.Step;
                videoDevController.Contrast.TryGetValue(out value);
                slCrt.Value = value;
            }
            else
            {
                slCrt.IsEnabled = false;
            }
            if (videoDevController.Contrast.Capabilities.AutoModeSupported)
            {
                videoDevController.Contrast.TryGetAuto(out bAuto);
                tsCrtAuto.IsOn = bAuto;
            }
            else
            {
                tsCrtAuto.IsOn      = false;
                tsCrtAuto.IsEnabled = false;
            }

            if (videoDevController.Focus.Capabilities.Step != 0)
            {
                slFocus.Minimum       = videoDevController.Focus.Capabilities.Min;
                slFocus.Maximum       = videoDevController.Focus.Capabilities.Max;
                slFocus.StepFrequency = videoDevController.Focus.Capabilities.Step;
                videoDevController.Focus.TryGetValue(out value);
                slFocus.Value = value;
            }
            else
            {
                slFocus.IsEnabled = false;
            }
            if (videoDevController.Focus.Capabilities.AutoModeSupported)
            {
                videoDevController.Focus.TryGetAuto(out bAuto);
                tsFocusAuto.IsOn = bAuto;
            }
            else
            {
                tsFocusAuto.IsOn      = false;
                tsFocusAuto.IsEnabled = false;
            }

            if (videoDevController.Exposure.Capabilities.Step != 0)
            {
                slExp.Minimum       = videoDevController.Exposure.Capabilities.Min;
                slExp.Maximum       = videoDevController.Exposure.Capabilities.Max;
                slExp.StepFrequency = videoDevController.Exposure.Capabilities.Step;
                videoDevController.Exposure.TryGetValue(out value);
                slExp.Value = value;
            }
            else
            {
                slExp.IsEnabled = false;
            }
            if (videoDevController.Exposure.Capabilities.AutoModeSupported)
            {
                videoDevController.Exposure.TryGetAuto(out bAuto);
                tsExpAuto.IsOn = bAuto;
            }
            else
            {
                tsExpAuto.IsOn      = false;
                tsExpAuto.IsEnabled = false;
            }

            if (lcWrapper != null)
            {
                slEffect.Minimum       = 0;
                slEffect.Maximum       = 100;
                slEffect.StepFrequency = 1;

                DspSettings dspSettings = lcWrapper.GetDspSetting();
                slEffect.Value = dspSettings.percentOfScreen;

                if (dspSettings.isEnabled == 1)
                {
                    tsEffectEnabled.IsOn = true;
                }
                else
                {
                    tsEffectEnabled.IsOn = false;
                    slEffect.IsEnabled   = false;
                }
            }
            else
            {
                tsEffectEnabled.IsEnabled = false;
                slEffect.IsEnabled        = false;
            }
        }
예제 #19
0
        private void UpdateOutputMatrix(Listener listener)
        {
            if (Sound.Is3DSound)
            {
                int inputChannels  = Sound.Format.Channels;
                int outputChannels = system.DeviceDetails.OutputFormat.Channels;

                Vector2 minMaxDistance = system._3DMinMaxDistance;
                float   range          = minMaxDistance.X + minMaxDistance.Y;
                float   breakingPoint  = minMaxDistance.X / range;

                Vector3 v = listener.Position - _3DPosition;
                Emitter e = new Emitter
                {
                    ChannelCount = 1,
                    VolumeCurve  = new CurvePoint[]
                    {
                        new CurvePoint {
                            Distance = 0f, DspSetting = 1f
                        },
                        new CurvePoint {
                            Distance = breakingPoint, DspSetting = 1f
                        },
                        new CurvePoint {
                            Distance = 1f, DspSetting = 0f
                        },
                    },
                    CurveDistance = range,
                    Position      = _3DPosition,
                    Velocity      = _3DVelocity,
                    OrientFront   = v.Length() > 0 ? Vector3.Normalize(v) : Vector3.UnitX,
                    OrientTop     = Vector3.UnitZ   // TODO: should be orthogonal with OrientFront
                };



                DspSettings dsp = system.X3DInstance.Calculate(listener, e, CalculateFlags.Matrix | CalculateFlags.LpfDirect,
                                                               inputChannels, outputChannels); // TODO: look up flags

                PanScale(dsp.MatrixCoefficients, _3DPanLevel, inputChannels, outputChannels);

#if DEBUG_PAN_COEFF_OUTPUT
                panCoeffAcc += dtime;
                if (panCoeffAcc > 0.3f)
                {
                    string  s   = "";
                    float[] mcs = dsp.MatrixCoefficients;
                    foreach (var mc in mcs)
                    {
                        s += mc + ", ";
                    }
                    JMOD.Sound.DebugOutput(s);
                    panCoeffAcc = 0;
                }
#endif
                SourceVoiceSlot.CurrentSourceVoice.SetOutputMatrix(inputChannels, outputChannels, dsp.MatrixCoefficients);
            }
            else
            {
                SourceVoiceSlot.CurrentSourceVoice.ResetOutputMatrix();
            }
        }
예제 #20
0
 /// <summary>
 /// Calculates the 3D audio effect
 /// </summary>
 /// <param name="listener">Listener</param>
 /// <param name="emitter">Emitter</param>
 /// <param name="flags">Calculate flags</param>
 /// <param name="dspSettings">DSP settings</param>
 internal void Calculate3D(Listener listener, Emitter emitter, CalculateFlags flags, DspSettings dspSettings)
 {
     this.x3DInstance?.Calculate(listener, emitter, flags, dspSettings);
 }
예제 #21
0
        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);
                }
            }
        }
예제 #22
0
 public MyX3DAudio(WaveFormatExtensible format)
 {
     m_x3dAudio = new X3DAudio(format.ChannelMask);
     m_dsp      = new DspSettings(1, format.Channels);
 }