diff options
Diffstat (limited to 'src/Ryujinx.Audio/Renderer/Server')
9 files changed, 118 insertions, 27 deletions
diff --git a/src/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs b/src/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs index 32c7de6c..f725eb9f 100644 --- a/src/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs +++ b/src/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs @@ -109,9 +109,17 @@ namespace Ryujinx.Audio.Renderer.Server public const int Revision12 = 12 << 24; /// <summary> + /// REV13: + /// The compressor effect can now output statistics. + /// Splitter destinations now explicitly reset the previous mix volume, instead of doing so on first use. + /// </summary> + /// <remarks>This was added in system update 18.0.0</remarks> + public const int Revision13 = 13 << 24; + + /// <summary> /// Last revision supported by the implementation. /// </summary> - public const int LastRevision = Revision12; + public const int LastRevision = Revision13; /// <summary> /// Target revision magic supported by the implementation. @@ -385,6 +393,15 @@ namespace Ryujinx.Audio.Renderer.Server } /// <summary> + /// Check if the audio renderer should support explicit previous mix volume reset on splitter. + /// </summary> + /// <returns>True if the audio renderer support explicit previous mix volume reset on splitter</returns> + public bool IsSplitterPrevVolumeResetSupported() + { + return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision13); + } + + /// <summary> /// Get the version of the <see cref="ICommandProcessingTimeEstimator"/>. /// </summary> /// <returns>The version of the <see cref="ICommandProcessingTimeEstimator"/>.</returns> diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 702f0546..4c353b37 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -583,11 +583,20 @@ namespace Ryujinx.Audio.Renderer.Server } } - public void GenerateCompressorEffect(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId) + /// <summary> + /// Generate a new <see cref="CompressorCommand"/>. + /// </summary> + /// <param name="bufferOffset">The target buffer offset.</param> + /// <param name="parameter">The compressor parameter.</param> + /// <param name="state">The compressor state.</param> + /// <param name="effectResultState">The DSP effect result state.</param> + /// <param name="isEnabled">Set to true if the effect should be active.</param> + /// <param name="nodeId">The node id associated to this command.</param> + public void GenerateCompressorEffect(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> effectResultState, bool isEnabled, int nodeId) { if (parameter.IsChannelCountValid()) { - CompressorCommand command = new(bufferOffset, parameter, state, isEnabled, nodeId); + CompressorCommand command = new(bufferOffset, parameter, state, effectResultState, isEnabled, nodeId); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs b/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs index d798230c..0b789537 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs @@ -735,14 +735,26 @@ namespace Ryujinx.Audio.Renderer.Server } } - private void GenerateCompressorEffect(uint bufferOffset, CompressorEffect effect, int nodeId) + private void GenerateCompressorEffect(uint bufferOffset, CompressorEffect effect, int nodeId, int effectId) { Debug.Assert(effect.Type == EffectType.Compressor); + Memory<EffectResultState> dspResultState; + + if (effect.Parameter.StatisticsEnabled) + { + dspResultState = _effectContext.GetDspStateMemory(effectId); + } + else + { + dspResultState = Memory<EffectResultState>.Empty; + } + _commandBuffer.GenerateCompressorEffect( bufferOffset, effect.Parameter, effect.State, + dspResultState, effect.IsEnabled, nodeId); } @@ -795,7 +807,7 @@ namespace Ryujinx.Audio.Renderer.Server GenerateCaptureEffect(mix.BufferOffset, (CaptureBufferEffect)effect, nodeId); break; case EffectType.Compressor: - GenerateCompressorEffect(mix.BufferOffset, (CompressorEffect)effect, nodeId); + GenerateCompressorEffect(mix.BufferOffset, (CompressorEffect)effect, nodeId, effectId); break; default: throw new NotImplementedException($"Unsupported effect type {effect.Type}"); diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs index 06f135a8..bc9ba073 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs @@ -169,14 +169,28 @@ namespace Ryujinx.Audio.Renderer.Server { if (command.Enabled) { - return command.Parameter.ChannelCount switch + if (command.Parameter.StatisticsEnabled) { - 1 => 34431, - 2 => 44253, - 4 => 63827, - 6 => 83361, - _ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"), - }; + return command.Parameter.ChannelCount switch + { + 1 => 22100, + 2 => 33211, + 4 => 41587, + 6 => 58819, + _ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"), + }; + } + else + { + return command.Parameter.ChannelCount switch + { + 1 => 19052, + 2 => 29852, + 4 => 37904, + 6 => 55020, + _ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"), + }; + } } return command.Parameter.ChannelCount switch @@ -191,14 +205,28 @@ namespace Ryujinx.Audio.Renderer.Server if (command.Enabled) { - return command.Parameter.ChannelCount switch + if (command.Parameter.StatisticsEnabled) { - 1 => 51095, - 2 => 65693, - 4 => 95383, - 6 => 124510, - _ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"), - }; + return command.Parameter.ChannelCount switch + { + 1 => 32518, + 2 => 49102, + 4 => 61685, + 6 => 87250, + _ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"), + }; + } + else + { + return command.Parameter.ChannelCount switch + { + 1 => 27963, + 2 => 44016, + 4 => 56183, + 6 => 81862, + _ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"), + }; + } } return command.Parameter.ChannelCount switch diff --git a/src/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs b/src/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs index eff60e7d..de0f44e4 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs @@ -62,6 +62,19 @@ namespace Ryujinx.Audio.Renderer.Server.Effect UpdateUsageStateForCommandGeneration(); Parameter.Status = UsageState.Enabled; + Parameter.StatisticsReset = false; + } + + public override void InitializeResultState(ref EffectResultState state) + { + ref CompressorStatistics statistics = ref MemoryMarshal.Cast<byte, CompressorStatistics>(state.SpecificData)[0]; + + statistics.Reset(Parameter.ChannelCount); + } + + public override void UpdateResultState(ref EffectResultState destState, ref EffectResultState srcState) + { + destState = srcState; } } } diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterContext.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterContext.cs index a7b82a6b..6dddb431 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterContext.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterContext.cs @@ -52,6 +52,11 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter public bool IsBugFixed { get; private set; } /// <summary> + /// If set to true, the previous mix volume is explicitly resetted using the input parameter, instead of implicitly on first use. + /// </summary> + public bool IsSplitterPrevVolumeResetSupported { get; private set; } + + /// <summary> /// Initialize <see cref="SplitterContext"/>. /// </summary> /// <param name="behaviourContext">The behaviour context.</param> @@ -139,6 +144,8 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter } } + IsSplitterPrevVolumeResetSupported = behaviourContext.IsSplitterPrevVolumeResetSupported(); + SplitterState.InitializeSplitters(splitters.Span); Setup(splitters, splitterDestinationsV1, splitterDestinationsV2, behaviourContext.IsSplitterBugFixed()); @@ -277,7 +284,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter { SplitterDestination destination = GetDestination(parameter.Id); - destination.Update(parameter); + destination.Update(parameter, IsSplitterPrevVolumeResetSupported); } return true; diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestination.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestination.cs index 36dfa5e4..1a46d41f 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestination.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestination.cs @@ -184,15 +184,16 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// Update the splitter destination data from user parameter. /// </summary> /// <param name="parameter">The user parameter.</param> - public void Update<T>(in T parameter) where T : ISplitterDestinationInParameter + /// <param name="isPrevVolumeResetSupported">Indicates that the audio renderer revision in use supports explicitly resetting the volume.</param> + public void Update<T>(in T parameter, bool isPrevVolumeResetSupported) where T : ISplitterDestinationInParameter { if (Unsafe.IsNullRef(ref _v2)) { - _v1.Update(parameter); + _v1.Update(parameter, isPrevVolumeResetSupported); } else { - _v2.Update(parameter); + _v2.Update(parameter, isPrevVolumeResetSupported); } } diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs index 5d2b8fb0..ce8f3368 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs @@ -93,7 +93,8 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// Update the <see cref="SplitterDestinationVersion1"/> from user parameter. /// </summary> /// <param name="parameter">The user parameter.</param> - public void Update<T>(in T parameter) where T : ISplitterDestinationInParameter + /// <param name="isPrevVolumeResetSupported">Indicates that the audio renderer revision in use supports explicitly resetting the volume.</param> + public void Update<T>(in T parameter, bool isPrevVolumeResetSupported) where T : ISplitterDestinationInParameter { Debug.Assert(Id == parameter.Id); @@ -103,7 +104,8 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter parameter.MixBufferVolume.CopyTo(MixBufferVolume); - if (!IsUsed && parameter.IsUsed) + bool resetPrevVolume = isPrevVolumeResetSupported ? parameter.ResetPrevVolume : !IsUsed && parameter.IsUsed; + if (resetPrevVolume) { MixBufferVolume.CopyTo(PreviousMixBufferVolume); diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs index f9487909..5f96ef3a 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs @@ -98,7 +98,8 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// Update the <see cref="SplitterDestinationVersion2"/> from user parameter. /// </summary> /// <param name="parameter">The user parameter.</param> - public void Update<T>(in T parameter) where T : ISplitterDestinationInParameter + /// <param name="isPrevVolumeResetSupported">Indicates that the audio renderer revision in use supports explicitly resetting the volume.</param> + public void Update<T>(in T parameter, bool isPrevVolumeResetSupported) where T : ISplitterDestinationInParameter { Debug.Assert(Id == parameter.Id); @@ -110,7 +111,8 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter _biquadFilters = parameter.BiquadFilters; - if (!IsUsed && parameter.IsUsed) + bool resetPrevVolume = isPrevVolumeResetSupported ? parameter.ResetPrevVolume : !IsUsed && parameter.IsUsed; + if (resetPrevVolume) { MixBufferVolume.CopyTo(PreviousMixBufferVolume); |