audio effects fix and audio object pooling (ryubing/ryujinx!192)

See merge request ryubing/ryujinx!192
This commit is contained in:
LotP
2025-10-25 21:07:10 -05:00
parent c6bc77e4bf
commit fd07453887
44 changed files with 764 additions and 595 deletions

View File

@@ -11,27 +11,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.AdpcmDataSourceVersion1;
public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; }
public uint SampleRate { get; }
public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; private set; }
public float Pitch { get; }
public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; }
public Memory<VoiceState> State { get; private set; }
public ulong AdpcmParameter { get; }
public ulong AdpcmParameterSize { get; }
public ulong AdpcmParameter { get; private set; }
public ulong AdpcmParameterSize { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; }
public DecodingBehaviour DecodingBehaviour { get; private set; }
public AdpcmDataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId)
public AdpcmDataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public AdpcmDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -42,8 +47,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
for (int i = 0; i < WaveBuffers.Length; i++)
{
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
@@ -55,6 +58,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
AdpcmParameterSize = serverInfo.DataSourceStateAddressInfo.Size;
State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
}
public void Process(CommandList context)

View File

@@ -12,26 +12,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.AuxiliaryBuffer;
public uint EstimatedProcessingTime { get; set; }
public uint InputBufferIndex { get; }
public uint OutputBufferIndex { get; }
public uint InputBufferIndex { get; private set; }
public uint OutputBufferIndex { get; private set; }
public AuxiliaryBufferAddresses BufferInfo { get; }
public AuxiliaryBufferAddresses BufferInfo { get; private set; }
public CpuAddress InputBuffer { get; }
public CpuAddress OutputBuffer { get; }
public uint CountMax { get; }
public uint UpdateCount { get; }
public uint WriteOffset { get; }
public CpuAddress InputBuffer { get; private set; }
public CpuAddress OutputBuffer { get; private set; }
public uint CountMax { get; private set; }
public uint UpdateCount { get; private set; }
public uint WriteOffset { get; private set; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
public AuxiliaryBufferCommand(
public AuxiliaryBufferCommand()
{
}
public AuxiliaryBufferCommand Initialize(
uint bufferOffset,
byte inputBufferOffset,
byte outputBufferOffset,
@@ -55,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
UpdateCount = updateCount;
WriteOffset = writeOffset;
IsEffectEnabled = isEnabled;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -9,32 +9,37 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.BiquadFilterAndMix;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
private BiquadFilterParameter2 _parameter;
public Memory<BiquadFilterState> BiquadFilterState { get; }
public Memory<BiquadFilterState> PreviousBiquadFilterState { get; }
public Memory<BiquadFilterState> BiquadFilterState { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState { get; private set; }
public Memory<VoiceState> State { get; }
public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; }
public int LastSampleIndex { get; private set; }
public float Volume0 { get; }
public float Volume1 { get; }
public float Volume0 { get; private set; }
public float Volume1 { get; private set; }
public bool NeedInitialization { get; }
public bool HasVolumeRamp { get; }
public bool IsFirstMixBuffer { get; }
public bool NeedInitialization { get; private set; }
public bool HasVolumeRamp { get; private set; }
public bool IsFirstMixBuffer { get; private set; }
public BiquadFilterAndMixCommand(
public BiquadFilterAndMixCommand()
{
}
public BiquadFilterAndMixCommand Initialize(
float volume0,
float volume1,
uint inputBufferIndex,
@@ -68,6 +73,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
NeedInitialization = needInitialization;
HasVolumeRamp = hasVolumeRamp;
IsFirstMixBuffer = isFirstMixBuffer;
return this;
}
public void Process(CommandList context)

View File

@@ -8,20 +8,25 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.BiquadFilter;
public uint EstimatedProcessingTime { get; set; }
public Memory<BiquadFilterState> BiquadFilterState { get; }
public int InputBufferIndex { get; }
public int OutputBufferIndex { get; }
public bool NeedInitialization { get; }
public Memory<BiquadFilterState> BiquadFilterState { get; private set; }
public int InputBufferIndex { get; private set; }
public int OutputBufferIndex { get; private set; }
public bool NeedInitialization { get; private set; }
private BiquadFilterParameter2 _parameter;
public BiquadFilterCommand(
public BiquadFilterCommand()
{
}
public BiquadFilterCommand Initialize(
int baseIndex,
ref BiquadFilterParameter2 filter,
Memory<BiquadFilterState> biquadFilterStateMemory,
@@ -38,6 +43,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Enabled = true;
NodeId = nodeId;
return this;
}
public void Process(CommandList context)

View File

@@ -12,25 +12,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CaptureBuffer;
public uint EstimatedProcessingTime { get; set; }
public uint InputBufferIndex { get; }
public uint InputBufferIndex { get; private set; }
public ulong CpuBufferInfoAddress { get; }
public ulong DspBufferInfoAddress { get; }
public ulong CpuBufferInfoAddress { get; private set; }
public ulong DspBufferInfoAddress { get; private set; }
public CpuAddress OutputBuffer { get; }
public uint CountMax { get; }
public uint UpdateCount { get; }
public uint WriteOffset { get; }
public CpuAddress OutputBuffer { get; private set; }
public uint CountMax { get; private set; }
public uint UpdateCount { get; private set; }
public uint WriteOffset { get; private set; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
public CaptureBufferCommand(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled,
public CaptureBufferCommand()
{
}
public CaptureBufferCommand Initialize(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled,
uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId)
{
Enabled = true;
@@ -43,6 +48,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
UpdateCount = updateCount;
WriteOffset = writeOffset;
IsEffectEnabled = isEnabled;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -9,25 +9,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CircularBufferSink;
public uint EstimatedProcessingTime { get; set; }
public ushort[] Input { get; }
public uint InputCount { get; }
public uint InputCount { get; private set; }
public ulong CircularBuffer { get; }
public ulong CircularBufferSize { get; }
public ulong CurrentOffset { get; }
public ulong CircularBuffer { get; private set; }
public ulong CircularBufferSize { get; private set; }
public ulong CurrentOffset { get; private set; }
public CircularBufferSinkCommand(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId)
public CircularBufferSinkCommand()
{
Input = new ushort[Constants.ChannelCountMax];
}
public CircularBufferSinkCommand Initialize(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId)
{
Enabled = true;
NodeId = nodeId;
Input = new ushort[Constants.ChannelCountMax];
InputCount = parameter.InputCount;
Span<byte> inputSpan = parameter.Input.AsSpan();
@@ -42,6 +46,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
CurrentOffset = currentOffset;
Debug.Assert(CircularBuffer != 0);
return this;
}
public void Process(CommandList context)

View File

@@ -4,16 +4,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.ClearMixBuffer;
public uint EstimatedProcessingTime { get; set; }
public ClearMixBufferCommand(int nodeId)
public ClearMixBufferCommand()
{
}
public ClearMixBufferCommand Initialize(int nodeId)
{
Enabled = true;
NodeId = nodeId;
return this;
}
public void Process(CommandList context)

View File

@@ -20,6 +20,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public Memory<float> Buffers { get; }
public uint BufferCount { get; }
private readonly static ObjectPool<List<ICommand>> CommandsListPool = new(() => new List<ICommand>(256));
public List<ICommand> Commands { get; }
public IVirtualMemoryManager MemoryManager { get; }
@@ -46,7 +47,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
SampleRate = sampleRate;
BufferCount = mixBufferCount + voiceChannelCountMax;
Buffers = mixBuffer;
Commands = [];
Commands = CommandsListPool.Allocate();
MemoryManager = memoryManager;
_buffersEntryCount = Buffers.Length;
@@ -142,6 +143,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
}
}
}
CommandBuffer.ReleaseCommand(command);
}
EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds;
@@ -149,6 +152,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public void Dispose()
{
Commands.Clear();
CommandsListPool.Release(Commands);
GC.SuppressFinalize(this);
_buffersMemoryHandle.Dispose();
}

View File

@@ -15,22 +15,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Compressor;
public uint EstimatedProcessingTime { get; set; }
public CompressorParameter Parameter => _parameter;
public Memory<CompressorState> State { get; }
public Memory<EffectResultState> ResultState { get; }
public Memory<CompressorState> State { get; private set; }
public Memory<EffectResultState> ResultState { get; private set; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
private CompressorParameter _parameter;
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId)
public CompressorCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public CompressorCommand Initialize(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ResultState = resultState;
IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan();
@@ -51,6 +54,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
}
return this;
}
public void Process(CommandList context)

View File

@@ -4,22 +4,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CopyMixBuffer;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
public CopyMixBufferCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId)
public CopyMixBufferCommand()
{
}
public CopyMixBufferCommand Initialize(uint inputBufferIndex, uint outputBufferIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
InputBufferIndex = (ushort)inputBufferIndex;
OutputBufferIndex = (ushort)outputBufferIndex;
return this;
}
public void Process(CommandList context)

View File

@@ -3,6 +3,7 @@ using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Server.Voice;
using System;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Memory;
using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer;
namespace Ryujinx.Audio.Renderer.Dsp.Command
@@ -11,35 +12,40 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType { get; }
public CommandType CommandType { get; private set; }
public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; }
public uint SampleRate { get; }
public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; private set; }
public float Pitch { get; }
public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; }
public Memory<VoiceState> State { get; private set; }
public ulong ExtraParameter { get; }
public ulong ExtraParameterSize { get; }
public ulong ExtraParameter { get; private set; }
public ulong ExtraParameterSize { get; private set; }
public uint ChannelIndex { get; }
public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; }
public uint ChannelCount { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; }
public DecodingBehaviour DecodingBehaviour { get; private set; }
public SampleFormat SampleFormat { get; }
public SampleFormat SampleFormat { get; private set; }
public SampleRateConversionQuality SrcQuality { get; }
public SampleRateConversionQuality SrcQuality { get; private set; }
public DataSourceVersion2Command(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
public DataSourceVersion2Command()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public DataSourceVersion2Command Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -55,8 +61,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
for (int i = 0; i < WaveBuffers.Length; i++)
{
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
@@ -72,6 +76,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
}
private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat)

View File

@@ -13,24 +13,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Delay;
public uint EstimatedProcessingTime { get; set; }
public DelayParameter Parameter => _parameter;
public Memory<DelayState> State { get; }
public ulong WorkBuffer { get; }
public Memory<DelayState> State { get; private set; }
public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
private DelayParameter _parameter;
private const int FixedPointPrecision = 14;
public DelayCommand(uint bufferOffset, DelayParameter parameter, Memory<DelayState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
public DelayCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public DelayCommand Initialize(uint bufferOffset, DelayParameter parameter, Memory<DelayState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
{
Enabled = true;
NodeId = nodeId;
@@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WorkBuffer = workBuffer;
IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan();
@@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]

View File

@@ -7,21 +7,26 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DepopForMixBuffers;
public uint EstimatedProcessingTime { get; set; }
public uint MixBufferOffset { get; }
public uint MixBufferOffset { get; private set; }
public uint MixBufferCount { get; }
public uint MixBufferCount { get; private set; }
public float Decay { get; }
public float Decay { get; private set; }
public Memory<float> DepopBuffer { get; }
public Memory<float> DepopBuffer { get; private set; }
public DepopForMixBuffersCommand(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate)
public DepopForMixBuffersCommand()
{
}
public DepopForMixBuffersCommand Initialize(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate)
{
Enabled = true;
NodeId = nodeId;
@@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
Decay = 0.943695f;
}
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -7,27 +7,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DepopPrepare;
public uint EstimatedProcessingTime { get; set; }
public uint MixBufferCount { get; }
public uint MixBufferCount { get; private set; }
public ushort[] OutputBufferIndices { get; }
public Memory<VoiceState> State { get; }
public Memory<float> DepopBuffer { get; }
public Memory<VoiceState> State { get; private set; }
public Memory<float> DepopBuffer { get; private set; }
public DepopPrepareCommand(Memory<VoiceState> state, Memory<float> depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled)
public DepopPrepareCommand()
{
OutputBufferIndices = new ushort[Constants.MixBufferCountMax];
}
public DepopPrepareCommand Initialize(Memory<VoiceState> state, Memory<float> depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled)
{
Enabled = enabled;
NodeId = nodeId;
MixBufferCount = mixBufferCount;
OutputBufferIndices = new ushort[Constants.MixBufferCountMax];
for (int i = 0; i < Constants.MixBufferCountMax; i++)
{
OutputBufferIndices[i] = (ushort)(bufferOffset + i);
@@ -35,6 +38,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state;
DepopBuffer = depopBuffer;
return this;
}
public void Process(CommandList context)

View File

@@ -10,22 +10,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DeviceSink;
public uint EstimatedProcessingTime { get; set; }
public string DeviceName { get; }
public string DeviceName { get; private set; }
public int SessionId { get; }
public int SessionId { get; private set; }
public uint InputCount { get; }
public ushort[] InputBufferIndices { get; }
public uint InputCount { get; private set; }
public ushort[] InputBufferIndices { get; private set; }
public Memory<float> Buffers { get; }
public Memory<float> Buffers { get; private set; }
public DeviceSinkCommand(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId)
public DeviceSinkCommand()
{
}
public DeviceSinkCommand Initialize(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -50,6 +55,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
Buffers = buffers;
}
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DownMixSurroundToStereo;
@@ -16,16 +16,19 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public ushort[] InputBufferIndices { get; }
public ushort[] OutputBufferIndices { get; }
public float[] Coefficients { get; }
public float[] Coefficients { get; private set; }
public DownMixSurroundToStereoCommand(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId)
public DownMixSurroundToStereoCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public DownMixSurroundToStereoCommand Initialize(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId)
{
Enabled = true;
NodeId = nodeId;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
for (int i = 0; i < Constants.VoiceChannelCountMax; i++)
{
InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]);
@@ -33,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
}
Coefficients = downMixParameter;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -8,38 +8,43 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.FillBuffer;
public uint EstimatedProcessingTime { get; set; }
public SplitterDestinationVersion1 Destination1 { get; }
public SplitterDestinationVersion2 Destination2 { get; }
public bool IsV2 { get; }
public int Length { get; }
public float Value { get; }
public SplitterDestinationVersion1 Destination1 { get; private set; }
public SplitterDestinationVersion2 Destination2 { get; private set; }
public bool IsV2 { get; private set; }
public int Length { get; private set; }
public float Value { get; private set; }
public FillBufferCommand(SplitterDestinationVersion1 destination, int length, float value, int nodeId)
public FillBufferCommand()
{
Enabled = true;
NodeId = nodeId;
Destination1 = destination;
IsV2 = false;
Length = length;
Value = value;
}
public FillBufferCommand(SplitterDestinationVersion2 destination, int length, float value, int nodeId)
public FillBufferCommand Initialize(SplitterDestination destination, int length, float value, int nodeId)
{
Enabled = true;
NodeId = nodeId;
if (Unsafe.IsNullRef(ref destination.GetV2RefOrNull()))
{
Destination1 = destination.GetV1RefOrNull();
IsV2 = false;
}
else
{
Destination2 = destination.GetV2RefOrNull();
IsV2 = true;
}
Destination2 = destination;
IsV2 = true;
Length = length;
Value = value;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -10,22 +10,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.LimiterVersion1;
public uint EstimatedProcessingTime { get; set; }
public LimiterParameter Parameter => _parameter;
public Memory<LimiterState> State { get; }
public ulong WorkBuffer { get; }
public Memory<LimiterState> State { get; private set; }
public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
private LimiterParameter _parameter;
public LimiterCommandVersion1(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId)
public LimiterCommandVersion1()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public LimiterCommandVersion1 Initialize(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -35,9 +41,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan();
@@ -46,6 +49,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
}
return this;
}
public void Process(CommandList context)

View File

@@ -12,23 +12,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.LimiterVersion2;
public uint EstimatedProcessingTime { get; set; }
public LimiterParameter Parameter => _parameter;
public Memory<LimiterState> State { get; }
public Memory<EffectResultState> ResultState { get; }
public ulong WorkBuffer { get; }
public Memory<LimiterState> State { get; private set; }
public Memory<EffectResultState> ResultState { get; private set; }
public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
private LimiterParameter _parameter;
public LimiterCommandVersion2(
public LimiterCommandVersion2()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public LimiterCommandVersion2 Initialize(
uint bufferOffset,
LimiterParameter parameter,
Memory<LimiterState> state,
@@ -45,9 +51,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WorkBuffer = workBuffer;
IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan();
@@ -57,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
}
return this;
}
public void Process(CommandList context)

View File

@@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Mix;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
public float Volume { get; }
public float Volume { get; private set; }
public MixCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume)
public MixCommand()
{
}
public MixCommand Initialize(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume)
{
Enabled = true;
NodeId = nodeId;
@@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
OutputBufferIndex = (ushort)outputBufferIndex;
Volume = volume;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MixRamp;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
public float Volume0 { get; }
public float Volume1 { get; }
public float Volume0 { get; private set; }
public float Volume1 { get; private set; }
public Memory<VoiceState> State { get; }
public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; }
public int LastSampleIndex { get; private set; }
public MixRampCommand(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId)
public MixRampCommand()
{
}
public MixRampCommand Initialize(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state;
LastSampleIndex = lastSampleIndex;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MixRampGrouped;
public uint EstimatedProcessingTime { get; set; }
public uint MixBufferCount { get; }
public uint MixBufferCount { get; private set; }
public ushort[] InputBufferIndices { get; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; private set; }
public ushort[] OutputBufferIndices { get; private set; }
public float[] Volume0 { get; }
public float[] Volume1 { get; }
public float[] Volume0 { get; private set; }
public float[] Volume1 { get; private set; }
public Memory<VoiceState> State { get; }
public Memory<VoiceState> State { get; private set; }
public MixRampGroupedCommand(
public MixRampGroupedCommand()
{
}
public MixRampGroupedCommand Initialize(
uint mixBufferCount,
uint inputBufferIndex,
uint outputBufferIndex,
@@ -52,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
}
State = state;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -9,36 +9,41 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
private BiquadFilterParameter2 _parameter0;
private BiquadFilterParameter2 _parameter1;
public Memory<BiquadFilterState> BiquadFilterState0 { get; }
public Memory<BiquadFilterState> BiquadFilterState1 { get; }
public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; }
public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; }
public Memory<BiquadFilterState> BiquadFilterState0 { get; private set; }
public Memory<BiquadFilterState> BiquadFilterState1 { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; private set; }
public Memory<VoiceState> State { get; }
public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; }
public int LastSampleIndex { get; private set; }
public float Volume0 { get; }
public float Volume1 { get; }
public float Volume0 { get; private set; }
public float Volume1 { get; private set; }
public bool NeedInitialization0 { get; }
public bool NeedInitialization1 { get; }
public bool HasVolumeRamp { get; }
public bool IsFirstMixBuffer { get; }
public bool NeedInitialization0 { get; private set; }
public bool NeedInitialization1 { get; private set; }
public bool HasVolumeRamp { get; private set; }
public bool IsFirstMixBuffer { get; private set; }
public MultiTapBiquadFilterAndMixCommand(
public MultiTapBiquadFilterAndMixCommand()
{
}
public MultiTapBiquadFilterAndMixCommand Initialize(
float volume0,
float volume1,
uint inputBufferIndex,
@@ -80,6 +85,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
NeedInitialization1 = needInitialization1;
HasVolumeRamp = hasVolumeRamp;
IsFirstMixBuffer = isFirstMixBuffer;
return this;
}
private void UpdateState(Memory<BiquadFilterState> state, Memory<BiquadFilterState> previousState, bool needInitialization)

View File

@@ -8,40 +8,47 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MultiTapBiquadFilter;
public uint EstimatedProcessingTime { get; set; }
private readonly BiquadFilterParameter2[] _parameters;
private readonly Memory<BiquadFilterState> _biquadFilterStates;
private readonly int _inputBufferIndex;
private readonly int _outputBufferIndex;
private readonly bool[] _isInitialized;
public BiquadFilterParameter2[] Parameters { get; private set; }
public Memory<BiquadFilterState> BiquadFilterStates { get; private set; }
public int InputBufferIndex { get; private set; }
public int OutputBufferIndex { get; private set; }
public bool[] IsInitialized { get; private set; }
public MultiTapBiquadFilterCommand(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId)
public MultiTapBiquadFilterCommand()
{
_parameters = filters.ToArray();
_biquadFilterStates = biquadFilterStateMemory;
_inputBufferIndex = baseIndex + inputBufferOffset;
_outputBufferIndex = baseIndex + outputBufferOffset;
_isInitialized = isInitialized.ToArray();
}
public MultiTapBiquadFilterCommand Initialize(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId)
{
Parameters = filters.ToArray();
BiquadFilterStates = biquadFilterStateMemory;
InputBufferIndex = baseIndex + inputBufferOffset;
OutputBufferIndex = baseIndex + outputBufferOffset;
IsInitialized = isInitialized.ToArray();
Enabled = true;
NodeId = nodeId;
return this;
}
public void Process(CommandList context)
{
Span<BiquadFilterState> states = _biquadFilterStates.Span;
Span<BiquadFilterState> states = BiquadFilterStates.Span;
ReadOnlySpan<float> inputBuffer = context.GetBuffer(_inputBufferIndex);
Span<float> outputBuffer = context.GetBuffer(_outputBufferIndex);
ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex);
Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex);
for (int i = 0; i < _parameters.Length; i++)
for (int i = 0; i < Parameters.Length; i++)
{
if (!_isInitialized[i])
if (!IsInitialized[i])
{
states[i] = new BiquadFilterState();
}
@@ -49,13 +56,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// NOTE: Nintendo only implement single and double biquad filters but no generic path when the command definition suggests it could be done.
// As such we currently only implement a generic path for simplicity for double biquad.
if (_parameters.Length == 1)
if (Parameters.Length == 1)
{
BiquadFilterHelper.ProcessBiquadFilter(ref _parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount);
BiquadFilterHelper.ProcessBiquadFilter(ref Parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount);
}
else
{
BiquadFilterHelper.ProcessBiquadFilter(_parameters, states, outputBuffer, inputBuffer, context.SampleCount);
BiquadFilterHelper.ProcessBiquadFilter(Parameters, states, outputBuffer, inputBuffer, context.SampleCount);
}
}
}

View File

@@ -11,26 +11,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1;
public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; }
public uint SampleRate { get; }
public uint ChannelIndex { get; }
public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; private set; }
public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; }
public uint ChannelCount { get; private set; }
public float Pitch { get; }
public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; }
public DecodingBehaviour DecodingBehaviour { get; }
public Memory<VoiceState> State { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; private set; }
public PcmFloatDataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
public PcmFloatDataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public PcmFloatDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -40,8 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ChannelIndex = channelIndex;
ChannelCount = serverInfo.ChannelsCount;
Pitch = serverInfo.Pitch;
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
@@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
}
public void Process(CommandList context)

View File

@@ -11,26 +11,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1;
public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; }
public uint SampleRate { get; }
public uint ChannelIndex { get; }
public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; private set; }
public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; }
public uint ChannelCount { get; private set; }
public float Pitch { get; }
public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; }
public DecodingBehaviour DecodingBehaviour { get; }
public Memory<VoiceState> State { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; private set; }
public PcmInt16DataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
public PcmInt16DataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public PcmInt16DataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -40,8 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ChannelIndex = channelIndex;
ChannelCount = serverInfo.ChannelsCount;
Pitch = serverInfo.Pitch;
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
@@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
}
public void Process(CommandList context)

View File

@@ -13,22 +13,34 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Performance;
public uint EstimatedProcessingTime { get; set; }
public PerformanceEntryAddresses PerformanceEntryAddresses { get; }
public PerformanceEntryAddresses PerformanceEntryAddresses { get; private set; }
public Type PerformanceType { get; set; }
public PerformanceCommand(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId)
public PerformanceCommand()
{
}
public PerformanceCommand Initialize(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId)
{
if (PerformanceEntryAddresses is not null)
{
PerformanceEntryAddresses.PerformanceEntryAddressesPool.Release(PerformanceEntryAddresses);
}
Enabled = true;
PerformanceEntryAddresses = performanceEntryAddresses;
PerformanceType = performanceType;
NodeId = nodeId;
return this;
}
public void Process(CommandList context)

View File

@@ -35,26 +35,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Reverb3d;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
public Reverb3dParameter Parameter => _parameter;
public Memory<Reverb3dState> State { get; }
public ulong WorkBuffer { get; }
public Memory<Reverb3dState> State { get; private set; }
public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
private Reverb3dParameter _parameter;
public Reverb3dCommand(uint bufferOffset, Reverb3dParameter parameter, Memory<Reverb3dState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
public Reverb3dCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public Reverb3dCommand Initialize(uint bufferOffset, Reverb3dParameter parameter, Memory<Reverb3dState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
{
Enabled = true;
IsEffectEnabled = isEnabled;
@@ -62,9 +68,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
_parameter = parameter;
State = state;
WorkBuffer = workBuffer;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan();
@@ -79,6 +82,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// TODO: Update reverb 3d processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping.
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -33,26 +33,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Reverb;
public uint EstimatedProcessingTime { get; set; }
public ReverbParameter Parameter => _parameter;
public Memory<ReverbState> State { get; }
public ulong WorkBuffer { get; }
public Memory<ReverbState> State { get; private set; }
public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsLongSizePreDelaySupported { get; }
public bool IsLongSizePreDelaySupported { get; private set; }
public bool IsEffectEnabled { get; }
public bool IsEffectEnabled { get; private set; }
private ReverbParameter _parameter;
private const int FixedPointPrecision = 14;
public ReverbCommand(uint bufferOffset, ReverbParameter parameter, Memory<ReverbState> state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported)
public ReverbCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public ReverbCommand Initialize(uint bufferOffset, ReverbParameter parameter, Memory<ReverbState> state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported)
{
Enabled = true;
IsEffectEnabled = isEnabled;
@@ -60,9 +66,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
_parameter = parameter;
State = state;
WorkBuffer = workBuffer;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan();
@@ -79,6 +82,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// TODO: Update reverb processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping.
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -7,22 +7,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Upsample;
public uint EstimatedProcessingTime { get; set; }
public uint BufferCount { get; }
public uint InputBufferIndex { get; }
public uint InputSampleCount { get; }
public uint InputSampleRate { get; }
public uint BufferCount { get; private set; }
public uint InputBufferIndex { get; private set; }
public uint InputSampleCount { get; private set; }
public uint InputSampleRate { get; private set; }
public UpsamplerInfo UpsamplerInfo { get; }
public UpsamplerInfo UpsamplerInfo { get; private set; }
public Memory<float> OutBuffer { get; }
public Memory<float> OutBuffer { get; private set; }
public UpsampleCommand(uint bufferOffset, UpsamplerInfo info, uint inputCount, Span<byte> inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId)
public UpsampleCommand()
{
}
public UpsampleCommand Initialize(uint bufferOffset, UpsamplerInfo info, uint inputCount, Span<byte> inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -47,6 +52,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
}
UpsamplerInfo = info;
return this;
}
private Span<float> GetBuffer(int index, int sampleCount)

View File

@@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Volume;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
public float Volume { get; }
public float Volume { get; private set; }
public VolumeCommand(float volume, uint bufferIndex, int nodeId)
public VolumeCommand()
{
}
public VolumeCommand Initialize(float volume, uint bufferIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
OutputBufferIndex = (ushort)bufferIndex;
Volume = volume;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -7,19 +7,24 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public bool Enabled { get; set; }
public int NodeId { get; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.VolumeRamp;
public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; }
public ushort OutputBufferIndex { get; }
public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; private set; }
public float Volume0 { get; }
public float Volume1 { get; }
public float Volume0 { get; private set; }
public float Volume1 { get; private set; }
public VolumeRampCommand(float volume0, float volume1, uint bufferIndex, int nodeId)
public VolumeRampCommand()
{
}
public VolumeRampCommand Initialize(float volume0, float volume1, uint bufferIndex, int nodeId)
{
Enabled = true;
NodeId = nodeId;
@@ -29,6 +34,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Volume0 = volume0;
Volume1 = volume1;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]