Beispiel #1
0
        private void PlatformApply3D(AudioListener listener, AudioEmitter emitter)
        {
            // If we have no voice then nothing to do.
            if (_voice == null)
            {
                return;
            }

            // Convert from XNA Emitter to a SharpDX Emitter
            var e = ToDXEmitter(emitter);

            e.CurveDistanceScaler = SoundEffect.DistanceScale;
            e.DopplerScaler       = SoundEffect.DopplerScale;
            e.ChannelCount        = _effect._format.Channels;

            // Convert from XNA Listener to a SharpDX Listener
            var l = ToDXListener(listener);

            // Number of channels in the sound being played.
            // Not actually sure if XNA supported 3D attenuation of sterio sounds, but X3DAudio does.
            var srcChannelCount = _effect._format.Channels;

            // Number of output channels.
            var dstChannelCount = SoundEffect.MasterVoice.VoiceDetails.InputChannelCount;

            // XNA supports distance attenuation and doppler.
            var dpsSettings = SoundEffect.Device3D.Calculate(l, e, CalculateFlags.Matrix | CalculateFlags.Doppler, srcChannelCount, dstChannelCount);

            // Apply Volume settings (from distance attenuation) ...
            _voice.SetOutputMatrix(SoundEffect.MasterVoice, srcChannelCount, dstChannelCount, dpsSettings.MatrixCoefficients, 0);

            // Apply Pitch settings (from doppler) ...
            _voice.SetFrequencyRatio(dpsSettings.DopplerFactor);
        }
Beispiel #2
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);
     }
 }
Beispiel #3
0
 public void NoteOn(byte num, byte key, byte velocity)
 {
     try
     {
         Instrument  instrument  = instrumentTable[new Tuple <byte, byte>(Bank, Instrument)];
         int         value       = instrument.GetSampleEntry(key).Value;
         Sample      sample      = soundData.SampleBanks[soundData.InstrumentBanks[Bank].Wsys][(short)instrument.Samples[value].Id];
         AudioBuffer audioBuffer = new AudioBuffer();
         audioBuffer.AudioBytes = sample.Data.Length;
         audioBuffer.Stream     = new DataStream(sample.Data.Length, canRead: true, canWrite: true);
         audioBuffer.Stream.Write(sample.Data, 0, sample.Data.Length);
         audioBuffer.PlayBegin  = 0;
         audioBuffer.PlayLength = 0;
         audioBuffer.LoopCount  = (sample.IsLooping ? 255 : 0);
         audioBuffer.LoopBegin  = sample.LoopStart;
         audioBuffer.LoopLength = 0;
         WaveFormat  sourceFormat = new WaveFormat(sample.SamplesPerSecond, sample.BitsPerSample, sample.Channels);
         SourceVoice sourceVoice  = new SourceVoice(engine, sourceFormat, VoiceFlags.None, 1024f);
         sourceVoice.SetOutputVoices(new VoiceSendDescriptor(submix));
         sourceVoice.SubmitSourceBuffer(audioBuffer, null);
         float num2 = XAudio2.SemitonesToFrequencyRatio((!instrument.IsPercussion) ? (key - sample.RootKey) : 0) * instrument.Samples[value].FrequenyMultiplier * instrument.FrequencyMultiplier;
         sourceVoice.SetFrequencyRatio(num2);
         sourceVoice.SetVolume(ValueToAmplitude(velocity));
         NoteData noteData = new NoteData(sourceVoice, num2, velocity, instrument.IsPercussion);
         if (instrument.IsPercussion)
         {
             noteData.PercussionPan = instrument.Samples[value].Pan.Value;
             sbyte b = (sbyte)(noteData.PercussionPan - 63);
             sourceVoice.SetOutputMatrix(1, 2, new float[2]
             {
                 0.5f - (float)b / 127f,
                 0.5f + (float)b / 127f
             });
         }
         else
         {
             sourceVoice.SetOutputMatrix(1, 2, outputMatrix);
         }
         noteData.BufferStream = audioBuffer.Stream;
         noteData.Voice.Start();
         voiceTable.Add(num, noteData);
         sourceFormat = null;
         GC.Collect();
     }
     catch
     {
     }
 }
Beispiel #4
0
        public void Apply3D(SourceVoice voice, Listener listener, Emitter emitter, int srcChannels, int dstChannels, CalculateFlags flags, float maxDistance, float frequencyRatio)
        {
            unsafe
            {
                DspSettings settings;

                int matrixCoefficientCount = srcChannels * dstChannels;

                float *matrixCoefficients = stackalloc float[matrixCoefficientCount];
                float *delay = stackalloc float[dstChannels];

                settings.SrcChannelCount           = srcChannels;
                settings.DstChannelCount           = dstChannels;
                settings.MatrixCoefficientsPointer = new IntPtr(matrixCoefficients);
                settings.DelayTimesPointer         = new IntPtr(delay);

                Calculate(listener, emitter, flags, &settings);

                if (emitter.InnerRadius == 0f)
                {
                    // approximated decay by distance
                    float decay = MathHelper.Clamp(1f - settings.EmitterToListenerDistance / maxDistance, 0f, 1f);
                    for (int i = 0; i < matrixCoefficientCount; i++)
                    {
                        matrixCoefficients[i] *= decay;
                    }
                }

                voice.SetOutputMatrix(null, settings.SrcChannelCount, settings.DstChannelCount, matrixCoefficients);
                voice.SetFrequencyRatio(frequencyRatio * settings.DopplerFactor);
            }
        }
Beispiel #5
0
        private void CreateSourceVoices(float playBegin = 0)
        {
            if (playBegin > 0)
            {
                foreach (var voice in voices)
                {
                    voice.audioBuffer.PlayBegin = (int)(voice.soundStream.Format.SampleRate * playBegin) / 128 * 128;
                }
                if (playtimer.IsRunning)
                {
                    playtimer.Restart();
                }
                else
                {
                    playtimer.Reset();
                }
                playBeginMs = (int)(playBegin * 1000);
            }
            else
            {
                playBeginMs = 0;
            }

            trackFinished = false;
            foreach (var voice in voices)
            {
                var sourceVoice = new SourceVoice(xAudio2, voice.soundStream.Format, true);
                sourceVoice.SubmitSourceBuffer(voice.audioBuffer, voice.soundStream.DecodedPacketsInfo);
                sourceVoice.BufferEnd += (context) => trackFinished = true;
                sourceVoice.SetVolume(volume);
                sourceVoice.SetOutputMatrix(1, 2, voice.outputMatrix);
                voice.sourceVoice = sourceVoice;
            }
        }
Beispiel #6
0
        private void PrepareVoiceSource(WaveFormat format)
        {
            if (_voice == null)
            {
                _linkedWaveFormat = format;
                //Voice Creation
                _voice = new SourceVoice(_soundEngine.Xaudio2, _linkedWaveFormat, true);

                //Do we have a special channel sound Mapping for this channel/speaker configuration ?
                float[] customMapping;
                if (_soundEngine.GetCustomChannelMapping(_voice.VoiceDetails.InputChannelCount, _soundEngine.DeviceDetail.OutputFormat.Channels, out customMapping))
                {
                    _defaultChannelMapping = customMapping;
                    _voice.SetOutputMatrix(_voice.VoiceDetails.InputChannelCount, _soundEngine.DeviceDetail.OutputFormat.Channels, _defaultChannelMapping);
                }
                else
                {
                    //Get default channel mapping
                    _defaultChannelMapping = new float[_voice.VoiceDetails.InputChannelCount * _soundEngine.DeviceDetail.OutputFormat.Channels];
                    _voice.GetOutputMatrix(null, _voice.VoiceDetails.InputChannelCount, _soundEngine.DeviceDetail.OutputFormat.Channels, _defaultChannelMapping);
                }

                _voice.BufferEnd += _callback;
            }
            else
            {
                if (_linkedWaveFormat.SampleRate != format.SampleRate)
                {
                    _voice.SourceSampleRate = format.SampleRate;
                    _linkedWaveFormat       = format;
                }
            }
        }
Beispiel #7
0
        private void UpdateSourcePosition()
        {
            Listener listener = PositionKind == AudioPositionKind.ListenerRelative ? s_centeredListener : _engine.Listener;

            _engine.X3DAudio.Calculate(
                listener,
                _emitter,
                CalculateFlags.Matrix | CalculateFlags.Doppler,
                _dspSettings);
            _sourceVoice.SetOutputMatrix(_channelCount, 2, _dspSettings.MatrixCoefficients);
            _sourceVoice.SetFrequencyRatio(_pitch * _dspSettings.DopplerFactor);
        }
Beispiel #8
0
        public float Apply3D(SourceVoice voice, Listener listener, Emitter emitter, int srcChannels, int dstChannels, CalculateFlags flags, float maxDistance, float frequencyRatio, bool silent, bool use3DCalculation = true)
        {
            unsafe
            {
                DspSettings settings;

                int matrixCoefficientCount = srcChannels * dstChannels;

                float *matrixCoefficients = stackalloc float[matrixCoefficientCount];
                float *delay = stackalloc float[dstChannels];

                settings.SrcChannelCount           = srcChannels;
                settings.DstChannelCount           = dstChannels;
                settings.MatrixCoefficientsPointer = new IntPtr(matrixCoefficients);
                settings.DelayTimesPointer         = new IntPtr(delay);

                if (use3DCalculation)
                {
                    Calculate(listener, emitter, flags, &settings);

                    voice.SetFrequencyRatio(frequencyRatio * settings.DopplerFactor);
                }
                else
                { //realistic sounds
                    settings.EmitterToListenerDistance = Vector3.Distance(new Vector3(listener.Position.X, listener.Position.Y, listener.Position.Z), new Vector3(emitter.Position.X, emitter.Position.Y, emitter.Position.Z));
                    for (int i = 0; i < matrixCoefficientCount; i++)
                    {
                        matrixCoefficients[i] = 1f;
                    }
                }

                if (emitter.InnerRadius == 0f)
                {
                    // approximated decay by distance
                    float decay;
                    if (silent)
                    {
                        decay = 0f;
                    }
                    else
                    {
                        decay = MathHelper.Clamp(1f - settings.EmitterToListenerDistance / maxDistance, 0f, 1f);
                    }
                    for (int i = 0; i < matrixCoefficientCount; i++)
                    {
                        matrixCoefficients[i] *= decay;
                    }
                }
                voice.SetOutputMatrix(null, settings.SrcChannelCount, settings.DstChannelCount, matrixCoefficients);
                return(settings.EmitterToListenerDistance);
            }
        }
Beispiel #9
0
        //Enqueue the currently linked datasource buffer for playing
        public void PushDataSourceForPlaying()
        {
            //Do nothing, start will be deferred !
            if (MaxDefferedStart > 0)
            {
                //Not playing the sound with Buffered start => Assign new rnd start
                if (_voice.State.BuffersQueued == 0 && _deferredPaused == false)
                {
                    AssignNewRndStart();
                    _deferredPaused = true;
                    logger.Trace("AssignNewRndStart {0} {1}", this.Id, this.PlayingDataSource.Alias);
                }

                if (_defferedStart > _deferredStartTimer.ElapsedMilliseconds)
                {
                    return;
                }
                _deferredPaused = false;
            }

            if (_playingDataSource is SoundStreamedDataSource)
            {
                ((SoundStreamedDataSource)_playingDataSource).StartVoiceDataFetching(this);
            }
            else
            {
                _voice.SubmitSourceBuffer(_playingDataSource.AudioBuffer, null);
            }

            if (is3DSound)
            {
                RefreshVoices();
            }
            else
            {
                //Reset Default Channel Mapping
                _voice.SetOutputMatrix(_playingDataSource.WaveFormat.Channels, _soundEngine.DeviceDetail.OutputFormat.Channels, _defaultChannelMapping);
            }
        }
Beispiel #10
0
        public int Play(PlayOptions options)
        {
            if (!isLoaded)
            {
                Load();
            }

            if (options.Repeats != defaultRepeat)
            {
                int loopCount;
                if (options.Repeats == -1)
                {
                    loopCount = AudioBuffer.LoopInfinite;
                }
                else
                {
                    loopCount = options.Repeats;
                }

                LoadNextVoice(loopCount);
            }

            if (options.Pan != 0)
            {
                float   panLeft    = (float)0.5 - (options.Pan / 2);
                float   panRight   = (float)0.5 + (options.Pan / 2);
                int     matrixSize = masteringVoice.VoiceDetails.InputChannelCount * nextVoice.VoiceDetails.InputChannelCount;
                float[] matrix     = new float[matrixSize];

                for (int i = 0; i < matrixSize; i++)
                {
                    if (i % 2 == 0)
                    {
                        matrix[i] = panLeft;
                    }
                    else
                    {
                        matrix[i] = panRight;
                    }
                }

                nextVoice.SetOutputMatrix(nextVoice.VoiceDetails.InputChannelCount, masteringVoice.VoiceDetails.InputChannelCount, matrix);
            }

            nextVoice.SetFrequencyRatio(options.Pitch);
            nextVoice.SetVolume(options.Volume);

            Play();

            return(voiceListKey);
        }
Beispiel #11
0
        public void Apply3D(SourceVoice voice, Listener listener, Emitter emitter, float maxDistance, float frequencyRatio)
        {
            m_x3dAudio.Calculate(listener, emitter, CalculateFlags.Matrix | CalculateFlags.Doppler, m_dsp);

            if (emitter.InnerRadius == 0f)
            {
                // approximated decay by distance
                float decay = MathHelper.Clamp(1f - m_dsp.EmitterToListenerDistance / maxDistance, 0f, 1f);
                for (int i = 0; i < m_dsp.MatrixCoefficients.Length; ++i)
                {
                    m_dsp.MatrixCoefficients[i] *= decay;
                }
            }

            voice.SetOutputMatrix(m_dsp.SourceChannelCount, m_dsp.DestinationChannelCount, m_dsp.MatrixCoefficients);
            voice.SetFrequencyRatio(frequencyRatio * m_dsp.DopplerFactor);
        }
        private void Update()
        {
            if (_voice.IsDisposed)
            {
                return;
            }

            var listener = new Listener
            {
                OrientFront = Vector3DToVector3(QuaternionHelper.FrontVectorFromQuaternion(Rotation)),
                OrientTop   = Vector3DToVector3(QuaternionHelper.UpVectorFromQuaternion(Rotation)),
                Position    = Vector3DToVector3(Position),
                Velocity    = new Vector3(0, 0, 0)
            };

            var dspSettings = _x3dAudio.Calculate(listener, _emitter, CalculateFlags.Matrix, _format.Channels, _deviceFormat.Channels);

            _voice.SetOutputMatrix(_format.Channels, _deviceFormat.Channels, dspSettings.MatrixCoefficients);
        }
        private void UpdateStereoVolumes()
        {
            var sourceChannelCount = WaveFormat.Channels;

            // then update the volume of each channel
            Single[] matrix;
            if (sourceChannelCount == 1)
            {   // panChannelVolumes and localizationChannelVolumes are both in [0,1] so multiplication too, no clamp is needed
                matrix = new[] { panChannelVolumes[0] * localizationChannelVolumes[0], panChannelVolumes[1] * localizationChannelVolumes[1] };
            }
            else if (sourceChannelCount == 2)
            {
                matrix = new[] { panChannelVolumes[0], 0, 0, panChannelVolumes[1] }; // no localization on stereo sounds.
            }
            else
            {
                throw new AudioSystemInternalException("The sound is not supposed to contain more than 2 channels");
            }

            SourceVoice.SetOutputMatrix(sourceChannelCount, MasterVoice.VoiceDetails.InputChannelCount, matrix);
        }
        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);
                }
            }
        }
Beispiel #15
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();
                }
        }
Beispiel #16
0
        internal SourceVoice Start(float pan = 0)
        {
            if (_voices.Any(v => v.State.BuffersQueued <= 0))
            {
                s = _voices.First(v => v.State.BuffersQueued <= 0);
            }
            else
            {
                s = new SourceVoice(Device, Stream.Format, true);

                _voices.Add(s);
            }
            var b = new AudioBuffer
            {
                Stream     = Stream.ToDataStream(),
                AudioBytes = (int)Stream.Length,
                LoopCount  = Loop ? AudioBuffer.LoopInfinite : 0,
                Flags      = BufferFlags.EndOfStream
            };

            s.SubmitSourceBuffer(b, Stream.DecodedPacketsInfo);
            float[] outputMatrix = new float[8];
            for (int i = 0; i < 8; i++)
            {
                outputMatrix[i] = 0;
            }
            // pan of -1.0 indicates all left speaker,
            // 1.0 is all right speaker, 0.0 is split between left and right

            float left  = 0.5f - pan / 2;
            float right = 0.5f + pan / 2;


            switch (Master.ChannelMask)
            {
            case (int)Speakers.Mono:
                outputMatrix[0] = 1.0f;
                break;

            case (int)Speakers.Stereo:
            case (int)Speakers.TwoPointOne:
            case (int)Speakers.Surround:
                outputMatrix[0] = left;
                outputMatrix[1] = right;
                break;

            case (int)Speakers.Quad:
                outputMatrix[0] = outputMatrix[2] = left;
                outputMatrix[1] = outputMatrix[3] = right;
                break;

            case (int)Speakers.FourPointOne:
                outputMatrix[0] = outputMatrix[3] = left;
                outputMatrix[1] = outputMatrix[4] = right;
                break;

            case (int)Speakers.FivePointOne:
            case (int)Speakers.SevenPointOne:
            case (int)Speakers.FivePointOneSurround:
                outputMatrix[0] = outputMatrix[4] = left;
                outputMatrix[1] = outputMatrix[5] = right;
                break;

            case (int)Speakers.SevenPointOneSurround:
                outputMatrix[0] = outputMatrix[4] = outputMatrix[6] = left;
                outputMatrix[1] = outputMatrix[5] = outputMatrix[7] = right;
                break;
            }
            s.SetOutputMatrix(null, s.VoiceDetails.InputChannelCount, Master.VoiceDetails.InputChannelCount, outputMatrix);
            s.Start();
            return(s);
        }
Beispiel #17
0
        /// <summary>
        /// SharpDX X3DAudio sample. Plays a generated sound rotating around the listener.
        /// </summary>
        static void Main(string[] args)
        {
            var xaudio2 = new XAudio2();

            using (var masteringVoice = new MasteringVoice(xaudio2))
            {
                // Instantiate X3DAudio
                var x3dAudio = new X3DAudio(Speakers.Stereo);

                var emitter = new Emitter
                {
                    ChannelCount        = 1,
                    CurveDistanceScaler = float.MinValue,
                    OrientFront         = new Vector3(0, 0, 1),
                    OrientTop           = new Vector3(0, 1, 0),
                    Position            = new Vector3(0, 0, 0),
                    Velocity            = new Vector3(0, 0, 0)
                };

                var listener = new Listener
                {
                    OrientFront = new Vector3(0, 0, 1),
                    OrientTop   = new Vector3(0, 1, 0),
                    Position    = new Vector3(0, 0, 0),
                    Velocity    = new Vector3(0, 0, 0)
                };

                var waveFormat  = new WaveFormat(44100, 32, 1);
                var sourceVoice = new SourceVoice(xaudio2, waveFormat);

                int bufferSize = waveFormat.ConvertLatencyToByteSize(60000);
                var dataStream = new DataStream(bufferSize, true, true);

                int numberOfSamples = bufferSize / waveFormat.BlockAlign;
                for (int i = 0; i < numberOfSamples; i++)
                {
                    float value = (float)(Math.Cos(2 * Math.PI * 220.0 * i / waveFormat.SampleRate) * 0.5);
                    dataStream.Write(value);
                }
                dataStream.Position = 0;

                var audioBuffer = new AudioBuffer
                {
                    Stream = dataStream, Flags = BufferFlags.EndOfStream, AudioBytes = bufferSize
                };

                //var reverb = new Reverb();
                //var effectDescriptor = new EffectDescriptor(reverb);
                //sourceVoice.SetEffectChain(effectDescriptor);
                //sourceVoice.EnableEffect(0);

                sourceVoice.SubmitSourceBuffer(audioBuffer, null);

                sourceVoice.Start();

                Console.WriteLine("Play a sound rotating around the listener");
                for (int i = 0; i < 1200; i++)
                {
                    // Rotates the emitter
                    var rotateEmitter      = Matrix.RotationY(i / 5.0f);
                    var newPosition        = Vector3.Transform(new Vector3(0, 0, 1000), rotateEmitter);
                    var newPositionVector3 = new Vector3(newPosition.X, newPosition.Y, newPosition.Z);
                    emitter.Velocity = (newPositionVector3 - emitter.Position) / 0.05f;
                    emitter.Position = newPositionVector3;

                    // Calculate X3DAudio settings
                    var dspSettings = x3dAudio.Calculate(listener, emitter, CalculateFlags.Matrix | CalculateFlags.Doppler, 1, 2);

                    // Modify XAudio2 source voice settings
                    sourceVoice.SetOutputMatrix(1, 2, dspSettings.MatrixCoefficients);
                    sourceVoice.SetFrequencyRatio(dspSettings.DopplerFactor);

                    // Wait for 50ms
                    Thread.Sleep(50);
                }
            }
        }
        /// <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);
        }