diff --git a/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs b/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs index f6638a9af..2680dcb1e 100644 --- a/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs +++ b/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs @@ -1,4 +1,5 @@ using Ryujinx.Audio.Renderer.Dsp.State; +using Ryujinx.Common.Logging; using System; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -71,6 +72,19 @@ namespace Ryujinx.Audio.Renderer.Dsp return (short)value; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static short GetCoefficientAtIndex(ReadOnlySpan 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 output, ReadOnlySpan input, int startSampleOffset, int endSampleOffset, int offset, int count, ReadOnlySpan coefficients, ref AdpcmLoopContext loopContext) { @@ -84,8 +98,8 @@ namespace Ryujinx.Audio.Renderer.Dsp byte coefficientIndex = (byte)((predScale >> 4) & 0xF); short history0 = loopContext.History0; short history1 = loopContext.History1; - short coefficient0 = coefficients[coefficientIndex * 2 + 0]; - short coefficient1 = coefficients[coefficientIndex * 2 + 1]; + 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); @@ -109,8 +123,8 @@ namespace Ryujinx.Audio.Renderer.Dsp coefficientIndex = (byte)((predScale >> 4) & 0xF); - coefficient0 = coefficients[coefficientIndex * 2 + 0]; - coefficient1 = coefficients[coefficientIndex * 2 + 1]; + coefficient0 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2); + coefficient1 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 1); nibbles += 2; diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs index 1ad629f49..1fe6069f7 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.AdpcmDataSourceVersion1; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort OutputBufferIndex { get; } public uint SampleRate { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs index cfa5400c1..5c3c0324b 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.AuxiliaryBuffer; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public uint InputBufferIndex { get; } public uint OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs index e35911b24..b994c1cb9 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.BiquadFilter; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public Memory BiquadFilterState { get; } public int InputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs index ab1ea77d9..da1cb2546 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.CaptureBuffer; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public uint InputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs index 27cd6e842..e50637eb3 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.CircularBufferSink; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort[] Input { get; } public uint InputCount { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs index c3530db1a..9e653e804 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.ClearMixBuffer; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ClearMixBufferCommand(int nodeId) { diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs index 64c297d11..7237fddf6 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.CopyMixBuffer; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort InputBufferIndex { get; } public ushort OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs index f602262e3..c1503b6a0 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType { get; } - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort OutputBufferIndex { get; } public uint SampleRate { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs index 8f11da958..cb5678c7b 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Delay; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public DelayParameter Parameter => _parameter; public Memory State { get; } @@ -49,15 +49,15 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]); } - // NOTE: We do the opposite as Nintendo here for now to restore previous behaviour - // TODO: Update delay processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. - DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices); - DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices); + 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); @@ -70,7 +70,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command float temp = input * inGain + delayLineValue * feedbackGain; - state.UpdateLowPassFilter(ref temp, 1); + state.UpdateLowPassFilter(ref temp, channelCount); outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64; } @@ -104,7 +104,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command Y = state.DelayLines[1].Read(), }; - Vector2 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain; + Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; state.UpdateLowPassFilter(ref Unsafe.As(ref temp), channelCount); @@ -148,7 +148,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command W = state.DelayLines[3].Read() }; - Vector4 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain; + Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; state.UpdateLowPassFilter(ref Unsafe.As(ref temp), channelCount); @@ -171,12 +171,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision); float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision); - Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain, 0.0f, 0.0f, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, - 0.0f, delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f, - delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, 0.0f, - 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, 0.0f, - delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackBaseGain, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, feedbackGain); + 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++) { @@ -200,7 +200,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command U = state.DelayLines[5].Read() }; - Vector6 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain; + Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; state.UpdateLowPassFilter(ref Unsafe.As(ref temp), channelCount); diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs index e3a87c102..1dba56e6c 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.DepopForMixBuffers; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public uint MixBufferOffset { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs index 1e37ff715..d02f7c121 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.DepopPrepare; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public uint MixBufferCount { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs index a34fbc562..9c88a4e7f 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.DeviceSink; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public string DeviceName { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs index d75da6f9f..79cefcc53 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.DownMixSurroundToStereo; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort[] InputBufferIndices { get; } public ushort[] OutputBufferIndices { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs index ae1ab12c5..b190cc10d 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/GroupedBiquadFilterCommand.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.GroupedBiquadFilter; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } private BiquadFilterParameter[] _parameters; private Memory _biquadFilterStates; @@ -47,9 +47,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } } - // NOTE: Nintendo also implements a hot path for 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. - // TODO: Implement double biquad filters fast path. + // 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); diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs index dddd2511e..d281e6e9f 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/ICommand.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType { get; } - public ulong EstimatedProcessingTime { get; } + public uint EstimatedProcessingTime { get; } public void Process(CommandList context); diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs index a393c8859..9cfef736e 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.LimiterVersion1; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public LimiterParameter Parameter => _parameter; public Memory State { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs index ad703de14..46c95e4f9 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.LimiterVersion2; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public LimiterParameter Parameter => _parameter; public Memory State { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs index d50309964..2616bda57 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Mix; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort InputBufferIndex { get; } public ushort OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs index 06af9f6fa..76a1aba25 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.MixRamp; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort InputBufferIndex { get; } public ushort OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs index 97bb0f508..e348e3588 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.MixRampGrouped; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public uint MixBufferCount { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs index 7c48a511c..7cec7d2ab 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort OutputBufferIndex { get; } public uint SampleRate { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs index 8483f6d41..dfe9814fe 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort OutputBufferIndex { get; } public uint SampleRate { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs index c2f94474d..d3e3f8056 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Performance; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public PerformanceEntryAddresses PerformanceEntryAddresses { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs index 04809245f..eeb645673 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Reverb3d; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort InputBufferIndex { get; } public ushort OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs index 130706d10..0a32a065d 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Reverb; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ReverbParameter Parameter => _parameter; public Memory State { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs index 6df44b327..1617a6421 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Upsample; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public uint BufferCount { get; } public uint InputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs index e29478911..0628f6d81 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.Volume; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort InputBufferIndex { get; } public ushort OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs index ffda8b1a0..5c0c88451 100644 --- a/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs +++ b/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public CommandType CommandType => CommandType.VolumeRamp; - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } public ushort InputBufferIndex { get; } public ushort OutputBufferIndex { get; } diff --git a/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs b/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs index af163ae04..34fdef8a1 100644 --- a/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs +++ b/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs @@ -28,6 +28,7 @@ namespace Ryujinx.Audio.Renderer.Server { private object _lock = new object(); + private AudioRendererRenderingDevice _renderingDevice; private AudioRendererExecutionMode _executionMode; private IWritableEvent _systemEvent; private ManualResetEvent _terminationEvent; @@ -63,6 +64,7 @@ namespace Ryujinx.Audio.Renderer.Server private uint _renderingTimeLimitPercent; private bool _voiceDropEnabled; private uint _voiceDropCount; + private float _voiceDropParameter; private bool _isDspRunningBehind; private ICommandProcessingTimeEstimator _commandProcessingTimeEstimator; @@ -95,6 +97,7 @@ namespace Ryujinx.Audio.Renderer.Server _totalElapsedTicksUpdating = 0; _sessionId = 0; + _voiceDropParameter = 1.0f; } public ResultCode Initialize( @@ -130,6 +133,7 @@ namespace Ryujinx.Audio.Renderer.Server _upsamplerCount = parameter.SinkCount + parameter.SubMixBufferCount; _appletResourceId = appletResourceId; _memoryPoolCount = parameter.EffectCount + parameter.VoiceCount * Constants.VoiceWaveBufferCount; + _renderingDevice = parameter.RenderingDevice; _executionMode = parameter.ExecutionMode; _sessionId = sessionId; MemoryManager = memoryManager; @@ -337,6 +341,7 @@ namespace Ryujinx.Audio.Renderer.Server _processHandle = processHandle; _elapsedFrameCount = 0; + _voiceDropParameter = 1.0f; switch (_behaviourContext.GetCommandProcessingTimeEstimatorVersion()) { @@ -515,7 +520,7 @@ namespace Ryujinx.Audio.Renderer.Server return (ulong)(_manager.TickSource.ElapsedSeconds * Constants.TargetTimerFrequency); } - private uint ComputeVoiceDrop(CommandBuffer commandBuffer, long voicesEstimatedTime, long deltaTimeDsp) + private uint ComputeVoiceDrop(CommandBuffer commandBuffer, uint voicesEstimatedTime, long deltaTimeDsp) { int i; @@ -584,7 +589,7 @@ namespace Ryujinx.Audio.Renderer.Server { command.Enabled = false; - voicesEstimatedTime -= (long)command.EstimatedProcessingTime; + voicesEstimatedTime -= (uint)(_voiceDropParameter * command.EstimatedProcessingTime); } } } @@ -618,13 +623,13 @@ namespace Ryujinx.Audio.Renderer.Server _voiceContext.Sort(); commandGenerator.GenerateVoices(); - long voicesEstimatedTime = (long)commandBuffer.EstimatedProcessingTime; + uint voicesEstimatedTime = (uint)(_voiceDropParameter * commandBuffer.EstimatedProcessingTime); commandGenerator.GenerateSubMixes(); commandGenerator.GenerateFinalMixes(); commandGenerator.GenerateSinks(); - long totalEstimatedTime = (long)commandBuffer.EstimatedProcessingTime; + uint totalEstimatedTime = (uint)(_voiceDropParameter * commandBuffer.EstimatedProcessingTime); if (_voiceDropEnabled) { @@ -856,5 +861,26 @@ namespace Ryujinx.Audio.Renderer.Server } } } + + public void SetVoiceDropParameter(float voiceDropParameter) + { + _voiceDropParameter = Math.Clamp(voiceDropParameter, 0.0f, 2.0f); + } + + public float GetVoiceDropParameter() + { + return _voiceDropParameter; + } + + public ResultCode ExecuteAudioRendererRendering() + { + if (_executionMode == AudioRendererExecutionMode.Manual && _renderingDevice == AudioRendererRenderingDevice.Cpu) + { + // NOTE: Here Nintendo aborts with this error code, we don't want that. + return ResultCode.InvalidExecutionContextOperation; + } + + return ResultCode.UnsupportedOperation; + } } } \ No newline at end of file diff --git a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs index 417204151..adf5294ea 100644 --- a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs +++ b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs @@ -94,8 +94,9 @@ namespace Ryujinx.Audio.Renderer.Server /// REV11: /// The "legacy" effects (Delay, Reverb and Reverb 3D) were updated to match the standard channel mapping used by the audio renderer. /// A new version of the command estimator was added to address timing changes caused by the legacy effects changes. + /// A voice drop parameter was added in 15.0.0: This allows an application to amplify or attenuate the estimated time of DSP commands. /// - /// This was added in system update 14.0.0 + /// This was added in system update 14.0.0 but some changes were made in 15.0.0 public const int Revision11 = 11 << 24; /// diff --git a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 3a3a981d7..e0741cc6e 100644 --- a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -25,7 +25,7 @@ namespace Ryujinx.Audio.Renderer.Server /// /// The estimated total processing time. /// - public ulong EstimatedProcessingTime { get; set; } + public uint EstimatedProcessingTime { get; set; } /// /// The command list that is populated by the . diff --git a/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs b/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs index cf0fc067e..6c79da157 100644 --- a/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs +++ b/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs @@ -263,12 +263,12 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool return UpdateResult.Success; } - if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress & (pageSize - 1)) != 0) + if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % pageSize) != 0) { return UpdateResult.InvalidParameter; } - if (inParameter.Size == 0 || (inParameter.Size & (pageSize - 1)) != 0) + if (inParameter.Size == 0 || (inParameter.Size % pageSize) != 0) { return UpdateResult.InvalidParameter; } diff --git a/Ryujinx.Audio/ResultCode.cs b/Ryujinx.Audio/ResultCode.cs index 8e0bfcb0c..1d05ac65e 100644 --- a/Ryujinx.Audio/ResultCode.cs +++ b/Ryujinx.Audio/ResultCode.cs @@ -17,5 +17,6 @@ namespace Ryujinx.Audio InvalidAddressInfo = (42 << ErrorCodeShift) | ModuleId, InvalidMixSorting = (43 << ErrorCodeShift) | ModuleId, UnsupportedOperation = (513 << ErrorCodeShift) | ModuleId, + InvalidExecutionContextOperation = (514 << ErrorCodeShift) | ModuleId, } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRenderer.cs index d69bde037..5b682bf84 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRenderer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRenderer.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer public ResultCode ExecuteAudioRendererRendering() { - throw new NotImplementedException(); + return (ResultCode)_impl.ExecuteAudioRendererRendering(); } public uint GetMixBufferCount() @@ -108,5 +108,15 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer _impl.Dispose(); } } + + public void SetVoiceDropParameter(float voiceDropParameter) + { + _impl.SetVoiceDropParameter(voiceDropParameter); + } + + public float GetVoiceDropParameter() + { + return _impl.GetVoiceDropParameter(); + } } } diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs index dd48a666b..b2ddb697a 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs @@ -172,6 +172,35 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer return result; } + [CommandHipc(11)] // 3.0.0+ + // ExecuteAudioRendererRendering() + public ResultCode ExecuteAudioRendererRendering(ServiceCtx context) + { + return _impl.ExecuteAudioRendererRendering(); + } + + [CommandHipc(12)] // 15.0.0+ + // SetVoiceDropParameter(f32 voiceDropParameter) + public ResultCode SetVoiceDropParameter(ServiceCtx context) + { + float voiceDropParameter = context.RequestData.ReadSingle(); + + _impl.SetVoiceDropParameter(voiceDropParameter); + + return ResultCode.Success; + } + + [CommandHipc(13)] // 15.0.0+ + // GetVoiceDropParameter() -> f32 voiceDropParameter + public ResultCode GetVoiceDropParameter(ServiceCtx context) + { + float voiceDropParameter = _impl.GetVoiceDropParameter(); + + context.ResponseData.Write(voiceDropParameter); + + return ResultCode.Success; + } + protected override void Dispose(bool isDisposing) { if (isDisposing) diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/IAudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/IAudioRenderer.cs index a59c94e97..404bf4c10 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/IAudioRenderer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/IAudioRenderer.cs @@ -16,5 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer void SetRenderingTimeLimit(uint percent); uint GetRenderingTimeLimit(); ResultCode ExecuteAudioRendererRendering(); + void SetVoiceDropParameter(float voiceDropParameter); + float GetVoiceDropParameter(); } }