mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-08-03 13:27:11 +02:00
Update audio renderer to REV13: Add support for compressor statistics and volume reset (#7372)
* Update audio renderer to REV13: Add support for compressor statistics and volume reset * XML docs * Disable stats reset * Wrong comment * Fix more XML docs * PR feedback
This commit is contained in:
parent
7d158acc3b
commit
a2c0035013
20 changed files with 352 additions and 88 deletions
|
@ -108,10 +108,18 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
/// <remarks>This was added in system update 17.0.0</remarks>
|
||||
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.
|
||||
|
@ -384,6 +392,15 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision12);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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}");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,11 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
|||
/// </summary>
|
||||
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>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue