diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2024-05-17 16:46:43 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-17 16:46:43 -0300 |
| commit | 4d84df94873a070f6f5c199438f957b24d8cf8a9 (patch) | |
| tree | 3e4b4cc9585526c63f3a9fdb3a150bfd721a5030 /src/Ryujinx.Audio/Renderer/Dsp/Command | |
| parent | 9ec8b2c01a0b00f3a33d9a23b9f5ff3758520484 (diff) | |
Update audio renderer to REV12: Add support for splitter biquad filter (#6813)
* Update audio renderer to REV12: Add support for splitter biquad filter
* Formatting
* Official names
* Update BiquadFilterState size + other fixes
* Update tests
* Update comment for version 2
* Size test for SplitterDestinationVersion2
* Should use Volume1 if no ramp
Diffstat (limited to 'src/Ryujinx.Audio/Renderer/Dsp/Command')
| -rw-r--r-- | src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs | 123 | ||||
| -rw-r--r-- | src/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs | 4 | ||||
| -rw-r--r-- | src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs | 16 | ||||
| -rw-r--r-- | src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs | 145 | ||||
| -rw-r--r-- | src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs (renamed from src/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs) | 6 |
5 files changed, 288 insertions, 6 deletions
diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs new file mode 100644 index 00000000..106fc035 --- /dev/null +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs @@ -0,0 +1,123 @@ +using Ryujinx.Audio.Renderer.Common; +using Ryujinx.Audio.Renderer.Dsp.State; +using Ryujinx.Audio.Renderer.Parameter; +using System; + +namespace Ryujinx.Audio.Renderer.Dsp.Command +{ + public class BiquadFilterAndMixCommand : ICommand + { + public bool Enabled { get; set; } + + public int NodeId { get; } + + public CommandType CommandType => CommandType.BiquadFilterAndMix; + + public uint EstimatedProcessingTime { get; set; } + + public ushort InputBufferIndex { get; } + public ushort OutputBufferIndex { get; } + + private BiquadFilterParameter _parameter; + + public Memory<BiquadFilterState> BiquadFilterState { get; } + public Memory<BiquadFilterState> PreviousBiquadFilterState { get; } + + public Memory<VoiceUpdateState> State { get; } + + public int LastSampleIndex { get; } + + public float Volume0 { get; } + public float Volume1 { get; } + + public bool NeedInitialization { get; } + public bool HasVolumeRamp { get; } + public bool IsFirstMixBuffer { get; } + + public BiquadFilterAndMixCommand( + float volume0, + float volume1, + uint inputBufferIndex, + uint outputBufferIndex, + int lastSampleIndex, + Memory<VoiceUpdateState> state, + ref BiquadFilterParameter filter, + Memory<BiquadFilterState> biquadFilterState, + Memory<BiquadFilterState> previousBiquadFilterState, + bool needInitialization, + bool hasVolumeRamp, + bool isFirstMixBuffer, + int nodeId) + { + Enabled = true; + NodeId = nodeId; + + InputBufferIndex = (ushort)inputBufferIndex; + OutputBufferIndex = (ushort)outputBufferIndex; + + _parameter = filter; + BiquadFilterState = biquadFilterState; + PreviousBiquadFilterState = previousBiquadFilterState; + + State = state; + LastSampleIndex = lastSampleIndex; + + Volume0 = volume0; + Volume1 = volume1; + + NeedInitialization = needInitialization; + HasVolumeRamp = hasVolumeRamp; + IsFirstMixBuffer = isFirstMixBuffer; + } + + public void Process(CommandList context) + { + ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); + Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); + + if (NeedInitialization) + { + // If there is no previous state, initialize to zero. + + BiquadFilterState.Span[0] = new BiquadFilterState(); + } + else if (IsFirstMixBuffer) + { + // This is the first buffer, set previous state to current state. + + PreviousBiquadFilterState.Span[0] = BiquadFilterState.Span[0]; + } + else + { + // Rewind the current state by copying back the previous state. + + BiquadFilterState.Span[0] = PreviousBiquadFilterState.Span[0]; + } + + if (HasVolumeRamp) + { + float volume = Volume0; + float ramp = (Volume1 - Volume0) / (int)context.SampleCount; + + State.Span[0].LastSamples[LastSampleIndex] = BiquadFilterHelper.ProcessBiquadFilterAndMixRamp( + ref _parameter, + ref BiquadFilterState.Span[0], + outputBuffer, + inputBuffer, + context.SampleCount, + volume, + ramp); + } + else + { + BiquadFilterHelper.ProcessBiquadFilterAndMix( + ref _parameter, + ref BiquadFilterState.Span[0], + outputBuffer, + inputBuffer, + context.SampleCount, + Volume1); + } + } + } +} diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs index 098a04a0..de5c0ea2 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs @@ -30,8 +30,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command CopyMixBuffer, LimiterVersion1, LimiterVersion2, - GroupedBiquadFilter, + MultiTapBiquadFilter, CaptureBuffer, Compressor, + BiquadFilterAndMix, + MultiTapBiquadFilterAndMix, } } diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs index 3c7dd63b..41ac84c1 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs @@ -24,7 +24,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public Memory<VoiceUpdateState> State { get; } - public MixRampGroupedCommand(uint mixBufferCount, uint inputBufferIndex, uint outputBufferIndex, Span<float> volume0, Span<float> volume1, Memory<VoiceUpdateState> state, int nodeId) + public MixRampGroupedCommand( + uint mixBufferCount, + uint inputBufferIndex, + uint outputBufferIndex, + ReadOnlySpan<float> volume0, + ReadOnlySpan<float> volume1, + Memory<VoiceUpdateState> state, + int nodeId) { Enabled = true; MixBufferCount = mixBufferCount; @@ -48,7 +55,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float ProcessMixRampGrouped(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float volume0, float volume1, int sampleCount) + private static float ProcessMixRampGrouped( + Span<float> outputBuffer, + ReadOnlySpan<float> inputBuffer, + float volume0, + float volume1, + int sampleCount) { float ramp = (volume1 - volume0) / sampleCount; float volume = volume0; diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs new file mode 100644 index 00000000..e359371b --- /dev/null +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs @@ -0,0 +1,145 @@ +using Ryujinx.Audio.Renderer.Common; +using Ryujinx.Audio.Renderer.Dsp.State; +using Ryujinx.Audio.Renderer.Parameter; +using System; + +namespace Ryujinx.Audio.Renderer.Dsp.Command +{ + public class MultiTapBiquadFilterAndMixCommand : ICommand + { + public bool Enabled { get; set; } + + public int NodeId { get; } + + public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix; + + public uint EstimatedProcessingTime { get; set; } + + public ushort InputBufferIndex { get; } + public ushort OutputBufferIndex { get; } + + private BiquadFilterParameter _parameter0; + private BiquadFilterParameter _parameter1; + + public Memory<BiquadFilterState> BiquadFilterState0 { get; } + public Memory<BiquadFilterState> BiquadFilterState1 { get; } + public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; } + public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; } + + public Memory<VoiceUpdateState> State { get; } + + public int LastSampleIndex { get; } + + public float Volume0 { get; } + public float Volume1 { get; } + + public bool NeedInitialization0 { get; } + public bool NeedInitialization1 { get; } + public bool HasVolumeRamp { get; } + public bool IsFirstMixBuffer { get; } + + public MultiTapBiquadFilterAndMixCommand( + float volume0, + float volume1, + uint inputBufferIndex, + uint outputBufferIndex, + int lastSampleIndex, + Memory<VoiceUpdateState> state, + ref BiquadFilterParameter filter0, + ref BiquadFilterParameter filter1, + Memory<BiquadFilterState> biquadFilterState0, + Memory<BiquadFilterState> biquadFilterState1, + Memory<BiquadFilterState> previousBiquadFilterState0, + Memory<BiquadFilterState> previousBiquadFilterState1, + bool needInitialization0, + bool needInitialization1, + bool hasVolumeRamp, + bool isFirstMixBuffer, + int nodeId) + { + Enabled = true; + NodeId = nodeId; + + InputBufferIndex = (ushort)inputBufferIndex; + OutputBufferIndex = (ushort)outputBufferIndex; + + _parameter0 = filter0; + _parameter1 = filter1; + BiquadFilterState0 = biquadFilterState0; + BiquadFilterState1 = biquadFilterState1; + PreviousBiquadFilterState0 = previousBiquadFilterState0; + PreviousBiquadFilterState1 = previousBiquadFilterState1; + + State = state; + LastSampleIndex = lastSampleIndex; + + Volume0 = volume0; + Volume1 = volume1; + + NeedInitialization0 = needInitialization0; + NeedInitialization1 = needInitialization1; + HasVolumeRamp = hasVolumeRamp; + IsFirstMixBuffer = isFirstMixBuffer; + } + + private void UpdateState(Memory<BiquadFilterState> state, Memory<BiquadFilterState> previousState, bool needInitialization) + { + if (needInitialization) + { + // If there is no previous state, initialize to zero. + + state.Span[0] = new BiquadFilterState(); + } + else if (IsFirstMixBuffer) + { + // This is the first buffer, set previous state to current state. + + previousState.Span[0] = state.Span[0]; + } + else + { + // Rewind the current state by copying back the previous state. + + state.Span[0] = previousState.Span[0]; + } + } + + public void Process(CommandList context) + { + ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); + Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); + + UpdateState(BiquadFilterState0, PreviousBiquadFilterState0, NeedInitialization0); + UpdateState(BiquadFilterState1, PreviousBiquadFilterState1, NeedInitialization1); + + if (HasVolumeRamp) + { + float volume = Volume0; + float ramp = (Volume1 - Volume0) / (int)context.SampleCount; + + State.Span[0].LastSamples[LastSampleIndex] = BiquadFilterHelper.ProcessDoubleBiquadFilterAndMixRamp( + ref _parameter0, + ref _parameter1, + ref BiquadFilterState0.Span[0], + ref BiquadFilterState1.Span[0], + outputBuffer, + inputBuffer, + context.SampleCount, + volume, + ramp); + } + else + { + BiquadFilterHelper.ProcessDoubleBiquadFilterAndMix( + ref _parameter0, + ref _parameter1, + ref BiquadFilterState0.Span[0], + ref BiquadFilterState1.Span[0], + outputBuffer, + inputBuffer, + context.SampleCount, + Volume1); + } + } + } +} diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs index 7af851bd..e159f8ef 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs @@ -4,13 +4,13 @@ using System; namespace Ryujinx.Audio.Renderer.Dsp.Command { - public class GroupedBiquadFilterCommand : ICommand + public class MultiTapBiquadFilterCommand : ICommand { public bool Enabled { get; set; } public int NodeId { get; } - public CommandType CommandType => CommandType.GroupedBiquadFilter; + public CommandType CommandType => CommandType.MultiTapBiquadFilter; public uint EstimatedProcessingTime { get; set; } @@ -20,7 +20,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command private readonly int _outputBufferIndex; private readonly bool[] _isInitialized; - public GroupedBiquadFilterCommand(int baseIndex, ReadOnlySpan<BiquadFilterParameter> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId) + public MultiTapBiquadFilterCommand(int baseIndex, ReadOnlySpan<BiquadFilterParameter> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId) { _parameters = filters.ToArray(); _biquadFilterStates = biquadFilterStateMemory; |
