diff options
Diffstat (limited to 'Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs')
-rw-r--r-- | Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs | 99 |
1 files changed, 47 insertions, 52 deletions
diff --git a/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs b/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs index 373776b7..4732f504 100644 --- a/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs +++ b/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs @@ -21,7 +21,6 @@ using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Common.Logging; using Ryujinx.Memory; using System; -using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -36,50 +35,43 @@ namespace Ryujinx.Audio.Renderer.Dsp { private const int FixedPointPrecision = 15; - public class WaveBufferInformation + public struct WaveBufferInformation { - public Memory<VoiceUpdateState> State; public uint SourceSampleRate; - public SampleFormat SampleFormat; public float Pitch; - public DecodingBehaviour DecodingBehaviour; - public WaveBuffer[] WaveBuffers; public ulong ExtraParameter; public ulong ExtraParameterSize; public int ChannelIndex; public int ChannelCount; + public DecodingBehaviour DecodingBehaviour; public SampleRateConversionQuality SrcQuality; + public SampleFormat SampleFormat; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int GetPitchLimitBySrcQuality(SampleRateConversionQuality quality) { - switch (quality) + return quality switch { - case SampleRateConversionQuality.Default: - case SampleRateConversionQuality.Low: - return 4; - case SampleRateConversionQuality.High: - return 8; - default: - throw new ArgumentException($"{quality}"); - } + SampleRateConversionQuality.Default or SampleRateConversionQuality.Low => 4, + SampleRateConversionQuality.High => 8, + _ => throw new ArgumentException(quality.ToString()), + }; } - public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, WaveBufferInformation info, uint targetSampleRate, int sampleCount) + public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, ref WaveBufferInformation info, Span<WaveBuffer> wavebuffers, ref VoiceUpdateState voiceState, uint targetSampleRate, int sampleCount) { const int tempBufferSize = 0x3F00; - ref VoiceUpdateState state = ref info.State.Span[0]; - - short[] tempBuffer = ArrayPool<short>.Shared.Rent(tempBufferSize); + Span<short> tempBuffer = stackalloc short[tempBufferSize]; - float sampleRateRatio = ((float)info.SourceSampleRate / targetSampleRate * info.Pitch); + float sampleRateRatio = (float)info.SourceSampleRate / targetSampleRate * info.Pitch; - float fraction = state.Fraction; - int waveBufferIndex = (int)state.WaveBufferIndex; - ulong playedSampleCount = state.PlayedSampleCount; - int offset = state.Offset; - uint waveBufferConsumed = state.WaveBufferConsumed; + float fraction = voiceState.Fraction; + int waveBufferIndex = (int)voiceState.WaveBufferIndex; + ulong playedSampleCount = voiceState.PlayedSampleCount; + int offset = voiceState.Offset; + uint waveBufferConsumed = voiceState.WaveBufferConsumed; int pitchMaxLength = GetPitchLimitBySrcQuality(info.SrcQuality); @@ -101,7 +93,7 @@ namespace Ryujinx.Audio.Renderer.Dsp if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) { - state.Pitch.ToSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer.AsSpan()); + voiceState.Pitch.ToSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer); tempBufferIndex += pitchMaxLength; } @@ -115,33 +107,31 @@ namespace Ryujinx.Audio.Renderer.Dsp { if (waveBufferIndex >= Constants.VoiceWaveBufferCount) { - Logger.Error?.Print(LogClass.AudioRenderer, $"Invalid WaveBuffer index {waveBufferIndex}"); - waveBufferIndex = 0; playedSampleCount = 0; } - if (!state.IsWaveBufferValid[waveBufferIndex]) + if (!voiceState.IsWaveBufferValid[waveBufferIndex]) { isStarving = true; break; } - ref WaveBuffer waveBuffer = ref info.WaveBuffers[waveBufferIndex]; + ref WaveBuffer waveBuffer = ref wavebuffers[waveBufferIndex]; if (offset == 0 && info.SampleFormat == SampleFormat.Adpcm && waveBuffer.Context != 0) { - state.LoopContext = memoryManager.Read<AdpcmLoopContext>(waveBuffer.Context); + voiceState.LoopContext = memoryManager.Read<AdpcmLoopContext>(waveBuffer.Context); } - Span<short> tempSpan = tempBuffer.AsSpan().Slice(tempBufferIndex + y); + Span<short> tempSpan = tempBuffer.Slice(tempBufferIndex + y); int decodedSampleCount = -1; int targetSampleStartOffset; int targetSampleEndOffset; - if (state.LoopCount > 0 && waveBuffer.LoopStartSampleOffset != 0 && waveBuffer.LoopEndSampleOffset != 0 && waveBuffer.LoopStartSampleOffset <= waveBuffer.LoopEndSampleOffset) + if (voiceState.LoopCount > 0 && waveBuffer.LoopStartSampleOffset != 0 && waveBuffer.LoopEndSampleOffset != 0 && waveBuffer.LoopStartSampleOffset <= waveBuffer.LoopEndSampleOffset) { targetSampleStartOffset = (int)waveBuffer.LoopStartSampleOffset; targetSampleEndOffset = (int)waveBuffer.LoopEndSampleOffset; @@ -166,7 +156,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } ReadOnlySpan<short> coefficients = MemoryMarshal.Cast<byte, short>(memoryManager.GetSpan(info.ExtraParameter, (int)info.ExtraParameterSize)); - decodedSampleCount = AdpcmHelper.Decode(tempSpan, waveBufferAdpcm, targetSampleStartOffset, targetSampleEndOffset, offset, sampleCountToDecode - y, coefficients, ref state.LoopContext); + decodedSampleCount = AdpcmHelper.Decode(tempSpan, waveBufferAdpcm, targetSampleStartOffset, targetSampleEndOffset, offset, sampleCountToDecode - y, coefficients, ref voiceState.LoopContext); break; case SampleFormat.PcmInt16: ReadOnlySpan<short> waveBufferPcm16 = ReadOnlySpan<short>.Empty; @@ -195,7 +185,7 @@ namespace Ryujinx.Audio.Renderer.Dsp decodedSampleCount = PcmHelper.Decode(tempSpan, waveBufferPcmFloat, targetSampleStartOffset, targetSampleEndOffset, info.ChannelIndex, info.ChannelCount); break; default: - Logger.Warning?.Print(LogClass.AudioRenderer, $"Unsupported sample format {info.SampleFormat}"); + Logger.Error?.Print(LogClass.AudioRenderer, $"Unsupported sample format " + info.SampleFormat); break; } @@ -203,9 +193,9 @@ namespace Ryujinx.Audio.Renderer.Dsp if (decodedSampleCount < 0) { - Logger.Warning?.Print(LogClass.AudioRenderer, $"Decoding failed, skipping WaveBuffer"); + Logger.Warning?.Print(LogClass.AudioRenderer, "Decoding failed, skipping WaveBuffer"); - state.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); + voiceState.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); decodedSampleCount = 0; } @@ -219,13 +209,13 @@ namespace Ryujinx.Audio.Renderer.Dsp if (waveBuffer.Looping) { - state.LoopCount++; + voiceState.LoopCount++; if (waveBuffer.LoopCount >= 0) { - if (decodedSampleCount == 0 || state.LoopCount > waveBuffer.LoopCount) + if (decodedSampleCount == 0 || voiceState.LoopCount > waveBuffer.LoopCount) { - state.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); + voiceState.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); } } @@ -242,13 +232,12 @@ namespace Ryujinx.Audio.Renderer.Dsp } else { - state.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); + voiceState.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); } } } - Span<float> outputSpan = outputBuffer.Slice(i); - Span<int> outputSpanInt = MemoryMarshal.Cast<float, int>(outputSpan); + Span<int> outputSpanInt = MemoryMarshal.Cast<float, int>(outputBuffer.Slice(i)); if (info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) { @@ -259,7 +248,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } else { - Span<short> tempSpan = tempBuffer.AsSpan().Slice(tempBufferIndex + y); + Span<short> tempSpan = tempBuffer.Slice(tempBufferIndex + y); tempSpan.Slice(0, sampleCountToDecode - y).Fill(0); @@ -267,7 +256,7 @@ namespace Ryujinx.Audio.Renderer.Dsp ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f); - tempBuffer.AsSpan().Slice(sampleCountToDecode, pitchMaxLength).CopyTo(state.Pitch.ToSpan()); + tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.ToSpan()); } i += sampleCountToProcess; @@ -275,16 +264,15 @@ namespace Ryujinx.Audio.Renderer.Dsp Debug.Assert(sourceSampleCountToProcess == i || !isStarving); - state.WaveBufferConsumed = waveBufferConsumed; - state.Offset = offset; - state.PlayedSampleCount = playedSampleCount; - state.WaveBufferIndex = (uint)waveBufferIndex; - state.Fraction = fraction; + voiceState.WaveBufferConsumed = waveBufferConsumed; + voiceState.Offset = offset; + voiceState.PlayedSampleCount = playedSampleCount; + voiceState.WaveBufferIndex = (uint)waveBufferIndex; + voiceState.Fraction = fraction; } - - ArrayPool<short>.Shared.Return(tempBuffer); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void ToFloatAvx(Span<float> output, ReadOnlySpan<int> input, int sampleCount) { ReadOnlySpan<Vector256<int>> inputVec = MemoryMarshal.Cast<int, Vector256<int>>(input); @@ -303,6 +291,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void ToFloatSse2(Span<float> output, ReadOnlySpan<int> input, int sampleCount) { ReadOnlySpan<Vector128<int>> inputVec = MemoryMarshal.Cast<int, Vector128<int>>(input); @@ -321,6 +310,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void ToFloatAdvSimd(Span<float> output, ReadOnlySpan<int> input, int sampleCount) { ReadOnlySpan<Vector128<int>> inputVec = MemoryMarshal.Cast<int, Vector128<int>>(input); @@ -348,6 +338,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToFloat(Span<float> output, ReadOnlySpan<int> input, int sampleCount) { if (Avx.IsSupported) @@ -368,6 +359,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToIntAvx(Span<int> output, ReadOnlySpan<float> input, int sampleCount) { ReadOnlySpan<Vector256<float>> inputVec = MemoryMarshal.Cast<float, Vector256<float>>(input); @@ -386,6 +378,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToIntSse2(Span<int> output, ReadOnlySpan<float> input, int sampleCount) { ReadOnlySpan<Vector128<float>> inputVec = MemoryMarshal.Cast<float, Vector128<float>>(input); @@ -404,6 +397,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToIntAdvSimd(Span<int> output, ReadOnlySpan<float> input, int sampleCount) { ReadOnlySpan<Vector128<float>> inputVec = MemoryMarshal.Cast<float, Vector128<float>>(input); @@ -431,6 +425,7 @@ namespace Ryujinx.Audio.Renderer.Dsp } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToInt(Span<int> output, ReadOnlySpan<float> input, int sampleCount) { if (Avx.IsSupported) |