예제 #1
0
        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);
        }
예제 #2
0
        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
        }
예제 #3
0
        /// <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();
        }
예제 #4
0
 internal static void PlatformSetReverbSettings(ReverbSettings reverbSettings)
 {
 }