mirror of
https://github.com/GreemDev/Ryujinx.git
synced 2024-12-23 06:55:48 +00:00
Fix audio renderer compressor effect (#5742)
* Delete DecibelToLinearExtended and fix Log10 function * Fix CopyBuffer and ClearBuffer * Change effect states from class to struct + formatting * Formatting * Make UpdateLowPassFilter readonly * More compressor fixes
This commit is contained in:
parent
bc44b85b0b
commit
41b104d0fb
13 changed files with 92 additions and 77 deletions
|
@ -31,9 +31,18 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
public bool IsEffectEnabled { get; }
|
public bool IsEffectEnabled { get; }
|
||||||
|
|
||||||
public AuxiliaryBufferCommand(uint bufferOffset, byte inputBufferOffset, byte outputBufferOffset,
|
public AuxiliaryBufferCommand(
|
||||||
ref AuxiliaryBufferAddresses sendBufferInfo, bool isEnabled, uint countMax,
|
uint bufferOffset,
|
||||||
CpuAddress outputBuffer, CpuAddress inputBuffer, uint updateCount, uint writeOffset, int nodeId)
|
byte inputBufferOffset,
|
||||||
|
byte outputBufferOffset,
|
||||||
|
ref AuxiliaryBufferAddresses sendBufferInfo,
|
||||||
|
bool isEnabled,
|
||||||
|
uint countMax,
|
||||||
|
CpuAddress outputBuffer,
|
||||||
|
CpuAddress inputBuffer,
|
||||||
|
uint updateCount,
|
||||||
|
uint writeOffset,
|
||||||
|
int nodeId)
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
NodeId = nodeId;
|
NodeId = nodeId;
|
||||||
|
|
|
@ -21,7 +21,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
private BiquadFilterParameter _parameter;
|
private BiquadFilterParameter _parameter;
|
||||||
|
|
||||||
public BiquadFilterCommand(int baseIndex, ref BiquadFilterParameter filter, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, bool needInitialization, int nodeId)
|
public BiquadFilterCommand(
|
||||||
|
int baseIndex,
|
||||||
|
ref BiquadFilterParameter filter,
|
||||||
|
Memory<BiquadFilterState> biquadFilterStateMemory,
|
||||||
|
int inputBufferOffset,
|
||||||
|
int outputBufferOffset,
|
||||||
|
bool needInitialization,
|
||||||
|
int nodeId)
|
||||||
{
|
{
|
||||||
_parameter = filter;
|
_parameter = filter;
|
||||||
BiquadFilterState = biquadFilterStateMemory;
|
BiquadFilterState = biquadFilterStateMemory;
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void ClearBuffer(int index)
|
public unsafe void ClearBuffer(int index)
|
||||||
{
|
{
|
||||||
Unsafe.InitBlock((void*)GetBufferPointer(index), 0, SampleCount);
|
Unsafe.InitBlock((void*)GetBufferPointer(index), 0, SampleCount * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -89,7 +89,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void CopyBuffer(int outputBufferIndex, int inputBufferIndex)
|
public unsafe void CopyBuffer(int outputBufferIndex, int inputBufferIndex)
|
||||||
{
|
{
|
||||||
Unsafe.CopyBlock((void*)GetBufferPointer(outputBufferIndex), (void*)GetBufferPointer(inputBufferIndex), SampleCount);
|
Unsafe.CopyBlock((void*)GetBufferPointer(outputBufferIndex), (void*)GetBufferPointer(inputBufferIndex), SampleCount * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
|
@ -94,18 +94,18 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
|
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
|
||||||
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
||||||
float z = 0.0f;
|
float z = 1.0f;
|
||||||
|
|
||||||
bool unknown10OutOfRange = false;
|
bool unknown10OutOfRange = y >= state.Unknown10;
|
||||||
|
|
||||||
if (newMean < 1.0e-10f)
|
if (newMean < 1.0e-10f)
|
||||||
{
|
{
|
||||||
z = 1.0f;
|
y = -100.0f;
|
||||||
|
|
||||||
unknown10OutOfRange = state.Unknown10 < -100.0f;
|
unknown10OutOfRange = state.Unknown10 <= -100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y >= state.Unknown10 || unknown10OutOfRange)
|
if (unknown10OutOfRange)
|
||||||
{
|
{
|
||||||
float tmpGain;
|
float tmpGain;
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
|
tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
|
||||||
}
|
}
|
||||||
|
|
||||||
z = FloatingPointHelper.DecibelToLinearExtended(tmpGain);
|
z = FloatingPointHelper.DecibelToLinear(tmpGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
float unknown4New = z;
|
float unknown4New = z;
|
||||||
|
|
|
@ -28,7 +28,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
|
|
||||||
private LimiterParameter _parameter;
|
private LimiterParameter _parameter;
|
||||||
|
|
||||||
public LimiterCommandVersion2(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, Memory<EffectResultState> resultState, bool isEnabled, ulong workBuffer, int nodeId)
|
public LimiterCommandVersion2(
|
||||||
|
uint bufferOffset,
|
||||||
|
LimiterParameter parameter,
|
||||||
|
Memory<LimiterState> state,
|
||||||
|
Memory<EffectResultState> resultState,
|
||||||
|
bool isEnabled,
|
||||||
|
ulong workBuffer,
|
||||||
|
int nodeId)
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
NodeId = nodeId;
|
NodeId = nodeId;
|
||||||
|
|
|
@ -79,7 +79,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbMono(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbMono(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
|
@ -92,7 +93,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbStereo(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbStereo(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
|
@ -105,7 +107,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbQuadraphonic(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbQuadraphonic(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
|
@ -118,7 +121,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbSurround(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbSurround(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||||
{
|
{
|
||||||
// NOTE: Nintendo uses an approximation of log10, we don't.
|
// NOTE: Nintendo uses an approximation of log10, we don't.
|
||||||
// As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
|
// As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
|
||||||
return MathF.Pow(10, MathF.Max(x, 1.0e-10f));
|
return MathF.Log10(MathF.Max(x, 1.0e-10f));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -62,7 +62,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||||
|
|
||||||
foreach (float input in inputs)
|
foreach (float input in inputs)
|
||||||
{
|
{
|
||||||
res += (input * input);
|
float normInput = input * (1f / 32768f);
|
||||||
|
res += normInput * normInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
res /= inputs.Length;
|
res /= inputs.Length;
|
||||||
|
@ -81,19 +82,6 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||||
return MathF.Pow(10.0f, db / 20.0f);
|
return MathF.Pow(10.0f, db / 20.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Map decibel to linear in [0, 2] range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="db">The decibel value to convert</param>
|
|
||||||
/// <returns>Converted linear value in [0, 2] range</returns>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static float DecibelToLinearExtended(float db)
|
|
||||||
{
|
|
||||||
float tmp = MathF.Log2(DecibelToLinear(db));
|
|
||||||
|
|
||||||
return MathF.Truncate(tmp) + MathF.Pow(2.0f, tmp - MathF.Truncate(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float DegreesToRadians(float degrees)
|
public static float DegreesToRadians(float degrees)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@ using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class CompressorState
|
public struct CompressorState
|
||||||
{
|
{
|
||||||
public ExponentialMovingAverage InputMovingAverage;
|
public ExponentialMovingAverage InputMovingAverage;
|
||||||
public float Unknown4;
|
public float Unknown4;
|
||||||
|
@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax;
|
CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax;
|
||||||
Unknown10 = threshold - 1.5f;
|
Unknown10 = threshold - 1.5f;
|
||||||
Unknown14 = threshold + 1.5f;
|
Unknown14 = threshold + 1.5f;
|
||||||
OutputGain = FloatingPointHelper.DecibelToLinearExtended(parameter.OutputGain + makeupGain);
|
OutputGain = FloatingPointHelper.DecibelToLinear(parameter.OutputGain + makeupGain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class DelayState
|
public struct DelayState
|
||||||
{
|
{
|
||||||
public DelayLine[] DelayLines { get; }
|
public DelayLine[] DelayLines { get; }
|
||||||
public float[] LowPassZ { get; set; }
|
public float[] LowPassZ { get; set; }
|
||||||
|
@ -53,7 +53,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
LowPassBaseGain = 1.0f - LowPassFeedbackGain;
|
LowPassBaseGain = 1.0f - LowPassFeedbackGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateLowPassFilter(ref float tempRawRef, uint channelCount)
|
public readonly void UpdateLowPassFilter(ref float tempRawRef, uint channelCount)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < channelCount; i++)
|
for (int i = 0; i < channelCount; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class LimiterState
|
public struct LimiterState
|
||||||
{
|
{
|
||||||
public ExponentialMovingAverage[] DetectorAverage;
|
public ExponentialMovingAverage[] DetectorAverage;
|
||||||
public ExponentialMovingAverage[] CompressionGainAverage;
|
public ExponentialMovingAverage[] CompressionGainAverage;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class Reverb3dState
|
public struct Reverb3dState
|
||||||
{
|
{
|
||||||
private readonly float[] _fdnDelayMinTimes = new float[4] { 5.0f, 6.0f, 13.0f, 14.0f };
|
private readonly float[] _fdnDelayMinTimes = new float[4] { 5.0f, 6.0f, 13.0f, 14.0f };
|
||||||
private readonly float[] _fdnDelayMaxTimes = new float[4] { 45.704f, 82.782f, 149.94f, 271.58f };
|
private readonly float[] _fdnDelayMaxTimes = new float[4] { 45.704f, 82.782f, 149.94f, 271.58f };
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class ReverbState
|
public struct ReverbState
|
||||||
{
|
{
|
||||||
private static readonly float[] _fdnDelayTimes = new float[20]
|
private static readonly float[] _fdnDelayTimes = new float[20]
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue