forked from Mirror/Ryujinx
1825bd87b4
This is the first commit of a series of reformat around the codebase as discussed internally some weeks ago. This project being one that isn't touched that much, it shouldn't cause conflict with any opened PRs.
270 lines
No EOL
9.5 KiB
C#
270 lines
No EOL
9.5 KiB
C#
using Ryujinx.Audio.Renderer.Common;
|
|
using Ryujinx.Audio.Renderer.Parameter;
|
|
using Ryujinx.Audio.Renderer.Server.MemoryPool;
|
|
using Ryujinx.Audio.Renderer.Utils;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using static Ryujinx.Audio.Renderer.Common.BehaviourParameter;
|
|
|
|
using DspAddress = System.UInt64;
|
|
|
|
namespace Ryujinx.Audio.Renderer.Server.Effect
|
|
{
|
|
/// <summary>
|
|
/// Base class used as a server state for an effect.
|
|
/// </summary>
|
|
public class BaseEffect
|
|
{
|
|
/// <summary>
|
|
/// The <see cref="EffectType"/> of the effect.
|
|
/// </summary>
|
|
public EffectType Type;
|
|
|
|
/// <summary>
|
|
/// Set to true if the effect must be active.
|
|
/// </summary>
|
|
public bool IsEnabled;
|
|
|
|
/// <summary>
|
|
/// Set to true if the internal effect work buffers used wasn't mapped.
|
|
/// </summary>
|
|
public bool BufferUnmapped;
|
|
|
|
/// <summary>
|
|
/// The current state of the effect.
|
|
/// </summary>
|
|
public UsageState UsageState;
|
|
|
|
/// <summary>
|
|
/// The target mix id of the effect.
|
|
/// </summary>
|
|
public int MixId;
|
|
|
|
/// <summary>
|
|
/// Position of the effect while processing effects.
|
|
/// </summary>
|
|
public uint ProcessingOrder;
|
|
|
|
/// <summary>
|
|
/// Array of all the work buffer used by the effect.
|
|
/// </summary>
|
|
protected AddressInfo[] WorkBuffers;
|
|
|
|
/// <summary>
|
|
/// Create a new <see cref="BaseEffect"/>.
|
|
/// </summary>
|
|
public BaseEffect()
|
|
{
|
|
Type = TargetEffectType;
|
|
UsageState = UsageState.Invalid;
|
|
|
|
IsEnabled = false;
|
|
BufferUnmapped = false;
|
|
MixId = Constants.UnusedMixId;
|
|
ProcessingOrder = uint.MaxValue;
|
|
|
|
WorkBuffers = new AddressInfo[2];
|
|
|
|
foreach (ref AddressInfo info in WorkBuffers.AsSpan())
|
|
{
|
|
info = AddressInfo.Create();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The target <see cref="EffectType"/> handled by this <see cref="BaseEffect"/>.
|
|
/// </summary>
|
|
public virtual EffectType TargetEffectType => EffectType.Invalid;
|
|
|
|
/// <summary>
|
|
/// Check if the <see cref="EffectType"/> sent by the user match the internal <see cref="EffectType"/>.
|
|
/// </summary>
|
|
/// <param name="parameter">The user parameter.</param>
|
|
/// <returns>Returns true if the <see cref="EffectType"/> sent by the user matches the internal <see cref="EffectType"/>.</returns>
|
|
public bool IsTypeValid<T>(ref T parameter) where T : unmanaged, IEffectInParameter
|
|
{
|
|
return parameter.Type == TargetEffectType;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the usage state during command generation.
|
|
/// </summary>
|
|
protected void UpdateUsageStateForCommandGeneration()
|
|
{
|
|
UsageState = IsEnabled ? UsageState.Enabled : UsageState.Disabled;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the internal common parameters from a user parameter.
|
|
/// </summary>
|
|
/// <param name="parameter">The user parameter.</param>
|
|
protected void UpdateParameterBase<T>(ref T parameter) where T : unmanaged, IEffectInParameter
|
|
{
|
|
MixId = parameter.MixId;
|
|
ProcessingOrder = parameter.ProcessingOrder;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Force unmap all the work buffers.
|
|
/// </summary>
|
|
/// <param name="mapper">The mapper to use.</param>
|
|
public void ForceUnmapBuffers(PoolMapper mapper)
|
|
{
|
|
foreach (ref AddressInfo info in WorkBuffers.AsSpan())
|
|
{
|
|
if (info.GetReference(false) != 0)
|
|
{
|
|
mapper.ForceUnmap(ref info);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if the effect needs to be skipped.
|
|
/// </summary>
|
|
/// <returns>Returns true if the effect needs to be skipped.</returns>
|
|
public bool ShouldSkip()
|
|
{
|
|
return BufferUnmapped;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the <see cref="BaseEffect"/> state during command generation.
|
|
/// </summary>
|
|
public virtual void UpdateForCommandGeneration()
|
|
{
|
|
Debug.Assert(Type == TargetEffectType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize the given <paramref name="state"/> result state.
|
|
/// </summary>
|
|
/// <param name="state">The state to initalize</param>
|
|
public virtual void InitializeResultState(ref EffectResultState state) { }
|
|
|
|
/// <summary>
|
|
/// Update the <paramref name="destState"/> result state with <paramref name="srcState"/>.
|
|
/// </summary>
|
|
/// <param name="destState">The destination result state</param>
|
|
/// <param name="srcState">The source result state</param>
|
|
public virtual void UpdateResultState(ref EffectResultState destState, ref EffectResultState srcState) { }
|
|
|
|
/// <summary>
|
|
/// Update the internal state from a user version 1 parameter.
|
|
/// </summary>
|
|
/// <param name="updateErrorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
|
|
/// <param name="parameter">The user parameter.</param>
|
|
/// <param name="mapper">The mapper to use.</param>
|
|
public virtual void Update(out ErrorInfo updateErrorInfo, ref EffectInParameterVersion1 parameter, PoolMapper mapper)
|
|
{
|
|
Debug.Assert(IsTypeValid(ref parameter));
|
|
|
|
updateErrorInfo = new ErrorInfo();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the internal state from a user version 2 parameter.
|
|
/// </summary>
|
|
/// <param name="updateErrorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
|
|
/// <param name="parameter">The user parameter.</param>
|
|
/// <param name="mapper">The mapper to use.</param>
|
|
public virtual void Update(out ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper)
|
|
{
|
|
Debug.Assert(IsTypeValid(ref parameter));
|
|
|
|
updateErrorInfo = new ErrorInfo();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the work buffer DSP address at the given index.
|
|
/// </summary>
|
|
/// <param name="index">The index of the work buffer</param>
|
|
/// <returns>The work buffer DSP address at the given index.</returns>
|
|
public virtual DspAddress GetWorkBuffer(int index)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the first work buffer DSP address.
|
|
/// </summary>
|
|
/// <returns>The first work buffer DSP address.</returns>
|
|
protected DspAddress GetSingleBuffer()
|
|
{
|
|
if (IsEnabled)
|
|
{
|
|
return WorkBuffers[0].GetReference(true);
|
|
}
|
|
|
|
if (UsageState != UsageState.Disabled)
|
|
{
|
|
DspAddress address = WorkBuffers[0].GetReference(false);
|
|
ulong size = WorkBuffers[0].Size;
|
|
|
|
if (address != 0 && size != 0)
|
|
{
|
|
AudioProcessorMemoryManager.InvalidateDataCache(address, size);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Store the output status to the given user output.
|
|
/// </summary>
|
|
/// <param name="outStatus">The given user output.</param>
|
|
/// <param name="isAudioRendererActive">If set to true, the <see cref="AudioRenderSystem"/> is active.</param>
|
|
public void StoreStatus<T>(ref T outStatus, bool isAudioRendererActive) where T : unmanaged, IEffectOutStatus
|
|
{
|
|
if (isAudioRendererActive)
|
|
{
|
|
if (UsageState == UsageState.Disabled)
|
|
{
|
|
outStatus.State = EffectState.Disabled;
|
|
}
|
|
else
|
|
{
|
|
outStatus.State = EffectState.Enabled;
|
|
}
|
|
}
|
|
else if (UsageState == UsageState.New)
|
|
{
|
|
outStatus.State = EffectState.Enabled;
|
|
}
|
|
else
|
|
{
|
|
outStatus.State = EffectState.Disabled;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the <see cref="PerformanceDetailType"/> associated to the <see cref="Type"/> of this effect.
|
|
/// </summary>
|
|
/// <returns>The <see cref="PerformanceDetailType"/> associated to the <see cref="Type"/> of this effect.</returns>
|
|
public PerformanceDetailType GetPerformanceDetailType()
|
|
{
|
|
switch (Type)
|
|
{
|
|
case EffectType.BiquadFilter:
|
|
return PerformanceDetailType.BiquadFilter;
|
|
case EffectType.AuxiliaryBuffer:
|
|
return PerformanceDetailType.Aux;
|
|
case EffectType.Delay:
|
|
return PerformanceDetailType.Delay;
|
|
case EffectType.Reverb:
|
|
return PerformanceDetailType.Reverb;
|
|
case EffectType.Reverb3d:
|
|
return PerformanceDetailType.Reverb3d;
|
|
case EffectType.BufferMix:
|
|
return PerformanceDetailType.Mix;
|
|
case EffectType.Limiter:
|
|
return PerformanceDetailType.Limiter;
|
|
case EffectType.CaptureBuffer:
|
|
return PerformanceDetailType.CaptureBuffer;
|
|
default:
|
|
throw new NotImplementedException($"{Type}");
|
|
}
|
|
}
|
|
}
|
|
} |