amadeus: Update to REV10 (#2654)
* amadeus: Update to REV10 This implements all the changes made with REV10 on 13.0.0. * Address Ack's comment * Address gdkchan's comment
This commit is contained in:
parent
fe9d5a1981
commit
e17eb7bfaf
29 changed files with 923 additions and 96 deletions
|
@ -360,6 +360,9 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
case 3:
|
||||
_commandProcessingTimeEstimator = new CommandProcessingTimeEstimatorVersion3(_sampleCount, _mixBufferCount);
|
||||
break;
|
||||
case 4:
|
||||
_commandProcessingTimeEstimator = new CommandProcessingTimeEstimatorVersion4(_sampleCount, _mixBufferCount);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"Unsupported processing time estimator version {_behaviourContext.GetCommandProcessingTimeEstimatorVersion()}.");
|
||||
}
|
||||
|
|
|
@ -97,10 +97,20 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
/// <remarks>This was added in system update 12.0.0</remarks>
|
||||
public const int Revision9 = 9 << 24;
|
||||
|
||||
/// <summary>
|
||||
/// REV10:
|
||||
/// Added Bluetooth audio device support and removed the unused "GetAudioSystemMasterVolumeSetting" audio device API.
|
||||
/// A new effect was added: Capture. This effect allows the client side to capture audio buffers of a mix.
|
||||
/// A new command was added for double biquad filters on voices. This is implemented using a direct form 1 (instead of the usual direct form 2).
|
||||
/// A new version of the command estimator was added to support the new commands.
|
||||
/// </summary>
|
||||
/// <remarks>This was added in system update 13.0.0</remarks>
|
||||
public const int Revision10 = 10 << 24;
|
||||
|
||||
/// <summary>
|
||||
/// Last revision supported by the implementation.
|
||||
/// </summary>
|
||||
public const int LastRevision = Revision9;
|
||||
public const int LastRevision = Revision10;
|
||||
|
||||
/// <summary>
|
||||
/// Target revision magic supported by the implementation.
|
||||
|
@ -347,12 +357,26 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision9);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the audio renderer should use an optimized Biquad Filter (Direct Form 1) in case of two biquad filters are defined on a voice.
|
||||
/// </summary>
|
||||
/// <returns>True if the audio renderer should use the optimization.</returns>
|
||||
public bool IsBiquadFilterGroupedOptimizationSupported()
|
||||
{
|
||||
return CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version of the <see cref="ICommandProcessingTimeEstimator"/>.
|
||||
/// </summary>
|
||||
/// <returns>The version of the <see cref="ICommandProcessingTimeEstimator"/>.</returns>
|
||||
public int GetCommandProcessingTimeEstimatorVersion()
|
||||
{
|
||||
if (CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision10))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (CheckFeatureSupported(UserRevision, BaseRevisionMagic + Revision8))
|
||||
{
|
||||
return 3;
|
||||
|
|
|
@ -24,6 +24,7 @@ using Ryujinx.Audio.Renderer.Server.Performance;
|
|||
using Ryujinx.Audio.Renderer.Server.Sink;
|
||||
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
||||
using Ryujinx.Audio.Renderer.Server.Voice;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using CpuAddress = System.UInt64;
|
||||
|
||||
|
@ -220,6 +221,25 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
AddCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="GroupedBiquadFilterCommand"/>.
|
||||
/// </summary>
|
||||
/// <param name="baseIndex">The base index of the input and output buffer.</param>
|
||||
/// <param name="filters">The biquad filter parameters.</param>
|
||||
/// <param name="biquadFilterStatesMemory">The biquad states.</param>
|
||||
/// <param name="inputBufferOffset">The input buffer offset.</param>
|
||||
/// <param name="outputBufferOffset">The output buffer offset.</param>
|
||||
/// <param name="isInitialized">Set to true if the biquad filter state is initialized.</param>
|
||||
/// <param name="nodeId">The node id associated to this command.</param>
|
||||
public void GenerateGroupedBiquadFilter(int baseIndex, ReadOnlySpan<BiquadFilterParameter> filters, Memory<BiquadFilterState> biquadFilterStatesMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId)
|
||||
{
|
||||
GroupedBiquadFilterCommand command = new GroupedBiquadFilterCommand(baseIndex, filters, biquadFilterStatesMemory, inputBufferOffset, outputBufferOffset, isInitialized, nodeId);
|
||||
|
||||
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
|
||||
|
||||
AddCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new <see cref="MixRampGroupedCommand"/>.
|
||||
/// </summary>
|
||||
|
@ -440,6 +460,30 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new <see cref="CaptureBufferCommand"/>.
|
||||
/// </summary>
|
||||
/// <param name="bufferOffset">The target buffer offset.</param>
|
||||
/// <param name="inputBufferOffset">The input buffer offset.</param>
|
||||
/// <param name="sendBufferInfo">The capture state.</param>
|
||||
/// <param name="isEnabled">Set to true if the effect should be active.</param>
|
||||
/// <param name="countMax">The limit of the circular buffer.</param>
|
||||
/// <param name="outputBuffer">The guest address of the output buffer.</param>
|
||||
/// <param name="updateCount">The count to add on the offset after write operations.</param>
|
||||
/// <param name="writeOffset">The write offset.</param>
|
||||
/// <param name="nodeId">The node id associated to this command.</param>
|
||||
public void GenerateCaptureEffect(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled, uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId)
|
||||
{
|
||||
if (sendBufferInfo != 0)
|
||||
{
|
||||
CaptureBufferCommand command = new CaptureBufferCommand(bufferOffset, inputBufferOffset, sendBufferInfo, isEnabled, countMax, outputBuffer, updateCount, writeOffset, nodeId);
|
||||
|
||||
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
|
||||
|
||||
AddCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new <see cref="VolumeCommand"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -151,23 +151,35 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
|
||||
private void GenerateBiquadFilterForVoice(ref VoiceState voiceState, Memory<VoiceUpdateState> state, int baseIndex, int bufferOffset, int nodeId)
|
||||
{
|
||||
for (int i = 0; i < voiceState.BiquadFilters.Length; i++)
|
||||
bool supportsOptimizedPath = _rendererContext.BehaviourContext.IsBiquadFilterGroupedOptimizationSupported();
|
||||
|
||||
if (supportsOptimizedPath && voiceState.BiquadFilters[0].Enable && voiceState.BiquadFilters[1].Enable)
|
||||
{
|
||||
ref BiquadFilterParameter filter = ref voiceState.BiquadFilters[i];
|
||||
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
|
||||
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
|
||||
|
||||
if (filter.Enable)
|
||||
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.ToSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < voiceState.BiquadFilters.Length; i++)
|
||||
{
|
||||
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
|
||||
ref BiquadFilterParameter filter = ref voiceState.BiquadFilters[i];
|
||||
|
||||
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
|
||||
if (filter.Enable)
|
||||
{
|
||||
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
|
||||
|
||||
_commandBuffer.GenerateBiquadFilter(baseIndex,
|
||||
ref filter,
|
||||
stateMemory.Slice(i, 1),
|
||||
bufferOffset,
|
||||
bufferOffset,
|
||||
!voiceState.BiquadFilterNeedInitialization[i],
|
||||
nodeId);
|
||||
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
|
||||
|
||||
_commandBuffer.GenerateBiquadFilter(baseIndex,
|
||||
ref filter,
|
||||
stateMemory.Slice(i, 1),
|
||||
bufferOffset,
|
||||
bufferOffset,
|
||||
!voiceState.BiquadFilterNeedInitialization[i],
|
||||
nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +455,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
|
||||
uint updateCount;
|
||||
|
||||
if ((channelIndex - 1) != 0)
|
||||
if (channelIndex != 1)
|
||||
{
|
||||
updateCount = 0;
|
||||
}
|
||||
|
@ -556,6 +568,52 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
}
|
||||
}
|
||||
|
||||
private void GenerateCaptureEffect(uint bufferOffset, CaptureBufferEffect effect, int nodeId)
|
||||
{
|
||||
Debug.Assert(effect.Type == EffectType.CaptureBuffer);
|
||||
|
||||
if (effect.IsEnabled)
|
||||
{
|
||||
effect.GetWorkBuffer(0);
|
||||
}
|
||||
|
||||
if (effect.State.SendBufferInfoBase != 0)
|
||||
{
|
||||
int i = 0;
|
||||
uint writeOffset = 0;
|
||||
|
||||
for (uint channelIndex = effect.Parameter.ChannelCount; channelIndex != 0; channelIndex--)
|
||||
{
|
||||
uint newUpdateCount = writeOffset + _commandBuffer.CommandList.SampleCount;
|
||||
|
||||
uint updateCount;
|
||||
|
||||
if (channelIndex != 1)
|
||||
{
|
||||
updateCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateCount = newUpdateCount;
|
||||
}
|
||||
|
||||
_commandBuffer.GenerateCaptureEffect(bufferOffset,
|
||||
effect.Parameter.Input[i],
|
||||
effect.State.SendBufferInfo,
|
||||
effect.IsEnabled,
|
||||
effect.Parameter.BufferStorageSize,
|
||||
effect.State.SendBufferInfoBase,
|
||||
updateCount,
|
||||
writeOffset,
|
||||
nodeId);
|
||||
|
||||
writeOffset = newUpdateCount;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateEffect(ref MixState mix, int effectId, BaseEffect effect)
|
||||
{
|
||||
int nodeId = mix.NodeId;
|
||||
|
@ -597,6 +655,9 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
case EffectType.Limiter:
|
||||
GenerateLimiterEffect(mix.BufferOffset, (LimiterEffect)effect, nodeId, effectId);
|
||||
break;
|
||||
case EffectType.CaptureBuffer:
|
||||
GenerateCaptureEffect(mix.BufferOffset, (CaptureBufferEffect)effect, nodeId);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"Unsupported effect type {effect.Type}");
|
||||
}
|
||||
|
|
|
@ -186,5 +186,15 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint Estimate(GroupedBiquadFilterCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint Estimate(CaptureBufferCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -550,5 +550,15 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint Estimate(GroupedBiquadFilterCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint Estimate(CaptureBufferCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
//
|
||||
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp.Command;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
|
@ -30,8 +29,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
/// </summary>
|
||||
public class CommandProcessingTimeEstimatorVersion3 : ICommandProcessingTimeEstimator
|
||||
{
|
||||
private uint _sampleCount;
|
||||
private uint _bufferCount;
|
||||
protected uint _sampleCount;
|
||||
protected uint _bufferCount;
|
||||
|
||||
public CommandProcessingTimeEstimatorVersion3(uint sampleCount, uint bufferCount)
|
||||
{
|
||||
|
@ -755,5 +754,15 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual uint Estimate(GroupedBiquadFilterCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual uint Estimate(CaptureBufferCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Ryujinx
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp.Command;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ICommandProcessingTimeEstimator"/> version 4. (added with REV10)
|
||||
/// </summary>
|
||||
public class CommandProcessingTimeEstimatorVersion4 : CommandProcessingTimeEstimatorVersion3
|
||||
{
|
||||
public CommandProcessingTimeEstimatorVersion4(uint sampleCount, uint bufferCount) : base(sampleCount, bufferCount) { }
|
||||
|
||||
public override uint Estimate(GroupedBiquadFilterCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)7424.5f;
|
||||
}
|
||||
|
||||
return (uint)9730.4f;
|
||||
}
|
||||
|
||||
public override uint Estimate(CaptureBufferCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
return (uint)435.2f;
|
||||
}
|
||||
|
||||
return (uint)4261.0f;
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
return (uint)5858.26f;
|
||||
}
|
||||
|
||||
return (uint)435.2f;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ using Ryujinx.Audio.Renderer.Server.MemoryPool;
|
|||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using static Ryujinx.Audio.Renderer.Dsp.State.AuxiliaryBufferHeader;
|
||||
using DspAddress = System.UInt64;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server.Effect
|
||||
|
@ -73,7 +73,7 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
|
|||
|
||||
if (BufferUnmapped || parameter.IsNew)
|
||||
{
|
||||
ulong bufferSize = (ulong)Unsafe.SizeOf<int>() * Parameter.BufferStorageSize + (ulong)Unsafe.SizeOf<AuxiliaryBufferHeader>() * 2;
|
||||
ulong bufferSize = (ulong)Unsafe.SizeOf<int>() * Parameter.BufferStorageSize + (ulong)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
|
||||
bool sendBufferUnmapped = !mapper.TryAttachBuffer(out updateErrorInfo, ref WorkBuffers[0], Parameter.SendBufferInfoAddress, bufferSize);
|
||||
bool returnBufferUnmapped = !mapper.TryAttachBuffer(out updateErrorInfo, ref WorkBuffers[1], Parameter.ReturnBufferInfoAddress, bufferSize);
|
||||
|
@ -85,11 +85,11 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
|
|||
DspAddress sendDspAddress = WorkBuffers[0].GetReference(false);
|
||||
DspAddress returnDspAddress = WorkBuffers[1].GetReference(false);
|
||||
|
||||
State.SendBufferInfo = sendDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
State.SendBufferInfoBase = sendDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferHeader>() * 2;
|
||||
State.SendBufferInfo = sendDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferInfo>();
|
||||
State.SendBufferInfoBase = sendDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
|
||||
State.ReturnBufferInfo = returnDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
State.ReturnBufferInfoBase = returnDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferHeader>() * 2;
|
||||
State.ReturnBufferInfo = returnDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferInfo>();
|
||||
State.ReturnBufferInfoBase = returnDspAddress + (uint)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -277,6 +277,8 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
|
|||
return PerformanceDetailType.Mix;
|
||||
case EffectType.Limiter:
|
||||
return PerformanceDetailType.Limiter;
|
||||
case EffectType.CaptureBuffer:
|
||||
return PerformanceDetailType.CaptureBuffer;
|
||||
default:
|
||||
throw new NotImplementedException($"{Type}");
|
||||
}
|
||||
|
|
99
Ryujinx.Audio/Renderer/Server/Effect/CaptureBufferEffect.cs
Normal file
99
Ryujinx.Audio/Renderer/Server/Effect/CaptureBufferEffect.cs
Normal file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Ryujinx
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp.State;
|
||||
using Ryujinx.Audio.Renderer.Parameter;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using Ryujinx.Audio.Renderer.Server.MemoryPool;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using DspAddress = System.UInt64;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// Server state for an capture buffer effect.
|
||||
/// </summary>
|
||||
public class CaptureBufferEffect : BaseEffect
|
||||
{
|
||||
/// <summary>
|
||||
/// The capture buffer parameter.
|
||||
/// </summary>
|
||||
public AuxiliaryBufferParameter Parameter;
|
||||
|
||||
/// <summary>
|
||||
/// Capture buffer state.
|
||||
/// </summary>
|
||||
public AuxiliaryBufferAddresses State;
|
||||
|
||||
public override EffectType TargetEffectType => EffectType.CaptureBuffer;
|
||||
|
||||
public override DspAddress GetWorkBuffer(int index)
|
||||
{
|
||||
return WorkBuffers[index].GetReference(true);
|
||||
}
|
||||
|
||||
public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion1 parameter, PoolMapper mapper)
|
||||
{
|
||||
Update(out updateErrorInfo, ref parameter, mapper);
|
||||
}
|
||||
|
||||
public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper)
|
||||
{
|
||||
Update(out updateErrorInfo, ref parameter, mapper);
|
||||
}
|
||||
|
||||
public void Update<T>(out BehaviourParameter.ErrorInfo updateErrorInfo, ref T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
|
||||
{
|
||||
Debug.Assert(IsTypeValid(ref parameter));
|
||||
|
||||
UpdateParameterBase(ref parameter);
|
||||
|
||||
Parameter = MemoryMarshal.Cast<byte, AuxiliaryBufferParameter>(parameter.SpecificData)[0];
|
||||
IsEnabled = parameter.IsEnabled;
|
||||
|
||||
updateErrorInfo = new BehaviourParameter.ErrorInfo();
|
||||
|
||||
if (BufferUnmapped || parameter.IsNew)
|
||||
{
|
||||
ulong bufferSize = (ulong)Unsafe.SizeOf<int>() * Parameter.BufferStorageSize + (ulong)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
|
||||
bool sendBufferUnmapped = !mapper.TryAttachBuffer(out updateErrorInfo, ref WorkBuffers[0], Parameter.SendBufferInfoAddress, bufferSize);
|
||||
|
||||
BufferUnmapped = sendBufferUnmapped;
|
||||
|
||||
if (!BufferUnmapped)
|
||||
{
|
||||
DspAddress sendDspAddress = WorkBuffers[0].GetReference(false);
|
||||
|
||||
// NOTE: Nintendo directly interact with the CPU side structure in the processing of the DSP command.
|
||||
State.SendBufferInfo = sendDspAddress;
|
||||
State.SendBufferInfoBase = sendDspAddress + (ulong)Unsafe.SizeOf<AuxiliaryBufferHeader>();
|
||||
State.ReturnBufferInfo = 0;
|
||||
State.ReturnBufferInfoBase = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateForCommandGeneration()
|
||||
{
|
||||
UpdateUsageStateForCommandGeneration();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,5 +50,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
uint Estimate(UpsampleCommand command);
|
||||
uint Estimate(LimiterCommandVersion1 command);
|
||||
uint Estimate(LimiterCommandVersion2 command);
|
||||
uint Estimate(GroupedBiquadFilterCommand command);
|
||||
uint Estimate(CaptureBufferCommand command);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,6 +254,9 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
case EffectType.Limiter:
|
||||
effect = new LimiterEffect();
|
||||
break;
|
||||
case EffectType.CaptureBuffer:
|
||||
effect = new CaptureBufferEffect();
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"EffectType {parameter.Type} not implemented!");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue