internal static void PlatformSetReverbSettings(ReverbSettings reverbSettings) { // All parameters related to sampling rate or time are relative to a 48kHz // voice and must be scaled for use with other sampling rates. var timeScale = 48000.0f / ReverbVoice.VoiceDetails.InputSampleRate; var settings = new SharpDX.XAudio2.Fx.ReverbParameters { ReflectionsGain = reverbSettings.ReflectionsGainDb, ReverbGain = reverbSettings.ReverbGainDb, DecayTime = reverbSettings.DecayTimeSec, ReflectionsDelay = (byte)(reverbSettings.ReflectionsDelayMs * timeScale), ReverbDelay = (byte)(reverbSettings.ReverbDelayMs * timeScale), RearDelay = (byte)(reverbSettings.RearDelayMs * timeScale), RoomSize = reverbSettings.RoomSizeFeet, Density = reverbSettings.DensityPct, LowEQGain = (byte)reverbSettings.LowEqGain, LowEQCutoff = (byte)reverbSettings.LowEqCutoff, HighEQGain = (byte)reverbSettings.HighEqGain, HighEQCutoff = (byte)reverbSettings.HighEqCutoff, PositionLeft = (byte)reverbSettings.PositionLeft, PositionRight = (byte)reverbSettings.PositionRight, PositionMatrixLeft = (byte)reverbSettings.PositionLeftMatrix, PositionMatrixRight = (byte)reverbSettings.PositionRightMatrix, EarlyDiffusion = (byte)reverbSettings.EarlyDiffusion, LateDiffusion = (byte)reverbSettings.LateDiffusion, RoomFilterMain = reverbSettings.RoomFilterMainDb, RoomFilterFreq = reverbSettings.RoomFilterFrequencyHz * timeScale, RoomFilterHF = reverbSettings.RoomFilterHighFrequencyDb, WetDryMix = reverbSettings.WetDryMixPct }; ReverbVoice.SetEffectParameters(0, settings); }
internal static void PlatformSetReverbSettings(ReverbSettings reverbSettings) { #if SUPPORTS_EFX if (!OpenALSoundController.Efx.IsInitialized) { return; } if (ReverbEffect != 0) { return; } var efx = OpenALSoundController.Efx; efx.GenAuxiliaryEffectSlots(1, out ReverbSlot); efx.GenEffect(out ReverbEffect); efx.Effect(ReverbEffect, EfxEffecti.EffectType, (int)EfxEffectType.Reverb); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbReflectionsDelay, reverbSettings.ReflectionsDelayMs / 1000.0f); efx.Effect(ReverbEffect, EfxEffectf.LateReverbDelay, reverbSettings.ReverbDelayMs / 1000.0f); // map these from range 0-15 to 0-1 efx.Effect(ReverbEffect, EfxEffectf.EaxReverbDiffusion, reverbSettings.EarlyDiffusion / 15f); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbDiffusion, reverbSettings.LateDiffusion / 15f); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbGainLF, Math.Min(XactHelpers.ParseVolumeFromDecibels(reverbSettings.LowEqGain - 8f), 1.0f)); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbLFReference, (reverbSettings.LowEqCutoff * 50f) + 50f); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbGainHF, XactHelpers.ParseVolumeFromDecibels(reverbSettings.HighEqGain - 8f)); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbHFReference, (reverbSettings.HighEqCutoff * 500f) + 1000f); // According to Xamarin docs EaxReverbReflectionsGain Unit: Linear gain Range [0.0f .. 3.16f] Default: 0.05f efx.Effect(ReverbEffect, EfxEffectf.EaxReverbReflectionsGain, Math.Min(XactHelpers.ParseVolumeFromDecibels(reverbSettings.ReflectionsGainDb), 3.16f)); efx.Effect(ReverbEffect, EfxEffectf.EaxReverbGain, Math.Min(XactHelpers.ParseVolumeFromDecibels(reverbSettings.ReverbGainDb), 1.0f)); // map these from 0-100 down to 0-1 efx.Effect(ReverbEffect, EfxEffectf.EaxReverbDensity, reverbSettings.DensityPct / 100f); efx.AuxiliaryEffectSlot(ReverbSlot, EfxEffectSlotf.EffectSlotGain, reverbSettings.WetDryMixPct / 200f); // Dont know what to do with these EFX has no mapping for them. Just ignore for now // we can enable them as we go. //efx.SetEffectParam (ReverbEffect, EfxEffectf.PositionLeft, reverbSettings.PositionLeft); //efx.SetEffectParam (ReverbEffect, EfxEffectf.PositionRight, reverbSettings.PositionRight); //efx.SetEffectParam (ReverbEffect, EfxEffectf.PositionLeftMatrix, reverbSettings.PositionLeftMatrix); //efx.SetEffectParam (ReverbEffect, EfxEffectf.PositionRightMatrix, reverbSettings.PositionRightMatrix); //efx.SetEffectParam (ReverbEffect, EfxEffectf.LowFrequencyReference, reverbSettings.RearDelayMs); //efx.SetEffectParam (ReverbEffect, EfxEffectf.LowFrequencyReference, reverbSettings.RoomFilterFrequencyHz); //efx.SetEffectParam (ReverbEffect, EfxEffectf.LowFrequencyReference, reverbSettings.RoomFilterMainDb); //efx.SetEffectParam (ReverbEffect, EfxEffectf.LowFrequencyReference, reverbSettings.RoomFilterHighFrequencyDb); //efx.SetEffectParam (ReverbEffect, EfxEffectf.LowFrequencyReference, reverbSettings.DecayTimeSec); //efx.SetEffectParam (ReverbEffect, EfxEffectf.LowFrequencyReference, reverbSettings.RoomSizeFeet); efx.BindEffectToAuxiliarySlot(ReverbSlot, ReverbEffect); #endif }
/// <param name="settingsFile">Path to a XACT settings file.</param> /// <param name="lookAheadTime">Determines how many milliseconds the engine will look ahead when determing when to transition to another sound.</param> /// <param name="rendererId">A string that specifies the audio renderer to use.</param> /// <remarks>For the best results, use a lookAheadTime of 250 milliseconds or greater.</remarks> public AudioEngine(string settingsFile, TimeSpan lookAheadTime, string rendererId) { if (string.IsNullOrEmpty(settingsFile)) { throw new ArgumentNullException("settingsFile"); } // Read the xact settings file // Credits to alisci01 for initial format documentation using (var stream = OpenStream(settingsFile)) using (var reader = new BinaryReader(stream)) { uint magic = reader.ReadUInt32(); if (magic != 0x46534758) //'XGFS' { throw new ArgumentException("XGS format not recognized"); } reader.ReadUInt16(); // toolVersion uint formatVersion = reader.ReadUInt16(); if (formatVersion != 42) { Debug.WriteLine("Warning: XGS format " + formatVersion + " not supported!"); } reader.ReadUInt16(); // crc reader.ReadUInt32(); // lastModifiedLow reader.ReadUInt32(); // lastModifiedHigh reader.ReadByte(); //unkn, 0x03. Platform? uint numCats = reader.ReadUInt16(); uint numVars = reader.ReadUInt16(); reader.ReadUInt16(); //unkn, 0x16 reader.ReadUInt16(); //unkn, 0x16 uint numRpc = reader.ReadUInt16(); uint numDspPresets = reader.ReadUInt16(); uint numDspParams = reader.ReadUInt16(); uint catsOffset = reader.ReadUInt32(); uint varsOffset = reader.ReadUInt32(); reader.ReadUInt32(); //unknown, leads to a short with value of 1? reader.ReadUInt32(); // catNameIndexOffset reader.ReadUInt32(); //unknown, two shorts of values 2 and 3? reader.ReadUInt32(); // varNameIndexOffset uint catNamesOffset = reader.ReadUInt32(); uint varNamesOffset = reader.ReadUInt32(); uint rpcOffset = reader.ReadUInt32(); reader.ReadUInt32(); // dspPresetsOffset uint dspParamsOffset = reader.ReadUInt32(); reader.BaseStream.Seek(catNamesOffset, SeekOrigin.Begin); string[] categoryNames = ReadNullTerminatedStrings(numCats, reader); _categories = new AudioCategory[numCats]; reader.BaseStream.Seek(catsOffset, SeekOrigin.Begin); for (int i = 0; i < numCats; i++) { _categories [i] = new AudioCategory(this, categoryNames [i], reader); _categoryLookup.Add(categoryNames [i], i); } reader.BaseStream.Seek(varNamesOffset, SeekOrigin.Begin); string[] varNames = ReadNullTerminatedStrings(numVars, reader); var variables = new List <RpcVariable>(); var cueVariables = new List <RpcVariable>(); var globalVariables = new List <RpcVariable>(); reader.BaseStream.Seek(varsOffset, SeekOrigin.Begin); for (var i = 0; i < numVars; i++) { var v = new RpcVariable(); v.Name = varNames[i]; v.Flags = reader.ReadByte(); v.InitValue = reader.ReadSingle(); v.MinValue = reader.ReadSingle(); v.MaxValue = reader.ReadSingle(); v.Value = v.InitValue; variables.Add(v); if (!v.IsGlobal) { cueVariables.Add(v); } else { globalVariables.Add(v); _variableLookup.Add(v.Name, globalVariables.Count - 1); } } _cueVariables = cueVariables.ToArray(); _variables = globalVariables.ToArray(); var reverbCurves = new List <RpcCurve>(); RpcCurves = new RpcCurve[numRpc]; if (numRpc > 0) { reader.BaseStream.Seek(rpcOffset, SeekOrigin.Begin); for (var i = 0; i < numRpc; i++) { var curve = new RpcCurve(); curve.FileOffset = (uint)reader.BaseStream.Position; var variable = variables[reader.ReadUInt16()]; if (variable.IsGlobal) { curve.IsGlobal = true; curve.Variable = globalVariables.FindIndex(e => e.Name == variable.Name); } else { curve.IsGlobal = false; curve.Variable = cueVariables.FindIndex(e => e.Name == variable.Name); } var pointCount = (int)reader.ReadByte(); curve.Parameter = (RpcParameter)reader.ReadUInt16(); curve.Points = new RpcPoint[pointCount]; for (var j = 0; j < pointCount; j++) { curve.Points[j].Position = reader.ReadSingle(); curve.Points[j].Value = reader.ReadSingle(); curve.Points[j].Type = (RpcPointType)reader.ReadByte(); } // If the parameter is greater than the max then this is a DSP // parameter which is for reverb. var dspParameter = curve.Parameter - RpcParameter.NumParameters; if (dspParameter >= 0 && variable.IsGlobal) { reverbCurves.Add(curve); } RpcCurves[i] = curve; } } _reverbCurves = reverbCurves.ToArray(); if (numDspPresets > 0) { // Note: It seemed like MS designed this to support multiple // DSP effects, but in practice XACT only has one... Microsoft Reverb. // // So because of this we know exactly how many presets and // parameters we should have. if (numDspPresets != 1) { throw new Exception("Unexpected number of DSP presets!"); } if (numDspParams != 22) { throw new Exception("Unexpected number of DSP parameters!"); } reader.BaseStream.Seek(dspParamsOffset, SeekOrigin.Begin); _reverbSettings = new ReverbSettings(reader); } } _stopwatch = new Stopwatch(); _stopwatch.Start(); }
internal static void PlatformSetReverbSettings(ReverbSettings reverbSettings) { }