From 5545297ea6dd768cfe785c921b7508a4de7d9908 Mon Sep 17 00:00:00 2001 From: Mary Date: Wed, 23 Mar 2022 19:46:17 +0100 Subject: [PATCH] amadeus: Update to REV11 This should implement all ABI changes from REV11 on 14.0.0 As Nintendo changed the channel disposition for "legacy" effects (Delay, Reverb and Reverb 3D) to match the standard channel mapping, I took the liberty to just remap to the old disposition for now. The proper changes will be handled at a later date with a complete rewriting of those 3 effects to be more readable (see https://github.com/Ryujinx/Ryujinx/pull/3205 for the first iteration of it). --- .../Renderer/Dsp/Command/DelayCommand.cs | 7 +- .../Renderer/Dsp/Command/Reverb3dCommand.cs | 9 +- .../Renderer/Dsp/Command/ReverbCommand.cs | 9 +- .../Renderer/Dsp/DataSourceHelper.cs | 34 +++ .../Renderer/Dsp/State/Reverb3dState.cs | 4 +- .../Renderer/Dsp/State/ReverbState.cs | 4 +- .../Renderer/Server/AudioRenderSystem.cs | 3 + .../Renderer/Server/BehaviourContext.cs | 24 +- .../Renderer/Server/CommandBuffer.cs | 15 +- .../Renderer/Server/CommandGenerator.cs | 18 +- .../CommandProcessingTimeEstimatorVersion3.cs | 6 +- .../CommandProcessingTimeEstimatorVersion5.cs | 253 ++++++++++++++++++ 12 files changed, 358 insertions(+), 28 deletions(-) create mode 100644 Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs index ace0f2741..8d416cc32 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs @@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command private const int FixedPointPrecision = 14; - public DelayCommand(uint bufferOffset, DelayParameter parameter, Memory state, bool isEnabled, ulong workBuffer, int nodeId) + public DelayCommand(uint bufferOffset, DelayParameter parameter, Memory state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) { Enabled = true; NodeId = nodeId; @@ -63,6 +63,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); } + + // NOTE: We do the opposite as Nintendo here for now to restore previous behaviour + // TODO: Update delay processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. + DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices); + DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs index 7da9804eb..5cbc10606 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs @@ -63,7 +63,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command private Reverb3dParameter _parameter; - public Reverb3dCommand(uint bufferOffset, Reverb3dParameter parameter, Memory state, bool isEnabled, ulong workBuffer, int nodeId) + public Reverb3dCommand(uint bufferOffset, Reverb3dParameter parameter, Memory state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) { Enabled = true; IsEffectEnabled = isEnabled; @@ -80,6 +80,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); } + + // NOTE: We do the opposite as Nintendo here for now to restore previous behaviour + // TODO: Update reverb 3d processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. + DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices); + DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -194,7 +199,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command if (isSurround) { - *((float*)outputBuffers[4] + sampleIndex) += (outputValues[4] + state.BackLeftDelayLine.Update((values[2] - values[3]) * 0.5f) + channelInput[4] * state.DryGain); + *((float*)outputBuffers[4] + sampleIndex) += (outputValues[4] + state.FrontCenterDelayLine.Update((values[2] - values[3]) * 0.5f) + channelInput[4] * state.DryGain); } } } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs index 1da9c81b3..15c67f170 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs @@ -66,7 +66,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command private const int FixedPointPrecision = 14; - public ReverbCommand(uint bufferOffset, ReverbParameter parameter, Memory state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported) + public ReverbCommand(uint bufferOffset, ReverbParameter parameter, Memory state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported) { Enabled = true; IsEffectEnabled = isEnabled; @@ -85,6 +85,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } IsLongSizePreDelaySupported = isLongSizePreDelaySupported; + + // NOTE: We do the opposite as Nintendo here for now to restore previous behaviour + // TODO: Update reverb processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. + DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices); + DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -214,7 +219,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command if (isSurround) { - outputValues[4] += state.BackLeftDelayLine.Update((feedbackOutputValues[2] - feedbackOutputValues[3]) * 0.5f); + outputValues[4] += state.FrontCenterDelayLine.Update((feedbackOutputValues[2] - feedbackOutputValues[3]) * 0.5f); } for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) diff --git a/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs b/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs index 4732f504b..5c413ee16 100644 --- a/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs +++ b/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs @@ -445,5 +445,39 @@ namespace Ryujinx.Audio.Renderer.Dsp ToIntSlow(output, input, sampleCount); } } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void RemapLegacyChannelEffectMappingToChannelResourceMapping(bool isSupported, Span bufferIndices) + { + if (!isSupported && bufferIndices.Length == 6) + { + ushort backLeft = bufferIndices[2]; + ushort backRight = bufferIndices[3]; + ushort frontCenter = bufferIndices[4]; + ushort lowFrequency = bufferIndices[5]; + + bufferIndices[2] = frontCenter; + bufferIndices[3] = lowFrequency; + bufferIndices[4] = backLeft; + bufferIndices[5] = backRight; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void RemapChannelResourceMappingToLegacy(bool isSupported, Span bufferIndices) + { + if (isSupported && bufferIndices.Length == 6) + { + ushort frontCenter = bufferIndices[2]; + ushort lowFrequency = bufferIndices[3]; + ushort backLeft = bufferIndices[4]; + ushort backRight = bufferIndices[5]; + + bufferIndices[2] = backLeft; + bufferIndices[3] = backRight; + bufferIndices[4] = frontCenter; + bufferIndices[5] = lowFrequency; + } + } } } diff --git a/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs b/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs index be0f9734f..dc7d6efe0 100644 --- a/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs +++ b/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State public DecayDelay[] DecayDelays1 { get; } public DecayDelay[] DecayDelays2 { get; } public IDelayLine PreDelayLine { get; } - public IDelayLine BackLeftDelayLine { get; } + public IDelayLine FrontCenterDelayLine { get; } public float DryGain { get; private set; } public uint[] EarlyDelayTime { get; private set; } public float PreviousPreDelayValue { get; set; } @@ -69,7 +69,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State } PreDelayLine = new DelayLine3d(sampleRate, 400); - BackLeftDelayLine = new DelayLine3d(sampleRate, 5); + FrontCenterDelayLine = new DelayLine3d(sampleRate, 5); UpdateParameter(ref parameter); } diff --git a/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs b/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs index c75bdce2d..fc0c6539a 100644 --- a/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs +++ b/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs @@ -97,7 +97,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State public DelayLine[] FdnDelayLines { get; } public DecayDelay[] DecayDelays { get; } public DelayLine PreDelayLine { get; } - public DelayLine BackLeftDelayLine { get; } + public DelayLine FrontCenterDelayLine { get; } public uint[] EarlyDelayTime { get; } public float[] EarlyGain { get; } public uint PreDelayLineDelayTime { get; private set; } @@ -149,7 +149,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State } PreDelayLine = new DelayLine(sampleRate, preDelayTimeMax); - BackLeftDelayLine = new DelayLine(sampleRate, 5.0f); + FrontCenterDelayLine = new DelayLine(sampleRate, 5.0f); UpdateParameter(ref parameter); } diff --git a/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs b/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs index 277c2474d..0c41909e5 100644 --- a/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs +++ b/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs @@ -363,6 +363,9 @@ namespace Ryujinx.Audio.Renderer.Server case 4: _commandProcessingTimeEstimator = new CommandProcessingTimeEstimatorVersion4(_sampleCount, _mixBufferCount); break; + case 5: + _commandProcessingTimeEstimator = new CommandProcessingTimeEstimatorVersion5(_sampleCount, _mixBufferCount); + break; default: throw new NotImplementedException($"Unsupported processing time estimator version {_behaviourContext.GetCommandProcessingTimeEstimatorVersion()}."); } diff --git a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs index d3a65b725..cf9cda0ba 100644 --- a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs +++ b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs @@ -107,10 +107,18 @@ namespace Ryujinx.Audio.Renderer.Server /// This was added in system update 13.0.0 public const int Revision10 = 10 << 24; + /// + /// REV11: + /// The "legacy" effects (Delay, Reverb and Reverb 3D) were updated to match the standard channel mapping used by the audio renderer. + /// A new version of the command estimator was added to address timing changes caused by the legacy effects changes. + /// + /// This was added in system update 14.0.0 + public const int Revision11 = 11 << 24; + /// /// Last revision supported by the implementation. /// - public const int LastRevision = Revision10; + public const int LastRevision = Revision11; /// /// Target revision magic supported by the implementation. @@ -366,12 +374,26 @@ namespace Ryujinx.Audio.Renderer.Server return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision10); } + /// + /// Check if the audio renderer should support new channel resource mapping for 5.1 on Delay, Reverb and Reverb 3D effects. + /// + /// True if the audio renderer support new channel resource mapping for 5.1. + public bool IsNewEffectChannelMappingSupported() + { + return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision11); + } + /// /// Get the version of the . /// /// The version of the . public int GetCommandProcessingTimeEstimatorVersion() { + if (CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision11)) + { + return 5; + } + if (CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision10)) { return 4; diff --git a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 0e74c301e..c3aae96de 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -336,11 +336,12 @@ namespace Ryujinx.Audio.Renderer.Server /// The work buffer to use for processing. /// The node id associated to this command. /// If set to true, the long size pre-delay is supported. - public void GenerateReverbEffect(uint bufferOffset, ReverbParameter parameter, Memory state, bool isEnabled, CpuAddress workBuffer, int nodeId, bool isLongSizePreDelaySupported) + /// If set to true, the new effect channel mapping for 5.1 is supported. + public void GenerateReverbEffect(uint bufferOffset, ReverbParameter parameter, Memory state, bool isEnabled, CpuAddress workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported) { if (parameter.IsChannelCountValid()) { - ReverbCommand command = new ReverbCommand(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, isLongSizePreDelaySupported); + ReverbCommand command = new ReverbCommand(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, isLongSizePreDelaySupported, newEffectChannelMappingSupported); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); @@ -357,11 +358,12 @@ namespace Ryujinx.Audio.Renderer.Server /// Set to true if the effect should be active. /// The work buffer to use for processing. /// The node id associated to this command. - public void GenerateReverb3dEffect(uint bufferOffset, Reverb3dParameter parameter, Memory state, bool isEnabled, CpuAddress workBuffer, int nodeId) + /// If set to true, the new effect channel mapping for 5.1 is supported. + public void GenerateReverb3dEffect(uint bufferOffset, Reverb3dParameter parameter, Memory state, bool isEnabled, CpuAddress workBuffer, int nodeId, bool newEffectChannelMappingSupported) { if (parameter.IsChannelCountValid()) { - Reverb3dCommand command = new Reverb3dCommand(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId); + Reverb3dCommand command = new Reverb3dCommand(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, newEffectChannelMappingSupported); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); @@ -379,11 +381,12 @@ namespace Ryujinx.Audio.Renderer.Server /// Set to true if the effect should be active. /// The work buffer to use for processing. /// The node id associated to this command. - public void GenerateDelayEffect(uint bufferOffset, DelayParameter parameter, Memory state, bool isEnabled, CpuAddress workBuffer, int nodeId) + /// If set to true, the new effect channel mapping for 5.1 is supported. + public void GenerateDelayEffect(uint bufferOffset, DelayParameter parameter, Memory state, bool isEnabled, CpuAddress workBuffer, int nodeId, bool newEffectChannelMappingSupported) { if (parameter.IsChannelCountValid()) { - DelayCommand command = new DelayCommand(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId); + DelayCommand command = new DelayCommand(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, newEffectChannelMappingSupported); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); diff --git a/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs b/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs index 85c019c25..8194ebf13 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs @@ -483,31 +483,31 @@ namespace Ryujinx.Audio.Renderer.Server } } - private void GenerateDelayEffect(uint bufferOffset, DelayEffect effect, int nodeId) + private void GenerateDelayEffect(uint bufferOffset, DelayEffect effect, int nodeId, bool newEffectChannelMappingSupported) { Debug.Assert(effect.Type == EffectType.Delay); ulong workBuffer = effect.GetWorkBuffer(-1); - _commandBuffer.GenerateDelayEffect(bufferOffset, effect.Parameter, effect.State, effect.IsEnabled, workBuffer, nodeId); + _commandBuffer.GenerateDelayEffect(bufferOffset, effect.Parameter, effect.State, effect.IsEnabled, workBuffer, nodeId, newEffectChannelMappingSupported); } - private void GenerateReverbEffect(uint bufferOffset, ReverbEffect effect, int nodeId, bool isLongSizePreDelaySupported) + private void GenerateReverbEffect(uint bufferOffset, ReverbEffect effect, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported) { Debug.Assert(effect.Type == EffectType.Reverb); ulong workBuffer = effect.GetWorkBuffer(-1); - _commandBuffer.GenerateReverbEffect(bufferOffset, effect.Parameter, effect.State, effect.IsEnabled, workBuffer, nodeId, isLongSizePreDelaySupported); + _commandBuffer.GenerateReverbEffect(bufferOffset, effect.Parameter, effect.State, effect.IsEnabled, workBuffer, nodeId, isLongSizePreDelaySupported, newEffectChannelMappingSupported); } - private void GenerateReverb3dEffect(uint bufferOffset, Reverb3dEffect effect, int nodeId) + private void GenerateReverb3dEffect(uint bufferOffset, Reverb3dEffect effect, int nodeId, bool newEffectChannelMappingSupported) { Debug.Assert(effect.Type == EffectType.Reverb3d); ulong workBuffer = effect.GetWorkBuffer(-1); - _commandBuffer.GenerateReverb3dEffect(bufferOffset, effect.Parameter, effect.State, effect.IsEnabled, workBuffer, nodeId); + _commandBuffer.GenerateReverb3dEffect(bufferOffset, effect.Parameter, effect.State, effect.IsEnabled, workBuffer, nodeId, newEffectChannelMappingSupported); } private void GenerateBiquadFilterEffect(uint bufferOffset, BiquadFilterEffect effect, int nodeId) @@ -650,13 +650,13 @@ namespace Ryujinx.Audio.Renderer.Server GenerateAuxEffect(mix.BufferOffset, (AuxiliaryBufferEffect)effect, nodeId); break; case EffectType.Delay: - GenerateDelayEffect(mix.BufferOffset, (DelayEffect)effect, nodeId); + GenerateDelayEffect(mix.BufferOffset, (DelayEffect)effect, nodeId, _rendererContext.BehaviourContext.IsNewEffectChannelMappingSupported()); break; case EffectType.Reverb: - GenerateReverbEffect(mix.BufferOffset, (ReverbEffect)effect, nodeId, mix.IsLongSizePreDelaySupported); + GenerateReverbEffect(mix.BufferOffset, (ReverbEffect)effect, nodeId, mix.IsLongSizePreDelaySupported, _rendererContext.BehaviourContext.IsNewEffectChannelMappingSupported()); break; case EffectType.Reverb3d: - GenerateReverb3dEffect(mix.BufferOffset, (Reverb3dEffect)effect, nodeId); + GenerateReverb3dEffect(mix.BufferOffset, (Reverb3dEffect)effect, nodeId, _rendererContext.BehaviourContext.IsNewEffectChannelMappingSupported()); break; case EffectType.BiquadFilter: GenerateBiquadFilterEffect(mix.BufferOffset, (BiquadFilterEffect)effect, nodeId); diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs index 75d3d05bc..d9afdfb09 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs @@ -198,7 +198,7 @@ namespace Ryujinx.Audio.Renderer.Server return (uint)1853.2f; } - public uint Estimate(DelayCommand command) + public virtual uint Estimate(DelayCommand command) { Debug.Assert(_sampleCount == 160 || _sampleCount == 240); @@ -272,7 +272,7 @@ namespace Ryujinx.Audio.Renderer.Server } } - public uint Estimate(ReverbCommand command) + public virtual uint Estimate(ReverbCommand command) { Debug.Assert(_sampleCount == 160 || _sampleCount == 240); @@ -346,7 +346,7 @@ namespace Ryujinx.Audio.Renderer.Server } } - public uint Estimate(Reverb3dCommand command) + public virtual uint Estimate(Reverb3dCommand command) { Debug.Assert(_sampleCount == 160 || _sampleCount == 240); diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs new file mode 100644 index 000000000..6b55a909c --- /dev/null +++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs @@ -0,0 +1,253 @@ +// +// Copyright (c) 2019-2022 Ryujinx +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// + +using Ryujinx.Audio.Renderer.Dsp.Command; +using System; +using System.Diagnostics; + +namespace Ryujinx.Audio.Renderer.Server +{ + /// + /// version 5. (added with REV11) + /// + public class CommandProcessingTimeEstimatorVersion5 : CommandProcessingTimeEstimatorVersion4 + { + public CommandProcessingTimeEstimatorVersion5(uint sampleCount, uint bufferCount) : base(sampleCount, bufferCount) { } + + public override uint Estimate(DelayCommand command) + { + Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + + if (_sampleCount == 160) + { + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 8929; + case 2: + return 25501; + case 4: + return 47760; + case 6: + return 82203; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)1295.20f; + case 2: + return (uint)1213.60f; + case 4: + return (uint)942.03f; + case 6: + return (uint)1001.6f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 11941; + case 2: + return 37197; + case 4: + return 69750; + case 6: + return 12004; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)997.67f; + case 2: + return (uint)977.63f; + case 4: + return (uint)792.31f; + case 6: + return (uint)875.43f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + + public override uint Estimate(ReverbCommand command) + { + Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + + if (_sampleCount == 160) + { + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 81475; + case 2: + return 84975; + case 4: + return 91625; + case 6: + return 95332; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)536.30f; + case 2: + return (uint)588.80f; + case 4: + return (uint)643.70f; + case 6: + return (uint)706.0f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 120170; + case 2: + return 125260; + case 4: + return 135750; + case 6: + return 141130; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)617.64f; + case 2: + return (uint)659.54f; + case 4: + return (uint)711.44f; + case 6: + return (uint)778.07f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + + public override uint Estimate(Reverb3dCommand command) + { + Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + + if (_sampleCount == 160) + { + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 116750; + case 2: + return 125910; + case 4: + return 146340; + case 6: + return 165810; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 735; + case 2: + return (uint)766.62f; + case 4: + return (uint)834.07f; + case 6: + return (uint)875.44f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 170290; + case 2: + return 183880; + case 4: + return 214700; + case 6: + return 243850; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)508.47f; + case 2: + return (uint)582.45f; + case 4: + return (uint)626.42f; + case 6: + return (uint)682.47f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + } +}