forked from Mirror/Ryujinx
Compare commits
1 commit
master
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
|
b5963eba2b |
21 changed files with 97 additions and 361 deletions
|
@ -3,18 +3,18 @@
|
||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.0.10" />
|
<PackageVersion Include="Avalonia" Version="11.1.3" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.1.3" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.1.3" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.1.3" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.1.3" />
|
||||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
|
<PackageVersion Include="Avalonia.Svg" Version="11.1.0.1" />
|
||||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
|
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.1.0.1" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.0" />
|
<PackageVersion Include="Concentus" Version="2.2.0" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="2.1.0" />
|
||||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" />
|
||||||
<PackageVersion Include="SkiaSharp" Version="2.88.7" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.8" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
using Ryujinx.Audio.Renderer.Dsp.Effect;
|
using Ryujinx.Audio.Renderer.Dsp.Effect;
|
||||||
using Ryujinx.Audio.Renderer.Dsp.State;
|
using Ryujinx.Audio.Renderer.Dsp.State;
|
||||||
using Ryujinx.Audio.Renderer.Parameter;
|
|
||||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
{
|
{
|
||||||
|
@ -23,20 +21,18 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
public CompressorParameter Parameter => _parameter;
|
public CompressorParameter Parameter => _parameter;
|
||||||
public Memory<CompressorState> State { get; }
|
public Memory<CompressorState> State { get; }
|
||||||
public Memory<EffectResultState> ResultState { get; }
|
|
||||||
public ushort[] OutputBufferIndices { get; }
|
public ushort[] OutputBufferIndices { get; }
|
||||||
public ushort[] InputBufferIndices { get; }
|
public ushort[] InputBufferIndices { get; }
|
||||||
public bool IsEffectEnabled { get; }
|
public bool IsEffectEnabled { get; }
|
||||||
|
|
||||||
private CompressorParameter _parameter;
|
private CompressorParameter _parameter;
|
||||||
|
|
||||||
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId)
|
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId)
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
NodeId = nodeId;
|
NodeId = nodeId;
|
||||||
_parameter = parameter;
|
_parameter = parameter;
|
||||||
State = state;
|
State = state;
|
||||||
ResultState = resultState;
|
|
||||||
|
|
||||||
IsEffectEnabled = isEnabled;
|
IsEffectEnabled = isEnabled;
|
||||||
|
|
||||||
|
@ -75,16 +71,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
if (IsEffectEnabled && _parameter.IsChannelCountValid())
|
if (IsEffectEnabled && _parameter.IsChannelCountValid())
|
||||||
{
|
{
|
||||||
if (!ResultState.IsEmpty && _parameter.StatisticsReset)
|
Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||||
{
|
Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||||
ref CompressorStatistics statistics = ref MemoryMarshal.Cast<byte, CompressorStatistics>(ResultState.Span[0].SpecificData)[0];
|
Span<float> channelInput = stackalloc float[Parameter.ChannelCount];
|
||||||
|
|
||||||
statistics.Reset(_parameter.ChannelCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
Span<IntPtr> inputBuffers = stackalloc IntPtr[_parameter.ChannelCount];
|
|
||||||
Span<IntPtr> outputBuffers = stackalloc IntPtr[_parameter.ChannelCount];
|
|
||||||
Span<float> channelInput = stackalloc float[_parameter.ChannelCount];
|
|
||||||
ExponentialMovingAverage inputMovingAverage = state.InputMovingAverage;
|
ExponentialMovingAverage inputMovingAverage = state.InputMovingAverage;
|
||||||
float unknown4 = state.Unknown4;
|
float unknown4 = state.Unknown4;
|
||||||
ExponentialMovingAverage compressionGainAverage = state.CompressionGainAverage;
|
ExponentialMovingAverage compressionGainAverage = state.CompressionGainAverage;
|
||||||
|
@ -103,8 +92,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
float mean = FloatingPointHelper.MeanSquare(channelInput);
|
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
|
||||||
float newMean = inputMovingAverage.Update(mean, _parameter.InputGain);
|
|
||||||
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
||||||
float z = 1.0f;
|
float z = 1.0f;
|
||||||
|
|
||||||
|
@ -123,7 +111,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
if (y >= state.Unknown14)
|
if (y >= state.Unknown14)
|
||||||
{
|
{
|
||||||
tmpGain = ((1.0f / _parameter.Ratio) - 1.0f) * (y - _parameter.Threshold);
|
tmpGain = ((1.0f / Parameter.Ratio) - 1.0f) * (y - Parameter.Threshold);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -138,7 +126,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
if ((unknown4 - z) <= 0.08f)
|
if ((unknown4 - z) <= 0.08f)
|
||||||
{
|
{
|
||||||
compressionEmaAlpha = _parameter.ReleaseCoefficient;
|
compressionEmaAlpha = Parameter.ReleaseCoefficient;
|
||||||
|
|
||||||
if ((unknown4 - z) >= -0.08f)
|
if ((unknown4 - z) >= -0.08f)
|
||||||
{
|
{
|
||||||
|
@ -152,31 +140,18 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
compressionEmaAlpha = _parameter.AttackCoefficient;
|
compressionEmaAlpha = Parameter.AttackCoefficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
float compressionGain = compressionGainAverage.Update(z, compressionEmaAlpha);
|
float compressionGain = compressionGainAverage.Update(z, compressionEmaAlpha);
|
||||||
|
|
||||||
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
|
||||||
{
|
{
|
||||||
*((float*)outputBuffers[channelIndex] + sampleIndex) = channelInput[channelIndex] * compressionGain * state.OutputGain;
|
*((float*)outputBuffers[channelIndex] + sampleIndex) = channelInput[channelIndex] * compressionGain * state.OutputGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
unknown4 = unknown4New;
|
unknown4 = unknown4New;
|
||||||
previousCompressionEmaAlpha = compressionEmaAlpha;
|
previousCompressionEmaAlpha = compressionEmaAlpha;
|
||||||
|
|
||||||
if (!ResultState.IsEmpty)
|
|
||||||
{
|
|
||||||
ref CompressorStatistics statistics = ref MemoryMarshal.Cast<byte, CompressorStatistics>(ResultState.Span[0].SpecificData)[0];
|
|
||||||
|
|
||||||
statistics.MinimumGain = MathF.Min(statistics.MinimumGain, compressionGain * state.OutputGain);
|
|
||||||
statistics.MaximumMean = MathF.Max(statistics.MaximumMean, mean);
|
|
||||||
|
|
||||||
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
|
||||||
{
|
|
||||||
statistics.LastSamples[channelIndex] = MathF.Abs(channelInput[channelIndex] * (1f / 32768f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.InputMovingAverage = inputMovingAverage;
|
state.InputMovingAverage = inputMovingAverage;
|
||||||
|
@ -186,7 +161,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,10 +38,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +51,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
if (IsEffectEnabled)
|
if (IsEffectEnabled)
|
||||||
{
|
{
|
||||||
if (_parameter.Status == UsageState.Invalid)
|
if (Parameter.Status == UsageState.Invalid)
|
||||||
{
|
{
|
||||||
state = new LimiterState(ref _parameter, WorkBuffer);
|
state = new LimiterState(ref _parameter, WorkBuffer);
|
||||||
}
|
}
|
||||||
else if (_parameter.Status == UsageState.New)
|
else if (Parameter.Status == UsageState.New)
|
||||||
{
|
{
|
||||||
LimiterState.UpdateParameter(ref _parameter);
|
LimiterState.UpdateParameter(ref _parameter);
|
||||||
}
|
}
|
||||||
|
@ -66,56 +66,56 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
private unsafe void ProcessLimiter(CommandList context, ref LimiterState state)
|
private unsafe void ProcessLimiter(CommandList context, ref LimiterState state)
|
||||||
{
|
{
|
||||||
Debug.Assert(_parameter.IsChannelCountValid());
|
Debug.Assert(Parameter.IsChannelCountValid());
|
||||||
|
|
||||||
if (IsEffectEnabled && _parameter.IsChannelCountValid())
|
if (IsEffectEnabled && Parameter.IsChannelCountValid())
|
||||||
{
|
{
|
||||||
Span<IntPtr> inputBuffers = stackalloc IntPtr[_parameter.ChannelCount];
|
Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||||
Span<IntPtr> outputBuffers = stackalloc IntPtr[_parameter.ChannelCount];
|
Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
|
inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
|
||||||
outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
|
outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
|
||||||
{
|
{
|
||||||
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
|
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
||||||
|
|
||||||
float inputSample = (rawInputSample / short.MaxValue) * _parameter.InputGain;
|
float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain;
|
||||||
|
|
||||||
float sampleInputMax = Math.Abs(inputSample);
|
float sampleInputMax = Math.Abs(inputSample);
|
||||||
|
|
||||||
float inputCoefficient = _parameter.ReleaseCoefficient;
|
float inputCoefficient = Parameter.ReleaseCoefficient;
|
||||||
|
|
||||||
if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
|
if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
|
||||||
{
|
{
|
||||||
inputCoefficient = _parameter.AttackCoefficient;
|
inputCoefficient = Parameter.AttackCoefficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
|
float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
|
||||||
float attenuation = 1.0f;
|
float attenuation = 1.0f;
|
||||||
|
|
||||||
if (detectorValue > _parameter.Threshold)
|
if (detectorValue > Parameter.Threshold)
|
||||||
{
|
{
|
||||||
attenuation = _parameter.Threshold / detectorValue;
|
attenuation = Parameter.Threshold / detectorValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float outputCoefficient = _parameter.ReleaseCoefficient;
|
float outputCoefficient = Parameter.ReleaseCoefficient;
|
||||||
|
|
||||||
if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
|
if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
|
||||||
{
|
{
|
||||||
outputCoefficient = _parameter.AttackCoefficient;
|
outputCoefficient = Parameter.AttackCoefficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
|
float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
|
||||||
|
|
||||||
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * _parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
|
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
|
||||||
|
|
||||||
float outputSample = delayedSample * compressionGain * _parameter.OutputGain;
|
float outputSample = delayedSample * compressionGain * Parameter.OutputGain;
|
||||||
|
|
||||||
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
|
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
|
||||||
|
|
||||||
|
@ -123,16 +123,16 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
state.DelayedSampleBufferPosition[channelIndex]++;
|
state.DelayedSampleBufferPosition[channelIndex]++;
|
||||||
|
|
||||||
while (state.DelayedSampleBufferPosition[channelIndex] >= _parameter.DelayBufferSampleCountMin)
|
while (state.DelayedSampleBufferPosition[channelIndex] >= Parameter.DelayBufferSampleCountMin)
|
||||||
{
|
{
|
||||||
state.DelayedSampleBufferPosition[channelIndex] -= _parameter.DelayBufferSampleCountMin;
|
state.DelayedSampleBufferPosition[channelIndex] -= Parameter.DelayBufferSampleCountMin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,10 +49,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
|
InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]);
|
||||||
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
|
OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,11 +62,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
if (IsEffectEnabled)
|
if (IsEffectEnabled)
|
||||||
{
|
{
|
||||||
if (_parameter.Status == UsageState.Invalid)
|
if (Parameter.Status == UsageState.Invalid)
|
||||||
{
|
{
|
||||||
state = new LimiterState(ref _parameter, WorkBuffer);
|
state = new LimiterState(ref _parameter, WorkBuffer);
|
||||||
}
|
}
|
||||||
else if (_parameter.Status == UsageState.New)
|
else if (Parameter.Status == UsageState.New)
|
||||||
{
|
{
|
||||||
LimiterState.UpdateParameter(ref _parameter);
|
LimiterState.UpdateParameter(ref _parameter);
|
||||||
}
|
}
|
||||||
|
@ -77,63 +77,63 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
private unsafe void ProcessLimiter(CommandList context, ref LimiterState state)
|
private unsafe void ProcessLimiter(CommandList context, ref LimiterState state)
|
||||||
{
|
{
|
||||||
Debug.Assert(_parameter.IsChannelCountValid());
|
Debug.Assert(Parameter.IsChannelCountValid());
|
||||||
|
|
||||||
if (IsEffectEnabled && _parameter.IsChannelCountValid())
|
if (IsEffectEnabled && Parameter.IsChannelCountValid())
|
||||||
{
|
{
|
||||||
if (!ResultState.IsEmpty && _parameter.StatisticsReset)
|
if (!ResultState.IsEmpty && Parameter.StatisticsReset)
|
||||||
{
|
{
|
||||||
ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0];
|
ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0];
|
||||||
|
|
||||||
statistics.Reset();
|
statistics.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<IntPtr> inputBuffers = stackalloc IntPtr[_parameter.ChannelCount];
|
Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||||
Span<IntPtr> outputBuffers = stackalloc IntPtr[_parameter.ChannelCount];
|
Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||||
|
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
|
inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
|
||||||
outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
|
outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
|
||||||
{
|
{
|
||||||
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
|
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
||||||
|
|
||||||
float inputSample = (rawInputSample / short.MaxValue) * _parameter.InputGain;
|
float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain;
|
||||||
|
|
||||||
float sampleInputMax = Math.Abs(inputSample);
|
float sampleInputMax = Math.Abs(inputSample);
|
||||||
|
|
||||||
float inputCoefficient = _parameter.ReleaseCoefficient;
|
float inputCoefficient = Parameter.ReleaseCoefficient;
|
||||||
|
|
||||||
if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
|
if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
|
||||||
{
|
{
|
||||||
inputCoefficient = _parameter.AttackCoefficient;
|
inputCoefficient = Parameter.AttackCoefficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
|
float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
|
||||||
float attenuation = 1.0f;
|
float attenuation = 1.0f;
|
||||||
|
|
||||||
if (detectorValue > _parameter.Threshold)
|
if (detectorValue > Parameter.Threshold)
|
||||||
{
|
{
|
||||||
attenuation = _parameter.Threshold / detectorValue;
|
attenuation = Parameter.Threshold / detectorValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float outputCoefficient = _parameter.ReleaseCoefficient;
|
float outputCoefficient = Parameter.ReleaseCoefficient;
|
||||||
|
|
||||||
if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
|
if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
|
||||||
{
|
{
|
||||||
outputCoefficient = _parameter.AttackCoefficient;
|
outputCoefficient = Parameter.AttackCoefficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
|
float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
|
||||||
|
|
||||||
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * _parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
|
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
|
||||||
|
|
||||||
float outputSample = delayedSample * compressionGain * _parameter.OutputGain;
|
float outputSample = delayedSample * compressionGain * Parameter.OutputGain;
|
||||||
|
|
||||||
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
|
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
|
||||||
|
|
||||||
|
@ -141,9 +141,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
state.DelayedSampleBufferPosition[channelIndex]++;
|
state.DelayedSampleBufferPosition[channelIndex]++;
|
||||||
|
|
||||||
while (state.DelayedSampleBufferPosition[channelIndex] >= _parameter.DelayBufferSampleCountMin)
|
while (state.DelayedSampleBufferPosition[channelIndex] >= Parameter.DelayBufferSampleCountMin)
|
||||||
{
|
{
|
||||||
state.DelayedSampleBufferPosition[channelIndex] -= _parameter.DelayBufferSampleCountMin;
|
state.DelayedSampleBufferPosition[channelIndex] -= Parameter.DelayBufferSampleCountMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ResultState.IsEmpty)
|
if (!ResultState.IsEmpty)
|
||||||
|
@ -158,7 +158,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||||
{
|
{
|
||||||
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,16 +90,9 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||||
public bool MakeupGainEnabled;
|
public bool MakeupGainEnabled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicate if the compressor effect should output statistics.
|
/// Reserved/padding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
private Array2<byte> _reserved;
|
||||||
public bool StatisticsEnabled;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicate to the DSP that the user did a statistics reset.
|
|
||||||
/// </summary>
|
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
|
||||||
public bool StatisticsReset;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if the <see cref="ChannelCount"/> is valid.
|
/// Check if the <see cref="ChannelCount"/> is valid.
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
using Ryujinx.Common.Memory;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Effect result state for <seealso cref="Common.EffectType.Compressor"/>.
|
|
||||||
/// </summary>
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
public struct CompressorStatistics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum input mean value since last reset.
|
|
||||||
/// </summary>
|
|
||||||
public float MaximumMean;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Minimum output gain since last reset.
|
|
||||||
/// </summary>
|
|
||||||
public float MinimumGain;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Last processed input sample, per channel.
|
|
||||||
/// </summary>
|
|
||||||
public Array6<float> LastSamples;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reset the statistics.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="channelCount">Number of channels to reset.</param>
|
|
||||||
public void Reset(ushort channelCount)
|
|
||||||
{
|
|
||||||
MaximumMean = 0.0f;
|
|
||||||
MinimumGain = 1.0f;
|
|
||||||
LastSamples.AsSpan()[..channelCount].Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -28,11 +28,6 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsUsed { get; }
|
bool IsUsed { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set to true to force resetting the previous mix volumes.
|
|
||||||
/// </summary>
|
|
||||||
bool ResetPrevVolume { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mix buffer volumes.
|
/// Mix buffer volumes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -37,16 +37,10 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
public bool IsUsed;
|
public bool IsUsed;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set to true to force resetting the previous mix volumes.
|
|
||||||
/// </summary>
|
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
|
||||||
public bool ResetPrevVolume;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reserved/padding.
|
/// Reserved/padding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private unsafe fixed byte _reserved[2];
|
private unsafe fixed byte _reserved[3];
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Size = sizeof(float) * Constants.MixBufferCountMax, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Size = sizeof(float) * Constants.MixBufferCountMax, Pack = 1)]
|
||||||
private struct MixArray { }
|
private struct MixArray { }
|
||||||
|
@ -64,7 +58,6 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
||||||
readonly Array2<BiquadFilterParameter> ISplitterDestinationInParameter.BiquadFilters => default;
|
readonly Array2<BiquadFilterParameter> ISplitterDestinationInParameter.BiquadFilters => default;
|
||||||
|
|
||||||
readonly bool ISplitterDestinationInParameter.IsUsed => IsUsed;
|
readonly bool ISplitterDestinationInParameter.IsUsed => IsUsed;
|
||||||
readonly bool ISplitterDestinationInParameter.ResetPrevVolume => ResetPrevVolume;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The expected constant of any input header.
|
/// The expected constant of any input header.
|
||||||
|
|
|
@ -42,16 +42,10 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
public bool IsUsed;
|
public bool IsUsed;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set to true to force resetting the previous mix volumes.
|
|
||||||
/// </summary>
|
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
|
||||||
public bool ResetPrevVolume;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reserved/padding.
|
/// Reserved/padding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private unsafe fixed byte _reserved[10];
|
private unsafe fixed byte _reserved[11];
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Size = sizeof(float) * Constants.MixBufferCountMax, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Size = sizeof(float) * Constants.MixBufferCountMax, Pack = 1)]
|
||||||
private struct MixArray { }
|
private struct MixArray { }
|
||||||
|
@ -69,7 +63,6 @@ namespace Ryujinx.Audio.Renderer.Parameter
|
||||||
readonly Array2<BiquadFilterParameter> ISplitterDestinationInParameter.BiquadFilters => BiquadFilters;
|
readonly Array2<BiquadFilterParameter> ISplitterDestinationInParameter.BiquadFilters => BiquadFilters;
|
||||||
|
|
||||||
readonly bool ISplitterDestinationInParameter.IsUsed => IsUsed;
|
readonly bool ISplitterDestinationInParameter.IsUsed => IsUsed;
|
||||||
readonly bool ISplitterDestinationInParameter.ResetPrevVolume => ResetPrevVolume;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The expected constant of any input header.
|
/// The expected constant of any input header.
|
||||||
|
|
|
@ -108,18 +108,10 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
/// <remarks>This was added in system update 17.0.0</remarks>
|
/// <remarks>This was added in system update 17.0.0</remarks>
|
||||||
public const int Revision12 = 12 << 24;
|
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>
|
/// <summary>
|
||||||
/// Last revision supported by the implementation.
|
/// Last revision supported by the implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int LastRevision = Revision13;
|
public const int LastRevision = Revision12;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Target revision magic supported by the implementation.
|
/// Target revision magic supported by the implementation.
|
||||||
|
@ -392,15 +384,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision12);
|
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>
|
/// <summary>
|
||||||
/// Get the version of the <see cref="ICommandProcessingTimeEstimator"/>.
|
/// Get the version of the <see cref="ICommandProcessingTimeEstimator"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -583,20 +583,11 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void GenerateCompressorEffect(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId)
|
||||||
/// 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())
|
if (parameter.IsChannelCountValid())
|
||||||
{
|
{
|
||||||
CompressorCommand command = new(bufferOffset, parameter, state, effectResultState, isEnabled, nodeId);
|
CompressorCommand command = new(bufferOffset, parameter, state, isEnabled, nodeId);
|
||||||
|
|
||||||
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
|
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
|
||||||
|
|
||||||
|
|
|
@ -735,26 +735,14 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateCompressorEffect(uint bufferOffset, CompressorEffect effect, int nodeId, int effectId)
|
private void GenerateCompressorEffect(uint bufferOffset, CompressorEffect effect, int nodeId)
|
||||||
{
|
{
|
||||||
Debug.Assert(effect.Type == EffectType.Compressor);
|
Debug.Assert(effect.Type == EffectType.Compressor);
|
||||||
|
|
||||||
Memory<EffectResultState> dspResultState;
|
|
||||||
|
|
||||||
if (effect.Parameter.StatisticsEnabled)
|
|
||||||
{
|
|
||||||
dspResultState = _effectContext.GetDspStateMemory(effectId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dspResultState = Memory<EffectResultState>.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
_commandBuffer.GenerateCompressorEffect(
|
_commandBuffer.GenerateCompressorEffect(
|
||||||
bufferOffset,
|
bufferOffset,
|
||||||
effect.Parameter,
|
effect.Parameter,
|
||||||
effect.State,
|
effect.State,
|
||||||
dspResultState,
|
|
||||||
effect.IsEnabled,
|
effect.IsEnabled,
|
||||||
nodeId);
|
nodeId);
|
||||||
}
|
}
|
||||||
|
@ -807,7 +795,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
GenerateCaptureEffect(mix.BufferOffset, (CaptureBufferEffect)effect, nodeId);
|
GenerateCaptureEffect(mix.BufferOffset, (CaptureBufferEffect)effect, nodeId);
|
||||||
break;
|
break;
|
||||||
case EffectType.Compressor:
|
case EffectType.Compressor:
|
||||||
GenerateCompressorEffect(mix.BufferOffset, (CompressorEffect)effect, nodeId, effectId);
|
GenerateCompressorEffect(mix.BufferOffset, (CompressorEffect)effect, nodeId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"Unsupported effect type {effect.Type}");
|
throw new NotImplementedException($"Unsupported effect type {effect.Type}");
|
||||||
|
|
|
@ -169,28 +169,14 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
{
|
{
|
||||||
if (command.Enabled)
|
if (command.Enabled)
|
||||||
{
|
{
|
||||||
if (command.Parameter.StatisticsEnabled)
|
return command.Parameter.ChannelCount switch
|
||||||
{
|
{
|
||||||
return command.Parameter.ChannelCount switch
|
1 => 34431,
|
||||||
{
|
2 => 44253,
|
||||||
1 => 22100,
|
4 => 63827,
|
||||||
2 => 33211,
|
6 => 83361,
|
||||||
4 => 41587,
|
_ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"),
|
||||||
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
|
return command.Parameter.ChannelCount switch
|
||||||
|
@ -205,28 +191,14 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
|
|
||||||
if (command.Enabled)
|
if (command.Enabled)
|
||||||
{
|
{
|
||||||
if (command.Parameter.StatisticsEnabled)
|
return command.Parameter.ChannelCount switch
|
||||||
{
|
{
|
||||||
return command.Parameter.ChannelCount switch
|
1 => 51095,
|
||||||
{
|
2 => 65693,
|
||||||
1 => 32518,
|
4 => 95383,
|
||||||
2 => 49102,
|
6 => 124510,
|
||||||
4 => 61685,
|
_ => throw new NotImplementedException($"{command.Parameter.ChannelCount}"),
|
||||||
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
|
return command.Parameter.ChannelCount switch
|
||||||
|
|
|
@ -62,19 +62,6 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
|
||||||
UpdateUsageStateForCommandGeneration();
|
UpdateUsageStateForCommandGeneration();
|
||||||
|
|
||||||
Parameter.Status = UsageState.Enabled;
|
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,11 +51,6 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsBugFixed { get; private set; }
|
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>
|
/// <summary>
|
||||||
/// Initialize <see cref="SplitterContext"/>.
|
/// Initialize <see cref="SplitterContext"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -144,8 +139,6 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IsSplitterPrevVolumeResetSupported = behaviourContext.IsSplitterPrevVolumeResetSupported();
|
|
||||||
|
|
||||||
SplitterState.InitializeSplitters(splitters.Span);
|
SplitterState.InitializeSplitters(splitters.Span);
|
||||||
|
|
||||||
Setup(splitters, splitterDestinationsV1, splitterDestinationsV2, behaviourContext.IsSplitterBugFixed());
|
Setup(splitters, splitterDestinationsV1, splitterDestinationsV2, behaviourContext.IsSplitterBugFixed());
|
||||||
|
@ -284,7 +277,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
{
|
{
|
||||||
SplitterDestination destination = GetDestination(parameter.Id);
|
SplitterDestination destination = GetDestination(parameter.Id);
|
||||||
|
|
||||||
destination.Update(parameter, IsSplitterPrevVolumeResetSupported);
|
destination.Update(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -184,16 +184,15 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
/// Update the splitter destination data from user parameter.
|
/// Update the splitter destination data from user parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parameter">The user parameter.</param>
|
/// <param name="parameter">The user parameter.</param>
|
||||||
/// <param name="isPrevVolumeResetSupported">Indicates that the audio renderer revision in use supports explicitly resetting the volume.</param>
|
public void Update<T>(in T parameter) where T : ISplitterDestinationInParameter
|
||||||
public void Update<T>(in T parameter, bool isPrevVolumeResetSupported) where T : ISplitterDestinationInParameter
|
|
||||||
{
|
{
|
||||||
if (Unsafe.IsNullRef(ref _v2))
|
if (Unsafe.IsNullRef(ref _v2))
|
||||||
{
|
{
|
||||||
_v1.Update(parameter, isPrevVolumeResetSupported);
|
_v1.Update(parameter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_v2.Update(parameter, isPrevVolumeResetSupported);
|
_v2.Update(parameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
/// Update the <see cref="SplitterDestinationVersion1"/> from user parameter.
|
/// Update the <see cref="SplitterDestinationVersion1"/> from user parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parameter">The user parameter.</param>
|
/// <param name="parameter">The user parameter.</param>
|
||||||
/// <param name="isPrevVolumeResetSupported">Indicates that the audio renderer revision in use supports explicitly resetting the volume.</param>
|
public void Update<T>(in T parameter) where T : ISplitterDestinationInParameter
|
||||||
public void Update<T>(in T parameter, bool isPrevVolumeResetSupported) where T : ISplitterDestinationInParameter
|
|
||||||
{
|
{
|
||||||
Debug.Assert(Id == parameter.Id);
|
Debug.Assert(Id == parameter.Id);
|
||||||
|
|
||||||
|
@ -104,8 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
|
|
||||||
parameter.MixBufferVolume.CopyTo(MixBufferVolume);
|
parameter.MixBufferVolume.CopyTo(MixBufferVolume);
|
||||||
|
|
||||||
bool resetPrevVolume = isPrevVolumeResetSupported ? parameter.ResetPrevVolume : !IsUsed && parameter.IsUsed;
|
if (!IsUsed && parameter.IsUsed)
|
||||||
if (resetPrevVolume)
|
|
||||||
{
|
{
|
||||||
MixBufferVolume.CopyTo(PreviousMixBufferVolume);
|
MixBufferVolume.CopyTo(PreviousMixBufferVolume);
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
/// Update the <see cref="SplitterDestinationVersion2"/> from user parameter.
|
/// Update the <see cref="SplitterDestinationVersion2"/> from user parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parameter">The user parameter.</param>
|
/// <param name="parameter">The user parameter.</param>
|
||||||
/// <param name="isPrevVolumeResetSupported">Indicates that the audio renderer revision in use supports explicitly resetting the volume.</param>
|
public void Update<T>(in T parameter) where T : ISplitterDestinationInParameter
|
||||||
public void Update<T>(in T parameter, bool isPrevVolumeResetSupported) where T : ISplitterDestinationInParameter
|
|
||||||
{
|
{
|
||||||
Debug.Assert(Id == parameter.Id);
|
Debug.Assert(Id == parameter.Id);
|
||||||
|
|
||||||
|
@ -111,8 +110,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||||
|
|
||||||
_biquadFilters = parameter.BiquadFilters;
|
_biquadFilters = parameter.BiquadFilters;
|
||||||
|
|
||||||
bool resetPrevVolume = isPrevVolumeResetSupported ? parameter.ResetPrevVolume : !IsUsed && parameter.IsUsed;
|
if (!IsUsed && parameter.IsUsed)
|
||||||
if (resetPrevVolume)
|
|
||||||
{
|
{
|
||||||
MixBufferVolume.CopyTo(PreviousMixBufferVolume);
|
MixBufferVolume.CopyTo(PreviousMixBufferVolume);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,5 @@ namespace Ryujinx.Horizon.Sdk.Audio
|
||||||
|
|
||||||
public static Result DeviceNotFound => new(ModuleId, 1);
|
public static Result DeviceNotFound => new(ModuleId, 1);
|
||||||
public static Result UnsupportedRevision => new(ModuleId, 2);
|
public static Result UnsupportedRevision => new(ModuleId, 2);
|
||||||
public static Result NotImplemented => new(ModuleId, 513);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,48 +233,6 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CmifCommand(15)] // 17.0.0+
|
|
||||||
public Result AcquireAudioOutputDeviceNotification([CopyHandle] out int eventHandle, ulong deviceId)
|
|
||||||
{
|
|
||||||
eventHandle = 0;
|
|
||||||
|
|
||||||
return AudioResult.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CmifCommand(16)] // 17.0.0+
|
|
||||||
public Result ReleaseAudioOutputDeviceNotification(ulong deviceId)
|
|
||||||
{
|
|
||||||
return AudioResult.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CmifCommand(17)] // 17.0.0+
|
|
||||||
public Result AcquireAudioInputDeviceNotification([CopyHandle] out int eventHandle, ulong deviceId)
|
|
||||||
{
|
|
||||||
eventHandle = 0;
|
|
||||||
|
|
||||||
return AudioResult.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CmifCommand(18)] // 17.0.0+
|
|
||||||
public Result ReleaseAudioInputDeviceNotification(ulong deviceId)
|
|
||||||
{
|
|
||||||
return AudioResult.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CmifCommand(19)] // 18.0.0+
|
|
||||||
public Result SetAudioDeviceOutputVolumeAutoTuneEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
return AudioResult.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CmifCommand(20)] // 18.0.0+
|
|
||||||
public Result IsAudioDeviceOutputVolumeAutoTuneEnabled(out bool enabled)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
|
|
||||||
return AudioResult.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
|
|
@ -55,7 +55,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.70f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.70f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -84,7 +83,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.70f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.70f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -113,7 +111,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.70f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.70f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -142,7 +139,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.75f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.75f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(1, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -171,7 +167,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(2, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(2, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -200,7 +195,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(2, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(2, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -229,7 +223,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(2, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(2, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -258,7 +251,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(3, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(3, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -287,7 +279,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsFalse(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(3, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(3, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -316,7 +307,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsFalse(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(4, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(4, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -345,7 +335,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsTrue(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsTrue(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsFalse(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(5, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(5, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
@ -374,36 +363,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server
|
||||||
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
||||||
Assert.IsTrue(behaviourContext.IsNewEffectChannelMappingSupported());
|
Assert.IsTrue(behaviourContext.IsNewEffectChannelMappingSupported());
|
||||||
Assert.IsTrue(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
Assert.IsTrue(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
||||||
Assert.IsFalse(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
|
||||||
Assert.AreEqual(5, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
|
||||||
Assert.AreEqual(2, behaviourContext.GetPerformanceMetricsDataFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestRevision13()
|
|
||||||
{
|
|
||||||
BehaviourContext behaviourContext = new();
|
|
||||||
|
|
||||||
behaviourContext.SetUserRevision(BehaviourContext.BaseRevisionMagic + BehaviourContext.Revision13);
|
|
||||||
|
|
||||||
Assert.IsTrue(behaviourContext.IsAdpcmLoopContextBugFixed());
|
|
||||||
Assert.IsTrue(behaviourContext.IsSplitterSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsLongSizePreDelaySupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsAudioUsbDeviceOutputSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsFlushVoiceWaveBuffersSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsSplitterBugFixed());
|
|
||||||
Assert.IsTrue(behaviourContext.IsElapsedFrameCountSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsDecodingBehaviourFlagSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsBiquadFilterEffectStateClearBugFixed());
|
|
||||||
Assert.IsTrue(behaviourContext.IsMixInParameterDirtyOnlyUpdateSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsWaveBufferVersion2Supported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsEffectInfoVersion2Supported());
|
|
||||||
Assert.IsTrue(behaviourContext.UseMultiTapBiquadFilterProcessing());
|
|
||||||
Assert.IsTrue(behaviourContext.IsNewEffectChannelMappingSupported());
|
|
||||||
Assert.IsTrue(behaviourContext.IsBiquadFilterParameterForSplitterEnabled());
|
|
||||||
Assert.IsTrue(behaviourContext.IsSplitterPrevVolumeResetSupported());
|
|
||||||
|
|
||||||
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
Assert.AreEqual(0.80f, behaviourContext.GetAudioRendererProcessingTimeLimit());
|
||||||
Assert.AreEqual(5, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
Assert.AreEqual(5, behaviourContext.GetCommandProcessingTimeEstimatorVersion());
|
||||||
|
|
Loading…
Reference in a new issue