public void Apply3D(Listener listener, Emitter emiter) { if (IsValid) { m_cue.Apply3D(listener, emiter); } }
public void Apply3D(Cue cue, Listener listener, Emitter emitter) { m_x3dAudio.Calculate(listener, emitter, CalculateFlags.Matrix | CalculateFlags.Doppler | CalculateFlags.EmitterAngle, m_dsp); cue.SetMatrixCoefficients(m_dsp.SourceChannelCount, m_dsp.DestinationChannelCount, m_dsp.MatrixCoefficients); cue.SetVariable(MyCueVariableEnum.Distance, m_dsp.EmitterToListenerDistance); cue.SetVariable(MyCueVariableEnum.DopplerPitchScalar, m_dsp.DopplerFactor); cue.SetVariable(MyCueVariableEnum.OrientationAngleDegrees, m_dsp.EmitterToListenerAngle * 57.29578f); // From radians to degrees }
private SharpDX.X3DAudio.Emitter ToDXEmitter(AudioEmitter emitter) { // Pulling out Vector properties for efficiency. var pos = emitter.Position; var vel = emitter.Velocity; var forward = emitter.Forward; var up = emitter.Up; // From MSDN: // X3DAudio uses a left-handed Cartesian coordinate system, // with values on the x-axis increasing from left to right, on the y-axis from bottom to top, // and on the z-axis from near to far. // Azimuths are measured clockwise from a given reference direction. // // From MSDN: // The XNA Framework uses a right-handed coordinate system, // with the positive z-axis pointing toward the observer when the positive x-axis is pointing to the right, // and the positive y-axis is pointing up. // // Programmer Notes: // According to this description the z-axis (forward vector) is inverted between these two coordinate systems. // Therefore, we need to negate the z component of any position/velocity values, and negate any forward vectors. forward *= -1.0f; pos.Z *= -1.0f; vel.Z *= -1.0f; if (_dxEmitter == null) { _dxEmitter = new Emitter(); } #if WINDOWS_UAP _dxEmitter.Position = new SharpDX.Mathematics.Interop.RawVector3 { X = pos.X, Y = pos.Y, Z = pos.Z }; _dxEmitter.Velocity = new SharpDX.Mathematics.Interop.RawVector3 { X = vel.X, Y = vel.Y, Z = vel.Z }; _dxEmitter.OrientFront = new SharpDX.Mathematics.Interop.RawVector3 { X = forward.X, Y = forward.Y, Z = forward.Z }; _dxEmitter.OrientTop = new SharpDX.Mathematics.Interop.RawVector3 { X = up.X, Y = up.Y, Z = up.Z }; #else _dxEmitter.Position = new SharpDX.Vector3(pos.X, pos.Y, pos.Z); _dxEmitter.Velocity = new SharpDX.Vector3(vel.X, vel.Y, vel.Z); _dxEmitter.OrientFront = new SharpDX.Vector3(forward.X, forward.Y, forward.Z); _dxEmitter.OrientTop = new SharpDX.Vector3(up.X, up.Y, up.Z); _dxEmitter.DopplerScaler = emitter.DopplerScale; #endif return(_dxEmitter); }
/// <summary> /// Calculates dsp settings for the specified listener and emitter. /// </summary> /// <param name="listener">The listener.</param> /// <param name="emitter">The emitter.</param> /// <param name="flags">The flags.</param> /// <param name="sourceChannelCount">The source channel count.</param> /// <param name="destinationChannelCount">The destination channel count.</param> /// <returns>Dsp settings</returns> public DspSettings Calculate(Listener listener, Emitter emitter, CalculateFlags flags, int sourceChannelCount, int destinationChannelCount) { var settings = new DspSettings { SourceChannelCount = sourceChannelCount, DestinationChannelCount = destinationChannelCount }; X3DAudioCalculate(ref handle, listener, emitter, flags, settings); return settings; }
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); }
public override void Setup(WaveFormatEx format) { _format = new WaveFormatExtensible(format.nSamplesPerSec, format.wBitsPerSample, format.nChannels); _voice = new SourceVoice(_xaudio2, _format); _voice.StreamEnd += _voice_StreamEnd; _voice.VoiceError += _voice_VoiceError; _emitter = new Emitter { ChannelAzimuths = GetAzimuths(_format.Channels), ChannelCount = _format.Channels, ChannelRadius = 10, 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) }; }
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(); }
/// <summary> /// Calculates DSP settings for the specified listener and emitter. See remarks. /// </summary> /// <param name="listener">The listener.</param> /// <param name="emitter">The emitter.</param> /// <param name="flags">The flags.</param> /// <param name="settings">The settings.</param> /// <remarks>The source and destination channel count must be set on <see cref="DspSettings" /> before calling this method.</remarks> /// <msdn-id>ee419052</msdn-id> /// <unmanaged>void X3DAudioCalculate([In] const X3DAUDIOHANDLE* Instance,[In] const X3DAUDIO_LISTENER* pListener,[In] const X3DAUDIO_EMITTER* pEmitter,[In] X3DAudioCalculateFlags Flags,[In] void* pDSPSettings)</unmanaged> /// <unmanaged-short>X3DAudioCalculate</unmanaged-short> public unsafe void Calculate(Listener listener, Emitter emitter, CalculateFlags flags, DspSettings settings) { if (settings == null) throw new ArgumentNullException("settings"); DspSettings.__Native settingsNative; settingsNative.SrcChannelCount = settings.SourceChannelCount; settingsNative.DstChannelCount = settings.DestinationChannelCount; fixed (void* pMatrix = settings.MatrixCoefficients) fixed (void* pDelays = settings.DelayTimes) { settingsNative.MatrixCoefficientsPointer = (IntPtr)pMatrix; settingsNative.DelayTimesPointer = (IntPtr)pDelays; X3DAudioCalculate(ref handle, listener, emitter, flags, new IntPtr(&settingsNative)); } settings.__MarshalFrom(ref settingsNative); }
/// <summary> /// Calculates DSP settings for the specified listener and emitter. /// </summary> /// <param name="listener">The listener.</param> /// <param name="emitter">The emitter.</param> /// <param name="flags">The flags.</param> /// <param name="sourceChannelCount">The source channel count.</param> /// <param name="destinationChannelCount">The destination channel count.</param> /// <returns>DSP settings</returns> /// <msdn-id>ee419052</msdn-id> /// <unmanaged>void X3DAudioCalculate([In] const X3DAUDIOHANDLE* Instance,[In] const X3DAUDIO_LISTENER* pListener,[In] const X3DAUDIO_EMITTER* pEmitter,[In] X3DAudioCalculateFlags Flags,[In] void* pDSPSettings)</unmanaged> /// <unmanaged-short>X3DAudioCalculate</unmanaged-short> 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; }
public static void Apply3D(this Cue cue, Listener listener, Emitter emitter) { MyAudio.X3DAudio.Apply3D(cue, listener, emitter); }
public static void LoadData() { MyMwcLog.WriteLine("MyAudio.LoadData - START"); MyMwcLog.IncreaseIndent(); m_canPlay = true; try { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("new AudioEngine"); //TimeSpan timeSpan = TimeSpan.FromMilliseconds(250); //m_audioEngine = new AudioEngine(MyPlugins.GetAudioFolder() + "Audio.xgs", timeSpan, ""); using (var file = File.OpenRead(MyPlugins.GetAudioFolder() + "Audio.xgs")) { m_audioEngine = new AudioEngine(file); m_cuePool = new MyCuePool(m_audioEngine); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("new MyX3DAudio"); m_x3dAudio = new MyX3DAudio(m_audioEngine); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } catch (Exception ex) { MyMwcLog.WriteLine("Exception during loading audio engine. Game continues, but without sound. Details: " + ex.ToString(), LoggingOptions.AUDIO); // This exception is the only way I can know if we can play sound (e.g. if computer doesn't have sound card). // I didn't find other ways of checking it. m_canPlay = false; } if (m_canPlay) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MyXactVariables.LoadData"); MyXactVariables.LoadData(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("AddWaveBanks"); // IMPORTANT!!! Currently, there is problem with multiple XACT projects, that when anything changes in Music.xap or Voice.xap, // it is necessary to open and save Sounds.xap also, in order to run the game properly(otherwise it has problem to load the SoundBank.xsb) // this will be solved later in future AddWaveBanks(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Adding sound banks"); MyMwcLog.WriteLine("Adding sound banks", LoggingOptions.AUDIO); using (var file = File.OpenRead(MyPlugins.GetAudioFolder() + "Music.xsb")) { m_musicSoundBank = new SoundBank(m_audioEngine, file); } using (var file = File.OpenRead(MyPlugins.GetAudioFolder() + "Sounds.xsb")) { m_sfxSoundBank = new SoundBank(m_audioEngine, file); } using (var file = File.OpenRead(MyPlugins.GetAudioFolder() + "Dialogues.xsb")) { m_dialogueSoundBank = new SoundBank(m_audioEngine, file); } using (var file = File.OpenRead(MyPlugins.GetAudioFolder() + "Voice.xsb")) { m_voiceSoundBank = new SoundBank(m_audioEngine, file); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Categories"); //m_voiceSoundBank = new SoundBank(m_audioEngine, MyPlugins.GetAudioFolder() + "Voice.xsb"); m_listener = new Listener(); m_listener.SetDefaultValues(); m_helperEmitter = new Emitter(); m_helperEmitter.SetDefaultValues(); m_defaultCategory = m_audioEngine.GetCategoryInstance("Default"); m_wep2DCategory = m_audioEngine.GetCategoryInstance("wep2d"); m_cockpitCategory = m_audioEngine.GetCategoryInstance("Cockpit"); m_musicCategory = m_audioEngine.GetCategoryInstance("Music"); m_guiCategory = m_audioEngine.GetCategoryInstance("Gui"); m_doorCategory = m_audioEngine.GetCategoryInstance("Door"); m_enginesCategory = m_audioEngine.GetCategoryInstance("Engines"); m_dialogueCategory = m_audioEngine.GetCategoryInstance("Dialogues"); m_shoutsCategory = m_audioEngine.GetCategoryInstance("Shouts"); m_hudCategory = m_audioEngine.GetCategoryInstance("VocHud"); m_ambCategory = m_audioEngine.GetCategoryInstance("Amb"); m_drillsCategory = m_audioEngine.GetCategoryInstance("Drills"); m_impCategory = m_audioEngine.GetCategoryInstance("Imp"); m_importantsCategory = m_audioEngine.GetCategoryInstance("IMPORTANTS"); m_sfxCategory = m_audioEngine.GetCategoryInstance("Sfx"); m_voiceCategory = m_audioEngine.GetCategoryInstance("Voice"); m_welcomeCategory = m_audioEngine.GetCategoryInstance("Welcomes"); m_wep3DCategory = m_audioEngine.GetCategoryInstance("Wep3D"); m_xCategory = m_audioEngine.GetCategoryInstance("X"); m_gameCategories = new List<AudioCategory>(); m_gameCategories.Add(m_defaultCategory); m_gameCategories.Add(m_wep2DCategory); m_gameCategories.Add(m_cockpitCategory); m_gameCategories.Add(m_doorCategory); m_gameCategories.Add(m_enginesCategory); m_gameCategories.Add(m_dialogueCategory); m_gameCategories.Add(m_shoutsCategory); m_gameCategories.Add(m_hudCategory); m_gameCategories.Add(m_ambCategory); m_gameCategories.Add(m_drillsCategory); m_gameCategories.Add(m_impCategory); m_gameCategories.Add(m_importantsCategory); m_gameCategories.Add(m_sfxCategory); m_gameCategories.Add(m_voiceCategory); m_gameCategories.Add(m_welcomeCategory); m_gameCategories.Add(m_wep3DCategory); m_gameCategories.Add(m_xCategory); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("WaitForWaveBanks"); // AudioEngine.Update needs to be called at least once before a streaming wave bank is ready MyMwcLog.WriteLine("Updating audio engine...", LoggingOptions.AUDIO); WaitForWaveBanks(); // This is reverb turned to off, so we hear sounds as they are defined in wav files ReverbControl = 100; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("PreloadCueInfo"); PreloadCueInfo(); // Takes about 26 ms MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("ValidateCues"); #if DEBUG ThreadPool.QueueUserWorkItem(ValidateCue_Thread); // Takes 4000 ms on background thread #endif MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("InitCueParameters"); InitCueParameters(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("InitNonLoopableCuesLimitRemoveHelper"); InitNonLoopableCuesLimitRemoveHelper(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("MyHudAudio.LoadData"); MyHudAudio.LoadData(); // Volume from config m_musicOn = true; m_gameSoundsOn = true; m_musicAllowed = true; VolumeMusic = MyConfig.MusicVolume; VolumeGame = MyConfig.GameVolume; VolumeGui = MyConfig.GameVolume; MyConfig.MusicVolume = VolumeMusic; MyConfig.GameVolume = VolumeGame; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("MyConfig.Save"); MyConfig.Save(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } MyMwcLog.DecreaseIndent(); MyMwcLog.WriteLine("MyAudio.LoadData - END"); }
/// <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); } } }
public static new void LoadData() { MySandboxGame.Log.WriteLine("MyAudio.LoadData - START"); MySandboxGame.Log.IncreaseIndent(); m_canPlay = true; MyObjectBuilder_CueDefinitions ob = null; try { #if DEBUG bool result = false; try { result = MyObjectBuilder_Base.DeserializeXML(MyCreateFileAudioSBA.GetFilenameSBA(), out ob); } catch (FileNotFoundException) { // generates the Audio.sba file MyCreateFileAudioSBA.Create(); result = MyObjectBuilder_Base.DeserializeXML(MyCreateFileAudioSBA.GetFilenameSBA(), out ob); } #else bool result = MyObjectBuilder_Base.DeserializeXML(MyCreateFileAudioSBA.GetFilenameSBA(), out ob); #endif //DEBUG if (result) { Init(); } else { MySandboxGame.Log.WriteLine("Unable to load audio data. Game continues, but without sound", LoggingOptions.AUDIO); m_canPlay = false; } } catch (Exception ex) { MySandboxGame.Log.WriteLine("Exception during loading audio engine. Game continues, but without sound. Details: " + ex.ToString(), LoggingOptions.AUDIO); MySandboxGame.Log.WriteLine("Device ID: " + m_deviceDetails.DeviceID, LoggingOptions.AUDIO); MySandboxGame.Log.WriteLine("Device name: " + m_deviceDetails.DisplayName, LoggingOptions.AUDIO); MySandboxGame.Log.WriteLine("Device role: " + m_deviceDetails.Role, LoggingOptions.AUDIO); MySandboxGame.Log.WriteLine("Output format: " + m_deviceDetails.OutputFormat, LoggingOptions.AUDIO); // This exception is the only way I can know if we can play sound (e.g. if computer doesn't have sound card). // I didn't find other ways of checking it. m_canPlay = false; } if (MyFakes.SIMULATE_NO_SOUND_CARD) m_canPlay = false; if (m_canPlay) { m_cueBank = new MyCueBank(m_audioEngine, ob); m_3Dsounds = new List<IMy3DSoundEmitter>(); m_listener = new Listener(); m_listener.SetDefaultValues(); m_helperEmitter = new Emitter(); m_helperEmitter.SetDefaultValues(); // This is reverb turned to off, so we hear sounds as they are defined in wav files ApplyReverb = false; m_musicOn = true; m_gameSoundsOn = true; // Volume from config VolumeMusic = MyConfig.MusicVolume; VolumeGame = MyConfig.GameVolume; VolumeHud = MyConfig.GameVolume; MyConfig.MusicVolume = VolumeMusic; MyConfig.GameVolume = VolumeGame; m_mute = false; m_musicAllowed = true; m_musicState = MyMusicState.Stopped; m_loopMusic = true; m_transitionForward = false; m_timeFromTransitionStart = 0; m_soundInstancesTotal2D = 0; m_soundInstancesTotal3D = 0; } MySandboxGame.Log.DecreaseIndent(); MySandboxGame.Log.WriteLine("MyAudio.LoadData - END"); }