diff options
Diffstat (limited to 'Ryujinx.Audio/Renderer/Server')
11 files changed, 191 insertions, 1 deletions
diff --git a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs index adf5294e..821947a9 100644 --- a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs +++ b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs @@ -44,7 +44,7 @@ namespace Ryujinx.Audio.Renderer.Server /// <see cref="Parameter.RendererInfoOutStatus"/> was added to supply the count of update done sent to the DSP. /// A new version of the command estimator was added to address timing changes caused by the voice changes. /// Additionally, the rendering limit percent was incremented to 80%. - /// + /// /// </summary> /// <remarks>This was added in system update 6.0.0</remarks> public const int Revision5 = 5 << 24; @@ -93,6 +93,7 @@ namespace Ryujinx.Audio.Renderer.Server /// <summary> /// REV11: /// The "legacy" effects (Delay, Reverb and Reverb 3D) were updated to match the standard channel mapping used by the audio renderer. + /// A new effect was added: Compressor. This effect is effectively implemented with a DRC. /// A new version of the command estimator was added to address timing changes caused by the legacy effects changes. /// A voice drop parameter was added in 15.0.0: This allows an application to amplify or attenuate the estimated time of DSP commands. /// </summary> diff --git a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index e0741cc6..905cb205 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -469,6 +469,18 @@ namespace Ryujinx.Audio.Renderer.Server } } + public void GenerateCompressorEffect(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId) + { + if (parameter.IsChannelCountValid()) + { + CompressorCommand command = new CompressorCommand(bufferOffset, parameter, state, isEnabled, nodeId); + + command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); + + AddCommand(command); + } + } + /// <summary> /// Generate a new <see cref="VolumeCommand"/>. /// </summary> diff --git a/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs b/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs index 87e5c77f..afc1e39b 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs @@ -606,6 +606,17 @@ namespace Ryujinx.Audio.Renderer.Server } } + private void GenerateCompressorEffect(uint bufferOffset, CompressorEffect effect, int nodeId) + { + Debug.Assert(effect.Type == EffectType.Compressor); + + _commandBuffer.GenerateCompressorEffect(bufferOffset, + effect.Parameter, + effect.State, + effect.IsEnabled, + nodeId); + } + private void GenerateEffect(ref MixState mix, int effectId, BaseEffect effect) { int nodeId = mix.NodeId; @@ -650,6 +661,9 @@ namespace Ryujinx.Audio.Renderer.Server case EffectType.CaptureBuffer: GenerateCaptureEffect(mix.BufferOffset, (CaptureBufferEffect)effect, nodeId); break; + case EffectType.Compressor: + GenerateCompressorEffect(mix.BufferOffset, (CompressorEffect)effect, nodeId); + break; default: throw new NotImplementedException($"Unsupported effect type {effect.Type}"); } diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs index 32c52dc4..63dc9ca9 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs @@ -179,5 +179,10 @@ namespace Ryujinx.Audio.Renderer.Server { return 0; } + + public uint Estimate(CompressorCommand command) + { + return 0; + } } }
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs index 15800c99..7ee491cd 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs @@ -543,5 +543,10 @@ namespace Ryujinx.Audio.Renderer.Server { return 0; } + + public uint Estimate(CompressorCommand command) + { + return 0; + } } }
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs index 6c6e2828..b79ca136 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs @@ -747,5 +747,10 @@ namespace Ryujinx.Audio.Renderer.Server { return 0; } + + public virtual uint Estimate(CompressorCommand command) + { + return 0; + } } }
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs index 961d92aa..2ed7e6a5 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs @@ -232,5 +232,79 @@ namespace Ryujinx.Audio.Renderer.Server } } } + + public override uint Estimate(CompressorCommand command) + { + Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + + if (_sampleCount == 160) + { + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 34431; + case 2: + return 44253; + case 4: + return 63827; + case 6: + return 83361; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)630.12f; + case 2: + return (uint)638.27f; + case 4: + return (uint)705.86f; + case 6: + return (uint)782.02f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } + + if (command.Enabled) + { + switch (command.Parameter.ChannelCount) + { + case 1: + return 51095; + case 2: + return 65693; + case 4: + return 95383; + case 6: + return 124510; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + else + { + switch (command.Parameter.ChannelCount) + { + case 1: + return (uint)840.14f; + case 2: + return (uint)826.1f; + case 4: + return (uint)901.88f; + case 6: + return (uint)965.29f; + default: + throw new NotImplementedException($"{command.Parameter.ChannelCount}"); + } + } + } } }
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs b/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs index 35314aca..825b3bf7 100644 --- a/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs +++ b/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs @@ -262,6 +262,8 @@ namespace Ryujinx.Audio.Renderer.Server.Effect return PerformanceDetailType.Limiter; case EffectType.CaptureBuffer: return PerformanceDetailType.CaptureBuffer; + case EffectType.Compressor: + return PerformanceDetailType.Compressor; default: throw new NotImplementedException($"{Type}"); } diff --git a/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs b/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs new file mode 100644 index 00000000..f4e5ae82 --- /dev/null +++ b/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs @@ -0,0 +1,67 @@ +using Ryujinx.Audio.Renderer.Common; +using Ryujinx.Audio.Renderer.Dsp.State; +using Ryujinx.Audio.Renderer.Parameter.Effect; +using Ryujinx.Audio.Renderer.Parameter; +using Ryujinx.Audio.Renderer.Server.MemoryPool; +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Ryujinx.Audio.Renderer.Server.Effect +{ + /// <summary> + /// Server state for a compressor effect. + /// </summary> + public class CompressorEffect : BaseEffect + { + /// <summary> + /// The compressor parameter. + /// </summary> + public CompressorParameter Parameter; + + /// <summary> + /// The compressor state. + /// </summary> + public Memory<CompressorState> State { get; } + + /// <summary> + /// Create a new <see cref="CompressorEffect"/>. + /// </summary> + public CompressorEffect() + { + State = new CompressorState[1]; + } + + public override EffectType TargetEffectType => EffectType.Compressor; + + public override ulong GetWorkBuffer(int index) + { + return GetSingleBuffer(); + } + + public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion1 parameter, PoolMapper mapper) + { + // Nintendo doesn't do anything here but we still require updateErrorInfo to be initialised. + updateErrorInfo = new BehaviourParameter.ErrorInfo(); + } + + public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper) + { + Debug.Assert(IsTypeValid(ref parameter)); + + UpdateParameterBase(ref parameter); + + Parameter = MemoryMarshal.Cast<byte, CompressorParameter>(parameter.SpecificData)[0]; + IsEnabled = parameter.IsEnabled; + + updateErrorInfo = new BehaviourParameter.ErrorInfo(); + } + + public override void UpdateForCommandGeneration() + { + UpdateUsageStateForCommandGeneration(); + + Parameter.Status = UsageState.Enabled; + } + } +} diff --git a/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs b/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs index e365a86c..4872ddb3 100644 --- a/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs +++ b/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs @@ -35,5 +35,6 @@ namespace Ryujinx.Audio.Renderer.Server uint Estimate(LimiterCommandVersion2 command); uint Estimate(GroupedBiquadFilterCommand command); uint Estimate(CaptureBufferCommand command); + uint Estimate(CompressorCommand command); } }
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs index 0c2cfa7e..0446cd8c 100644 --- a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs +++ b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs @@ -240,6 +240,10 @@ namespace Ryujinx.Audio.Renderer.Server case EffectType.CaptureBuffer: effect = new CaptureBufferEffect(); break; + case EffectType.Compressor: + effect = new CompressorEffect(); + break; + default: throw new NotImplementedException($"EffectType {parameter.Type} not implemented!"); } |
