diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Audio/Renderer/Dsp | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Audio/Renderer/Dsp')
53 files changed, 0 insertions, 6263 deletions
diff --git a/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs b/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs deleted file mode 100644 index 2680dcb1..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs +++ /dev/null @@ -1,216 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Common.Logging; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class AdpcmHelper - { - private const int FixedPointPrecision = 11; - private const int SamplesPerFrame = 14; - private const int NibblesPerFrame = SamplesPerFrame + 2; - private const int BytesPerFrame = 8; - private const int BitsPerFrame = BytesPerFrame * 8; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint GetAdpcmDataSize(int sampleCount) - { - Debug.Assert(sampleCount >= 0); - - int frames = sampleCount / SamplesPerFrame; - int extraSize = 0; - - if ((sampleCount % SamplesPerFrame) != 0) - { - extraSize = (sampleCount % SamplesPerFrame) / 2 + 1 + (sampleCount % 2); - } - - return (uint)(BytesPerFrame * frames + extraSize); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetAdpcmOffsetFromSampleOffset(int sampleOffset) - { - Debug.Assert(sampleOffset >= 0); - - return GetNibblesFromSampleCount(sampleOffset) / 2; - } - - public static int NibbleToSample(int nibble) - { - int frames = nibble / NibblesPerFrame; - int extraNibbles = nibble % NibblesPerFrame; - int samples = SamplesPerFrame * frames; - - return samples + extraNibbles - 2; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetNibblesFromSampleCount(int sampleCount) - { - byte headerSize = 0; - - if ((sampleCount % SamplesPerFrame) != 0) - { - headerSize = 2; - } - - return sampleCount % SamplesPerFrame + NibblesPerFrame * (sampleCount / SamplesPerFrame) + headerSize; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static short Saturate(int value) - { - if (value > short.MaxValue) - value = short.MaxValue; - - if (value < short.MinValue) - value = short.MinValue; - - return (short)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static short GetCoefficientAtIndex(ReadOnlySpan<short> coefficients, int index) - { - if ((uint)index > (uint)coefficients.Length) - { - Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}"); - - return 0; - } - - return coefficients[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Decode(Span<short> output, ReadOnlySpan<byte> input, int startSampleOffset, int endSampleOffset, int offset, int count, ReadOnlySpan<short> coefficients, ref AdpcmLoopContext loopContext) - { - if (input.IsEmpty || endSampleOffset < startSampleOffset) - { - return 0; - } - - byte predScale = (byte)loopContext.PredScale; - byte scale = (byte)(predScale & 0xF); - byte coefficientIndex = (byte)((predScale >> 4) & 0xF); - short history0 = loopContext.History0; - short history1 = loopContext.History1; - short coefficient0 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 0); - short coefficient1 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 1); - - int decodedCount = Math.Min(count, endSampleOffset - startSampleOffset - offset); - int nibbles = GetNibblesFromSampleCount(offset + startSampleOffset); - int remaining = decodedCount; - int outputBufferIndex = 0; - int inputIndex = 0; - - ReadOnlySpan<byte> targetInput; - - targetInput = input.Slice(nibbles / 2); - - while (remaining > 0) - { - int samplesCount; - - if (((uint)nibbles % NibblesPerFrame) == 0) - { - predScale = targetInput[inputIndex++]; - - scale = (byte)(predScale & 0xF); - - coefficientIndex = (byte)((predScale >> 4) & 0xF); - - coefficient0 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2); - coefficient1 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 1); - - nibbles += 2; - - samplesCount = Math.Min(remaining, SamplesPerFrame); - } - else - { - samplesCount = 1; - } - - int scaleFixedPoint = FixedPointHelper.ToFixed(1.0f, FixedPointPrecision) << scale; - - if (samplesCount < SamplesPerFrame) - { - for (int i = 0; i < samplesCount; i++) - { - int value = targetInput[inputIndex]; - - int sample; - - if ((nibbles & 1) != 0) - { - sample = (value << 28) >> 28; - - inputIndex++; - } - else - { - sample = (value << 24) >> 28; - } - - nibbles++; - - int prediction = coefficient0 * history0 + coefficient1 * history1; - - sample = FixedPointHelper.RoundUpAndToInt(sample * scaleFixedPoint + prediction, FixedPointPrecision); - - short saturatedSample = Saturate(sample); - - history1 = history0; - history0 = saturatedSample; - - output[outputBufferIndex++] = saturatedSample; - - remaining--; - } - } - else - { - for (int i = 0; i < SamplesPerFrame / 2; i++) - { - int value = targetInput[inputIndex]; - - int sample0; - int sample1; - - sample0 = (value << 24) >> 28; - sample1 = (value << 28) >> 28; - - inputIndex++; - - int prediction0 = coefficient0 * history0 + coefficient1 * history1; - sample0 = FixedPointHelper.RoundUpAndToInt(sample0 * scaleFixedPoint + prediction0, FixedPointPrecision); - short saturatedSample0 = Saturate(sample0); - - int prediction1 = coefficient0 * saturatedSample0 + coefficient1 * history0; - sample1 = FixedPointHelper.RoundUpAndToInt(sample1 * scaleFixedPoint + prediction1, FixedPointPrecision); - short saturatedSample1 = Saturate(sample1); - - history1 = saturatedSample0; - history0 = saturatedSample1; - - output[outputBufferIndex++] = saturatedSample0; - output[outputBufferIndex++] = saturatedSample1; - } - - nibbles += SamplesPerFrame; - remaining -= SamplesPerFrame; - } - } - - loopContext.PredScale = predScale; - loopContext.History0 = history0; - loopContext.History1 = history1; - - return decodedCount; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/AudioProcessor.cs b/Ryujinx.Audio/Renderer/Dsp/AudioProcessor.cs deleted file mode 100644 index 7bd0443c..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/AudioProcessor.cs +++ /dev/null @@ -1,276 +0,0 @@ -using Ryujinx.Audio.Integration; -using Ryujinx.Audio.Renderer.Dsp.Command; -using Ryujinx.Audio.Renderer.Utils; -using Ryujinx.Common; -using Ryujinx.Common.Logging; -using System; -using System.Threading; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public class AudioProcessor : IDisposable - { - private const int MaxBufferedFrames = 5; - private const int TargetBufferedFrames = 3; - - private enum MailboxMessage : uint - { - Start, - Stop, - RenderStart, - RenderEnd - } - - private class RendererSession - { - public CommandList CommandList; - public int RenderingLimit; - public ulong AppletResourceId; - } - - private Mailbox<MailboxMessage> _mailbox; - private RendererSession[] _sessionCommandList; - private Thread _workerThread; - - public IHardwareDevice[] OutputDevices { get; private set; } - - private long _lastTime; - private long _playbackEnds; - private ManualResetEvent _event; - - private ManualResetEvent _pauseEvent; - - public AudioProcessor() - { - _event = new ManualResetEvent(false); - } - - private static uint GetHardwareChannelCount(IHardwareDeviceDriver deviceDriver) - { - // Get the real device driver (In case the compat layer is on top of it). - deviceDriver = deviceDriver.GetRealDeviceDriver(); - - if (deviceDriver.SupportsChannelCount(6)) - { - return 6; - } - else - { - // NOTE: We default to stereo as this will get downmixed to mono by the compat layer if it's not compatible. - return 2; - } - } - - public void Start(IHardwareDeviceDriver deviceDriver, float volume) - { - OutputDevices = new IHardwareDevice[Constants.AudioRendererSessionCountMax]; - - // TODO: Before enabling this, we need up-mixing from stereo to 5.1. - // uint channelCount = GetHardwareChannelCount(deviceDriver); - uint channelCount = 2; - - for (int i = 0; i < OutputDevices.Length; i++) - { - // TODO: Don't hardcode sample rate. - OutputDevices[i] = new HardwareDeviceImpl(deviceDriver, channelCount, Constants.TargetSampleRate, volume); - } - - _mailbox = new Mailbox<MailboxMessage>(); - _sessionCommandList = new RendererSession[Constants.AudioRendererSessionCountMax]; - _event.Reset(); - _lastTime = PerformanceCounter.ElapsedNanoseconds; - _pauseEvent = deviceDriver.GetPauseEvent(); - - StartThread(); - - _mailbox.SendMessage(MailboxMessage.Start); - - if (_mailbox.ReceiveResponse() != MailboxMessage.Start) - { - throw new InvalidOperationException("Audio Processor Start response was invalid!"); - } - } - - public void Stop() - { - _mailbox.SendMessage(MailboxMessage.Stop); - - if (_mailbox.ReceiveResponse() != MailboxMessage.Stop) - { - throw new InvalidOperationException("Audio Processor Stop response was invalid!"); - } - - foreach (IHardwareDevice device in OutputDevices) - { - device.Dispose(); - } - } - - public void Send(int sessionId, CommandList commands, int renderingLimit, ulong appletResourceId) - { - _sessionCommandList[sessionId] = new RendererSession - { - CommandList = commands, - RenderingLimit = renderingLimit, - AppletResourceId = appletResourceId - }; - } - - public bool HasRemainingCommands(int sessionId) - { - return _sessionCommandList[sessionId] != null; - } - - public void Signal() - { - _mailbox.SendMessage(MailboxMessage.RenderStart); - } - - public void Wait() - { - if (_mailbox.ReceiveResponse() != MailboxMessage.RenderEnd) - { - throw new InvalidOperationException("Audio Processor Wait response was invalid!"); - } - - long increment = Constants.AudioProcessorMaxUpdateTimeTarget; - - long timeNow = PerformanceCounter.ElapsedNanoseconds; - - if (timeNow > _playbackEnds) - { - // Playback has restarted. - _playbackEnds = timeNow; - } - - _playbackEnds += increment; - - // The number of frames we are behind where the timer says we should be. - long framesBehind = (timeNow - _lastTime) / increment; - - // The number of frames yet to play on the backend. - long bufferedFrames = (_playbackEnds - timeNow) / increment + framesBehind; - - // If we've entered a situation where a lot of buffers will be queued on the backend, - // Skip some audio frames so that playback can catch up. - if (bufferedFrames > MaxBufferedFrames) - { - // Skip a few frames so that we're not too far behind. (the target number of frames) - _lastTime += increment * (bufferedFrames - TargetBufferedFrames); - } - - while (timeNow < _lastTime + increment) - { - _event.WaitOne(1); - - timeNow = PerformanceCounter.ElapsedNanoseconds; - } - - _lastTime += increment; - } - - private void StartThread() - { - _workerThread = new Thread(Work) - { - Name = "AudioProcessor.Worker" - }; - - _workerThread.Start(); - } - - private void Work() - { - if (_mailbox.ReceiveMessage() != MailboxMessage.Start) - { - throw new InvalidOperationException("Audio Processor Start message was invalid!"); - } - - _mailbox.SendResponse(MailboxMessage.Start); - _mailbox.SendResponse(MailboxMessage.RenderEnd); - - Logger.Info?.Print(LogClass.AudioRenderer, "Starting audio processor"); - - while (true) - { - _pauseEvent?.WaitOne(); - - MailboxMessage message = _mailbox.ReceiveMessage(); - - if (message == MailboxMessage.Stop) - { - break; - } - - if (message == MailboxMessage.RenderStart) - { - long startTicks = PerformanceCounter.ElapsedNanoseconds; - - for (int i = 0; i < _sessionCommandList.Length; i++) - { - if (_sessionCommandList[i] != null) - { - _sessionCommandList[i].CommandList.Process(OutputDevices[i]); - _sessionCommandList[i].CommandList.Dispose(); - _sessionCommandList[i] = null; - } - } - - long endTicks = PerformanceCounter.ElapsedNanoseconds; - - long elapsedTime = endTicks - startTicks; - - if (Constants.AudioProcessorMaxUpdateTime < elapsedTime) - { - Logger.Debug?.Print(LogClass.AudioRenderer, $"DSP too slow (exceeded by {elapsedTime - Constants.AudioProcessorMaxUpdateTime}ns)"); - } - - _mailbox.SendResponse(MailboxMessage.RenderEnd); - } - } - - Logger.Info?.Print(LogClass.AudioRenderer, "Stopping audio processor"); - _mailbox.SendResponse(MailboxMessage.Stop); - } - - public float GetVolume() - { - if (OutputDevices != null) - { - foreach (IHardwareDevice outputDevice in OutputDevices) - { - if (outputDevice != null) - { - return outputDevice.GetVolume(); - } - } - } - - return 0f; - } - - public void SetVolume(float volume) - { - if (OutputDevices != null) - { - foreach (IHardwareDevice outputDevice in OutputDevices) - { - outputDevice?.SetVolume(volume); - } - } - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _event.Dispose(); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/BiquadFilterHelper.cs b/Ryujinx.Audio/Renderer/Dsp/BiquadFilterHelper.cs deleted file mode 100644 index 98460ff1..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/BiquadFilterHelper.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter; -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class BiquadFilterHelper - { - private const int FixedPointPrecisionForParameter = 14; - - /// <summary> - /// Apply a single biquad filter. - /// </summary> - /// <remarks>This is implemented with a direct form 2.</remarks> - /// <param name="parameter">The biquad filter parameter</param> - /// <param name="state">The biquad filter state</param> - /// <param name="outputBuffer">The output buffer to write the result</param> - /// <param name="inputBuffer">The input buffer to write the result</param> - /// <param name="sampleCount">The count of samples to process</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ProcessBiquadFilter(ref BiquadFilterParameter parameter, ref BiquadFilterState state, Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, uint sampleCount) - { - float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter); - float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter); - float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter); - - float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter); - float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter); - - for (int i = 0; i < sampleCount; i++) - { - float input = inputBuffer[i]; - float output = input * a0 + state.State0; - - state.State0 = input * a1 + output * b1 + state.State1; - state.State1 = input * a2 + output * b2; - - outputBuffer[i] = output; - } - } - - /// <summary> - /// Apply multiple biquad filter. - /// </summary> - /// <remarks>This is implemented with a direct form 1.</remarks> - /// <param name="parameters">The biquad filter parameter</param> - /// <param name="states">The biquad filter state</param> - /// <param name="outputBuffer">The output buffer to write the result</param> - /// <param name="inputBuffer">The input buffer to write the result</param> - /// <param name="sampleCount">The count of samples to process</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ProcessBiquadFilter(ReadOnlySpan<BiquadFilterParameter> parameters, Span<BiquadFilterState> states, Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, uint sampleCount) - { - for (int stageIndex = 0; stageIndex < parameters.Length; stageIndex++) - { - BiquadFilterParameter parameter = parameters[stageIndex]; - - ref BiquadFilterState state = ref states[stageIndex]; - - float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter); - float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter); - float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter); - - float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter); - float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter); - - for (int i = 0; i < sampleCount; i++) - { - float input = inputBuffer[i]; - float output = input * a0 + state.State0 * a1 + state.State1 * a2 + state.State2 * b1 + state.State3 * b2; - - state.State1 = state.State0; - state.State0 = input; - state.State3 = state.State2; - state.State2 = output; - - outputBuffer[i] = output; - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs deleted file mode 100644 index 1fe6069f..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Ryujinx.Audio.Common; -using Ryujinx.Audio.Renderer.Common; -using System; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class AdpcmDataSourceCommandVersion1 : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.AdpcmDataSourceVersion1; - - public uint EstimatedProcessingTime { get; set; } - - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } - - public float Pitch { get; } - - public WaveBuffer[] WaveBuffers { get; } - - public Memory<VoiceUpdateState> State { get; } - - public ulong AdpcmParameter { get; } - public ulong AdpcmParameterSize { get; } - - public DecodingBehaviour DecodingBehaviour { get; } - - public AdpcmDataSourceCommandVersion1(ref Server.Voice.VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - OutputBufferIndex = outputBufferIndex; - SampleRate = serverState.SampleRate; - Pitch = serverState.Pitch; - - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; - - for (int i = 0; i < WaveBuffers.Length; i++) - { - ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i]; - - WaveBuffers[i] = voiceWaveBuffer.ToCommon(1); - } - - AdpcmParameter = serverState.DataSourceStateAddressInfo.GetReference(true); - AdpcmParameterSize = serverState.DataSourceStateAddressInfo.Size; - State = state; - DecodingBehaviour = serverState.DecodingBehaviour; - } - - public void Process(CommandList context) - { - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - DataSourceHelper.WaveBufferInformation info = new DataSourceHelper.WaveBufferInformation - { - SourceSampleRate = SampleRate, - SampleFormat = SampleFormat.Adpcm, - Pitch = Pitch, - DecodingBehaviour = DecodingBehaviour, - ExtraParameter = AdpcmParameter, - ExtraParameterSize = AdpcmParameterSize, - ChannelIndex = 0, - ChannelCount = 1, - }; - - DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs deleted file mode 100644 index 5c3c0324..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Memory; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using static Ryujinx.Audio.Renderer.Dsp.State.AuxiliaryBufferHeader; -using CpuAddress = System.UInt64; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class AuxiliaryBufferCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.AuxiliaryBuffer; - - public uint EstimatedProcessingTime { get; set; } - - public uint InputBufferIndex { get; } - public uint OutputBufferIndex { get; } - - public AuxiliaryBufferAddresses BufferInfo { get; } - - public CpuAddress InputBuffer { get; } - public CpuAddress OutputBuffer { get; } - public uint CountMax { get; } - public uint UpdateCount { get; } - public uint WriteOffset { get; } - - public bool IsEffectEnabled { get; } - - public AuxiliaryBufferCommand(uint bufferOffset, byte inputBufferOffset, byte outputBufferOffset, - ref AuxiliaryBufferAddresses sendBufferInfo, bool isEnabled, uint countMax, - CpuAddress outputBuffer, CpuAddress inputBuffer, uint updateCount, uint writeOffset, int nodeId) - { - Enabled = true; - NodeId = nodeId; - InputBufferIndex = bufferOffset + inputBufferOffset; - OutputBufferIndex = bufferOffset + outputBufferOffset; - BufferInfo = sendBufferInfo; - InputBuffer = inputBuffer; - OutputBuffer = outputBuffer; - CountMax = countMax; - UpdateCount = updateCount; - WriteOffset = writeOffset; - IsEffectEnabled = isEnabled; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private uint Read(IVirtualMemoryManager memoryManager, ulong bufferAddress, uint countMax, Span<int> outBuffer, uint count, uint readOffset, uint updateCount) - { - if (countMax == 0 || bufferAddress == 0) - { - return 0; - } - - uint targetReadOffset = readOffset + AuxiliaryBufferInfo.GetReadOffset(memoryManager, BufferInfo.ReturnBufferInfo); - - if (targetReadOffset > countMax) - { - return 0; - } - - uint remaining = count; - - uint outBufferOffset = 0; - - while (remaining != 0) - { - uint countToWrite = Math.Min(countMax - targetReadOffset, remaining); - - memoryManager.Read(bufferAddress + targetReadOffset * sizeof(int), MemoryMarshal.Cast<int, byte>(outBuffer.Slice((int)outBufferOffset, (int)countToWrite))); - - targetReadOffset = (targetReadOffset + countToWrite) % countMax; - remaining -= countToWrite; - outBufferOffset += countToWrite; - } - - if (updateCount != 0) - { - uint newReadOffset = (AuxiliaryBufferInfo.GetReadOffset(memoryManager, BufferInfo.ReturnBufferInfo) + updateCount) % countMax; - - AuxiliaryBufferInfo.SetReadOffset(memoryManager, BufferInfo.ReturnBufferInfo, newReadOffset); - } - - return count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private uint Write(IVirtualMemoryManager memoryManager, ulong outBufferAddress, uint countMax, ReadOnlySpan<int> buffer, uint count, uint writeOffset, uint updateCount) - { - if (countMax == 0 || outBufferAddress == 0) - { - return 0; - } - - uint targetWriteOffset = writeOffset + AuxiliaryBufferInfo.GetWriteOffset(memoryManager, BufferInfo.SendBufferInfo); - - if (targetWriteOffset > countMax) - { - return 0; - } - - uint remaining = count; - - uint inBufferOffset = 0; - - while (remaining != 0) - { - uint countToWrite = Math.Min(countMax - targetWriteOffset, remaining); - - memoryManager.Write(outBufferAddress + targetWriteOffset * sizeof(int), MemoryMarshal.Cast<int, byte>(buffer.Slice((int)inBufferOffset, (int)countToWrite))); - - targetWriteOffset = (targetWriteOffset + countToWrite) % countMax; - remaining -= countToWrite; - inBufferOffset += countToWrite; - } - - if (updateCount != 0) - { - uint newWriteOffset = (AuxiliaryBufferInfo.GetWriteOffset(memoryManager, BufferInfo.SendBufferInfo) + updateCount) % countMax; - - AuxiliaryBufferInfo.SetWriteOffset(memoryManager, BufferInfo.SendBufferInfo, newWriteOffset); - } - - return count; - } - - public void Process(CommandList context) - { - Span<float> inputBuffer = context.GetBuffer((int)InputBufferIndex); - Span<float> outputBuffer = context.GetBuffer((int)OutputBufferIndex); - - if (IsEffectEnabled) - { - Span<int> inputBufferInt = MemoryMarshal.Cast<float, int>(inputBuffer); - Span<int> outputBufferInt = MemoryMarshal.Cast<float, int>(outputBuffer); - - // Convert input data to the target format for user (int) - DataSourceHelper.ToInt(inputBufferInt, inputBuffer, inputBuffer.Length); - - // Send the input to the user - Write(context.MemoryManager, OutputBuffer, CountMax, inputBufferInt, context.SampleCount, WriteOffset, UpdateCount); - - // Convert back to float just in case it's reused - DataSourceHelper.ToFloat(inputBuffer, inputBufferInt, inputBuffer.Length); - - // Retrieve the input from user - uint readResult = Read(context.MemoryManager, InputBuffer, CountMax, outputBufferInt, context.SampleCount, WriteOffset, UpdateCount); - - // Convert the outputBuffer back to the target format of the renderer (float) - DataSourceHelper.ToFloat(outputBuffer, outputBufferInt, outputBuffer.Length); - - if (readResult != context.SampleCount) - { - outputBuffer.Slice((int)readResult, (int)context.SampleCount - (int)readResult).Fill(0); - } - } - else - { - AuxiliaryBufferInfo.Reset(context.MemoryManager, BufferInfo.SendBufferInfo); - AuxiliaryBufferInfo.Reset(context.MemoryManager, BufferInfo.ReturnBufferInfo); - - if (InputBufferIndex != OutputBufferIndex) - { - inputBuffer.CopyTo(outputBuffer); - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs deleted file mode 100644 index b994c1cb..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class BiquadFilterCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - 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; } - - private BiquadFilterParameter _parameter; - - public BiquadFilterCommand(int baseIndex, ref BiquadFilterParameter filter, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, bool needInitialization, int nodeId) - { - _parameter = filter; - BiquadFilterState = biquadFilterStateMemory; - InputBufferIndex = baseIndex + inputBufferOffset; - OutputBufferIndex = baseIndex + outputBufferOffset; - NeedInitialization = needInitialization; - - Enabled = true; - NodeId = nodeId; - } - - public void Process(CommandList context) - { - ref BiquadFilterState state = ref BiquadFilterState.Span[0]; - - ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - if (NeedInitialization) - { - state = new BiquadFilterState(); - } - - BiquadFilterHelper.ProcessBiquadFilter(ref _parameter, ref state, outputBuffer, inputBuffer, context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs deleted file mode 100644 index da1cb254..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs +++ /dev/null @@ -1,136 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Memory; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using static Ryujinx.Audio.Renderer.Dsp.State.AuxiliaryBufferHeader; -using CpuAddress = System.UInt64; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class CaptureBufferCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.CaptureBuffer; - - public uint EstimatedProcessingTime { get; set; } - - public uint InputBufferIndex { get; } - - public ulong CpuBufferInfoAddress { get; } - public ulong DspBufferInfoAddress { get; } - - public CpuAddress OutputBuffer { get; } - public uint CountMax { get; } - public uint UpdateCount { get; } - public uint WriteOffset { get; } - - public bool IsEffectEnabled { get; } - - public CaptureBufferCommand(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled, - uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId) - { - Enabled = true; - NodeId = nodeId; - InputBufferIndex = bufferOffset + inputBufferOffset; - CpuBufferInfoAddress = sendBufferInfo; - DspBufferInfoAddress = sendBufferInfo + (ulong)Unsafe.SizeOf<AuxiliaryBufferHeader>(); - OutputBuffer = outputBuffer; - CountMax = countMax; - UpdateCount = updateCount; - WriteOffset = writeOffset; - IsEffectEnabled = isEnabled; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private uint Write(IVirtualMemoryManager memoryManager, ulong outBufferAddress, uint countMax, ReadOnlySpan<int> buffer, uint count, uint writeOffset, uint updateCount) - { - if (countMax == 0 || outBufferAddress == 0) - { - return 0; - } - - uint targetWriteOffset = writeOffset + AuxiliaryBufferInfo.GetWriteOffset(memoryManager, DspBufferInfoAddress); - - if (targetWriteOffset > countMax) - { - return 0; - } - - uint remaining = count; - - uint inBufferOffset = 0; - - while (remaining != 0) - { - uint countToWrite = Math.Min(countMax - targetWriteOffset, remaining); - - memoryManager.Write(outBufferAddress + targetWriteOffset * sizeof(int), MemoryMarshal.Cast<int, byte>(buffer.Slice((int)inBufferOffset, (int)countToWrite))); - - targetWriteOffset = (targetWriteOffset + countToWrite) % countMax; - remaining -= countToWrite; - inBufferOffset += countToWrite; - } - - if (updateCount != 0) - { - uint dspTotalSampleCount = AuxiliaryBufferInfo.GetTotalSampleCount(memoryManager, DspBufferInfoAddress); - uint cpuTotalSampleCount = AuxiliaryBufferInfo.GetTotalSampleCount(memoryManager, CpuBufferInfoAddress); - - uint totalSampleCountDiff = dspTotalSampleCount - cpuTotalSampleCount; - - if (totalSampleCountDiff >= countMax) - { - uint dspLostSampleCount = AuxiliaryBufferInfo.GetLostSampleCount(memoryManager, DspBufferInfoAddress); - uint cpuLostSampleCount = AuxiliaryBufferInfo.GetLostSampleCount(memoryManager, CpuBufferInfoAddress); - - uint lostSampleCountDiff = dspLostSampleCount - cpuLostSampleCount; - uint newLostSampleCount = lostSampleCountDiff + updateCount; - - if (lostSampleCountDiff > newLostSampleCount) - { - newLostSampleCount = cpuLostSampleCount - 1; - } - - AuxiliaryBufferInfo.SetLostSampleCount(memoryManager, DspBufferInfoAddress, newLostSampleCount); - } - - uint newWriteOffset = (AuxiliaryBufferInfo.GetWriteOffset(memoryManager, DspBufferInfoAddress) + updateCount) % countMax; - - AuxiliaryBufferInfo.SetWriteOffset(memoryManager, DspBufferInfoAddress, newWriteOffset); - - uint newTotalSampleCount = totalSampleCountDiff + newWriteOffset; - - AuxiliaryBufferInfo.SetTotalSampleCount(memoryManager, DspBufferInfoAddress, newTotalSampleCount); - } - - return count; - } - - public void Process(CommandList context) - { - Span<float> inputBuffer = context.GetBuffer((int)InputBufferIndex); - - if (IsEffectEnabled) - { - Span<int> inputBufferInt = MemoryMarshal.Cast<float, int>(inputBuffer); - - // Convert input data to the target format for user (int) - DataSourceHelper.ToInt(inputBufferInt, inputBuffer, inputBuffer.Length); - - // Send the input to the user - Write(context.MemoryManager, OutputBuffer, CountMax, inputBufferInt, context.SampleCount, WriteOffset, UpdateCount); - - // Convert back to float - DataSourceHelper.ToFloat(inputBuffer, inputBufferInt, inputBuffer.Length); - } - else - { - AuxiliaryBufferInfo.Reset(context.MemoryManager, DspBufferInfoAddress); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs deleted file mode 100644 index e50637eb..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Ryujinx.Audio.Renderer.Parameter.Sink; -using Ryujinx.Audio.Renderer.Server.MemoryPool; -using System.Diagnostics; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class CircularBufferSinkCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.CircularBufferSink; - - public uint EstimatedProcessingTime { get; set; } - - public ushort[] Input { get; } - public uint InputCount { get; } - - public ulong CircularBuffer { get; } - public ulong CircularBufferSize { get; } - public ulong CurrentOffset { get; } - - public CircularBufferSinkCommand(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - Input = new ushort[Constants.ChannelCountMax]; - InputCount = parameter.InputCount; - - for (int i = 0; i < InputCount; i++) - { - Input[i] = (ushort)(bufferOffset + parameter.Input[i]); - } - - CircularBuffer = circularBufferAddressInfo.GetReference(true); - CircularBufferSize = parameter.BufferSize; - CurrentOffset = currentOffset; - - Debug.Assert(CircularBuffer != 0); - } - - public void Process(CommandList context) - { - const int targetChannelCount = 2; - - ulong currentOffset = CurrentOffset; - - if (CircularBufferSize > 0) - { - for (int i = 0; i < InputCount; i++) - { - unsafe - { - float* inputBuffer = (float*)context.GetBufferPointer(Input[i]); - - ulong targetOffset = CircularBuffer + currentOffset; - - for (int y = 0; y < context.SampleCount; y++) - { - context.MemoryManager.Write(targetOffset + (ulong)y * targetChannelCount, PcmHelper.Saturate(inputBuffer[y])); - } - - currentOffset += context.SampleCount * targetChannelCount; - - if (currentOffset >= CircularBufferSize) - { - currentOffset = 0; - } - } - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs deleted file mode 100644 index 9e653e80..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class ClearMixBufferCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.ClearMixBuffer; - - public uint EstimatedProcessingTime { get; set; } - - public ClearMixBufferCommand(int nodeId) - { - Enabled = true; - NodeId = nodeId; - } - - public void Process(CommandList context) - { - context.ClearBuffers(); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs deleted file mode 100644 index 2cbed9c2..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs +++ /dev/null @@ -1,155 +0,0 @@ -using Ryujinx.Audio.Integration; -using Ryujinx.Audio.Renderer.Server; -using Ryujinx.Common; -using Ryujinx.Common.Logging; -using Ryujinx.Memory; -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class CommandList : IDisposable - { - public ulong StartTime { get; private set; } - public ulong EndTime { get; private set; } - public uint SampleCount { get; } - public uint SampleRate { get; } - - public Memory<float> Buffers { get; } - public uint BufferCount { get; } - - public List<ICommand> Commands { get; } - - public IVirtualMemoryManager MemoryManager { get; } - - public IHardwareDevice OutputDevice { get; private set; } - - private readonly int _sampleCount; - private readonly int _buffersEntryCount; - private readonly MemoryHandle _buffersMemoryHandle; - - public CommandList(AudioRenderSystem renderSystem) : this(renderSystem.MemoryManager, - renderSystem.GetMixBuffer(), - renderSystem.GetSampleCount(), - renderSystem.GetSampleRate(), - renderSystem.GetMixBufferCount(), - renderSystem.GetVoiceChannelCountMax()) - { - } - - public CommandList(IVirtualMemoryManager memoryManager, Memory<float> mixBuffer, uint sampleCount, uint sampleRate, uint mixBufferCount, uint voiceChannelCountMax) - { - SampleCount = sampleCount; - _sampleCount = (int)SampleCount; - SampleRate = sampleRate; - BufferCount = mixBufferCount + voiceChannelCountMax; - Buffers = mixBuffer; - Commands = new List<ICommand>(); - MemoryManager = memoryManager; - - _buffersEntryCount = Buffers.Length; - _buffersMemoryHandle = Buffers.Pin(); - } - - public void AddCommand(ICommand command) - { - Commands.Add(command); - } - - public void AddCommand<T>(T command) where T : unmanaged, ICommand - { - throw new NotImplementedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe IntPtr GetBufferPointer(int index) - { - if (index >= 0 && index < _buffersEntryCount) - { - return (IntPtr)((float*)_buffersMemoryHandle.Pointer + index * _sampleCount); - } - - throw new ArgumentOutOfRangeException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void ClearBuffer(int index) - { - Unsafe.InitBlock((void*)GetBufferPointer(index), 0, SampleCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void ClearBuffers() - { - Unsafe.InitBlock(_buffersMemoryHandle.Pointer, 0, (uint)_buffersEntryCount * sizeof(float)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void CopyBuffer(int outputBufferIndex, int inputBufferIndex) - { - Unsafe.CopyBlock((void*)GetBufferPointer(outputBufferIndex), (void*)GetBufferPointer(inputBufferIndex), SampleCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span<float> GetBuffer(int index) - { - if (index < 0 || index >= _buffersEntryCount) - { - return Span<float>.Empty; - } - - unsafe - { - return new Span<float>((float*)_buffersMemoryHandle.Pointer + index * _sampleCount, _sampleCount); - } - } - - public ulong GetTimeElapsedSinceDspStartedProcessing() - { - return (ulong)PerformanceCounter.ElapsedNanoseconds - StartTime; - } - - public void Process(IHardwareDevice outputDevice) - { - OutputDevice = outputDevice; - - StartTime = (ulong)PerformanceCounter.ElapsedNanoseconds; - - foreach (ICommand command in Commands) - { - if (command.Enabled) - { - bool shouldMeter = command.ShouldMeter(); - - long startTime = 0; - - if (shouldMeter) - { - startTime = PerformanceCounter.ElapsedNanoseconds; - } - - command.Process(this); - - if (shouldMeter) - { - ulong effectiveElapsedTime = (ulong)(PerformanceCounter.ElapsedNanoseconds - startTime); - - if (effectiveElapsedTime > command.EstimatedProcessingTime) - { - Logger.Warning?.Print(LogClass.AudioRenderer, $"Command {command.GetType().Name} took {effectiveElapsedTime}ns (expected {command.EstimatedProcessingTime}ns)"); - } - } - } - } - - EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds; - } - - public void Dispose() - { - _buffersMemoryHandle.Dispose(); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs deleted file mode 100644 index 9ce181b1..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public enum CommandType : byte - { - Invalid, - PcmInt16DataSourceVersion1, - PcmInt16DataSourceVersion2, - PcmFloatDataSourceVersion1, - PcmFloatDataSourceVersion2, - AdpcmDataSourceVersion1, - AdpcmDataSourceVersion2, - Volume, - VolumeRamp, - BiquadFilter, - Mix, - MixRamp, - MixRampGrouped, - DepopPrepare, - DepopForMixBuffers, - Delay, - Upsample, - DownMixSurroundToStereo, - AuxiliaryBuffer, - DeviceSink, - CircularBufferSink, - Reverb, - Reverb3d, - Performance, - ClearMixBuffer, - CopyMixBuffer, - LimiterVersion1, - LimiterVersion2, - GroupedBiquadFilter, - CaptureBuffer, - Compressor - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs deleted file mode 100644 index 34231e61..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.Effect; -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; -using System.Diagnostics; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class CompressorCommand : ICommand - { - private const int FixedPointPrecision = 15; - - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Compressor; - - public uint EstimatedProcessingTime { get; set; } - - public CompressorParameter Parameter => _parameter; - public Memory<CompressorState> State { get; } - public ushort[] OutputBufferIndices { get; } - public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } - - private CompressorParameter _parameter; - - public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId) - { - Enabled = true; - NodeId = nodeId; - _parameter = parameter; - State = state; - - IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - - for (int i = 0; i < _parameter.ChannelCount; i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]); - OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]); - } - } - - public void Process(CommandList context) - { - ref CompressorState state = ref State.Span[0]; - - if (IsEffectEnabled) - { - if (_parameter.Status == Server.Effect.UsageState.Invalid) - { - state = new CompressorState(ref _parameter); - } - else if (_parameter.Status == Server.Effect.UsageState.New) - { - state.UpdateParameter(ref _parameter); - } - } - - ProcessCompressor(context, ref state); - } - - private unsafe void ProcessCompressor(CommandList context, ref CompressorState state) - { - Debug.Assert(_parameter.IsChannelCountValid()); - - if (IsEffectEnabled && _parameter.IsChannelCountValid()) - { - 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; - float unknown4 = state.Unknown4; - ExponentialMovingAverage compressionGainAverage = state.CompressionGainAverage; - float previousCompressionEmaAlpha = state.PreviousCompressionEmaAlpha; - - for (int i = 0; i < _parameter.ChannelCount; i++) - { - inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]); - outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]); - } - - for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++) - { - for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++) - { - channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex); - } - - float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain); - float y = FloatingPointHelper.Log10(newMean) * 10.0f; - float z = 0.0f; - - bool unknown10OutOfRange = false; - - if (newMean < 1.0e-10f) - { - z = 1.0f; - - unknown10OutOfRange = state.Unknown10 < -100.0f; - } - - if (y >= state.Unknown10 || unknown10OutOfRange) - { - float tmpGain; - - if (y >= state.Unknown14) - { - tmpGain = ((1.0f / Parameter.Ratio) - 1.0f) * (y - Parameter.Threshold); - } - else - { - tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction); - } - - z = FloatingPointHelper.DecibelToLinearExtended(tmpGain); - } - - float unknown4New = z; - float compressionEmaAlpha; - - if ((unknown4 - z) <= 0.08f) - { - compressionEmaAlpha = Parameter.ReleaseCoefficient; - - if ((unknown4 - z) >= -0.08f) - { - if (MathF.Abs(compressionGainAverage.Read() - z) >= 0.001f) - { - unknown4New = unknown4; - } - - compressionEmaAlpha = previousCompressionEmaAlpha; - } - } - else - { - compressionEmaAlpha = Parameter.AttackCoefficient; - } - - float compressionGain = compressionGainAverage.Update(z, compressionEmaAlpha); - - for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) - { - *((float*)outputBuffers[channelIndex] + sampleIndex) = channelInput[channelIndex] * compressionGain * state.OutputGain; - } - - unknown4 = unknown4New; - previousCompressionEmaAlpha = compressionEmaAlpha; - } - - state.InputMovingAverage = inputMovingAverage; - state.Unknown4 = unknown4; - state.CompressionGainAverage = compressionGainAverage; - state.PreviousCompressionEmaAlpha = previousCompressionEmaAlpha; - } - else - { - for (int i = 0; i < Parameter.ChannelCount; i++) - { - if (InputBufferIndices[i] != OutputBufferIndices[i]) - { - context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]); - } - } - } - } - } -} diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs deleted file mode 100644 index 7237fddf..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class CopyMixBufferCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.CopyMixBuffer; - - public uint EstimatedProcessingTime { get; set; } - - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } - - public CopyMixBufferCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - InputBufferIndex = (ushort)inputBufferIndex; - OutputBufferIndex = (ushort)outputBufferIndex; - } - - public void Process(CommandList context) - { - context.CopyBuffer(OutputBufferIndex, InputBufferIndex); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs deleted file mode 100644 index c1503b6a..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs +++ /dev/null @@ -1,108 +0,0 @@ -using Ryujinx.Audio.Common; -using Ryujinx.Audio.Renderer.Common; -using System; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class DataSourceVersion2Command : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType { get; } - - public uint EstimatedProcessingTime { get; set; } - - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } - - public float Pitch { get; } - - public WaveBuffer[] WaveBuffers { get; } - - public Memory<VoiceUpdateState> State { get; } - - public ulong ExtraParameter { get; } - public ulong ExtraParameterSize { get; } - - public uint ChannelIndex { get; } - - public uint ChannelCount { get; } - - public DecodingBehaviour DecodingBehaviour { get; } - - public SampleFormat SampleFormat { get; } - - public SampleRateConversionQuality SrcQuality { get; } - - public DataSourceVersion2Command(ref Server.Voice.VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - ChannelIndex = channelIndex; - ChannelCount = serverState.ChannelsCount; - SampleFormat = serverState.SampleFormat; - SrcQuality = serverState.SrcQuality; - CommandType = GetCommandTypeBySampleFormat(SampleFormat); - - OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex); - SampleRate = serverState.SampleRate; - Pitch = serverState.Pitch; - - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; - - for (int i = 0; i < WaveBuffers.Length; i++) - { - ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i]; - - WaveBuffers[i] = voiceWaveBuffer.ToCommon(2); - } - - if (SampleFormat == SampleFormat.Adpcm) - { - ExtraParameter = serverState.DataSourceStateAddressInfo.GetReference(true); - ExtraParameterSize = serverState.DataSourceStateAddressInfo.Size; - } - - State = state; - DecodingBehaviour = serverState.DecodingBehaviour; - } - - private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat) - { - switch (sampleFormat) - { - case SampleFormat.Adpcm: - return CommandType.AdpcmDataSourceVersion2; - case SampleFormat.PcmInt16: - return CommandType.PcmInt16DataSourceVersion2; - case SampleFormat.PcmFloat: - return CommandType.PcmFloatDataSourceVersion2; - default: - throw new NotImplementedException($"{sampleFormat}"); - } - } - - public void Process(CommandList context) - { - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - DataSourceHelper.WaveBufferInformation info = new DataSourceHelper.WaveBufferInformation - { - SourceSampleRate = SampleRate, - SampleFormat = SampleFormat, - Pitch = Pitch, - DecodingBehaviour = DecodingBehaviour, - ExtraParameter = ExtraParameter, - ExtraParameterSize = ExtraParameterSize, - ChannelIndex = (int)ChannelIndex, - ChannelCount = (int)ChannelCount, - SrcQuality = SrcQuality - }; - - DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs deleted file mode 100644 index cb5678c7..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs +++ /dev/null @@ -1,280 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using Ryujinx.Audio.Renderer.Server.Effect; -using Ryujinx.Audio.Renderer.Utils.Math; -using System; -using System.Diagnostics; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class DelayCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Delay; - - public uint EstimatedProcessingTime { get; set; } - - public DelayParameter Parameter => _parameter; - public Memory<DelayState> State { get; } - public ulong WorkBuffer { get; } - public ushort[] OutputBufferIndices { get; } - public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } - - 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) - { - Enabled = true; - NodeId = nodeId; - _parameter = parameter; - State = state; - WorkBuffer = workBuffer; - - IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); - OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); - } - - DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices); - DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private unsafe void ProcessDelayMono(ref DelayState state, float* outputBuffer, float* inputBuffer, uint sampleCount) - { - const ushort channelCount = 1; - - float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision); - float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision); - float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision); - float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision); - - for (int i = 0; i < sampleCount; i++) - { - float input = inputBuffer[i] * 64; - float delayLineValue = state.DelayLines[0].Read(); - - float temp = input * inGain + delayLineValue * feedbackGain; - - state.UpdateLowPassFilter(ref temp, channelCount); - - outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private unsafe void ProcessDelayStereo(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - const ushort channelCount = 2; - - float delayFeedbackBaseGain = state.DelayFeedbackBaseGain; - float delayFeedbackCrossGain = state.DelayFeedbackCrossGain; - float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision); - float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision); - float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision); - - Matrix2x2 delayFeedback = new Matrix2x2(delayFeedbackBaseGain, delayFeedbackCrossGain, - delayFeedbackCrossGain, delayFeedbackBaseGain); - - for (int i = 0; i < sampleCount; i++) - { - Vector2 channelInput = new Vector2 - { - X = *((float*)inputBuffers[0] + i) * 64, - Y = *((float*)inputBuffers[1] + i) * 64, - }; - - Vector2 delayLineValues = new Vector2() - { - X = state.DelayLines[0].Read(), - Y = state.DelayLines[1].Read(), - }; - - Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; - - state.UpdateLowPassFilter(ref Unsafe.As<Vector2, float>(ref temp), channelCount); - - *((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64; - *((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private unsafe void ProcessDelayQuadraphonic(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - const ushort channelCount = 4; - - float delayFeedbackBaseGain = state.DelayFeedbackBaseGain; - float delayFeedbackCrossGain = state.DelayFeedbackCrossGain; - float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision); - float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision); - float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision); - - Matrix4x4 delayFeedback = new Matrix4x4(delayFeedbackBaseGain, delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f, - delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, - delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, - 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain); - - - for (int i = 0; i < sampleCount; i++) - { - Vector4 channelInput = new Vector4 - { - X = *((float*)inputBuffers[0] + i) * 64, - Y = *((float*)inputBuffers[1] + i) * 64, - Z = *((float*)inputBuffers[2] + i) * 64, - W = *((float*)inputBuffers[3] + i) * 64 - }; - - Vector4 delayLineValues = new Vector4() - { - X = state.DelayLines[0].Read(), - Y = state.DelayLines[1].Read(), - Z = state.DelayLines[2].Read(), - W = state.DelayLines[3].Read() - }; - - Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; - - state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), channelCount); - - *((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64; - *((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64; - *((float*)outputBuffers[2] + i) = (channelInput.Z * dryGain + delayLineValues.Z * outGain) / 64; - *((float*)outputBuffers[3] + i) = (channelInput.W * dryGain + delayLineValues.W * outGain) / 64; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private unsafe void ProcessDelaySurround(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - const ushort channelCount = 6; - - float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision); - float delayFeedbackBaseGain = state.DelayFeedbackBaseGain; - float delayFeedbackCrossGain = state.DelayFeedbackCrossGain; - float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision); - float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision); - float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision); - - Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, 0.0f, delayFeedbackCrossGain, 0.0f, - 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackCrossGain, - delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, feedbackGain, 0.0f, 0.0f, - delayFeedbackCrossGain, 0.0f, 0.0f, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, - 0.0f, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackCrossGain, delayFeedbackBaseGain); - - for (int i = 0; i < sampleCount; i++) - { - Vector6 channelInput = new Vector6 - { - X = *((float*)inputBuffers[0] + i) * 64, - Y = *((float*)inputBuffers[1] + i) * 64, - Z = *((float*)inputBuffers[2] + i) * 64, - W = *((float*)inputBuffers[3] + i) * 64, - V = *((float*)inputBuffers[4] + i) * 64, - U = *((float*)inputBuffers[5] + i) * 64 - }; - - Vector6 delayLineValues = new Vector6 - { - X = state.DelayLines[0].Read(), - Y = state.DelayLines[1].Read(), - Z = state.DelayLines[2].Read(), - W = state.DelayLines[3].Read(), - V = state.DelayLines[4].Read(), - U = state.DelayLines[5].Read() - }; - - Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; - - state.UpdateLowPassFilter(ref Unsafe.As<Vector6, float>(ref temp), channelCount); - - *((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64; - *((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64; - *((float*)outputBuffers[2] + i) = (channelInput.Z * dryGain + delayLineValues.Z * outGain) / 64; - *((float*)outputBuffers[3] + i) = (channelInput.W * dryGain + delayLineValues.W * outGain) / 64; - *((float*)outputBuffers[4] + i) = (channelInput.V * dryGain + delayLineValues.V * outGain) / 64; - *((float*)outputBuffers[5] + i) = (channelInput.U * dryGain + delayLineValues.U * outGain) / 64; - } - } - - private unsafe void ProcessDelay(CommandList context, ref DelayState state) - { - Debug.Assert(Parameter.IsChannelCountValid()); - - if (IsEffectEnabled && Parameter.IsChannelCountValid()) - { - Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]); - outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]); - } - - switch (Parameter.ChannelCount) - { - case 1: - ProcessDelayMono(ref state, (float*)outputBuffers[0], (float*)inputBuffers[0], context.SampleCount); - break; - case 2: - ProcessDelayStereo(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 4: - ProcessDelayQuadraphonic(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 6: - ProcessDelaySurround(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - default: - throw new NotImplementedException(Parameter.ChannelCount.ToString()); - } - } - else - { - for (int i = 0; i < Parameter.ChannelCount; i++) - { - if (InputBufferIndices[i] != OutputBufferIndices[i]) - { - context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]); - } - } - } - } - - public void Process(CommandList context) - { - ref DelayState state = ref State.Span[0]; - - if (IsEffectEnabled) - { - if (Parameter.Status == UsageState.Invalid) - { - state = new DelayState(ref _parameter, WorkBuffer); - } - else if (Parameter.Status == UsageState.New) - { - state.UpdateParameter(ref _parameter); - } - } - - ProcessDelay(context, ref state); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs deleted file mode 100644 index 1dba56e6..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class DepopForMixBuffersCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.DepopForMixBuffers; - - public uint EstimatedProcessingTime { get; set; } - - public uint MixBufferOffset { get; } - - public uint MixBufferCount { get; } - - public float Decay { get; } - - public Memory<float> DepopBuffer { get; } - - public DepopForMixBuffersCommand(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate) - { - Enabled = true; - NodeId = nodeId; - MixBufferOffset = bufferOffset; - MixBufferCount = mixBufferCount; - DepopBuffer = depopBuffer; - - if (sampleRate == 48000) - { - Decay = 0.962189f; - } - else // if (sampleRate == 32000) - { - Decay = 0.943695f; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe float ProcessDepopMix(float* buffer, float depopValue, uint sampleCount) - { - if (depopValue < 0) - { - depopValue = -depopValue; - - for (int i = 0; i < sampleCount; i++) - { - depopValue = FloatingPointHelper.MultiplyRoundDown(Decay, depopValue); - - buffer[i] -= depopValue; - } - - return -depopValue; - } - else - { - for (int i = 0; i < sampleCount; i++) - { - depopValue = FloatingPointHelper.MultiplyRoundDown(Decay, depopValue); - - buffer[i] += depopValue; - } - - return depopValue; - } - } - - public void Process(CommandList context) - { - Span<float> depopBuffer = DepopBuffer.Span; - - uint bufferCount = Math.Min(MixBufferOffset + MixBufferCount, context.BufferCount); - - for (int i = (int)MixBufferOffset; i < bufferCount; i++) - { - float depopValue = depopBuffer[i]; - if (depopValue != 0) - { - unsafe - { - float* buffer = (float*)context.GetBufferPointer(i); - - depopBuffer[i] = ProcessDepopMix(buffer, depopValue, context.SampleCount); - } - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs deleted file mode 100644 index d02f7c12..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Ryujinx.Audio.Renderer.Common; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class DepopPrepareCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.DepopPrepare; - - public uint EstimatedProcessingTime { get; set; } - - public uint MixBufferCount { get; } - - public ushort[] OutputBufferIndices { get; } - - public Memory<VoiceUpdateState> State { get; } - public Memory<float> DepopBuffer { get; } - - public DepopPrepareCommand(Memory<VoiceUpdateState> 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); - } - - State = state; - DepopBuffer = depopBuffer; - } - - public void Process(CommandList context) - { - ref VoiceUpdateState state = ref State.Span[0]; - - Span<float> depopBuffer = DepopBuffer.Span; - - for (int i = 0; i < MixBufferCount; i++) - { - if (state.LastSamples[i] != 0) - { - depopBuffer[OutputBufferIndices[i]] += state.LastSamples[i]; - - state.LastSamples[i] = 0; - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs deleted file mode 100644 index 9c88a4e7..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs +++ /dev/null @@ -1,91 +0,0 @@ -using Ryujinx.Audio.Integration; -using Ryujinx.Audio.Renderer.Server.Sink; -using System; -using System.Runtime.CompilerServices; -using System.Text; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class DeviceSinkCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.DeviceSink; - - public uint EstimatedProcessingTime { get; set; } - - public string DeviceName { get; } - - public int SessionId { get; } - - public uint InputCount { get; } - public ushort[] InputBufferIndices { get; } - - public Memory<float> Buffers { get; } - - public DeviceSinkCommand(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - DeviceName = Encoding.ASCII.GetString(sink.Parameter.DeviceName).TrimEnd('\0'); - SessionId = sessionId; - InputCount = sink.Parameter.InputCount; - InputBufferIndices = new ushort[InputCount]; - - for (int i = 0; i < Math.Min(InputCount, Constants.ChannelCountMax); i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + sink.Parameter.Input[i]); - } - - if (sink.UpsamplerState != null) - { - Buffers = sink.UpsamplerState.OutputBuffer; - } - else - { - Buffers = buffers; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Span<float> GetBuffer(int index, int sampleCount) - { - return Buffers.Span.Slice(index * sampleCount, sampleCount); - } - - public void Process(CommandList context) - { - IHardwareDevice device = context.OutputDevice; - - if (device.GetSampleRate() == Constants.TargetSampleRate) - { - int channelCount = (int)device.GetChannelCount(); - uint bufferCount = Math.Min(device.GetChannelCount(), InputCount); - - const int sampleCount = Constants.TargetSampleCount; - - short[] outputBuffer = new short[bufferCount * sampleCount]; - - for (int i = 0; i < bufferCount; i++) - { - ReadOnlySpan<float> inputBuffer = GetBuffer(InputBufferIndices[i], sampleCount); - - for (int j = 0; j < sampleCount; j++) - { - outputBuffer[i + j * channelCount] = PcmHelper.Saturate(inputBuffer[j]); - } - } - - device.AppendBuffer(outputBuffer, InputCount); - } - else - { - // TODO: support resampling for device only supporting something different - throw new NotImplementedException(); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs deleted file mode 100644 index 79cefcc5..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class DownMixSurroundToStereoCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.DownMixSurroundToStereo; - - public uint EstimatedProcessingTime { get; set; } - - public ushort[] InputBufferIndices { get; } - public ushort[] OutputBufferIndices { get; } - - public float[] Coefficients { get; } - - public DownMixSurroundToStereoCommand(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]); - OutputBufferIndices[i] = (ushort)(bufferOffset + outputBufferOffset[i]); - } - - Coefficients = downMixParameter; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float DownMixSurroundToStereo(ReadOnlySpan<float> coefficients, float back, float lfe, float center, float front) - { - return FloatingPointHelper.RoundUp(coefficients[3] * back + coefficients[2] * lfe + coefficients[1] * center + coefficients[0] * front); - } - - public void Process(CommandList context) - { - ReadOnlySpan<float> frontLeft = context.GetBuffer(InputBufferIndices[0]); - ReadOnlySpan<float> frontRight = context.GetBuffer(InputBufferIndices[1]); - ReadOnlySpan<float> frontCenter = context.GetBuffer(InputBufferIndices[2]); - ReadOnlySpan<float> lowFrequency = context.GetBuffer(InputBufferIndices[3]); - ReadOnlySpan<float> backLeft = context.GetBuffer(InputBufferIndices[4]); - ReadOnlySpan<float> backRight = context.GetBuffer(InputBufferIndices[5]); - - Span<float> stereoLeft = context.GetBuffer(OutputBufferIndices[0]); - Span<float> stereoRight = context.GetBuffer(OutputBufferIndices[1]); - - for (int i = 0; i < context.SampleCount; i++) - { - stereoLeft[i] = DownMixSurroundToStereo(Coefficients, backLeft[i], lowFrequency[i], frontCenter[i], frontLeft[i]); - stereoRight[i] = DownMixSurroundToStereo(Coefficients, backRight[i], lowFrequency[i], frontCenter[i], frontRight[i]); - } - - context.ClearBuffer(OutputBufferIndices[2]); - context.ClearBuffer(OutputBufferIndices[3]); - context.ClearBuffer(OutputBufferIndices[4]); - context.ClearBuffer(OutputBufferIndices[5]); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs deleted file mode 100644 index b190cc10..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class GroupedBiquadFilterCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.GroupedBiquadFilter; - - public uint EstimatedProcessingTime { get; set; } - - private BiquadFilterParameter[] _parameters; - private Memory<BiquadFilterState> _biquadFilterStates; - private int _inputBufferIndex; - private int _outputBufferIndex; - private bool[] _isInitialized; - - public GroupedBiquadFilterCommand(int baseIndex, ReadOnlySpan<BiquadFilterParameter> 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; - } - - public void Process(CommandList context) - { - Span<BiquadFilterState> states = _biquadFilterStates.Span; - - ReadOnlySpan<float> inputBuffer = context.GetBuffer(_inputBufferIndex); - Span<float> outputBuffer = context.GetBuffer(_outputBufferIndex); - - for (int i = 0; i < _parameters.Length; i++) - { - if (!_isInitialized[i]) - { - states[i] = new BiquadFilterState(); - } - } - - // 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) - { - BiquadFilterHelper.ProcessBiquadFilter(ref _parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount); - } - else - { - BiquadFilterHelper.ProcessBiquadFilter(_parameters, states, outputBuffer, inputBuffer, context.SampleCount); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs deleted file mode 100644 index d281e6e9..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public interface ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType { get; } - - public uint EstimatedProcessingTime { get; } - - public void Process(CommandList context); - - public bool ShouldMeter() - { - return false; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs deleted file mode 100644 index a464ad70..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs +++ /dev/null @@ -1,144 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; -using System.Diagnostics; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class LimiterCommandVersion1 : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.LimiterVersion1; - - public uint EstimatedProcessingTime { get; set; } - - public LimiterParameter Parameter => _parameter; - public Memory<LimiterState> State { get; } - public ulong WorkBuffer { get; } - public ushort[] OutputBufferIndices { get; } - public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } - - private LimiterParameter _parameter; - - public LimiterCommandVersion1(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId) - { - Enabled = true; - NodeId = nodeId; - _parameter = parameter; - State = state; - WorkBuffer = workBuffer; - - IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); - OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); - } - } - - public void Process(CommandList context) - { - ref LimiterState state = ref State.Span[0]; - - if (IsEffectEnabled) - { - if (Parameter.Status == Server.Effect.UsageState.Invalid) - { - state = new LimiterState(ref _parameter, WorkBuffer); - } - else if (Parameter.Status == Server.Effect.UsageState.New) - { - state.UpdateParameter(ref _parameter); - } - } - - ProcessLimiter(context, ref state); - } - - private unsafe void ProcessLimiter(CommandList context, ref LimiterState state) - { - Debug.Assert(Parameter.IsChannelCountValid()); - - if (IsEffectEnabled && Parameter.IsChannelCountValid()) - { - Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]); - outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]); - } - - for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) - { - for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++) - { - float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex); - - float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain; - - float sampleInputMax = Math.Abs(inputSample); - - float inputCoefficient = Parameter.ReleaseCoefficient; - - if (sampleInputMax > state.DetectorAverage[channelIndex].Read()) - { - inputCoefficient = Parameter.AttackCoefficient; - } - - float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient); - float attenuation = 1.0f; - - if (detectorValue > Parameter.Threshold) - { - attenuation = Parameter.Threshold / detectorValue; - } - - float outputCoefficient = Parameter.ReleaseCoefficient; - - if (state.CompressionGainAverage[channelIndex].Read() > attenuation) - { - outputCoefficient = Parameter.AttackCoefficient; - } - - float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient); - - ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]]; - - float outputSample = delayedSample * compressionGain * Parameter.OutputGain; - - *((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue; - - delayedSample = inputSample; - - state.DelayedSampleBufferPosition[channelIndex]++; - - while (state.DelayedSampleBufferPosition[channelIndex] >= Parameter.DelayBufferSampleCountMin) - { - state.DelayedSampleBufferPosition[channelIndex] -= Parameter.DelayBufferSampleCountMin; - } - } - } - } - else - { - for (int i = 0; i < Parameter.ChannelCount; i++) - { - if (InputBufferIndices[i] != OutputBufferIndices[i]) - { - context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]); - } - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs deleted file mode 100644 index 950de97b..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs +++ /dev/null @@ -1,163 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class LimiterCommandVersion2 : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - 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 ushort[] OutputBufferIndices { get; } - public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } - - private LimiterParameter _parameter; - - public LimiterCommandVersion2(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, Memory<EffectResultState> resultState, bool isEnabled, ulong workBuffer, int nodeId) - { - Enabled = true; - NodeId = nodeId; - _parameter = parameter; - State = state; - ResultState = resultState; - WorkBuffer = workBuffer; - - IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); - OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); - } - } - - public void Process(CommandList context) - { - ref LimiterState state = ref State.Span[0]; - - if (IsEffectEnabled) - { - if (Parameter.Status == Server.Effect.UsageState.Invalid) - { - state = new LimiterState(ref _parameter, WorkBuffer); - } - else if (Parameter.Status == Server.Effect.UsageState.New) - { - state.UpdateParameter(ref _parameter); - } - } - - ProcessLimiter(context, ref state); - } - - private unsafe void ProcessLimiter(CommandList context, ref LimiterState state) - { - Debug.Assert(Parameter.IsChannelCountValid()); - - if (IsEffectEnabled && Parameter.IsChannelCountValid()) - { - if (!ResultState.IsEmpty && Parameter.StatisticsReset) - { - ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0]; - - statistics.Reset(); - } - - Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]); - outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]); - } - - for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) - { - for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++) - { - float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex); - - float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain; - - float sampleInputMax = Math.Abs(inputSample); - - float inputCoefficient = Parameter.ReleaseCoefficient; - - if (sampleInputMax > state.DetectorAverage[channelIndex].Read()) - { - inputCoefficient = Parameter.AttackCoefficient; - } - - float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient); - float attenuation = 1.0f; - - if (detectorValue > Parameter.Threshold) - { - attenuation = Parameter.Threshold / detectorValue; - } - - float outputCoefficient = Parameter.ReleaseCoefficient; - - if (state.CompressionGainAverage[channelIndex].Read() > attenuation) - { - outputCoefficient = Parameter.AttackCoefficient; - } - - float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient); - - ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]]; - - float outputSample = delayedSample * compressionGain * Parameter.OutputGain; - - *((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue; - - delayedSample = inputSample; - - state.DelayedSampleBufferPosition[channelIndex]++; - - while (state.DelayedSampleBufferPosition[channelIndex] >= Parameter.DelayBufferSampleCountMin) - { - state.DelayedSampleBufferPosition[channelIndex] -= Parameter.DelayBufferSampleCountMin; - } - - if (!ResultState.IsEmpty) - { - ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0]; - - statistics.InputMax[channelIndex] = Math.Max(statistics.InputMax[channelIndex], sampleInputMax); - statistics.CompressionGainMin[channelIndex] = Math.Min(statistics.CompressionGainMin[channelIndex], compressionGain); - } - } - } - } - else - { - for (int i = 0; i < Parameter.ChannelCount; i++) - { - if (InputBufferIndices[i] != OutputBufferIndices[i]) - { - context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]); - } - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs deleted file mode 100644 index 2616bda5..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; -using System.Runtime.Intrinsics.X86; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class MixCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Mix; - - public uint EstimatedProcessingTime { get; set; } - - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } - - public float Volume { get; } - - public MixCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume) - { - Enabled = true; - NodeId = nodeId; - - InputBufferIndex = (ushort)inputBufferIndex; - OutputBufferIndex = (ushort)outputBufferIndex; - - Volume = volume; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessMixAvx(Span<float> outputMix, ReadOnlySpan<float> inputMix) - { - Vector256<float> volumeVec = Vector256.Create(Volume); - - ReadOnlySpan<Vector256<float>> inputVec = MemoryMarshal.Cast<float, Vector256<float>>(inputMix); - Span<Vector256<float>> outputVec = MemoryMarshal.Cast<float, Vector256<float>>(outputMix); - - int sisdStart = inputVec.Length * 8; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Avx.Add(outputVec[i], Avx.Ceiling(Avx.Multiply(inputVec[i], volumeVec))); - } - - for (int i = sisdStart; i < inputMix.Length; i++) - { - outputMix[i] += FloatingPointHelper.MultiplyRoundUp(inputMix[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessMixSse41(Span<float> outputMix, ReadOnlySpan<float> inputMix) - { - Vector128<float> volumeVec = Vector128.Create(Volume); - - ReadOnlySpan<Vector128<float>> inputVec = MemoryMarshal.Cast<float, Vector128<float>>(inputMix); - Span<Vector128<float>> outputVec = MemoryMarshal.Cast<float, Vector128<float>>(outputMix); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Sse.Add(outputVec[i], Sse41.Ceiling(Sse.Multiply(inputVec[i], volumeVec))); - } - - for (int i = sisdStart; i < inputMix.Length; i++) - { - outputMix[i] += FloatingPointHelper.MultiplyRoundUp(inputMix[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessMixAdvSimd(Span<float> outputMix, ReadOnlySpan<float> inputMix) - { - Vector128<float> volumeVec = Vector128.Create(Volume); - - ReadOnlySpan<Vector128<float>> inputVec = MemoryMarshal.Cast<float, Vector128<float>>(inputMix); - Span<Vector128<float>> outputVec = MemoryMarshal.Cast<float, Vector128<float>>(outputMix); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = AdvSimd.Add(outputVec[i], AdvSimd.Ceiling(AdvSimd.Multiply(inputVec[i], volumeVec))); - } - - for (int i = sisdStart; i < inputMix.Length; i++) - { - outputMix[i] += FloatingPointHelper.MultiplyRoundUp(inputMix[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessMixSlowPath(Span<float> outputMix, ReadOnlySpan<float> inputMix) - { - for (int i = 0; i < inputMix.Length; i++) - { - outputMix[i] += FloatingPointHelper.MultiplyRoundUp(inputMix[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessMix(Span<float> outputMix, ReadOnlySpan<float> inputMix) - { - if (Avx.IsSupported) - { - ProcessMixAvx(outputMix, inputMix); - } - else if (Sse41.IsSupported) - { - ProcessMixSse41(outputMix, inputMix); - } - else if (AdvSimd.IsSupported) - { - ProcessMixAdvSimd(outputMix, inputMix); - } - else - { - ProcessMixSlowPath(outputMix, inputMix); - } - } - - public void Process(CommandList context) - { - ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - ProcessMix(outputBuffer, inputBuffer); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs deleted file mode 100644 index 76a1aba2..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Ryujinx.Audio.Renderer.Common; -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class MixRampCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.MixRamp; - - public uint EstimatedProcessingTime { get; set; } - - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } - - public float Volume0 { get; } - public float Volume1 { get; } - - public Memory<VoiceUpdateState> State { get; } - - public int LastSampleIndex { get; } - - public MixRampCommand(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceUpdateState> state, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - InputBufferIndex = (ushort)inputBufferIndex; - OutputBufferIndex = (ushort)outputBufferIndex; - - Volume0 = volume0; - Volume1 = volume1; - - State = state; - LastSampleIndex = lastSampleIndex; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float ProcessMixRamp(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, int sampleCount) - { - float ramp = (Volume1 - Volume0) / sampleCount; - float volume = Volume0; - float state = 0; - - for (int i = 0; i < sampleCount; i++) - { - state = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], volume); - - outputBuffer[i] += state; - volume += ramp; - } - - return state; - } - - public void Process(CommandList context) - { - ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - State.Span[0].LastSamples[LastSampleIndex] = ProcessMixRamp(outputBuffer, inputBuffer, (int)context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs deleted file mode 100644 index e348e358..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs +++ /dev/null @@ -1,91 +0,0 @@ -using Ryujinx.Audio.Renderer.Common; -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class MixRampGroupedCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.MixRampGrouped; - - public uint EstimatedProcessingTime { get; set; } - - public uint MixBufferCount { get; } - - public ushort[] InputBufferIndices { get; } - public ushort[] OutputBufferIndices { get; } - - public float[] Volume0 { get; } - public float[] Volume1 { get; } - - public Memory<VoiceUpdateState> State { get; } - - public MixRampGroupedCommand(uint mixBufferCount, uint inputBufferIndex, uint outputBufferIndex, Span<float> volume0, Span<float> volume1, Memory<VoiceUpdateState> state, int nodeId) - { - Enabled = true; - MixBufferCount = mixBufferCount; - NodeId = nodeId; - - InputBufferIndices = new ushort[Constants.MixBufferCountMax]; - OutputBufferIndices = new ushort[Constants.MixBufferCountMax]; - Volume0 = new float[Constants.MixBufferCountMax]; - Volume1 = new float[Constants.MixBufferCountMax]; - - for (int i = 0; i < mixBufferCount; i++) - { - InputBufferIndices[i] = (ushort)inputBufferIndex; - OutputBufferIndices[i] = (ushort)(outputBufferIndex + i); - - Volume0[i] = volume0[i]; - Volume1[i] = volume1[i]; - } - - State = state; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float ProcessMixRampGrouped(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float volume0, float volume1, int sampleCount) - { - float ramp = (volume1 - volume0) / sampleCount; - float volume = volume0; - float state = 0; - - for (int i = 0; i < sampleCount; i++) - { - state = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], volume); - - outputBuffer[i] += state; - volume += ramp; - } - - return state; - } - - public void Process(CommandList context) - { - for (int i = 0; i < MixBufferCount; i++) - { - ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndices[i]); - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndices[i]); - - float volume0 = Volume0[i]; - float volume1 = Volume1[i]; - - ref VoiceUpdateState state = ref State.Span[0]; - - if (volume0 != 0 || volume1 != 0) - { - state.LastSamples[i] = ProcessMixRampGrouped(outputBuffer, inputBuffer, volume0, volume1, (int)context.SampleCount); - } - else - { - state.LastSamples[i] = 0; - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs deleted file mode 100644 index 7cec7d2a..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Ryujinx.Audio.Common; -using Ryujinx.Audio.Renderer.Common; -using System; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class PcmFloatDataSourceCommandVersion1 : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1; - - public uint EstimatedProcessingTime { get; set; } - - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } - public uint ChannelIndex { get; } - - public uint ChannelCount { get; } - - public float Pitch { get; } - - public WaveBuffer[] WaveBuffers { get; } - - public Memory<VoiceUpdateState> State { get; } - public DecodingBehaviour DecodingBehaviour { get; } - - public PcmFloatDataSourceCommandVersion1(ref Server.Voice.VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex); - SampleRate = serverState.SampleRate; - ChannelIndex = channelIndex; - ChannelCount = serverState.ChannelsCount; - Pitch = serverState.Pitch; - - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; - - for (int i = 0; i < WaveBuffers.Length; i++) - { - ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i]; - - WaveBuffers[i] = voiceWaveBuffer.ToCommon(1); - } - - State = state; - DecodingBehaviour = serverState.DecodingBehaviour; - } - - public void Process(CommandList context) - { - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - DataSourceHelper.WaveBufferInformation info = new DataSourceHelper.WaveBufferInformation - { - SourceSampleRate = SampleRate, - SampleFormat = SampleFormat.PcmFloat, - Pitch = Pitch, - DecodingBehaviour = DecodingBehaviour, - ExtraParameter = 0, - ExtraParameterSize = 0, - ChannelIndex = (int)ChannelIndex, - ChannelCount = (int)ChannelCount, - }; - - DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs deleted file mode 100644 index dfe9814f..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Ryujinx.Audio.Common; -using Ryujinx.Audio.Renderer.Common; -using System; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class PcmInt16DataSourceCommandVersion1 : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1; - - public uint EstimatedProcessingTime { get; set; } - - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } - public uint ChannelIndex { get; } - - public uint ChannelCount { get; } - - public float Pitch { get; } - - public WaveBuffer[] WaveBuffers { get; } - - public Memory<VoiceUpdateState> State { get; } - public DecodingBehaviour DecodingBehaviour { get; } - - public PcmInt16DataSourceCommandVersion1(ref Server.Voice.VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex); - SampleRate = serverState.SampleRate; - ChannelIndex = channelIndex; - ChannelCount = serverState.ChannelsCount; - Pitch = serverState.Pitch; - - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; - - for (int i = 0; i < WaveBuffers.Length; i++) - { - ref Server.Voice.WaveBuffer voiceWaveBuffer = ref serverState.WaveBuffers[i]; - - WaveBuffers[i] = voiceWaveBuffer.ToCommon(1); - } - - State = state; - DecodingBehaviour = serverState.DecodingBehaviour; - } - - public void Process(CommandList context) - { - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - DataSourceHelper.WaveBufferInformation info = new DataSourceHelper.WaveBufferInformation - { - SourceSampleRate = SampleRate, - SampleFormat = SampleFormat.PcmInt16, - Pitch = Pitch, - DecodingBehaviour = DecodingBehaviour, - ExtraParameter = 0, - ExtraParameterSize = 0, - ChannelIndex = (int)ChannelIndex, - ChannelCount = (int)ChannelCount, - }; - - DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs deleted file mode 100644 index d3e3f805..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Ryujinx.Audio.Renderer.Server.Performance; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class PerformanceCommand : ICommand - { - public enum Type - { - Invalid, - Start, - End - } - - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Performance; - - public uint EstimatedProcessingTime { get; set; } - - public PerformanceEntryAddresses PerformanceEntryAddresses { get; } - - public Type PerformanceType { get; set; } - - public PerformanceCommand(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId) - { - Enabled = true; - PerformanceEntryAddresses = performanceEntryAddresses; - PerformanceType = performanceType; - NodeId = nodeId; - } - - public void Process(CommandList context) - { - if (PerformanceType == Type.Start) - { - PerformanceEntryAddresses.SetStartTime(context.GetTimeElapsedSinceDspStartedProcessing()); - } - else if (PerformanceType == Type.End) - { - PerformanceEntryAddresses.SetProcessingTime(context.GetTimeElapsedSinceDspStartedProcessing()); - PerformanceEntryAddresses.IncrementEntryCount(); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs deleted file mode 100644 index eeb64567..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs +++ /dev/null @@ -1,254 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using Ryujinx.Audio.Renderer.Server.Effect; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class Reverb3dCommand : ICommand - { - private static readonly int[] OutputEarlyIndicesTableMono = new int[20] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableMono = new int[20] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; - private static readonly int[] TargetOutputFeedbackIndicesTableMono = new int[1] { 0 }; - - private static readonly int[] OutputEarlyIndicesTableStereo = new int[20] { 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableStereo = new int[20] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; - private static readonly int[] TargetOutputFeedbackIndicesTableStereo = new int[2] { 0, 1 }; - - private static readonly int[] OutputEarlyIndicesTableQuadraphonic = new int[20] { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableQuadraphonic = new int[20] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; - private static readonly int[] TargetOutputFeedbackIndicesTableQuadraphonic = new int[4] { 0, 1, 2, 3 }; - - private static readonly int[] OutputEarlyIndicesTableSurround = new int[40] { 4, 5, 0, 5, 0, 5, 1, 5, 1, 5, 1, 5, 1, 5, 2, 5, 2, 5, 2, 5, 1, 5, 1, 5, 1, 5, 0, 5, 0, 5, 0, 5, 0, 5, 3, 5, 3, 5, 3, 5 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableSurround = new int[40] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19 }; - private static readonly int[] TargetOutputFeedbackIndicesTableSurround = new int[6] { 0, 1, 2, 3, -1, 3 }; - - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Reverb3d; - - public uint EstimatedProcessingTime { get; set; } - - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } - - public Reverb3dParameter Parameter => _parameter; - public Memory<Reverb3dState> State { get; } - public ulong WorkBuffer { get; } - public ushort[] OutputBufferIndices { get; } - public ushort[] InputBufferIndices { get; } - - public bool IsEffectEnabled { get; } - - private Reverb3dParameter _parameter; - - public Reverb3dCommand(uint bufferOffset, Reverb3dParameter parameter, Memory<Reverb3dState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) - { - Enabled = true; - IsEffectEnabled = isEnabled; - NodeId = nodeId; - _parameter = parameter; - State = state; - WorkBuffer = workBuffer; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); - OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); - } - - // NOTE: We do the opposite as Nintendo here for now to restore previous behaviour - // TODO: Update reverb 3d processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. - DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices); - DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverb3dMono(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverb3dGeneric(ref state, outputBuffers, inputBuffers, sampleCount, OutputEarlyIndicesTableMono, TargetEarlyDelayLineIndicesTableMono, TargetOutputFeedbackIndicesTableMono); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverb3dStereo(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverb3dGeneric(ref state, outputBuffers, inputBuffers, sampleCount, OutputEarlyIndicesTableStereo, TargetEarlyDelayLineIndicesTableStereo, TargetOutputFeedbackIndicesTableStereo); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverb3dQuadraphonic(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverb3dGeneric(ref state, outputBuffers, inputBuffers, sampleCount, OutputEarlyIndicesTableQuadraphonic, TargetEarlyDelayLineIndicesTableQuadraphonic, TargetOutputFeedbackIndicesTableQuadraphonic); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverb3dSurround(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverb3dGeneric(ref state, outputBuffers, inputBuffers, sampleCount, OutputEarlyIndicesTableSurround, TargetEarlyDelayLineIndicesTableSurround, TargetOutputFeedbackIndicesTableSurround); - } - - private unsafe void ProcessReverb3dGeneric(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan<int> outputEarlyIndicesTable, ReadOnlySpan<int> targetEarlyDelayLineIndicesTable, ReadOnlySpan<int> targetOutputFeedbackIndicesTable) - { - const int delayLineSampleIndexOffset = 1; - - bool isMono = Parameter.ChannelCount == 1; - bool isSurround = Parameter.ChannelCount == 6; - - Span<float> outputValues = stackalloc float[Constants.ChannelCountMax]; - Span<float> channelInput = stackalloc float[Parameter.ChannelCount]; - Span<float> feedbackValues = stackalloc float[4]; - Span<float> feedbackOutputValues = stackalloc float[4]; - Span<float> values = stackalloc float[4]; - - for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) - { - outputValues.Fill(0); - - float tapOut = state.PreDelayLine.TapUnsafe(state.ReflectionDelayTime, delayLineSampleIndexOffset); - - for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++) - { - int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i]; - int outputIndex = outputEarlyIndicesTable[i]; - - float tempTapOut = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], delayLineSampleIndexOffset); - - outputValues[outputIndex] += tempTapOut * state.EarlyGain[earlyDelayIndex]; - } - - float targetPreDelayValue = 0; - - for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) - { - channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex); - targetPreDelayValue += channelInput[channelIndex]; - } - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - outputValues[i] *= state.EarlyReflectionsGain; - } - - state.PreviousPreDelayValue = (targetPreDelayValue * state.TargetPreDelayGain) + (state.PreviousPreDelayValue * state.PreviousPreDelayGain); - - state.PreDelayLine.Update(state.PreviousPreDelayValue); - - for (int i = 0; i < state.FdnDelayLines.Length; i++) - { - float fdnValue = state.FdnDelayLines[i].Read(); - - float feedbackOutputValue = fdnValue * state.DecayDirectFdnGain[i] + state.PreviousFeedbackOutputDecayed[i]; - - state.PreviousFeedbackOutputDecayed[i] = (fdnValue * state.DecayCurrentFdnGain[i]) + (feedbackOutputValue * state.DecayCurrentOutputGain[i]); - - feedbackOutputValues[i] = feedbackOutputValue; - } - - feedbackValues[0] = feedbackOutputValues[2] + feedbackOutputValues[1]; - feedbackValues[1] = -feedbackOutputValues[0] - feedbackOutputValues[3]; - feedbackValues[2] = feedbackOutputValues[0] - feedbackOutputValues[3]; - feedbackValues[3] = feedbackOutputValues[1] - feedbackOutputValues[2]; - - for (int i = 0; i < state.DecayDelays1.Length; i++) - { - float temp = state.DecayDelays1[i].Update(tapOut * state.LateReverbGain + feedbackValues[i]); - - values[i] = state.DecayDelays2[i].Update(temp); - - state.FdnDelayLines[i].Update(values[i]); - } - - for (int channelIndex = 0; channelIndex < targetOutputFeedbackIndicesTable.Length; channelIndex++) - { - int targetOutputFeedbackIndex = targetOutputFeedbackIndicesTable[channelIndex]; - - if (targetOutputFeedbackIndex >= 0) - { - *((float*)outputBuffers[channelIndex] + sampleIndex) = (outputValues[channelIndex] + values[targetOutputFeedbackIndex] + channelInput[channelIndex] * state.DryGain); - } - } - - if (isMono) - { - *((float*)outputBuffers[0] + sampleIndex) += values[1]; - } - - if (isSurround) - { - *((float*)outputBuffers[4] + sampleIndex) += (outputValues[4] + state.FrontCenterDelayLine.Update((values[2] - values[3]) * 0.5f) + channelInput[4] * state.DryGain); - } - } - } - - public void ProcessReverb3d(CommandList context, ref Reverb3dState state) - { - Debug.Assert(Parameter.IsChannelCountValid()); - - if (IsEffectEnabled && Parameter.IsChannelCountValid()) - { - Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]); - outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]); - } - - switch (Parameter.ChannelCount) - { - case 1: - ProcessReverb3dMono(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 2: - ProcessReverb3dStereo(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 4: - ProcessReverb3dQuadraphonic(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 6: - ProcessReverb3dSurround(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - default: - throw new NotImplementedException(Parameter.ChannelCount.ToString()); - } - } - else - { - for (int i = 0; i < Parameter.ChannelCount; i++) - { - if (InputBufferIndices[i] != OutputBufferIndices[i]) - { - context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]); - } - } - } - } - - public void Process(CommandList context) - { - ref Reverb3dState state = ref State.Span[0]; - - if (IsEffectEnabled) - { - if (Parameter.ParameterStatus == UsageState.Invalid) - { - state = new Reverb3dState(ref _parameter, WorkBuffer); - } - else if (Parameter.ParameterStatus == UsageState.New) - { - state.UpdateParameter(ref _parameter); - } - } - - ProcessReverb3d(context, ref state); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs deleted file mode 100644 index 0a32a065..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs +++ /dev/null @@ -1,279 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class ReverbCommand : ICommand - { - private static readonly int[] OutputEarlyIndicesTableMono = new int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableMono = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - private static readonly int[] OutputIndicesTableMono = new int[4] { 0, 0, 0, 0 }; - private static readonly int[] TargetOutputFeedbackIndicesTableMono = new int[4] { 0, 1, 2, 3 }; - - private static readonly int[] OutputEarlyIndicesTableStereo = new int[10] { 0, 0, 1, 1, 0, 1, 0, 0, 1, 1 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableStereo = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - private static readonly int[] OutputIndicesTableStereo = new int[4] { 0, 0, 1, 1 }; - private static readonly int[] TargetOutputFeedbackIndicesTableStereo = new int[4] { 2, 0, 3, 1 }; - - private static readonly int[] OutputEarlyIndicesTableQuadraphonic = new int[10] { 0, 0, 1, 1, 0, 1, 2, 2, 3, 3 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableQuadraphonic = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - private static readonly int[] OutputIndicesTableQuadraphonic = new int[4] { 0, 1, 2, 3 }; - private static readonly int[] TargetOutputFeedbackIndicesTableQuadraphonic = new int[4] { 0, 1, 2, 3 }; - - private static readonly int[] OutputEarlyIndicesTableSurround = new int[20] { 0, 5, 0, 5, 1, 5, 1, 5, 4, 5, 4, 5, 2, 5, 2, 5, 3, 5, 3, 5 }; - private static readonly int[] TargetEarlyDelayLineIndicesTableSurround = new int[20] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 }; - private static readonly int[] OutputIndicesTableSurround = new int[Constants.ChannelCountMax] { 0, 1, 2, 3, 4, 5 }; - private static readonly int[] TargetOutputFeedbackIndicesTableSurround = new int[Constants.ChannelCountMax] { 0, 1, 2, 3, -1, 3 }; - - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Reverb; - - public uint EstimatedProcessingTime { get; set; } - - public ReverbParameter Parameter => _parameter; - public Memory<ReverbState> State { get; } - public ulong WorkBuffer { get; } - public ushort[] OutputBufferIndices { get; } - public ushort[] InputBufferIndices { get; } - public bool IsLongSizePreDelaySupported { get; } - - public bool IsEffectEnabled { get; } - - 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) - { - Enabled = true; - IsEffectEnabled = isEnabled; - NodeId = nodeId; - _parameter = parameter; - State = state; - WorkBuffer = workBuffer; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - InputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Input[i]); - OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); - } - - IsLongSizePreDelaySupported = isLongSizePreDelaySupported; - - // NOTE: We do the opposite as Nintendo here for now to restore previous behaviour - // TODO: Update reverb processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. - DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices); - DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverbMono(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverbGeneric(ref state, - outputBuffers, - inputBuffers, - sampleCount, - OutputEarlyIndicesTableMono, - TargetEarlyDelayLineIndicesTableMono, - TargetOutputFeedbackIndicesTableMono, - OutputIndicesTableMono); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverbStereo(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverbGeneric(ref state, - outputBuffers, - inputBuffers, - sampleCount, - OutputEarlyIndicesTableStereo, - TargetEarlyDelayLineIndicesTableStereo, - TargetOutputFeedbackIndicesTableStereo, - OutputIndicesTableStereo); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverbQuadraphonic(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverbGeneric(ref state, - outputBuffers, - inputBuffers, - sampleCount, - OutputEarlyIndicesTableQuadraphonic, - TargetEarlyDelayLineIndicesTableQuadraphonic, - TargetOutputFeedbackIndicesTableQuadraphonic, - OutputIndicesTableQuadraphonic); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessReverbSurround(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) - { - ProcessReverbGeneric(ref state, - outputBuffers, - inputBuffers, - sampleCount, - OutputEarlyIndicesTableSurround, - TargetEarlyDelayLineIndicesTableSurround, - TargetOutputFeedbackIndicesTableSurround, - OutputIndicesTableSurround); - } - - private unsafe void ProcessReverbGeneric(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan<int> outputEarlyIndicesTable, ReadOnlySpan<int> targetEarlyDelayLineIndicesTable, ReadOnlySpan<int> targetOutputFeedbackIndicesTable, ReadOnlySpan<int> outputIndicesTable) - { - bool isSurround = Parameter.ChannelCount == 6; - - float reverbGain = FixedPointHelper.ToFloat(Parameter.ReverbGain, FixedPointPrecision); - float lateGain = FixedPointHelper.ToFloat(Parameter.LateGain, FixedPointPrecision); - float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision); - float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision); - - Span<float> outputValues = stackalloc float[Constants.ChannelCountMax]; - Span<float> feedbackValues = stackalloc float[4]; - Span<float> feedbackOutputValues = stackalloc float[4]; - Span<float> channelInput = stackalloc float[Parameter.ChannelCount]; - - for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) - { - outputValues.Fill(0); - - for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++) - { - int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i]; - int outputIndex = outputEarlyIndicesTable[i]; - - float tapOutput = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], 0); - - outputValues[outputIndex] += tapOutput * state.EarlyGain[earlyDelayIndex]; - } - - if (isSurround) - { - outputValues[5] *= 0.2f; - } - - float targetPreDelayValue = 0; - - for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) - { - channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex) * 64; - targetPreDelayValue += channelInput[channelIndex] * reverbGain; - } - - state.PreDelayLine.Update(targetPreDelayValue); - - float lateValue = state.PreDelayLine.Tap(state.PreDelayLineDelayTime) * lateGain; - - for (int i = 0; i < state.FdnDelayLines.Length; i++) - { - feedbackOutputValues[i] = state.FdnDelayLines[i].Read() * state.HighFrequencyDecayDirectGain[i] + state.PreviousFeedbackOutput[i] * state.HighFrequencyDecayPreviousGain[i]; - state.PreviousFeedbackOutput[i] = feedbackOutputValues[i]; - } - - feedbackValues[0] = feedbackOutputValues[2] + feedbackOutputValues[1]; - feedbackValues[1] = -feedbackOutputValues[0] - feedbackOutputValues[3]; - feedbackValues[2] = feedbackOutputValues[0] - feedbackOutputValues[3]; - feedbackValues[3] = feedbackOutputValues[1] - feedbackOutputValues[2]; - - for (int i = 0; i < state.FdnDelayLines.Length; i++) - { - feedbackOutputValues[i] = state.DecayDelays[i].Update(feedbackValues[i] + lateValue); - state.FdnDelayLines[i].Update(feedbackOutputValues[i]); - } - - for (int i = 0; i < targetOutputFeedbackIndicesTable.Length; i++) - { - int targetOutputFeedbackIndex = targetOutputFeedbackIndicesTable[i]; - int outputIndex = outputIndicesTable[i]; - - if (targetOutputFeedbackIndex >= 0) - { - outputValues[outputIndex] += feedbackOutputValues[targetOutputFeedbackIndex]; - } - } - - if (isSurround) - { - outputValues[4] += state.FrontCenterDelayLine.Update((feedbackOutputValues[2] - feedbackOutputValues[3]) * 0.5f); - } - - for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++) - { - *((float*)outputBuffers[channelIndex] + sampleIndex) = (outputValues[channelIndex] * outGain + channelInput[channelIndex] * dryGain) / 64; - } - } - } - - private void ProcessReverb(CommandList context, ref ReverbState state) - { - Debug.Assert(Parameter.IsChannelCountValid()); - - if (IsEffectEnabled && Parameter.IsChannelCountValid()) - { - Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount]; - - for (int i = 0; i < Parameter.ChannelCount; i++) - { - inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]); - outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]); - } - - switch (Parameter.ChannelCount) - { - case 1: - ProcessReverbMono(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 2: - ProcessReverbStereo(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 4: - ProcessReverbQuadraphonic(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - case 6: - ProcessReverbSurround(ref state, outputBuffers, inputBuffers, context.SampleCount); - break; - default: - throw new NotImplementedException(Parameter.ChannelCount.ToString()); - } - } - else - { - for (int i = 0; i < Parameter.ChannelCount; i++) - { - if (InputBufferIndices[i] != OutputBufferIndices[i]) - { - context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]); - } - } - } - } - - public void Process(CommandList context) - { - ref ReverbState state = ref State.Span[0]; - - if (IsEffectEnabled) - { - if (Parameter.Status == Server.Effect.UsageState.Invalid) - { - state = new ReverbState(ref _parameter, WorkBuffer, IsLongSizePreDelaySupported); - } - else if (Parameter.Status == Server.Effect.UsageState.New) - { - state.UpdateParameter(ref _parameter); - } - } - - ProcessReverb(context, ref state); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs deleted file mode 100644 index 0870d59c..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Ryujinx.Audio.Renderer.Server.Upsampler; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class UpsampleCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - 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 UpsamplerState UpsamplerInfo { get; } - - public Memory<float> OutBuffer { get; } - - public UpsampleCommand(uint bufferOffset, UpsamplerState info, uint inputCount, Span<byte> inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - InputBufferIndex = 0; - OutBuffer = info.OutputBuffer; - BufferCount = bufferCount; - InputSampleCount = sampleCount; - InputSampleRate = sampleRate; - info.SourceSampleCount = inputCount; - info.InputBufferIndices = new ushort[inputCount]; - - for (int i = 0; i < inputCount; i++) - { - info.InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]); - } - - if (info.BufferStates?.Length != (int)inputCount) - { - // Keep state if possible. - info.BufferStates = new UpsamplerBufferState[(int)inputCount]; - } - - UpsamplerInfo = info; - } - - private Span<float> GetBuffer(int index, int sampleCount) - { - return UpsamplerInfo.OutputBuffer.Span.Slice(index * sampleCount, sampleCount); - } - - public void Process(CommandList context) - { - uint bufferCount = Math.Min(BufferCount, UpsamplerInfo.SourceSampleCount); - - for (int i = 0; i < bufferCount; i++) - { - Span<float> inputBuffer = context.GetBuffer(UpsamplerInfo.InputBufferIndices[i]); - Span<float> outputBuffer = GetBuffer(UpsamplerInfo.InputBufferIndices[i], (int)UpsamplerInfo.SampleCount); - - UpsamplerHelper.Upsample(outputBuffer, inputBuffer, (int)UpsamplerInfo.SampleCount, (int)InputSampleCount, ref UpsamplerInfo.BufferStates[i]); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs deleted file mode 100644 index 0628f6d8..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; -using System.Runtime.Intrinsics.X86; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class VolumeCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.Volume; - - public uint EstimatedProcessingTime { get; set; } - - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } - - public float Volume { get; } - - public VolumeCommand(float volume, uint bufferIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - InputBufferIndex = (ushort)bufferIndex; - OutputBufferIndex = (ushort)bufferIndex; - - Volume = volume; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessVolumeAvx(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer) - { - Vector256<float> volumeVec = Vector256.Create(Volume); - - ReadOnlySpan<Vector256<float>> inputVec = MemoryMarshal.Cast<float, Vector256<float>>(inputBuffer); - Span<Vector256<float>> outputVec = MemoryMarshal.Cast<float, Vector256<float>>(outputBuffer); - - int sisdStart = inputVec.Length * 8; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Avx.Ceiling(Avx.Multiply(inputVec[i], volumeVec)); - } - - for (int i = sisdStart; i < inputBuffer.Length; i++) - { - outputBuffer[i] = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessVolumeSse41(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer) - { - Vector128<float> volumeVec = Vector128.Create(Volume); - - ReadOnlySpan<Vector128<float>> inputVec = MemoryMarshal.Cast<float, Vector128<float>>(inputBuffer); - Span<Vector128<float>> outputVec = MemoryMarshal.Cast<float, Vector128<float>>(outputBuffer); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Sse41.Ceiling(Sse.Multiply(inputVec[i], volumeVec)); - } - - for (int i = sisdStart; i < inputBuffer.Length; i++) - { - outputBuffer[i] = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessVolumeAdvSimd(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer) - { - Vector128<float> volumeVec = Vector128.Create(Volume); - - ReadOnlySpan<Vector128<float>> inputVec = MemoryMarshal.Cast<float, Vector128<float>>(inputBuffer); - Span<Vector128<float>> outputVec = MemoryMarshal.Cast<float, Vector128<float>>(outputBuffer); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = AdvSimd.Ceiling(AdvSimd.Multiply(inputVec[i], volumeVec)); - } - - for (int i = sisdStart; i < inputBuffer.Length; i++) - { - outputBuffer[i] = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], Volume); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessVolume(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer) - { - if (Avx.IsSupported) - { - ProcessVolumeAvx(outputBuffer, inputBuffer); - } - else if (Sse41.IsSupported) - { - ProcessVolumeSse41(outputBuffer, inputBuffer); - } - else if (AdvSimd.IsSupported) - { - ProcessVolumeAdvSimd(outputBuffer, inputBuffer); - } - else - { - ProcessVolumeSlowPath(outputBuffer, inputBuffer); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessVolumeSlowPath(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer) - { - for (int i = 0; i < outputBuffer.Length; i++) - { - outputBuffer[i] = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], Volume); - } - } - - public void Process(CommandList context) - { - ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - ProcessVolume(outputBuffer, inputBuffer); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs deleted file mode 100644 index 5c0c8845..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Command -{ - public class VolumeRampCommand : ICommand - { - public bool Enabled { get; set; } - - public int NodeId { get; } - - public CommandType CommandType => CommandType.VolumeRamp; - - public uint EstimatedProcessingTime { get; set; } - - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } - - public float Volume0 { get; } - public float Volume1 { get; } - - public VolumeRampCommand(float volume0, float volume1, uint bufferIndex, int nodeId) - { - Enabled = true; - NodeId = nodeId; - - InputBufferIndex = (ushort)bufferIndex; - OutputBufferIndex = (ushort)bufferIndex; - - Volume0 = volume0; - Volume1 = volume1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ProcessVolumeRamp(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, int sampleCount) - { - float ramp = (Volume1 - Volume0) / sampleCount; - - float volume = Volume0; - - for (int i = 0; i < sampleCount; i++) - { - outputBuffer[i] = FloatingPointHelper.MultiplyRoundUp(inputBuffer[i], volume); - volume += ramp; - } - } - - public void Process(CommandList context) - { - ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex); - Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex); - - ProcessVolumeRamp(outputBuffer, inputBuffer, (int)context.SampleCount); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs b/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs deleted file mode 100644 index 5ca1ddba..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/DataSourceHelper.cs +++ /dev/null @@ -1,466 +0,0 @@ -using Ryujinx.Audio.Common; -using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Audio.Renderer.Dsp.State; -using Ryujinx.Common.Logging; -using Ryujinx.Memory; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; -using System.Runtime.Intrinsics.X86; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class DataSourceHelper - { - private const int FixedPointPrecision = 15; - - public struct WaveBufferInformation - { - public uint SourceSampleRate; - public float Pitch; - 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) - { - return quality switch - { - SampleRateConversionQuality.Default or SampleRateConversionQuality.Low => 4, - SampleRateConversionQuality.High => 8, - _ => throw new ArgumentException(quality.ToString()), - }; - } - - 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; - - Span<short> tempBuffer = stackalloc short[tempBufferSize]; - - float sampleRateRatio = (float)info.SourceSampleRate / targetSampleRate * info.Pitch; - - 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); - - int totalNeededSize = (int)MathF.Truncate(fraction + sampleRateRatio * sampleCount); - - if (totalNeededSize + pitchMaxLength <= tempBufferSize && totalNeededSize >= 0) - { - int sourceSampleCountToProcess = sampleCount; - - int maxSampleCountPerIteration = Math.Min((int)MathF.Truncate((tempBufferSize - fraction) / sampleRateRatio), sampleCount); - - bool isStarving = false; - - int i = 0; - - while (i < sourceSampleCountToProcess) - { - int tempBufferIndex = 0; - - if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) - { - voiceState.Pitch.AsSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer); - tempBufferIndex += pitchMaxLength; - } - - int sampleCountToProcess = Math.Min(sourceSampleCountToProcess, maxSampleCountPerIteration); - - int y = 0; - - int sampleCountToDecode = (int)MathF.Truncate(fraction + sampleRateRatio * sampleCountToProcess); - - while (y < sampleCountToDecode) - { - if (waveBufferIndex >= Constants.VoiceWaveBufferCount) - { - waveBufferIndex = 0; - playedSampleCount = 0; - } - - if (!voiceState.IsWaveBufferValid[waveBufferIndex]) - { - isStarving = true; - break; - } - - ref WaveBuffer waveBuffer = ref wavebuffers[waveBufferIndex]; - - if (offset == 0 && info.SampleFormat == SampleFormat.Adpcm && waveBuffer.Context != 0) - { - voiceState.LoopContext = memoryManager.Read<AdpcmLoopContext>(waveBuffer.Context); - } - - Span<short> tempSpan = tempBuffer.Slice(tempBufferIndex + y); - - int decodedSampleCount = -1; - - int targetSampleStartOffset; - int targetSampleEndOffset; - - if (voiceState.LoopCount > 0 && waveBuffer.LoopStartSampleOffset != 0 && waveBuffer.LoopEndSampleOffset != 0 && waveBuffer.LoopStartSampleOffset <= waveBuffer.LoopEndSampleOffset) - { - targetSampleStartOffset = (int)waveBuffer.LoopStartSampleOffset; - targetSampleEndOffset = (int)waveBuffer.LoopEndSampleOffset; - } - else - { - targetSampleStartOffset = (int)waveBuffer.StartSampleOffset; - targetSampleEndOffset = (int)waveBuffer.EndSampleOffset; - } - - int targetWaveBufferSampleCount = targetSampleEndOffset - targetSampleStartOffset; - - switch (info.SampleFormat) - { - case SampleFormat.Adpcm: - ReadOnlySpan<byte> waveBufferAdpcm = ReadOnlySpan<byte>.Empty; - - if (waveBuffer.Buffer != 0 && waveBuffer.BufferSize != 0) - { - // TODO: we are possibly copying a lot of unneeded data here, we should only take what we need. - waveBufferAdpcm = memoryManager.GetSpan(waveBuffer.Buffer, (int)waveBuffer.BufferSize); - } - - 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 voiceState.LoopContext); - break; - case SampleFormat.PcmInt16: - ReadOnlySpan<short> waveBufferPcm16 = ReadOnlySpan<short>.Empty; - - if (waveBuffer.Buffer != 0 && waveBuffer.BufferSize != 0) - { - ulong bufferOffset = waveBuffer.Buffer + PcmHelper.GetBufferOffset<short>(targetSampleStartOffset, offset, info.ChannelCount); - int bufferSize = PcmHelper.GetBufferSize<short>(targetSampleStartOffset, targetSampleEndOffset, offset, sampleCountToDecode - y) * info.ChannelCount; - - waveBufferPcm16 = MemoryMarshal.Cast<byte, short>(memoryManager.GetSpan(bufferOffset, bufferSize)); - } - - decodedSampleCount = PcmHelper.Decode(tempSpan, waveBufferPcm16, targetSampleStartOffset, targetSampleEndOffset, info.ChannelIndex, info.ChannelCount); - break; - case SampleFormat.PcmFloat: - ReadOnlySpan<float> waveBufferPcmFloat = ReadOnlySpan<float>.Empty; - - if (waveBuffer.Buffer != 0 && waveBuffer.BufferSize != 0) - { - ulong bufferOffset = waveBuffer.Buffer + PcmHelper.GetBufferOffset<float>(targetSampleStartOffset, offset, info.ChannelCount); - int bufferSize = PcmHelper.GetBufferSize<float>(targetSampleStartOffset, targetSampleEndOffset, offset, sampleCountToDecode - y) * info.ChannelCount; - - waveBufferPcmFloat = MemoryMarshal.Cast<byte, float>(memoryManager.GetSpan(bufferOffset, bufferSize)); - } - - decodedSampleCount = PcmHelper.Decode(tempSpan, waveBufferPcmFloat, targetSampleStartOffset, targetSampleEndOffset, info.ChannelIndex, info.ChannelCount); - break; - default: - Logger.Error?.Print(LogClass.AudioRenderer, $"Unsupported sample format " + info.SampleFormat); - break; - } - - Debug.Assert(decodedSampleCount <= sampleCountToDecode); - - if (decodedSampleCount < 0) - { - Logger.Warning?.Print(LogClass.AudioRenderer, "Decoding failed, skipping WaveBuffer"); - - voiceState.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); - decodedSampleCount = 0; - } - - y += decodedSampleCount; - offset += decodedSampleCount; - playedSampleCount += (uint)decodedSampleCount; - - if (offset >= targetWaveBufferSampleCount || decodedSampleCount == 0) - { - offset = 0; - - if (waveBuffer.Looping) - { - voiceState.LoopCount++; - - if (waveBuffer.LoopCount >= 0) - { - if (decodedSampleCount == 0 || voiceState.LoopCount > waveBuffer.LoopCount) - { - voiceState.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); - } - } - - if (decodedSampleCount == 0) - { - isStarving = true; - break; - } - - if (info.DecodingBehaviour.HasFlag(DecodingBehaviour.PlayedSampleCountResetWhenLooping)) - { - playedSampleCount = 0; - } - } - else - { - voiceState.MarkEndOfBufferWaveBufferProcessing(ref waveBuffer, ref waveBufferIndex, ref waveBufferConsumed, ref playedSampleCount); - } - } - } - - Span<int> outputSpanInt = MemoryMarshal.Cast<float, int>(outputBuffer.Slice(i)); - - if (info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) - { - for (int j = 0; j < y; j++) - { - outputBuffer[j] = tempBuffer[j]; - } - } - else - { - Span<short> tempSpan = tempBuffer.Slice(tempBufferIndex + y); - - tempSpan.Slice(0, sampleCountToDecode - y).Fill(0); - - ToFloat(outputBuffer, outputSpanInt, sampleCountToProcess); - - ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f); - - tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.AsSpan()); - } - - i += sampleCountToProcess; - } - - Debug.Assert(sourceSampleCountToProcess == i || !isStarving); - - voiceState.WaveBufferConsumed = waveBufferConsumed; - voiceState.Offset = offset; - voiceState.PlayedSampleCount = playedSampleCount; - voiceState.WaveBufferIndex = (uint)waveBufferIndex; - voiceState.Fraction = fraction; - } - } - - [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); - Span<Vector256<float>> outputVec = MemoryMarshal.Cast<float, Vector256<float>>(output); - - int sisdStart = inputVec.Length * 8; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Avx.ConvertToVector256Single(inputVec[i]); - } - - for (int i = sisdStart; i < sampleCount; i++) - { - output[i] = input[i]; - } - } - - [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); - Span<Vector128<float>> outputVec = MemoryMarshal.Cast<float, Vector128<float>>(output); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Sse2.ConvertToVector128Single(inputVec[i]); - } - - for (int i = sisdStart; i < sampleCount; i++) - { - output[i] = input[i]; - } - } - - [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); - Span<Vector128<float>> outputVec = MemoryMarshal.Cast<float, Vector128<float>>(output); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = AdvSimd.ConvertToSingle(inputVec[i]); - } - - for (int i = sisdStart; i < sampleCount; i++) - { - output[i] = input[i]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToFloatSlow(Span<float> output, ReadOnlySpan<int> input, int sampleCount) - { - for (int i = 0; i < sampleCount; i++) - { - output[i] = input[i]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToFloat(Span<float> output, ReadOnlySpan<int> input, int sampleCount) - { - if (Avx.IsSupported) - { - ToFloatAvx(output, input, sampleCount); - } - else if (Sse2.IsSupported) - { - ToFloatSse2(output, input, sampleCount); - } - else if (AdvSimd.IsSupported) - { - ToFloatAdvSimd(output, input, sampleCount); - } - else - { - ToFloatSlow(output, input, sampleCount); - } - } - - [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); - Span<Vector256<int>> outputVec = MemoryMarshal.Cast<int, Vector256<int>>(output); - - int sisdStart = inputVec.Length * 8; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Avx.ConvertToVector256Int32(inputVec[i]); - } - - for (int i = sisdStart; i < sampleCount; i++) - { - output[i] = (int)input[i]; - } - } - - [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); - Span<Vector128<int>> outputVec = MemoryMarshal.Cast<int, Vector128<int>>(output); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = Sse2.ConvertToVector128Int32(inputVec[i]); - } - - for (int i = sisdStart; i < sampleCount; i++) - { - output[i] = (int)input[i]; - } - } - - [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); - Span<Vector128<int>> outputVec = MemoryMarshal.Cast<int, Vector128<int>>(output); - - int sisdStart = inputVec.Length * 4; - - for (int i = 0; i < inputVec.Length; i++) - { - outputVec[i] = AdvSimd.ConvertToInt32RoundToZero(inputVec[i]); - } - - for (int i = sisdStart; i < sampleCount; i++) - { - output[i] = (int)input[i]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToIntSlow(Span<int> output, ReadOnlySpan<float> input, int sampleCount) - { - for (int i = 0; i < sampleCount; i++) - { - output[i] = (int)input[i]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToInt(Span<int> output, ReadOnlySpan<float> input, int sampleCount) - { - if (Avx.IsSupported) - { - ToIntAvx(output, input, sampleCount); - } - else if (Sse2.IsSupported) - { - ToIntSse2(output, input, sampleCount); - } - else if (AdvSimd.IsSupported) - { - ToIntAdvSimd(output, input, sampleCount); - } - else - { - ToIntSlow(output, input, sampleCount); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemapLegacyChannelEffectMappingToChannelResourceMapping(bool isSupported, Span<ushort> bufferIndices) - { - if (!isSupported && bufferIndices.Length == 6) - { - ushort backLeft = bufferIndices[2]; - ushort backRight = bufferIndices[3]; - ushort frontCenter = bufferIndices[4]; - ushort lowFrequency = bufferIndices[5]; - - bufferIndices[2] = frontCenter; - bufferIndices[3] = lowFrequency; - bufferIndices[4] = backLeft; - bufferIndices[5] = backRight; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemapChannelResourceMappingToLegacy(bool isSupported, Span<ushort> bufferIndices) - { - if (isSupported && bufferIndices.Length == 6) - { - ushort frontCenter = bufferIndices[2]; - ushort lowFrequency = bufferIndices[3]; - ushort backLeft = bufferIndices[4]; - ushort backRight = bufferIndices[5]; - - bufferIndices[2] = backLeft; - bufferIndices[3] = backRight; - bufferIndices[4] = frontCenter; - bufferIndices[5] = lowFrequency; - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Effect/DecayDelay.cs b/Ryujinx.Audio/Renderer/Dsp/Effect/DecayDelay.cs deleted file mode 100644 index 37e066bf..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Effect/DecayDelay.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace Ryujinx.Audio.Renderer.Dsp.Effect -{ - public class DecayDelay : IDelayLine - { - private readonly IDelayLine _delayLine; - - public uint CurrentSampleCount => _delayLine.CurrentSampleCount; - - public uint SampleCountMax => _delayLine.SampleCountMax; - - private float _decayRate; - - public DecayDelay(IDelayLine delayLine) - { - _decayRate = 0.0f; - _delayLine = delayLine; - } - - public void SetDecayRate(float decayRate) - { - _decayRate = decayRate; - } - - public float Update(float value) - { - float delayLineValue = _delayLine.Read(); - float processedValue = value - (_decayRate * delayLineValue); - - return _delayLine.Update(processedValue) + processedValue * _decayRate; - } - - public void SetDelay(float delayTime) - { - _delayLine.SetDelay(delayTime); - } - - public float Read() - { - return _delayLine.Read(); - } - - public float TapUnsafe(uint sampleIndex, int offset) - { - return _delayLine.TapUnsafe(sampleIndex, offset); - } - - public float Tap(uint sampleIndex) - { - return _delayLine.Tap(sampleIndex); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLine.cs b/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLine.cs deleted file mode 100644 index 56890ebe..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLine.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.Effect -{ - public class DelayLine : IDelayLine - { - private float[] _workBuffer; - private uint _sampleRate; - private uint _currentSampleIndex; - private uint _lastSampleIndex; - - public uint CurrentSampleCount { get; private set; } - public uint SampleCountMax { get; private set; } - - public DelayLine(uint sampleRate, float delayTimeMax) - { - _sampleRate = sampleRate; - SampleCountMax = IDelayLine.GetSampleCount(_sampleRate, delayTimeMax); - _workBuffer = new float[SampleCountMax + 1]; - - SetDelay(delayTimeMax); - } - - private void ConfigureDelay(uint targetSampleCount) - { - CurrentSampleCount = Math.Min(SampleCountMax, targetSampleCount); - _currentSampleIndex = 0; - - if (CurrentSampleCount == 0) - { - _lastSampleIndex = 0; - } - else - { - _lastSampleIndex = CurrentSampleCount - 1; - } - } - - public void SetDelay(float delayTime) - { - ConfigureDelay(IDelayLine.GetSampleCount(_sampleRate, delayTime)); - } - - public float Read() - { - return _workBuffer[_currentSampleIndex]; - } - - public float Update(float value) - { - float output = Read(); - - _workBuffer[_currentSampleIndex++] = value; - - if (_currentSampleIndex >= _lastSampleIndex) - { - _currentSampleIndex = 0; - } - - return output; - } - - public float TapUnsafe(uint sampleIndex, int offset) - { - return IDelayLine.Tap(_workBuffer, (int)_currentSampleIndex, (int)sampleIndex + offset, (int)CurrentSampleCount); - } - - public float Tap(uint sampleIndex) - { - if (sampleIndex >= CurrentSampleCount) - { - sampleIndex = CurrentSampleCount - 1; - } - - return TapUnsafe(sampleIndex, -1); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLineReverb3d.cs b/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLineReverb3d.cs deleted file mode 100644 index a2ac9d26..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLineReverb3d.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Diagnostics; - -namespace Ryujinx.Audio.Renderer.Dsp.Effect -{ - public class DelayLine3d : IDelayLine - { - private float[] _workBuffer; - private uint _sampleRate; - private uint _currentSampleIndex; - private uint _lastSampleIndex; - - public uint CurrentSampleCount { get; private set; } - public uint SampleCountMax { get; private set; } - - public DelayLine3d(uint sampleRate, float delayTimeMax) - { - _sampleRate = sampleRate; - SampleCountMax = IDelayLine.GetSampleCount(_sampleRate, delayTimeMax); - _workBuffer = new float[SampleCountMax + 1]; - - SetDelay(delayTimeMax); - } - - private void ConfigureDelay(uint targetSampleCount) - { - if (SampleCountMax >= targetSampleCount) - { - CurrentSampleCount = targetSampleCount; - _lastSampleIndex = (_currentSampleIndex + targetSampleCount) % (SampleCountMax + 1); - } - } - - public void SetDelay(float delayTime) - { - ConfigureDelay(IDelayLine.GetSampleCount(_sampleRate, delayTime)); - } - - public float Read() - { - return _workBuffer[_currentSampleIndex]; - } - - public float Update(float value) - { - Debug.Assert(!float.IsNaN(value) && !float.IsInfinity(value)); - - _workBuffer[_lastSampleIndex++] = value; - - float output = Read(); - - _currentSampleIndex++; - - if (_currentSampleIndex >= SampleCountMax) - { - _currentSampleIndex = 0; - } - - if (_lastSampleIndex >= SampleCountMax) - { - _lastSampleIndex = 0; - } - - return output; - } - - public float TapUnsafe(uint sampleIndex, int offset) - { - return IDelayLine.Tap(_workBuffer, (int)_lastSampleIndex, (int)sampleIndex + offset, (int)SampleCountMax + 1); - } - - public float Tap(uint sampleIndex) - { - return TapUnsafe(sampleIndex, -1); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/Effect/ExponentialMovingAverage.cs b/Ryujinx.Audio/Renderer/Dsp/Effect/ExponentialMovingAverage.cs deleted file mode 100644 index 78e46bf9..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Effect/ExponentialMovingAverage.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Effect -{ - public struct ExponentialMovingAverage - { - private float _mean; - - public ExponentialMovingAverage(float mean) - { - _mean = mean; - } - - public float Read() - { - return _mean; - } - - public float Update(float value, float alpha) - { - _mean += alpha * (value - _mean); - - return _mean; - } - } -} diff --git a/Ryujinx.Audio/Renderer/Dsp/Effect/IDelayLine.cs b/Ryujinx.Audio/Renderer/Dsp/Effect/IDelayLine.cs deleted file mode 100644 index fd902525..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/Effect/IDelayLine.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.Effect -{ - public interface IDelayLine - { - uint CurrentSampleCount { get; } - uint SampleCountMax { get; } - - void SetDelay(float delayTime); - float Read(); - float Update(float value); - - float TapUnsafe(uint sampleIndex, int offset); - float Tap(uint sampleIndex); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Tap(Span<float> workBuffer, int baseIndex, int sampleIndex, int delaySampleCount) - { - int targetIndex = baseIndex - sampleIndex; - - if (targetIndex < 0) - { - targetIndex += delaySampleCount; - } - - return workBuffer[targetIndex]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint GetSampleCount(uint sampleRate, float delayTime) - { - return (uint)MathF.Round(sampleRate * delayTime); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs b/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs deleted file mode 100644 index 280e47c0..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class FixedPointHelper - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int ToInt(long value, int qBits) - { - return (int)(value >> qBits); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ToFloat(long value, int qBits) - { - return (float)value / (1 << qBits); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ConvertFloat(float value, int qBits) - { - return value / (1 << qBits); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int ToFixed(float value, int qBits) - { - return (int)(value * (1 << qBits)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int RoundUpAndToInt(long value, int qBits) - { - int half = 1 << (qBits - 1); - - return ToInt(value + half, qBits); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs b/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs deleted file mode 100644 index 6645e20a..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Reflection.Metadata; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class FloatingPointHelper - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float MultiplyRoundDown(float a, float b) - { - return RoundDown(a * b); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float RoundDown(float a) - { - return MathF.Round(a, 0); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float RoundUp(float a) - { - return MathF.Round(a); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float MultiplyRoundUp(float a, float b) - { - return RoundUp(a * b); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Pow10(float x) - { - // NOTE: Nintendo implementation uses Q15 and a LUT for this, we don't. - // As such, we support the same ranges as Nintendo to avoid unexpected behaviours. - if (x >= 0.0f) - { - return 1.0f; - } - else if (x <= -5.3f) - { - return 0.0f; - } - - return MathF.Pow(10, x); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Log10(float x) - { - // NOTE: Nintendo uses an approximation of log10, we don't. - // As such, we support the same ranges as Nintendo to avoid unexpected behaviours. - return MathF.Pow(10, MathF.Max(x, 1.0e-10f)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float MeanSquare(ReadOnlySpan<float> inputs) - { - float res = 0.0f; - - foreach (float input in inputs) - { - res += (input * input); - } - - res /= inputs.Length; - - return res; - } - - /// <summary> - /// Map decibel to linear. - /// </summary> - /// <param name="db">The decibel value to convert</param> - /// <returns>Converted linear value/returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float DecibelToLinear(float db) - { - 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)] - public static float DegreesToRadians(float degrees) - { - return degrees * MathF.PI / 180.0f; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Cos(float value) - { - return MathF.Cos(DegreesToRadians(value)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sin(float value) - { - return MathF.Sin(DegreesToRadians(value)); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/PcmHelper.cs b/Ryujinx.Audio/Renderer/Dsp/PcmHelper.cs deleted file mode 100644 index 0233a8d7..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/PcmHelper.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class PcmHelper - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetCountToDecode(int startSampleOffset, int endSampleOffset, int offset, int count) - { - return Math.Min(count, endSampleOffset - startSampleOffset - offset); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong GetBufferOffset<T>(int startSampleOffset, int offset, int channelCount) where T : unmanaged - { - return (ulong)(Unsafe.SizeOf<T>() * channelCount * (startSampleOffset + offset)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetBufferSize<T>(int startSampleOffset, int endSampleOffset, int offset, int count) where T : unmanaged - { - return GetCountToDecode(startSampleOffset, endSampleOffset, offset, count) * Unsafe.SizeOf<T>(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ConvertSampleToPcmFloat(short sample) - { - return (float)sample / short.MaxValue; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static short ConvertSampleToPcmInt16(float sample) - { - return Saturate(sample * short.MaxValue); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ConvertSampleToPcm8(Span<sbyte> output, ReadOnlySpan<short> input) - { - for (int i = 0; i < input.Length; i++) - { - // Output most significant byte - output[i] = (sbyte)(input[i] >> 8); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ConvertSampleToPcm24(Span<byte> output, ReadOnlySpan<short> input) - { - for (int i = 0; i < input.Length; i++) - { - output[i * 3 + 2] = (byte)(input[i] >> 8); - output[i * 3 + 1] = (byte)(input[i] & 0xff); - output[i * 3 + 0] = 0; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ConvertSampleToPcm32(Span<int> output, ReadOnlySpan<short> input) - { - for (int i = 0; i < input.Length; i++) - { - output[i] = ((int)input[i]) << 16; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ConvertSampleToPcmFloat(Span<float> output, ReadOnlySpan<short> input) - { - for (int i = 0; i < input.Length; i++) - { - output[i] = ConvertSampleToPcmFloat(input[i]); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Decode(Span<short> output, ReadOnlySpan<short> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount) - { - if (input.IsEmpty || endSampleOffset < startSampleOffset) - { - return 0; - } - - int decodedCount = input.Length / channelCount; - - for (int i = 0; i < decodedCount; i++) - { - output[i] = input[i * channelCount + channelIndex]; - } - - return decodedCount; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Decode(Span<short> output, ReadOnlySpan<float> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount) - { - if (input.IsEmpty || endSampleOffset < startSampleOffset) - { - return 0; - } - - int decodedCount = input.Length / channelCount; - - for (int i = 0; i < decodedCount; i++) - { - output[i] = ConvertSampleToPcmInt16(input[i * channelCount + channelIndex]); - } - - return decodedCount; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static short Saturate(float value) - { - if (value > short.MaxValue) - { - return short.MaxValue; - } - - if (value < short.MinValue) - { - return short.MinValue; - } - - return (short)value; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/ResamplerHelper.cs b/Ryujinx.Audio/Renderer/Dsp/ResamplerHelper.cs deleted file mode 100644 index 7873c4d2..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/ResamplerHelper.cs +++ /dev/null @@ -1,604 +0,0 @@ -using System; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public static class ResamplerHelper - { - #region "Default Quality Lookup Tables" - private static short[] _normalCurveLut0 = new short[] - { - 6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239, 19412, 7093, 22, - 6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377, 7472, 41, 5773, 19361, 7600, 48, - 5659, 19342, 7728, 55, 5546, 19321, 7857, 62, 5434, 19298, 7987, 69, 5323, 19273, 8118, 77, - 5213, 19245, 8249, 84, 5104, 19215, 8381, 92, 4997, 19183, 8513, 101, 4890, 19148, 8646, 109, - 4785, 19112, 8780, 118, 4681, 19073, 8914, 127, 4579, 19031, 9048, 137, 4477, 18988, 9183, 147, - 4377, 18942, 9318, 157, 4277, 18895, 9454, 168, 4179, 18845, 9590, 179, 4083, 18793, 9726, 190, - 3987, 18738, 9863, 202, 3893, 18682, 10000, 215, 3800, 18624, 10137, 228, 3709, 18563, 10274, 241, - 3618, 18500, 10411, 255, 3529, 18436, 10549, 270, 3441, 18369, 10687, 285, 3355, 18300, 10824, 300, - 3269, 18230, 10962, 317, 3186, 18157, 11100, 334, 3103, 18082, 11238, 351, 3022, 18006, 11375, 369, - 2942, 17927, 11513, 388, 2863, 17847, 11650, 408, 2785, 17765, 11788, 428, 2709, 17681, 11925, 449, - 2635, 17595, 12062, 471, 2561, 17507, 12198, 494, 2489, 17418, 12334, 517, 2418, 17327, 12470, 541, - 2348, 17234, 12606, 566, 2280, 17140, 12741, 592, 2213, 17044, 12876, 619, 2147, 16946, 13010, 647, - 2083, 16846, 13144, 675, 2020, 16745, 13277, 704, 1958, 16643, 13409, 735, 1897, 16539, 13541, 766, - 1838, 16434, 13673, 798, 1780, 16327, 13803, 832, 1723, 16218, 13933, 866, 1667, 16109, 14062, 901, - 1613, 15998, 14191, 937, 1560, 15885, 14318, 975, 1508, 15772, 14445, 1013, 1457, 15657, 14571, 1052, - 1407, 15540, 14695, 1093, 1359, 15423, 14819, 1134, 1312, 15304, 14942, 1177, 1266, 15185, 15064, 1221, - 1221, 15064, 15185, 1266, 1177, 14942, 15304, 1312, 1134, 14819, 15423, 1359, 1093, 14695, 15540, 1407, - 1052, 14571, 15657, 1457, 1013, 14445, 15772, 1508, 975, 14318, 15885, 1560, 937, 14191, 15998, 1613, - 901, 14062, 16109, 1667, 866, 13933, 16218, 1723, 832, 13803, 16327, 1780, 798, 13673, 16434, 1838, - 766, 13541, 16539, 1897, 735, 13409, 16643, 1958, 704, 13277, 16745, 2020, 675, 13144, 16846, 2083, - 647, 13010, 16946, 2147, 619, 12876, 17044, 2213, 592, 12741, 17140, 2280, 566, 12606, 17234, 2348, - 541, 12470, 17327, 2418, 517, 12334, 17418, 2489, 494, 12198, 17507, 2561, 471, 12062, 17595, 2635, - 449, 11925, 17681, 2709, 428, 11788, 17765, 2785, 408, 11650, 17847, 2863, 388, 11513, 17927, 2942, - 369, 11375, 18006, 3022, 351, 11238, 18082, 3103, 334, 11100, 18157, 3186, 317, 10962, 18230, 3269, - 300, 10824, 18300, 3355, 285, 10687, 18369, 3441, 270, 10549, 18436, 3529, 255, 10411, 18500, 3618, - 241, 10274, 18563, 3709, 228, 10137, 18624, 3800, 215, 10000, 18682, 3893, 202, 9863, 18738, 3987, - 190, 9726, 18793, 4083, 179, 9590, 18845, 4179, 168, 9454, 18895, 4277, 157, 9318, 18942, 4377, - 147, 9183, 18988, 4477, 137, 9048, 19031, 4579, 127, 8914, 19073, 4681, 118, 8780, 19112, 4785, - 109, 8646, 19148, 4890, 101, 8513, 19183, 4997, 92, 8381, 19215, 5104, 84, 8249, 19245, 5213, - 77, 8118, 19273, 5323, 69, 7987, 19298, 5434, 62, 7857, 19321, 5546, 55, 7728, 19342, 5659, - 48, 7600, 19361, 5773, 41, 7472, 19377, 5888, 34, 7345, 19391, 6004, 28, 7219, 19403, 6121, - 22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424, 6479, 3, 6722, 19426, 6600 - }; - - private static short[] _normalCurveLut1 = new short[] - { - -68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450, 32586, 512, -36, - -568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454, 1000, -69, -891, 32393, 1174, -80, - -990, 32323, 1352, -92, -1084, 32244, 1536, -103, -1173, 32157, 1724, -115, -1258, 32061, 1919, -128, - -1338, 31956, 2118, -140, -1414, 31844, 2322, -153, -1486, 31723, 2532, -167, -1554, 31593, 2747, -180, - -1617, 31456, 2967, -194, -1676, 31310, 3192, -209, -1732, 31157, 3422, -224, -1783, 30995, 3657, -240, - -1830, 30826, 3897, -256, -1874, 30649, 4143, -272, -1914, 30464, 4393, -289, -1951, 30272, 4648, -307, - -1984, 30072, 4908, -325, -2014, 29866, 5172, -343, -2040, 29652, 5442, -362, -2063, 29431, 5716, -382, - -2083, 29203, 5994, -403, -2100, 28968, 6277, -424, -2114, 28727, 6565, -445, -2125, 28480, 6857, -468, - -2133, 28226, 7153, -490, -2139, 27966, 7453, -514, -2142, 27700, 7758, -538, -2142, 27428, 8066, -563, - -2141, 27151, 8378, -588, -2136, 26867, 8694, -614, -2130, 26579, 9013, -641, -2121, 26285, 9336, -668, - -2111, 25987, 9663, -696, -2098, 25683, 9993, -724, -2084, 25375, 10326, -753, -2067, 25063, 10662, -783, - -2049, 24746, 11000, -813, -2030, 24425, 11342, -844, -2009, 24100, 11686, -875, -1986, 23771, 12033, -907, - -1962, 23438, 12382, -939, -1937, 23103, 12733, -972, -1911, 22764, 13086, -1005, -1883, 22422, 13441, -1039, - -1855, 22077, 13798, -1072, -1825, 21729, 14156, -1107, -1795, 21380, 14516, -1141, -1764, 21027, 14877, -1176, - -1732, 20673, 15239, -1211, -1700, 20317, 15602, -1246, -1667, 19959, 15965, -1282, -1633, 19600, 16329, -1317, - -1599, 19239, 16694, -1353, -1564, 18878, 17058, -1388, -1530, 18515, 17423, -1424, -1495, 18151, 17787, -1459, - -1459, 17787, 18151, -1495, -1424, 17423, 18515, -1530, -1388, 17058, 18878, -1564, -1353, 16694, 19239, -1599, - -1317, 16329, 19600, -1633, -1282, 15965, 19959, -1667, -1246, 15602, 20317, -1700, -1211, 15239, 20673, -1732, - -1176, 14877, 21027, -1764, -1141, 14516, 21380, -1795, -1107, 14156, 21729, -1825, -1072, 13798, 22077, -1855, - -1039, 13441, 22422, -1883, -1005, 13086, 22764, -1911, -972, 12733, 23103, -1937, -939, 12382, 23438, -1962, - -907, 12033, 23771, -1986, -875, 11686, 24100, -2009, -844, 11342, 24425, -2030, -813, 11000, 24746, -2049, - -783, 10662, 25063, -2067, -753, 10326, 25375, -2084, -724, 9993, 25683, -2098, -696, 9663, 25987, -2111, - -668, 9336, 26285, -2121, -641, 9013, 26579, -2130, -614, 8694, 26867, -2136, -588, 8378, 27151, -2141, - -563, 8066, 27428, -2142, -538, 7758, 27700, -2142, -514, 7453, 27966, -2139, -490, 7153, 28226, -2133, - -468, 6857, 28480, -2125, -445, 6565, 28727, -2114, -424, 6277, 28968, -2100, -403, 5994, 29203, -2083, - -382, 5716, 29431, -2063, -362, 5442, 29652, -2040, -343, 5172, 29866, -2014, -325, 4908, 30072, -1984, - -307, 4648, 30272, -1951, -289, 4393, 30464, -1914, -272, 4143, 30649, -1874, -256, 3897, 30826, -1830, - -240, 3657, 30995, -1783, -224, 3422, 31157, -1732, -209, 3192, 31310, -1676, -194, 2967, 31456, -1617, - -180, 2747, 31593, -1554, -167, 2532, 31723, -1486, -153, 2322, 31844, -1414, -140, 2118, 31956, -1338, - -128, 1919, 32061, -1258, -115, 1724, 32157, -1173, -103, 1536, 32244, -1084, -92, 1352, 32323, -990, - -80, 1174, 32393, -891, -69, 1000, 32454, -788, -58, 832, 32507, -680, -47, 669, 32551, -568, - -36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630, -200, -5, 69, 32639, -68 - }; - - private static short[] _normalCurveLut2 = new short[] - { - 3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811, 26253, 3751, -42, - 2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169, 4199, -54, 2338, 26130, 4354, -58, - 2227, 26085, 4512, -63, 2120, 26035, 4673, -67, 2015, 25980, 4837, -72, 1912, 25919, 5004, -76, - 1813, 25852, 5174, -81, 1716, 25780, 5347, -87, 1622, 25704, 5522, -92, 1531, 25621, 5701, -98, - 1442, 25533, 5882, -103, 1357, 25440, 6066, -109, 1274, 25342, 6253, -115, 1193, 25239, 6442, -121, - 1115, 25131, 6635, -127, 1040, 25018, 6830, -133, 967, 24899, 7027, -140, 897, 24776, 7227, -146, - 829, 24648, 7430, -153, 764, 24516, 7635, -159, 701, 24379, 7842, -166, 641, 24237, 8052, -174, - 583, 24091, 8264, -181, 526, 23940, 8478, -187, 472, 23785, 8695, -194, 420, 23626, 8914, -202, - 371, 23462, 9135, -209, 324, 23295, 9358, -215, 279, 23123, 9583, -222, 236, 22948, 9809, -230, - 194, 22769, 10038, -237, 154, 22586, 10269, -243, 117, 22399, 10501, -250, 81, 22208, 10735, -258, - 47, 22015, 10970, -265, 15, 21818, 11206, -271, -16, 21618, 11444, -277, -44, 21415, 11684, -283, - -71, 21208, 11924, -290, -97, 20999, 12166, -296, -121, 20786, 12409, -302, -143, 20571, 12653, -306, - -163, 20354, 12898, -311, -183, 20134, 13143, -316, -201, 19911, 13389, -321, -218, 19686, 13635, -325, - -234, 19459, 13882, -328, -248, 19230, 14130, -332, -261, 18998, 14377, -335, -273, 18765, 14625, -337, - -284, 18531, 14873, -339, -294, 18295, 15121, -341, -302, 18057, 15369, -341, -310, 17817, 15617, -341, - -317, 17577, 15864, -340, -323, 17335, 16111, -340, -328, 17092, 16357, -338, -332, 16848, 16603, -336, - -336, 16603, 16848, -332, -338, 16357, 17092, -328, -340, 16111, 17335, -323, -340, 15864, 17577, -317, - -341, 15617, 17817, -310, -341, 15369, 18057, -302, -341, 15121, 18295, -294, -339, 14873, 18531, -284, - -337, 14625, 18765, -273, -335, 14377, 18998, -261, -332, 14130, 19230, -248, -328, 13882, 19459, -234, - -325, 13635, 19686, -218, -321, 13389, 19911, -201, -316, 13143, 20134, -183, -311, 12898, 20354, -163, - -306, 12653, 20571, -143, -302, 12409, 20786, -121, -296, 12166, 20999, -97, -290, 11924, 21208, -71, - -283, 11684, 21415, -44, -277, 11444, 21618, -16, -271, 11206, 21818, 15, -265, 10970, 22015, 47, - -258, 10735, 22208, 81, -250, 10501, 22399, 117, -243, 10269, 22586, 154, -237, 10038, 22769, 194, - -230, 9809, 22948, 236, -222, 9583, 23123, 279, -215, 9358, 23295, 324, -209, 9135, 23462, 371, - -202, 8914, 23626, 420, -194, 8695, 23785, 472, -187, 8478, 23940, 526, -181, 8264, 24091, 583, - -174, 8052, 24237, 641, -166, 7842, 24379, 701, -159, 7635, 24516, 764, -153, 7430, 24648, 829, - -146, 7227, 24776, 897, -140, 7027, 24899, 967, -133, 6830, 25018, 1040, -127, 6635, 25131, 1115, - -121, 6442, 25239, 1193, -115, 6253, 25342, 1274, -109, 6066, 25440, 1357, -103, 5882, 25533, 1442, - -98, 5701, 25621, 1531, -92, 5522, 25704, 1622, -87, 5347, 25780, 1716, -81, 5174, 25852, 1813, - -76, 5004, 25919, 1912, -72, 4837, 25980, 2015, -67, 4673, 26035, 2120, -63, 4512, 26085, 2227, - -58, 4354, 26130, 2338, -54, 4199, 26169, 2451, -50, 4046, 26202, 2568, -46, 3897, 26230, 2688, - -42, 3751, 26253, 2811, -38, 3608, 26270, 2936, -34, 3467, 26281, 3064, -32, 3329, 26287, 3195 - }; - #endregion - - #region "High Quality Lookup Tables" - private static short[] _highCurveLut0 = new short[] - { - -582, -23, 8740, 16386, 8833, 8, -590, 0, -573, -54, 8647, 16385, 8925, 40, -598, -1, - -565, -84, 8555, 16383, 9018, 72, -606, -1, -557, -113, 8462, 16379, 9110, 105, -614, -2, - -549, -142, 8370, 16375, 9203, 139, -622, -2, -541, -170, 8277, 16369, 9295, 173, -630, -3, - -533, -198, 8185, 16362, 9387, 208, -638, -4, -525, -225, 8093, 16354, 9480, 244, -646, -5, - -516, -251, 8000, 16344, 9572, 280, -654, -5, -508, -277, 7908, 16334, 9664, 317, -662, -6, - -500, -302, 7816, 16322, 9756, 355, -670, -7, -492, -327, 7724, 16310, 9847, 393, -678, -8, - -484, -351, 7632, 16296, 9939, 432, -686, -9, -476, -374, 7540, 16281, 10030, 471, -694, -10, - -468, -397, 7449, 16265, 10121, 511, -702, -11, -460, -419, 7357, 16247, 10212, 552, -709, -13, - -452, -441, 7266, 16229, 10303, 593, -717, -14, -445, -462, 7175, 16209, 10394, 635, -724, -15, - -437, -483, 7084, 16189, 10484, 678, -732, -16, -429, -503, 6994, 16167, 10574, 722, -739, -18, - -421, -523, 6903, 16144, 10664, 766, -747, -19, -414, -542, 6813, 16120, 10754, 810, -754, -21, - -406, -560, 6723, 16095, 10843, 856, -761, -22, -398, -578, 6633, 16068, 10932, 902, -768, -24, - -391, -596, 6544, 16041, 11021, 949, -775, -26, -383, -612, 6454, 16012, 11109, 996, -782, -27, - -376, -629, 6366, 15983, 11197, 1044, -789, -29, -368, -645, 6277, 15952, 11285, 1093, -796, -31, - -361, -660, 6189, 15920, 11372, 1142, -802, -33, -354, -675, 6100, 15887, 11459, 1192, -809, -35, - -347, -689, 6013, 15853, 11546, 1243, -815, -37, -339, -703, 5925, 15818, 11632, 1294, -821, -39, - -332, -717, 5838, 15782, 11718, 1346, -827, -41, -325, -730, 5751, 15745, 11803, 1399, -833, -43, - -318, -742, 5665, 15707, 11888, 1452, -839, -46, -312, -754, 5579, 15668, 11973, 1506, -845, -48, - -305, -766, 5493, 15627, 12057, 1561, -850, -50, -298, -777, 5408, 15586, 12140, 1616, -855, -53, - -291, -787, 5323, 15544, 12224, 1672, -861, -56, -285, -798, 5239, 15500, 12306, 1729, -866, -58, - -278, -807, 5155, 15456, 12388, 1786, -871, -61, -272, -817, 5071, 15410, 12470, 1844, -875, -64, - -265, -826, 4988, 15364, 12551, 1902, -880, -67, -259, -834, 4905, 15317, 12631, 1962, -884, -70, - -253, -842, 4823, 15268, 12711, 2022, -888, -73, -247, -850, 4741, 15219, 12790, 2082, -892, -76, - -241, -857, 4659, 15168, 12869, 2143, -896, -79, -235, -864, 4578, 15117, 12947, 2205, -899, -82, - -229, -870, 4498, 15065, 13025, 2267, -903, -85, -223, -876, 4417, 15012, 13102, 2331, -906, -89, - -217, -882, 4338, 14958, 13178, 2394, -909, -92, -211, -887, 4259, 14903, 13254, 2459, -911, -96, - -206, -892, 4180, 14847, 13329, 2523, -914, -100, -200, -896, 4102, 14790, 13403, 2589, -916, -103, - -195, -900, 4024, 14732, 13477, 2655, -918, -107, -190, -904, 3947, 14673, 13550, 2722, -919, -111, - -184, -908, 3871, 14614, 13622, 2789, -921, -115, -179, -911, 3795, 14553, 13693, 2857, -922, -119, - -174, -913, 3719, 14492, 13764, 2926, -923, -123, -169, -916, 3644, 14430, 13834, 2995, -923, -127, - -164, -918, 3570, 14367, 13904, 3065, -924, -132, -159, -920, 3496, 14303, 13972, 3136, -924, -136, - -154, -921, 3423, 14239, 14040, 3207, -924, -140, -150, -922, 3350, 14173, 14107, 3278, -923, -145, - -145, -923, 3278, 14107, 14173, 3350, -922, -150, -140, -924, 3207, 14040, 14239, 3423, -921, -154, - -136, -924, 3136, 13972, 14303, 3496, -920, -159, -132, -924, 3065, 13904, 14367, 3570, -918, -164, - -127, -923, 2995, 13834, 14430, 3644, -916, -169, -123, -923, 2926, 13764, 14492, 3719, -913, -174, - -119, -922, 2857, 13693, 14553, 3795, -911, -179, -115, -921, 2789, 13622, 14614, 3871, -908, -184, - -111, -919, 2722, 13550, 14673, 3947, -904, -190, -107, -918, 2655, 13477, 14732, 4024, -900, -195, - -103, -916, 2589, 13403, 14790, 4102, -896, -200, -100, -914, 2523, 13329, 14847, 4180, -892, -206, - -96, -911, 2459, 13254, 14903, 4259, -887, -211, -92, -909, 2394, 13178, 14958, 4338, -882, -217, - -89, -906, 2331, 13102, 15012, 4417, -876, -223, -85, -903, 2267, 13025, 15065, 4498, -870, -229, - -82, -899, 2205, 12947, 15117, 4578, -864, -235, -79, -896, 2143, 12869, 15168, 4659, -857, -241, - -76, -892, 2082, 12790, 15219, 4741, -850, -247, -73, -888, 2022, 12711, 15268, 4823, -842, -253, - -70, -884, 1962, 12631, 15317, 4905, -834, -259, -67, -880, 1902, 12551, 15364, 4988, -826, -265, - -64, -875, 1844, 12470, 15410, 5071, -817, -272, -61, -871, 1786, 12388, 15456, 5155, -807, -278, - -58, -866, 1729, 12306, 15500, 5239, -798, -285, -56, -861, 1672, 12224, 15544, 5323, -787, -291, - -53, -855, 1616, 12140, 15586, 5408, -777, -298, -50, -850, 1561, 12057, 15627, 5493, -766, -305, - -48, -845, 1506, 11973, 15668, 5579, -754, -312, -46, -839, 1452, 11888, 15707, 5665, -742, -318, - -43, -833, 1399, 11803, 15745, 5751, -730, -325, -41, -827, 1346, 11718, 15782, 5838, -717, -332, - -39, -821, 1294, 11632, 15818, 5925, -703, -339, -37, -815, 1243, 11546, 15853, 6013, -689, -347, - -35, -809, 1192, 11459, 15887, 6100, -675, -354, -33, -802, 1142, 11372, 15920, 6189, -660, -361, - -31, -796, 1093, 11285, 15952, 6277, -645, -368, -29, -789, 1044, 11197, 15983, 6366, -629, -376, - -27, -782, 996, 11109, 16012, 6454, -612, -383, -26, -775, 949, 11021, 16041, 6544, -596, -391, - -24, -768, 902, 10932, 16068, 6633, -578, -398, -22, -761, 856, 10843, 16095, 6723, -560, -406, - -21, -754, 810, 10754, 16120, 6813, -542, -414, -19, -747, 766, 10664, 16144, 6903, -523, -421, - -18, -739, 722, 10574, 16167, 6994, -503, -429, -16, -732, 678, 10484, 16189, 7084, -483, -437, - -15, -724, 635, 10394, 16209, 7175, -462, -445, -14, -717, 593, 10303, 16229, 7266, -441, -452, - -13, -709, 552, 10212, 16247, 7357, -419, -460, -11, -702, 511, 10121, 16265, 7449, -397, -468, - -10, -694, 471, 10030, 16281, 7540, -374, -476, -9, -686, 432, 9939, 16296, 7632, -351, -484, - -8, -678, 393, 9847, 16310, 7724, -327, -492, -7, -670, 355, 9756, 16322, 7816, -302, -500, - -6, -662, 317, 9664, 16334, 7908, -277, -508, -5, -654, 280, 9572, 16344, 8000, -251, -516, - -5, -646, 244, 9480, 16354, 8093, -225, -525, -4, -638, 208, 9387, 16362, 8185, -198, -533, - -3, -630, 173, 9295, 16369, 8277, -170, -541, -2, -622, 139, 9203, 16375, 8370, -142, -549, - -2, -614, 105, 9110, 16379, 8462, -113, -557, -1, -606, 72, 9018, 16383, 8555, -84, -565, - -1, -598, 40, 8925, 16385, 8647, -54, -573, 0, -590, 8, 8833, 16386, 8740, -23, -582, - }; - - private static short[] _highCurveLut1 = new short[] - { - -12, 47, -134, 32767, 81, -16, 2, 0, -26, 108, -345, 32760, 301, -79, 17, -1, - -40, 168, -552, 32745, 526, -144, 32, -2, -53, 226, -753, 32723, 755, -210, 47, -3, - -66, 284, -950, 32694, 989, -277, 63, -5, -78, 340, -1143, 32658, 1226, -346, 79, -6, - -90, 394, -1331, 32615, 1469, -415, 96, -8, -101, 447, -1514, 32564, 1715, -486, 113, -9, - -112, 499, -1692, 32506, 1966, -557, 130, -11, -123, 550, -1865, 32441, 2221, -630, 148, -13, - -133, 599, -2034, 32369, 2480, -703, 166, -14, -143, 646, -2198, 32290, 2743, -778, 185, -16, - -152, 693, -2357, 32204, 3010, -853, 204, -18, -162, 738, -2512, 32110, 3281, -929, 223, -20, - -170, 781, -2662, 32010, 3555, -1007, 242, -23, -178, 823, -2807, 31903, 3834, -1084, 262, -25, - -186, 864, -2947, 31789, 4116, -1163, 282, -27, -194, 903, -3082, 31668, 4403, -1242, 303, -30, - -201, 940, -3213, 31540, 4692, -1322, 323, -32, -207, 977, -3339, 31406, 4985, -1403, 344, -35, - -214, 1011, -3460, 31265, 5282, -1484, 365, -37, -220, 1045, -3577, 31117, 5582, -1566, 387, -40, - -225, 1077, -3688, 30963, 5885, -1648, 409, -43, -230, 1107, -3796, 30802, 6191, -1730, 431, -46, - -235, 1136, -3898, 30635, 6501, -1813, 453, -49, -240, 1164, -3996, 30462, 6813, -1896, 475, -52, - -244, 1190, -4089, 30282, 7128, -1980, 498, -55, -247, 1215, -4178, 30097, 7446, -2064, 520, -58, - -251, 1239, -4262, 29905, 7767, -2148, 543, -62, -254, 1261, -4342, 29707, 8091, -2231, 566, -65, - -257, 1281, -4417, 29503, 8416, -2315, 589, -69, -259, 1301, -4488, 29293, 8745, -2399, 613, -72, - -261, 1319, -4555, 29078, 9075, -2483, 636, -76, -263, 1336, -4617, 28857, 9408, -2567, 659, -80, - -265, 1351, -4674, 28631, 9743, -2651, 683, -83, -266, 1365, -4728, 28399, 10080, -2734, 706, -87, - -267, 1378, -4777, 28161, 10418, -2817, 730, -91, -267, 1389, -4822, 27919, 10759, -2899, 753, -95, - -268, 1400, -4863, 27671, 11100, -2981, 777, -99, -268, 1409, -4900, 27418, 11444, -3063, 800, -103, - -268, 1416, -4933, 27161, 11789, -3144, 824, -107, -267, 1423, -4962, 26898, 12135, -3224, 847, -112, - -267, 1428, -4987, 26631, 12482, -3303, 870, -116, -266, 1433, -5008, 26359, 12830, -3382, 893, -120, - -265, 1436, -5026, 26083, 13179, -3460, 916, -125, -264, 1438, -5039, 25802, 13529, -3537, 939, -129, - -262, 1438, -5049, 25517, 13880, -3613, 962, -133, -260, 1438, -5055, 25228, 14231, -3687, 984, -138, - -258, 1437, -5058, 24935, 14582, -3761, 1006, -142, -256, 1435, -5058, 24639, 14934, -3833, 1028, -147, - -254, 1431, -5053, 24338, 15286, -3904, 1049, -151, -252, 1427, -5046, 24034, 15638, -3974, 1071, -155, - -249, 1422, -5035, 23726, 15989, -4042, 1091, -160, -246, 1416, -5021, 23415, 16341, -4109, 1112, -164, - -243, 1408, -5004, 23101, 16691, -4174, 1132, -169, -240, 1400, -4984, 22783, 17042, -4237, 1152, -173, - -237, 1392, -4960, 22463, 17392, -4299, 1171, -178, -234, 1382, -4934, 22140, 17740, -4358, 1190, -182, - -230, 1371, -4905, 21814, 18088, -4416, 1209, -186, -227, 1360, -4873, 21485, 18435, -4472, 1226, -191, - -223, 1348, -4839, 21154, 18781, -4526, 1244, -195, -219, 1335, -4801, 20821, 19125, -4578, 1260, -199, - -215, 1321, -4761, 20486, 19468, -4627, 1277, -203, -211, 1307, -4719, 20148, 19809, -4674, 1292, -207, - -207, 1292, -4674, 19809, 20148, -4719, 1307, -211, -203, 1277, -4627, 19468, 20486, -4761, 1321, -215, - -199, 1260, -4578, 19125, 20821, -4801, 1335, -219, -195, 1244, -4526, 18781, 21154, -4839, 1348, -223, - -191, 1226, -4472, 18435, 21485, -4873, 1360, -227, -186, 1209, -4416, 18088, 21814, -4905, 1371, -230, - -182, 1190, -4358, 17740, 22140, -4934, 1382, -234, -178, 1171, -4299, 17392, 22463, -4960, 1392, -237, - -173, 1152, -4237, 17042, 22783, -4984, 1400, -240, -169, 1132, -4174, 16691, 23101, -5004, 1408, -243, - -164, 1112, -4109, 16341, 23415, -5021, 1416, -246, -160, 1091, -4042, 15989, 23726, -5035, 1422, -249, - -155, 1071, -3974, 15638, 24034, -5046, 1427, -252, -151, 1049, -3904, 15286, 24338, -5053, 1431, -254, - -147, 1028, -3833, 14934, 24639, -5058, 1435, -256, -142, 1006, -3761, 14582, 24935, -5058, 1437, -258, - -138, 984, -3687, 14231, 25228, -5055, 1438, -260, -133, 962, -3613, 13880, 25517, -5049, 1438, -262, - -129, 939, -3537, 13529, 25802, -5039, 1438, -264, -125, 916, -3460, 13179, 26083, -5026, 1436, -265, - -120, 893, -3382, 12830, 26359, -5008, 1433, -266, -116, 870, -3303, 12482, 26631, -4987, 1428, -267, - -112, 847, -3224, 12135, 26898, -4962, 1423, -267, -107, 824, -3144, 11789, 27161, -4933, 1416, -268, - -103, 800, -3063, 11444, 27418, -4900, 1409, -268, -99, 777, -2981, 11100, 27671, -4863, 1400, -268, - -95, 753, -2899, 10759, 27919, -4822, 1389, -267, -91, 730, -2817, 10418, 28161, -4777, 1378, -267, - -87, 706, -2734, 10080, 28399, -4728, 1365, -266, -83, 683, -2651, 9743, 28631, -4674, 1351, -265, - -80, 659, -2567, 9408, 28857, -4617, 1336, -263, -76, 636, -2483, 9075, 29078, -4555, 1319, -261, - -72, 613, -2399, 8745, 29293, -4488, 1301, -259, -69, 589, -2315, 8416, 29503, -4417, 1281, -257, - -65, 566, -2231, 8091, 29707, -4342, 1261, -254, -62, 543, -2148, 7767, 29905, -4262, 1239, -251, - -58, 520, -2064, 7446, 30097, -4178, 1215, -247, -55, 498, -1980, 7128, 30282, -4089, 1190, -244, - -52, 475, -1896, 6813, 30462, -3996, 1164, -240, -49, 453, -1813, 6501, 30635, -3898, 1136, -235, - -46, 431, -1730, 6191, 30802, -3796, 1107, -230, -43, 409, -1648, 5885, 30963, -3688, 1077, -225, - -40, 387, -1566, 5582, 31117, -3577, 1045, -220, -37, 365, -1484, 5282, 31265, -3460, 1011, -214, - -35, 344, -1403, 4985, 31406, -3339, 977, -207, -32, 323, -1322, 4692, 31540, -3213, 940, -201, - -30, 303, -1242, 4403, 31668, -3082, 903, -194, -27, 282, -1163, 4116, 31789, -2947, 864, -186, - -25, 262, -1084, 3834, 31903, -2807, 823, -178, -23, 242, -1007, 3555, 32010, -2662, 781, -170, - -20, 223, -929, 3281, 32110, -2512, 738, -162, -18, 204, -853, 3010, 32204, -2357, 693, -152, - -16, 185, -778, 2743, 32290, -2198, 646, -143, -14, 166, -703, 2480, 32369, -2034, 599, -133, - -13, 148, -630, 2221, 32441, -1865, 550, -123, -11, 130, -557, 1966, 32506, -1692, 499, -112, - -9, 113, -486, 1715, 32564, -1514, 447, -101, -8, 96, -415, 1469, 32615, -1331, 394, -90, - -6, 79, -346, 1226, 32658, -1143, 340, -78, -5, 63, -277, 989, 32694, -950, 284, -66, - -3, 47, -210, 755, 32723, -753, 226, -53, -2, 32, -144, 526, 32745, -552, 168, -40, - -1, 17, -79, 301, 32760, -345, 108, -26, 0, 2, -16, 81, 32767, -134, 47, -12, - }; - - private static short[] _highCurveLut2 = new short[] - { - 418, -2538, 6118, 24615, 6298, -2563, 417, 0, 420, -2512, 5939, 24611, 6479, -2588, 415, 1, - 421, -2485, 5761, 24605, 6662, -2612, 412, 2, 422, -2458, 5585, 24595, 6846, -2635, 409, 3, - 423, -2430, 5410, 24582, 7030, -2658, 406, 4, 423, -2402, 5236, 24565, 7216, -2680, 403, 5, - 423, -2373, 5064, 24546, 7403, -2701, 399, 6, 423, -2343, 4893, 24523, 7591, -2721, 395, 7, - 423, -2313, 4724, 24496, 7780, -2741, 391, 8, 422, -2283, 4556, 24467, 7970, -2759, 386, 9, - 421, -2252, 4390, 24434, 8161, -2777, 381, 11, 420, -2221, 4225, 24398, 8353, -2794, 376, 12, - 419, -2190, 4062, 24359, 8545, -2810, 370, 14, 418, -2158, 3900, 24316, 8739, -2825, 364, 15, - 416, -2126, 3740, 24271, 8933, -2839, 358, 17, 414, -2093, 3582, 24222, 9127, -2851, 351, 19, - 412, -2060, 3425, 24170, 9323, -2863, 344, 21, 410, -2027, 3270, 24115, 9519, -2874, 336, 22, - 407, -1993, 3117, 24056, 9715, -2884, 328, 24, 404, -1960, 2966, 23995, 9912, -2893, 319, 26, - 402, -1926, 2816, 23930, 10110, -2900, 311, 29, 398, -1892, 2668, 23863, 10308, -2907, 301, 31, - 395, -1858, 2522, 23792, 10506, -2912, 292, 33, 392, -1823, 2378, 23718, 10705, -2916, 282, 35, - 389, -1789, 2235, 23641, 10904, -2919, 271, 38, 385, -1754, 2095, 23561, 11103, -2920, 261, 40, - 381, -1719, 1956, 23478, 11303, -2921, 249, 43, 377, -1684, 1819, 23393, 11502, -2920, 238, 45, - 373, -1649, 1684, 23304, 11702, -2917, 225, 48, 369, -1615, 1551, 23212, 11902, -2914, 213, 51, - 365, -1580, 1420, 23118, 12102, -2909, 200, 54, 361, -1545, 1291, 23020, 12302, -2902, 186, 57, - 356, -1510, 1163, 22920, 12502, -2895, 173, 60, 352, -1475, 1038, 22817, 12702, -2885, 158, 63, - 347, -1440, 915, 22711, 12901, -2875, 143, 66, 342, -1405, 793, 22602, 13101, -2863, 128, 69, - 338, -1370, 674, 22491, 13300, -2849, 113, 73, 333, -1335, 557, 22377, 13499, -2834, 97, 76, - 328, -1301, 441, 22260, 13698, -2817, 80, 80, 323, -1266, 328, 22141, 13896, -2799, 63, 83, - 318, -1232, 217, 22019, 14094, -2779, 46, 87, 313, -1197, 107, 21894, 14291, -2758, 28, 91, - 307, -1163, 0, 21767, 14488, -2735, 9, 95, 302, -1129, -105, 21637, 14684, -2710, -9, 98, - 297, -1096, -208, 21506, 14879, -2684, -29, 102, 292, -1062, -310, 21371, 15074, -2656, -48, 106, - 286, -1029, -409, 21234, 15268, -2626, -69, 111, 281, -996, -506, 21095, 15461, -2595, -89, 115, - 276, -963, -601, 20954, 15654, -2562, -110, 119, 270, -930, -694, 20810, 15846, -2527, -132, 123, - 265, -898, -785, 20664, 16036, -2490, -154, 128, 260, -866, -874, 20516, 16226, -2452, -176, 132, - 254, -834, -961, 20366, 16415, -2411, -199, 137, 249, -803, -1046, 20213, 16602, -2369, -222, 141, - 243, -771, -1129, 20059, 16789, -2326, -246, 146, 238, -740, -1209, 19902, 16974, -2280, -270, 151, - 233, -710, -1288, 19744, 17158, -2232, -294, 156, 227, -680, -1365, 19583, 17341, -2183, -319, 160, - 222, -650, -1440, 19421, 17523, -2132, -345, 165, 217, -620, -1513, 19257, 17703, -2079, -370, 170, - 211, -591, -1583, 19091, 17882, -2023, -396, 175, 206, -562, -1652, 18923, 18059, -1966, -423, 180, - 201, -533, -1719, 18754, 18235, -1907, -450, 185, 196, -505, -1784, 18582, 18410, -1847, -477, 191, - 191, -477, -1847, 18410, 18582, -1784, -505, 196, 185, -450, -1907, 18235, 18754, -1719, -533, 201, - 180, -423, -1966, 18059, 18923, -1652, -562, 206, 175, -396, -2023, 17882, 19091, -1583, -591, 211, - 170, -370, -2079, 17703, 19257, -1513, -620, 217, 165, -345, -2132, 17523, 19421, -1440, -650, 222, - 160, -319, -2183, 17341, 19583, -1365, -680, 227, 156, -294, -2232, 17158, 19744, -1288, -710, 233, - 151, -270, -2280, 16974, 19902, -1209, -740, 238, 146, -246, -2326, 16789, 20059, -1129, -771, 243, - 141, -222, -2369, 16602, 20213, -1046, -803, 249, 137, -199, -2411, 16415, 20366, -961, -834, 254, - 132, -176, -2452, 16226, 20516, -874, -866, 260, 128, -154, -2490, 16036, 20664, -785, -898, 265, - 123, -132, -2527, 15846, 20810, -694, -930, 270, 119, -110, -2562, 15654, 20954, -601, -963, 276, - 115, -89, -2595, 15461, 21095, -506, -996, 281, 111, -69, -2626, 15268, 21234, -409, -1029, 286, - 106, -48, -2656, 15074, 21371, -310, -1062, 292, 102, -29, -2684, 14879, 21506, -208, -1096, 297, - 98, -9, -2710, 14684, 21637, -105, -1129, 302, 95, 9, -2735, 14488, 21767, 0, -1163, 307, - 91, 28, -2758, 14291, 21894, 107, -1197, 313, 87, 46, -2779, 14094, 22019, 217, -1232, 318, - 83, 63, -2799, 13896, 22141, 328, -1266, 323, 80, 80, -2817, 13698, 22260, 441, -1301, 328, - 76, 97, -2834, 13499, 22377, 557, -1335, 333, 73, 113, -2849, 13300, 22491, 674, -1370, 338, - 69, 128, -2863, 13101, 22602, 793, -1405, 342, 66, 143, -2875, 12901, 22711, 915, -1440, 347, - 63, 158, -2885, 12702, 22817, 1038, -1475, 352, 60, 173, -2895, 12502, 22920, 1163, -1510, 356, - 57, 186, -2902, 12302, 23020, 1291, -1545, 361, 54, 200, -2909, 12102, 23118, 1420, -1580, 365, - 51, 213, -2914, 11902, 23212, 1551, -1615, 369, 48, 225, -2917, 11702, 23304, 1684, -1649, 373, - 45, 238, -2920, 11502, 23393, 1819, -1684, 377, 43, 249, -2921, 11303, 23478, 1956, -1719, 381, - 40, 261, -2920, 11103, 23561, 2095, -1754, 385, 38, 271, -2919, 10904, 23641, 2235, -1789, 389, - 35, 282, -2916, 10705, 23718, 2378, -1823, 392, 33, 292, -2912, 10506, 23792, 2522, -1858, 395, - 31, 301, -2907, 10308, 23863, 2668, -1892, 398, 29, 311, -2900, 10110, 23930, 2816, -1926, 402, - 26, 319, -2893, 9912, 23995, 2966, -1960, 404, 24, 328, -2884, 9715, 24056, 3117, -1993, 407, - 22, 336, -2874, 9519, 24115, 3270, -2027, 410, 21, 344, -2863, 9323, 24170, 3425, -2060, 412, - 19, 351, -2851, 9127, 24222, 3582, -2093, 414, 17, 358, -2839, 8933, 24271, 3740, -2126, 416, - 15, 364, -2825, 8739, 24316, 3900, -2158, 418, 14, 370, -2810, 8545, 24359, 4062, -2190, 419, - 12, 376, -2794, 8353, 24398, 4225, -2221, 420, 11, 381, -2777, 8161, 24434, 4390, -2252, 421, - 9, 386, -2759, 7970, 24467, 4556, -2283, 422, 8, 391, -2741, 7780, 24496, 4724, -2313, 423, - 7, 395, -2721, 7591, 24523, 4893, -2343, 423, 6, 399, -2701, 7403, 24546, 5064, -2373, 423, - 5, 403, -2680, 7216, 24565, 5236, -2402, 423, 4, 406, -2658, 7030, 24582, 5410, -2430, 423, - 3, 409, -2635, 6846, 24595, 5585, -2458, 422, 2, 412, -2612, 6662, 24605, 5761, -2485, 421, - 1, 415, -2588, 6479, 24611, 5939, -2512, 420, 0, 417, -2563, 6298, 24615, 6118, -2538, 418, - }; - #endregion - - private static float[] _normalCurveLut0F; - private static float[] _normalCurveLut1F; - private static float[] _normalCurveLut2F; - - private static float[] _highCurveLut0F; - private static float[] _highCurveLut1F; - private static float[] _highCurveLut2F; - - static ResamplerHelper() - { - _normalCurveLut0F = _normalCurveLut0.Select(x => x / 32768f).ToArray(); - _normalCurveLut1F = _normalCurveLut1.Select(x => x / 32768f).ToArray(); - _normalCurveLut2F = _normalCurveLut2.Select(x => x / 32768f).ToArray(); - - _highCurveLut0F = _highCurveLut0.Select(x => x / 32768f).ToArray(); - _highCurveLut1F = _highCurveLut1.Select(x => x / 32768f).ToArray(); - _highCurveLut2F = _highCurveLut2.Select(x => x / 32768f).ToArray(); - } - - private const int FixedPointPrecision = 15; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Resample(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount, SampleRateConversionQuality srcQuality, bool needPitch) - { - switch (srcQuality) - { - case SampleRateConversionQuality.Default: - ResampleDefaultQuality(outputBuffer, inputBuffer, ratio, ref fraction, sampleCount, needPitch); - break; - case SampleRateConversionQuality.Low: - ResampleLowQuality(outputBuffer, inputBuffer, ratio, ref fraction, sampleCount); - break; - case SampleRateConversionQuality.High: - ResampleHighQuality(outputBuffer, inputBuffer, ratio, ref fraction, sampleCount); - break; - default: - throw new NotImplementedException($"{srcQuality}"); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ReadOnlySpan<float> GetDefaultParameter(float ratio) - { - if (ratio <= 1.0f) - { - return _normalCurveLut1F; - } - else if (ratio > 1.333313f) - { - return _normalCurveLut0F; - } - - return _normalCurveLut2F; - } - - private unsafe static void ResampleDefaultQuality(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount, bool needPitch) - { - ReadOnlySpan<float> parameters = GetDefaultParameter(ratio); - - int inputBufferIndex = 0, i = 0; - - // TODO: REV8 fast path (when needPitch == false the input index progression is constant + we need SIMD) - - if (Sse41.IsSupported) - { - if (ratio == 1f) - { - fixed (short* pInput = inputBuffer) - fixed (float* pOutput = outputBuffer, pParameters = parameters) - { - Vector128<float> parameter = Sse.LoadVector128(pParameters); - - for (; i < (sampleCount & ~3); i += 4) - { - Vector128<int> intInput0 = Sse41.ConvertToVector128Int32(pInput + (uint)i); - Vector128<int> intInput1 = Sse41.ConvertToVector128Int32(pInput + (uint)i + 1); - Vector128<int> intInput2 = Sse41.ConvertToVector128Int32(pInput + (uint)i + 2); - Vector128<int> intInput3 = Sse41.ConvertToVector128Int32(pInput + (uint)i + 3); - - Vector128<float> input0 = Sse2.ConvertToVector128Single(intInput0); - Vector128<float> input1 = Sse2.ConvertToVector128Single(intInput1); - Vector128<float> input2 = Sse2.ConvertToVector128Single(intInput2); - Vector128<float> input3 = Sse2.ConvertToVector128Single(intInput3); - - Vector128<float> mix0 = Sse.Multiply(input0, parameter); - Vector128<float> mix1 = Sse.Multiply(input1, parameter); - Vector128<float> mix2 = Sse.Multiply(input2, parameter); - Vector128<float> mix3 = Sse.Multiply(input3, parameter); - - Vector128<float> mix01 = Sse3.HorizontalAdd(mix0, mix1); - Vector128<float> mix23 = Sse3.HorizontalAdd(mix2, mix3); - - Vector128<float> mix0123 = Sse3.HorizontalAdd(mix01, mix23); - - Sse.Store(pOutput + (uint)i, Sse41.RoundToNearestInteger(mix0123)); - } - } - - inputBufferIndex = i; - } - else - { - fixed (short* pInput = inputBuffer) - fixed (float* pOutput = outputBuffer, pParameters = parameters) - { - for (; i < (sampleCount & ~3); i += 4) - { - uint baseIndex0 = (uint)(fraction * 128) * 4; - uint inputIndex0 = (uint)inputBufferIndex; - - fraction += ratio; - - uint baseIndex1 = ((uint)(fraction * 128) & 127) * 4; - uint inputIndex1 = (uint)inputBufferIndex + (uint)fraction; - - fraction += ratio; - - uint baseIndex2 = ((uint)(fraction * 128) & 127) * 4; - uint inputIndex2 = (uint)inputBufferIndex + (uint)fraction; - - fraction += ratio; - - uint baseIndex3 = ((uint)(fraction * 128) & 127) * 4; - uint inputIndex3 = (uint)inputBufferIndex + (uint)fraction; - - fraction += ratio; - inputBufferIndex += (int)fraction; - - // Only keep lower part (safe as fraction isn't supposed to be negative) - fraction -= (int)fraction; - - Vector128<float> parameter0 = Sse.LoadVector128(pParameters + baseIndex0); - Vector128<float> parameter1 = Sse.LoadVector128(pParameters + baseIndex1); - Vector128<float> parameter2 = Sse.LoadVector128(pParameters + baseIndex2); - Vector128<float> parameter3 = Sse.LoadVector128(pParameters + baseIndex3); - - Vector128<int> intInput0 = Sse41.ConvertToVector128Int32(pInput + inputIndex0); - Vector128<int> intInput1 = Sse41.ConvertToVector128Int32(pInput + inputIndex1); - Vector128<int> intInput2 = Sse41.ConvertToVector128Int32(pInput + inputIndex2); - Vector128<int> intInput3 = Sse41.ConvertToVector128Int32(pInput + inputIndex3); - - Vector128<float> input0 = Sse2.ConvertToVector128Single(intInput0); - Vector128<float> input1 = Sse2.ConvertToVector128Single(intInput1); - Vector128<float> input2 = Sse2.ConvertToVector128Single(intInput2); - Vector128<float> input3 = Sse2.ConvertToVector128Single(intInput3); - - Vector128<float> mix0 = Sse.Multiply(input0, parameter0); - Vector128<float> mix1 = Sse.Multiply(input1, parameter1); - Vector128<float> mix2 = Sse.Multiply(input2, parameter2); - Vector128<float> mix3 = Sse.Multiply(input3, parameter3); - - Vector128<float> mix01 = Sse3.HorizontalAdd(mix0, mix1); - Vector128<float> mix23 = Sse3.HorizontalAdd(mix2, mix3); - - Vector128<float> mix0123 = Sse3.HorizontalAdd(mix01, mix23); - - Sse.Store(pOutput + (uint)i, Sse41.RoundToNearestInteger(mix0123)); - } - } - } - } - - for (; i < sampleCount; i++) - { - int baseIndex = (int)(fraction * 128) * 4; - ReadOnlySpan<float> parameter = parameters.Slice(baseIndex, 4); - ReadOnlySpan<short> currentInput = inputBuffer.Slice(inputBufferIndex, 4); - - outputBuffer[i] = (float)Math.Round(currentInput[0] * parameter[0] + - currentInput[1] * parameter[1] + - currentInput[2] * parameter[2] + - currentInput[3] * parameter[3]); - - fraction += ratio; - inputBufferIndex += (int)fraction; - - // Only keep lower part (safe as fraction isn't supposed to be negative) - fraction -= (int)fraction; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ReadOnlySpan<float> GetHighParameter(float ratio) - { - if (ratio <= 1.0f) - { - return _highCurveLut1F; - } - else if (ratio > 1.333313f) - { - return _highCurveLut0F; - } - - return _highCurveLut2F; - } - - private static unsafe void ResampleHighQuality(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount) - { - ReadOnlySpan<float> parameters = GetHighParameter(ratio); - - int inputBufferIndex = 0; - - if (Avx2.IsSupported) - { - // Fast path; assumes 256-bit vectors for simplicity because the filter is 8 taps - fixed (short* pInput = inputBuffer) - fixed (float* pParameters = parameters) - { - for (int i = 0; i < sampleCount; i++) - { - int baseIndex = (int)(fraction * 128) * 8; - - Vector256<int> intInput = Avx2.ConvertToVector256Int32(pInput + inputBufferIndex); - Vector256<float> floatInput = Avx.ConvertToVector256Single(intInput); - Vector256<float> parameter = Avx.LoadVector256(pParameters + baseIndex); - Vector256<float> dp = Avx.DotProduct(floatInput, parameter, control: 0xFF); - - // avx2 does an 8-element dot product piecewise so we have to sum up 2 intermediate results - outputBuffer[i] = (float)Math.Round(dp[0] + dp[4]); - - fraction += ratio; - inputBufferIndex += (int)MathF.Truncate(fraction); - - fraction -= (int)fraction; - } - } - } - else - { - for (int i = 0; i < sampleCount; i++) - { - int baseIndex = (int)(fraction * 128) * 8; - ReadOnlySpan<float> parameter = parameters.Slice(baseIndex, 8); - ReadOnlySpan<short> currentInput = inputBuffer.Slice(inputBufferIndex, 8); - - outputBuffer[i] = (float)Math.Round(currentInput[0] * parameter[0] + - currentInput[1] * parameter[1] + - currentInput[2] * parameter[2] + - currentInput[3] * parameter[3] + - currentInput[4] * parameter[4] + - currentInput[5] * parameter[5] + - currentInput[6] * parameter[6] + - currentInput[7] * parameter[7]); - - fraction += ratio; - inputBufferIndex += (int)MathF.Truncate(fraction); - - fraction -= (int)fraction; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ResampleLowQuality(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount) - { - int inputBufferIndex = 0; - - for (int i = 0; i < sampleCount; i++) - { - int outputData = inputBuffer[inputBufferIndex]; - - if (fraction > 1.0f) - { - outputData = inputBuffer[inputBufferIndex + 1]; - } - - outputBuffer[i] = outputData; - - fraction += ratio; - inputBufferIndex += (int)MathF.Truncate(fraction); - - fraction -= (int)fraction; - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/AdpcmLoopContext.cs b/Ryujinx.Audio/Renderer/Dsp/State/AdpcmLoopContext.cs deleted file mode 100644 index 821a135e..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/AdpcmLoopContext.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 6)] - public struct AdpcmLoopContext - { - public short PredScale; - public short History0; - public short History1; - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/AuxiliaryBufferHeader.cs b/Ryujinx.Audio/Renderer/Dsp/State/AuxiliaryBufferHeader.cs deleted file mode 100644 index 4e8d11e4..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/AuxiliaryBufferHeader.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Ryujinx.Memory; -using System.Runtime.InteropServices; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x80)] - public struct AuxiliaryBufferHeader - { - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x40)] - public struct AuxiliaryBufferInfo - { - private const uint ReadOffsetPosition = 0x0; - private const uint WriteOffsetPosition = 0x4; - private const uint LostSampleCountPosition = 0x8; - private const uint TotalSampleCountPosition = 0xC; - - public uint ReadOffset; - public uint WriteOffset; - public uint LostSampleCount; - public uint TotalSampleCount; - private unsafe fixed uint _unknown[12]; - - public static uint GetReadOffset(IVirtualMemoryManager manager, ulong bufferAddress) - { - return manager.Read<uint>(bufferAddress + ReadOffsetPosition); - } - - public static uint GetWriteOffset(IVirtualMemoryManager manager, ulong bufferAddress) - { - return manager.Read<uint>(bufferAddress + WriteOffsetPosition); - } - - public static uint GetLostSampleCount(IVirtualMemoryManager manager, ulong bufferAddress) - { - return manager.Read<uint>(bufferAddress + LostSampleCountPosition); - } - - public static uint GetTotalSampleCount(IVirtualMemoryManager manager, ulong bufferAddress) - { - return manager.Read<uint>(bufferAddress + TotalSampleCountPosition); - } - - public static void SetReadOffset(IVirtualMemoryManager manager, ulong bufferAddress, uint value) - { - manager.Write(bufferAddress + ReadOffsetPosition, value); - } - - public static void SetWriteOffset(IVirtualMemoryManager manager, ulong bufferAddress, uint value) - { - manager.Write(bufferAddress + WriteOffsetPosition, value); - } - - public static void SetLostSampleCount(IVirtualMemoryManager manager, ulong bufferAddress, uint value) - { - manager.Write(bufferAddress + LostSampleCountPosition, value); - } - - public static void SetTotalSampleCount(IVirtualMemoryManager manager, ulong bufferAddress, uint value) - { - manager.Write(bufferAddress + TotalSampleCountPosition, value); - } - - public static void Reset(IVirtualMemoryManager manager, ulong bufferAddress) - { - // NOTE: Lost sample count is never reset, since REV10. - manager.Write(bufferAddress + ReadOffsetPosition, 0UL); - manager.Write(bufferAddress + TotalSampleCountPosition, 0); - } - } - - public AuxiliaryBufferInfo CpuBufferInfo; - public AuxiliaryBufferInfo DspBufferInfo; - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/BiquadFilterState.cs b/Ryujinx.Audio/Renderer/Dsp/State/BiquadFilterState.cs deleted file mode 100644 index 4220e6d5..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/BiquadFilterState.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x10)] - public struct BiquadFilterState - { - public float State0; - public float State1; - public float State2; - public float State3; - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs b/Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs deleted file mode 100644 index 76aff807..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.Effect; -using Ryujinx.Audio.Renderer.Parameter.Effect; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - public class CompressorState - { - public ExponentialMovingAverage InputMovingAverage; - public float Unknown4; - public ExponentialMovingAverage CompressionGainAverage; - public float CompressorGainReduction; - public float Unknown10; - public float Unknown14; - public float PreviousCompressionEmaAlpha; - public float MakeupGain; - public float OutputGain; - - public CompressorState(ref CompressorParameter parameter) - { - InputMovingAverage = new ExponentialMovingAverage(0.0f); - Unknown4 = 1.0f; - CompressionGainAverage = new ExponentialMovingAverage(1.0f); - - UpdateParameter(ref parameter); - } - - public void UpdateParameter(ref CompressorParameter parameter) - { - float threshold = parameter.Threshold; - float ratio = 1.0f / parameter.Ratio; - float attackCoefficient = parameter.AttackCoefficient; - float makeupGain; - - if (parameter.MakeupGainEnabled) - { - makeupGain = (threshold * 0.5f * (ratio - 1.0f)) - 3.0f; - } - else - { - makeupGain = 0.0f; - } - - PreviousCompressionEmaAlpha = attackCoefficient; - MakeupGain = makeupGain; - CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax; - Unknown10 = threshold - 1.5f; - Unknown14 = threshold + 1.5f; - OutputGain = FloatingPointHelper.DecibelToLinearExtended(parameter.OutputGain + makeupGain); - } - } -} diff --git a/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs b/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs deleted file mode 100644 index 2a1e7f83..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.Effect; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - public class DelayState - { - public DelayLine[] DelayLines { get; } - public float[] LowPassZ { get; set; } - public float FeedbackGain { get; private set; } - public float DelayFeedbackBaseGain { get; private set; } - public float DelayFeedbackCrossGain { get; private set; } - public float LowPassFeedbackGain { get; private set; } - public float LowPassBaseGain { get; private set; } - - private const int FixedPointPrecision = 14; - - public DelayState(ref DelayParameter parameter, ulong workBuffer) - { - DelayLines = new DelayLine[parameter.ChannelCount]; - LowPassZ = new float[parameter.ChannelCount]; - - uint sampleRate = (uint)FixedPointHelper.ToInt(parameter.SampleRate, FixedPointPrecision) / 1000; - - for (int i = 0; i < DelayLines.Length; i++) - { - DelayLines[i] = new DelayLine(sampleRate, parameter.DelayTimeMax); - DelayLines[i].SetDelay(parameter.DelayTime); - } - - UpdateParameter(ref parameter); - } - - public void UpdateParameter(ref DelayParameter parameter) - { - FeedbackGain = FixedPointHelper.ToFloat(parameter.FeedbackGain, FixedPointPrecision) * 0.98f; - - float channelSpread = FixedPointHelper.ToFloat(parameter.ChannelSpread, FixedPointPrecision); - - DelayFeedbackBaseGain = (1.0f - channelSpread) * FeedbackGain; - - if (parameter.ChannelCount == 4 || parameter.ChannelCount == 6) - { - DelayFeedbackCrossGain = channelSpread * 0.5f * FeedbackGain; - } - else - { - DelayFeedbackCrossGain = channelSpread * FeedbackGain; - } - - LowPassFeedbackGain = 0.95f * FixedPointHelper.ToFloat(parameter.LowPassAmount, FixedPointPrecision); - LowPassBaseGain = 1.0f - LowPassFeedbackGain; - } - - public void UpdateLowPassFilter(ref float tempRawRef, uint channelCount) - { - for (int i = 0; i < channelCount; i++) - { - float lowPassResult = LowPassFeedbackGain * LowPassZ[i] + Unsafe.Add(ref tempRawRef, i) * LowPassBaseGain; - - LowPassZ[i] = lowPassResult; - DelayLines[i].Update(lowPassResult); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs b/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs deleted file mode 100644 index 0560757c..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.Effect; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - public class LimiterState - { - public ExponentialMovingAverage[] DetectorAverage; - public ExponentialMovingAverage[] CompressionGainAverage; - public float[] DelayedSampleBuffer; - public int[] DelayedSampleBufferPosition; - - public LimiterState(ref LimiterParameter parameter, ulong workBuffer) - { - DetectorAverage = new ExponentialMovingAverage[parameter.ChannelCount]; - CompressionGainAverage = new ExponentialMovingAverage[parameter.ChannelCount]; - DelayedSampleBuffer = new float[parameter.ChannelCount * parameter.DelayBufferSampleCountMax]; - DelayedSampleBufferPosition = new int[parameter.ChannelCount]; - - DetectorAverage.AsSpan().Fill(new ExponentialMovingAverage(0.0f)); - CompressionGainAverage.AsSpan().Fill(new ExponentialMovingAverage(1.0f)); - DelayedSampleBufferPosition.AsSpan().Fill(0); - DelayedSampleBuffer.AsSpan().Fill(0.0f); - - UpdateParameter(ref parameter); - } - - public void UpdateParameter(ref LimiterParameter parameter) { } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs b/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs deleted file mode 100644 index c0646603..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/Reverb3dState.cs +++ /dev/null @@ -1,119 +0,0 @@ -using Ryujinx.Audio.Renderer.Dsp.Effect; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - public class Reverb3dState - { - 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[] DecayDelayMaxTimes1 = new float[4] { 17.0f, 13.0f, 9.0f, 7.0f }; - private readonly float[] DecayDelayMaxTimes2 = new float[4] { 19.0f, 11.0f, 10.0f, 6.0f }; - private readonly float[] EarlyDelayTimes = new float[20] { 0.017136f, 0.059154f, 0.16173f, 0.39019f, 0.42526f, 0.45541f, 0.68974f, 0.74591f, 0.83384f, 0.8595f, 0.0f, 0.075024f, 0.16879f, 0.2999f, 0.33744f, 0.3719f, 0.59901f, 0.71674f, 0.81786f, 0.85166f }; - public readonly float[] EarlyGain = new float[20] { 0.67096f, 0.61027f, 1.0f, 0.35680f, 0.68361f, 0.65978f, 0.51939f, 0.24712f, 0.45945f, 0.45021f, 0.64196f, 0.54879f, 0.92925f, 0.38270f, 0.72867f, 0.69794f, 0.5464f, 0.24563f, 0.45214f, 0.44042f }; - - public IDelayLine[] FdnDelayLines { get; } - public DecayDelay[] DecayDelays1 { get; } - public DecayDelay[] DecayDelays2 { get; } - public IDelayLine PreDelayLine { get; } - public IDelayLine FrontCenterDelayLine { get; } - public float DryGain { get; private set; } - public uint[] EarlyDelayTime { get; private set; } - public float PreviousPreDelayValue { get; set; } - public float PreviousPreDelayGain { get; private set; } - public float TargetPreDelayGain { get; private set; } - public float EarlyReflectionsGain { get; private set; } - public float LateReverbGain { get; private set; } - public uint ReflectionDelayTime { get; private set; } - public float EchoLateReverbDecay { get; private set; } - public float[] DecayDirectFdnGain { get; private set; } - public float[] DecayCurrentFdnGain { get; private set; } - public float[] DecayCurrentOutputGain { get; private set; } - public float[] PreviousFeedbackOutputDecayed { get; private set; } - - public Reverb3dState(ref Reverb3dParameter parameter, ulong workBuffer) - { - FdnDelayLines = new IDelayLine[4]; - DecayDelays1 = new DecayDelay[4]; - DecayDelays2 = new DecayDelay[4]; - DecayDirectFdnGain = new float[4]; - DecayCurrentFdnGain = new float[4]; - DecayCurrentOutputGain = new float[4]; - PreviousFeedbackOutputDecayed = new float[4]; - - uint sampleRate = parameter.SampleRate / 1000; - - for (int i = 0; i < 4; i++) - { - FdnDelayLines[i] = new DelayLine3d(sampleRate, FdnDelayMaxTimes[i]); - DecayDelays1[i] = new DecayDelay(new DelayLine3d(sampleRate, DecayDelayMaxTimes1[i])); - DecayDelays2[i] = new DecayDelay(new DelayLine3d(sampleRate, DecayDelayMaxTimes2[i])); - } - - PreDelayLine = new DelayLine3d(sampleRate, 400); - FrontCenterDelayLine = new DelayLine3d(sampleRate, 5); - - UpdateParameter(ref parameter); - } - - public void UpdateParameter(ref Reverb3dParameter parameter) - { - uint sampleRate = parameter.SampleRate / 1000; - - EarlyDelayTime = new uint[20]; - DryGain = parameter.DryGain; - PreviousFeedbackOutputDecayed.AsSpan().Fill(0); - PreviousPreDelayValue = 0; - - EarlyReflectionsGain = FloatingPointHelper.Pow10(Math.Min(parameter.RoomGain + parameter.ReflectionsGain, 5000.0f) / 2000.0f); - LateReverbGain = FloatingPointHelper.Pow10(Math.Min(parameter.RoomGain + parameter.ReverbGain, 5000.0f) / 2000.0f); - - float highFrequencyRoomGain = FloatingPointHelper.Pow10(parameter.RoomHf / 2000.0f); - - if (highFrequencyRoomGain < 1.0f) - { - float tempA = 1.0f - highFrequencyRoomGain; - float tempB = 2.0f - ((2.0f * highFrequencyRoomGain) * FloatingPointHelper.Cos(256.0f * parameter.HfReference / parameter.SampleRate)); - float tempC = MathF.Sqrt(MathF.Pow(tempB, 2) - (4.0f * (1.0f - highFrequencyRoomGain) * (1.0f - highFrequencyRoomGain))); - - PreviousPreDelayGain = (tempB - tempC) / (2.0f * tempA); - TargetPreDelayGain = 1.0f - PreviousPreDelayGain; - } - else - { - PreviousPreDelayGain = 0.0f; - TargetPreDelayGain = 1.0f; - } - - ReflectionDelayTime = IDelayLine.GetSampleCount(sampleRate, 1000.0f * (parameter.ReflectionDelay + parameter.ReverbDelayTime)); - EchoLateReverbDecay = 0.6f * parameter.Diffusion * 0.01f; - - for (int i = 0; i < FdnDelayLines.Length; i++) - { - FdnDelayLines[i].SetDelay(FdnDelayMinTimes[i] + (parameter.Density / 100 * (FdnDelayMaxTimes[i] - FdnDelayMinTimes[i]))); - - uint tempSampleCount = FdnDelayLines[i].CurrentSampleCount + DecayDelays1[i].CurrentSampleCount + DecayDelays2[i].CurrentSampleCount; - - float tempA = (-60.0f * tempSampleCount) / (parameter.DecayTime * parameter.SampleRate); - float tempB = tempA / parameter.HfDecayRatio; - float tempC = FloatingPointHelper.Cos(128.0f * 0.5f * parameter.HfReference / parameter.SampleRate) / FloatingPointHelper.Sin(128.0f * 0.5f * parameter.HfReference / parameter.SampleRate); - float tempD = FloatingPointHelper.Pow10((tempB - tempA) / 40.0f); - float tempE = FloatingPointHelper.Pow10((tempB + tempA) / 40.0f) * 0.7071f; - - DecayDirectFdnGain[i] = tempE * ((tempD * tempC) + 1.0f) / (tempC + tempD); - DecayCurrentFdnGain[i] = tempE * (1.0f - (tempD * tempC)) / (tempC + tempD); - DecayCurrentOutputGain[i] = (tempC - tempD) / (tempC + tempD); - - DecayDelays1[i].SetDecayRate(EchoLateReverbDecay); - DecayDelays2[i].SetDecayRate(EchoLateReverbDecay * -0.9f); - } - - for (int i = 0; i < EarlyDelayTime.Length; i++) - { - uint sampleCount = Math.Min(IDelayLine.GetSampleCount(sampleRate, (parameter.ReflectionDelay * 1000.0f) + (EarlyDelayTimes[i] * 1000.0f * ((parameter.ReverbDelayTime * 0.9998f) + 0.02f))), PreDelayLine.SampleCountMax); - EarlyDelayTime[i] = sampleCount; - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs b/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs deleted file mode 100644 index 1ffabe05..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/State/ReverbState.cs +++ /dev/null @@ -1,204 +0,0 @@ -using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Audio.Renderer.Dsp.Effect; -using Ryujinx.Audio.Renderer.Parameter.Effect; -using System; - -namespace Ryujinx.Audio.Renderer.Dsp.State -{ - public class ReverbState - { - private static readonly float[] FdnDelayTimes = new float[20] - { - // Room - 53.953247f, 79.192566f, 116.238770f, 130.615295f, - // Hall - 53.953247f, 79.192566f, 116.238770f, 170.615295f, - // Plate - 5f, 10f, 5f, 10f, - // Cathedral - 47.03f, 71f, 103f, 170f, - // Max delay (Hall is the one with the highest values so identical to Hall) - 53.953247f, 79.192566f, 116.238770f, 170.615295f, - }; - - private static readonly float[] DecayDelayTimes = new float[20] - { - // Room - 7f, 9f, 13f, 17f, - // Hall - 7f, 9f, 13f, 17f, - // Plate (no decay) - 1f, 1f, 1f, 1f, - // Cathedral - 7f, 7f, 13f, 9f, - // Max delay (Hall is the one with the highest values so identical to Hall) - 7f, 9f, 13f, 17f, - }; - - private static readonly float[] EarlyDelayTimes = new float[50] - { - // Room - 0.0f, 3.5f, 2.8f, 3.9f, 2.7f, 13.4f, 7.9f, 8.4f, 9.9f, 12.0f, - // Chamber - 0.0f, 11.8f, 5.5f, 11.2f, 10.4f, 38.1f, 22.2f, 29.6f, 21.2f, 24.8f, - // Hall - 0.0f, 41.5f, 20.5f, 41.3f, 0.0f, 29.5f, 33.8f, 45.2f, 46.8f, 0.0f, - // Cathedral - 33.1f, 43.3f, 22.8f, 37.9f, 14.9f, 35.3f, 17.9f, 34.2f, 0.0f, 43.3f, - // Disabled - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f - }; - - private static readonly float[] EarlyGainBase = new float[50] - { - // Room - 0.70f, 0.68f, 0.70f, 0.68f, 0.70f, 0.68f, 0.70f, 0.68f, 0.68f, 0.68f, - // Chamber - 0.70f, 0.68f, 0.70f, 0.68f, 0.70f, 0.68f, 0.68f, 0.68f, 0.68f, 0.68f, - // Hall - 0.50f, 0.70f, 0.70f, 0.68f, 0.50f, 0.68f, 0.68f, 0.70f, 0.68f, 0.00f, - // Cathedral - 0.93f, 0.92f, 0.87f, 0.86f, 0.94f, 0.81f, 0.80f, 0.77f, 0.76f, 0.65f, - // Disabled - 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f - }; - - private static readonly float[] PreDelayTimes = new float[5] - { - // Room - 12.5f, - // Chamber - 40.0f, - // Hall - 50.0f, - // Cathedral - 50.0f, - // Disabled - 0.0f - }; - - public DelayLine[] FdnDelayLines { get; } - public DecayDelay[] DecayDelays { get; } - public DelayLine PreDelayLine { get; } - public DelayLine FrontCenterDelayLine { get; } - public uint[] EarlyDelayTime { get; } - public float[] EarlyGain { get; } - public uint PreDelayLineDelayTime { get; private set; } - - public float[] HighFrequencyDecayDirectGain { get; } - public float[] HighFrequencyDecayPreviousGain { get; } - public float[] PreviousFeedbackOutput { get; } - - public const int EarlyModeCount = 10; - - private const int FixedPointPrecision = 14; - - private ReadOnlySpan<float> GetFdnDelayTimesByLateMode(ReverbLateMode lateMode) - { - return FdnDelayTimes.AsSpan((int)lateMode * 4, 4); - } - - private ReadOnlySpan<float> GetDecayDelayTimesByLateMode(ReverbLateMode lateMode) - { - return DecayDelayTimes.AsSpan((int)lateMode * 4, 4); - } - - public ReverbState(ref ReverbParameter parameter, ulong workBuffer, bool isLongSizePreDelaySupported) - { - FdnDelayLines = new DelayLine[4]; - DecayDelays = new DecayDelay[4]; - EarlyDelayTime = new uint[EarlyModeCount]; - EarlyGain = new float[EarlyModeCount]; - HighFrequencyDecayDirectGain = new float[4]; - HighFrequencyDecayPreviousGain = new float[4]; - PreviousFeedbackOutput = new float[4]; - - ReadOnlySpan<float> fdnDelayTimes = GetFdnDelayTimesByLateMode(ReverbLateMode.Limit); - ReadOnlySpan<float> decayDelayTimes = GetDecayDelayTimesByLateMode(ReverbLateMode.Limit); - - uint sampleRate = (uint)FixedPointHelper.ToFloat((uint)parameter.SampleRate, FixedPointPrecision); - - for (int i = 0; i < 4; i++) - { - FdnDelayLines[i] = new DelayLine(sampleRate, fdnDelayTimes[i]); - DecayDelays[i] = new DecayDelay(new DelayLine(sampleRate, decayDelayTimes[i])); - } - - float preDelayTimeMax = 150.0f; - - if (isLongSizePreDelaySupported) - { - preDelayTimeMax = 350.0f; - } - - PreDelayLine = new DelayLine(sampleRate, preDelayTimeMax); - FrontCenterDelayLine = new DelayLine(sampleRate, 5.0f); - - UpdateParameter(ref parameter); - } - - public void UpdateParameter(ref ReverbParameter parameter) - { - uint sampleRate = (uint)FixedPointHelper.ToFloat((uint)parameter.SampleRate, FixedPointPrecision); - - float preDelayTimeInMilliseconds = FixedPointHelper.ToFloat(parameter.PreDelayTime, FixedPointPrecision); - float earlyGain = FixedPointHelper.ToFloat(parameter.EarlyGain, FixedPointPrecision); - float coloration = FixedPointHelper.ToFloat(parameter.Coloration, FixedPointPrecision); - float decayTime = FixedPointHelper.ToFloat(parameter.DecayTime, FixedPointPrecision); - - for (int i = 0; i < 10; i++) - { - EarlyDelayTime[i] = Math.Min(IDelayLine.GetSampleCount(sampleRate, EarlyDelayTimes[i] + preDelayTimeInMilliseconds), PreDelayLine.SampleCountMax) + 1; - EarlyGain[i] = EarlyGainBase[i] * earlyGain; - } - - if (parameter.ChannelCount == 2) - { - EarlyGain[4] = EarlyGain[4] * 0.5f; - EarlyGain[5] = EarlyGain[5] * 0.5f; - } - - PreDelayLineDelayTime = Math.Min(IDelayLine.GetSampleCount(sampleRate, PreDelayTimes[(int)parameter.EarlyMode] + preDelayTimeInMilliseconds), PreDelayLine.SampleCountMax); - - ReadOnlySpan<float> fdnDelayTimes = GetFdnDelayTimesByLateMode(parameter.LateMode); - ReadOnlySpan<float> decayDelayTimes = GetDecayDelayTimesByLateMode(parameter.LateMode); - - float highFrequencyDecayRatio = FixedPointHelper.ToFloat(parameter.HighFrequencyDecayRatio, FixedPointPrecision); - float highFrequencyUnknownValue = FloatingPointHelper.Cos(1280.0f / sampleRate); - - for (int i = 0; i < 4; i++) - { - FdnDelayLines[i].SetDelay(fdnDelayTimes[i]); - DecayDelays[i].SetDelay(decayDelayTimes[i]); - - float tempA = -3 * (DecayDelays[i].CurrentSampleCount + FdnDelayLines[i].CurrentSampleCount); - float tempB = tempA / (decayTime * sampleRate); - float tempC; - float tempD; - - if (highFrequencyDecayRatio < 0.995f) - { - float tempE = FloatingPointHelper.Pow10((((1.0f / highFrequencyDecayRatio) - 1.0f) * 2) / 100 * (tempB / 10)); - float tempF = 1.0f - tempE; - float tempG = 2.0f - (tempE * 2 * highFrequencyUnknownValue); - float tempH = MathF.Sqrt((tempG * tempG) - (tempF * tempF * 4)); - - tempC = (tempG - tempH) / (tempF * 2); - tempD = 1.0f - tempC; - } - else - { - // no high frequency decay ratio - tempC = 0.0f; - tempD = 1.0f; - } - - HighFrequencyDecayDirectGain[i] = FloatingPointHelper.Pow10(tempB / 1000) * tempD * 0.7071f; - HighFrequencyDecayPreviousGain[i] = tempC; - PreviousFeedbackOutput[i] = 0.0f; - - DecayDelays[i].SetDecayRate(0.6f * (1.0f - coloration)); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs b/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs deleted file mode 100644 index 6cdab5a7..00000000 --- a/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs +++ /dev/null @@ -1,192 +0,0 @@ -using Ryujinx.Audio.Renderer.Server.Upsampler; -using Ryujinx.Common.Memory; -using System; -using System.Diagnostics; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Audio.Renderer.Dsp -{ - public class UpsamplerHelper - { - private const int HistoryLength = UpsamplerBufferState.HistoryLength; - private const int FilterBankLength = 20; - // Bank0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - private const int Bank0CenterIndex = 9; - private static readonly Array20<float> Bank1 = PrecomputeFilterBank(1.0f / 6.0f); - private static readonly Array20<float> Bank2 = PrecomputeFilterBank(2.0f / 6.0f); - private static readonly Array20<float> Bank3 = PrecomputeFilterBank(3.0f / 6.0f); - private static readonly Array20<float> Bank4 = PrecomputeFilterBank(4.0f / 6.0f); - private static readonly Array20<float> Bank5 = PrecomputeFilterBank(5.0f / 6.0f); - - private static Array20<float> PrecomputeFilterBank(float offset) - { - float Sinc(float x) - { - if (x == 0) - { - return 1.0f; - } - return (MathF.Sin(MathF.PI * x) / (MathF.PI * x)); - } - - float BlackmanWindow(float x) - { - const float a = 0.18f; - const float a0 = 0.5f - 0.5f * a; - const float a1 = -0.5f; - const float a2 = 0.5f * a; - return a0 + a1 * MathF.Cos(2 * MathF.PI * x) + a2 * MathF.Cos(4 * MathF.PI * x); - } - - Array20<float> result = new Array20<float>(); - - for (int i = 0; i < FilterBankLength; i++) - { - float x = (Bank0CenterIndex - i) + offset; - result[i] = Sinc(x) * BlackmanWindow(x / FilterBankLength + 0.5f); - } - - return result; - } - - // Polyphase upsampling algorithm - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Upsample(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, int outputSampleCount, int inputSampleCount, ref UpsamplerBufferState state) - { - if (!state.Initialized) - { - state.Scale = inputSampleCount switch - { - 40 => 6.0f, - 80 => 3.0f, - 160 => 1.5f, - _ => throw new ArgumentOutOfRangeException() - }; - state.Initialized = true; - } - - if (outputSampleCount == 0) - { - return; - } - - float DoFilterBank(ref UpsamplerBufferState state, in Array20<float> bank) - { - float result = 0.0f; - - Debug.Assert(state.History.Length == HistoryLength); - Debug.Assert(bank.Length == FilterBankLength); - - int curIdx = 0; - if (Vector.IsHardwareAccelerated) - { - // Do SIMD-accelerated block operations where possible. - // Only about a 2x speedup since filter bank length is short - int stopIdx = FilterBankLength - (FilterBankLength % Vector<float>.Count); - while (curIdx < stopIdx) - { - result += Vector.Dot( - new Vector<float>(bank.AsSpan().Slice(curIdx, Vector<float>.Count)), - new Vector<float>(state.History.AsSpan().Slice(curIdx, Vector<float>.Count))); - curIdx += Vector<float>.Count; - } - } - - while (curIdx < FilterBankLength) - { - result += bank[curIdx] * state.History[curIdx]; - curIdx++; - } - - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void NextInput(ref UpsamplerBufferState state, float input) - { - state.History.AsSpan().Slice(1).CopyTo(state.History.AsSpan()); - state.History[HistoryLength - 1] = input; - } - - int inputBufferIndex = 0; - - switch (state.Scale) - { - case 6.0f: - for (int i = 0; i < outputSampleCount; i++) - { - switch (state.Phase) - { - case 0: - NextInput(ref state, inputBuffer[inputBufferIndex++]); - outputBuffer[i] = state.History[Bank0CenterIndex]; - break; - case 1: - outputBuffer[i] = DoFilterBank(ref state, Bank1); - break; - case 2: - outputBuffer[i] = DoFilterBank(ref state, Bank2); - break; - case 3: - outputBuffer[i] = DoFilterBank(ref state, Bank3); - break; - case 4: - outputBuffer[i] = DoFilterBank(ref state, Bank4); - break; - case 5: - outputBuffer[i] = DoFilterBank(ref state, Bank5); - break; - } - - state.Phase = (state.Phase + 1) % 6; - } - break; - case 3.0f: - for (int i = 0; i < outputSampleCount; i++) - { - switch (state.Phase) - { - case 0: - NextInput(ref state, inputBuffer[inputBufferIndex++]); - outputBuffer[i] = state.History[Bank0CenterIndex]; - break; - case 1: - outputBuffer[i] = DoFilterBank(ref state, Bank2); - break; - case 2: - outputBuffer[i] = DoFilterBank(ref state, Bank4); - break; - } - - state.Phase = (state.Phase + 1) % 3; - } - break; - case 1.5f: - // Upsample by 3 then decimate by 2. - for (int i = 0; i < outputSampleCount; i++) - { - switch (state.Phase) - { - case 0: - NextInput(ref state, inputBuffer[inputBufferIndex++]); - outputBuffer[i] = state.History[Bank0CenterIndex]; - break; - case 1: - outputBuffer[i] = DoFilterBank(ref state, Bank4); - break; - case 2: - NextInput(ref state, inputBuffer[inputBufferIndex++]); - outputBuffer[i] = DoFilterBank(ref state, Bank2); - break; - } - - state.Phase = (state.Phase + 1) % 3; - } - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } -}
\ No newline at end of file |
