Move solution and projects to src
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Types;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Renderer user configuration.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct AudioRendererConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// The target sample rate of the user.
|
||||
/// </summary>
|
||||
/// <remarks>Only 32000Hz and 48000Hz are considered valid, other sample rates will cause undefined behaviour.</remarks>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample count per <see cref="Dsp.AudioProcessor"/> updates.
|
||||
/// </summary>
|
||||
public uint SampleCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum mix buffer count.
|
||||
/// </summary>
|
||||
public uint MixBufferCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of sub mixes that could be used by the user.
|
||||
/// </summary>
|
||||
public uint SubMixBufferCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of voices that could be used by the user.
|
||||
/// </summary>
|
||||
public uint VoiceCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of sinks that could be used by the user.
|
||||
/// </summary>
|
||||
public uint SinkCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of effects that could be used by the user.
|
||||
/// </summary>
|
||||
public uint EffectCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of performance metric frames that could be used by the user.
|
||||
/// </summary>
|
||||
public uint PerformanceMetricFramesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the user allows the <see cref="Server.AudioRenderSystem"/> to drop voices.
|
||||
/// </summary>
|
||||
/// <seealso cref="Server.AudioRenderSystem.ComputeVoiceDrop(Server.CommandBuffer, long, long)"/>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool VoiceDropEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused
|
||||
/// </summary>
|
||||
private byte _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// The target rendering device.
|
||||
/// </summary>
|
||||
/// <remarks>Must be <see cref="AudioRendererRenderingDevice.Dsp"/></remarks>
|
||||
public AudioRendererRenderingDevice RenderingDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The target execution mode.
|
||||
/// </summary>
|
||||
/// <remarks>Must be <see cref="AudioRendererExecutionMode.Auto"/></remarks>
|
||||
public AudioRendererExecutionMode ExecutionMode;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of splitters that could be used by the user.
|
||||
/// </summary>
|
||||
public uint SplitterCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of splitters destinations that could be used by the user.
|
||||
/// </summary>
|
||||
public uint SplitterDestinationCount;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the external context.
|
||||
/// </summary>
|
||||
/// <remarks>This is a leftover of the old "codec" interface system that was present between 1.0.0 and 3.0.0. This was entirely removed from the server side with REV8.</remarks>
|
||||
public uint ExternalContextSize;
|
||||
|
||||
/// <summary>
|
||||
/// The user audio revision
|
||||
/// </summary>
|
||||
/// <seealso cref="Server.BehaviourContext"/>
|
||||
public int Revision;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Ryujinx.Audio.Renderer.Common.BehaviourParameter;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information for behaviour.
|
||||
/// </summary>
|
||||
/// <remarks>This is used to report errors to the user during <see cref="Server.AudioRenderSystem.Update(Memory{byte}, Memory{byte}, ReadOnlyMemory{byte})"/> processing.</remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct BehaviourErrorInfoOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The reported errors.
|
||||
/// </summary>
|
||||
public Array10<ErrorInfo> ErrorInfos;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of error that got reported.
|
||||
/// </summary>
|
||||
public uint ErrorInfosCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved[3];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Biquad filter parameters.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0xC, Pack = 1)]
|
||||
public struct BiquadFilterParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Set to true if the biquad filter is active.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool Enable;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private byte _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Biquad filter numerator (b0, b1, b2).
|
||||
/// </summary>
|
||||
public Array3<short> Numerator;
|
||||
|
||||
/// <summary>
|
||||
/// Biquad filter denominator (a1, a2).
|
||||
/// </summary>
|
||||
/// <remarks>a0 = 1</remarks>
|
||||
public Array2<short> Denominator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.AuxiliaryBuffer"/> and <see cref="Common.EffectType.CaptureBuffer"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct AuxiliaryBufferParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/> to write data to <see cref="SendBufferInfoAddress"/>.
|
||||
/// </summary>
|
||||
public Array24<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/> to read data from <see cref="ReturnBufferInfoAddress"/>.
|
||||
/// </summary>
|
||||
public Array24<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public uint ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample rate.
|
||||
/// </summary>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The buffer storage total size.
|
||||
/// </summary>
|
||||
public uint BufferStorageSize;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of channels supported.
|
||||
/// </summary>
|
||||
/// <remarks>This is unused.</remarks>
|
||||
public uint ChannelCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the start of the region containing two <see cref="Dsp.State.AuxiliaryBufferHeader"/> followed by the data that will be written by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public ulong SendBufferInfoAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the start of the region containling data that will be written by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
/// <remarks>This is unused.</remarks>
|
||||
public ulong SendBufferStorageAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the start of the region containing two <see cref="Dsp.State.AuxiliaryBufferHeader"/> followed by the data that will be read by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Unused with <see cref="Common.EffectType.CaptureBuffer"/>.</remarks>
|
||||
public ulong ReturnBufferInfoAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the start of the region containling data that will be read by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
/// <remarks>This is unused.</remarks>
|
||||
public ulong ReturnBufferStorageAddress;
|
||||
|
||||
/// <summary>
|
||||
/// Size of a sample of the mix buffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is unused.</remarks>
|
||||
public uint MixBufferSampleSize;
|
||||
|
||||
/// <summary>
|
||||
/// The total count of sample that can be stored.
|
||||
/// </summary>
|
||||
/// <remarks>This is unused.</remarks>
|
||||
public uint TotalSampleCount;
|
||||
|
||||
/// <summary>
|
||||
/// The count of sample of the mix buffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is unused.</remarks>
|
||||
public uint MixBufferSampleCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.BiquadFilter"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct BiquadFilterEffectParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// Biquad filter numerator (b0, b1, b2).
|
||||
/// </summary>
|
||||
public Array3<short> Numerator;
|
||||
|
||||
/// <summary>
|
||||
/// Biquad filter denominator (a1, a2).
|
||||
/// </summary>
|
||||
/// <remarks>a0 = 1</remarks>
|
||||
public Array2<short> Denominator;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public byte ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The current usage status of the effect on the client side.
|
||||
/// </summary>
|
||||
public UsageState Status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.BufferMix"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct BufferMixParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array24<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array24<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The output volumes of the mixes.
|
||||
/// </summary>
|
||||
public Array24<float> Volumes;
|
||||
|
||||
/// <summary>
|
||||
/// The total count of mixes used.
|
||||
/// </summary>
|
||||
public uint MixesCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.Compressor"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct CompressorParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of channels supported.
|
||||
/// </summary>
|
||||
public ushort ChannelCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public ushort ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample rate.
|
||||
/// </summary>
|
||||
/// <remarks>This is in kHz.</remarks>
|
||||
public int SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The threshold.
|
||||
/// </summary>
|
||||
public float Threshold;
|
||||
|
||||
/// <summary>
|
||||
/// The compressor ratio.
|
||||
/// </summary>
|
||||
public float Ratio;
|
||||
|
||||
/// <summary>
|
||||
/// The attack time.
|
||||
/// <remarks>This is in microseconds.</remarks>
|
||||
/// </summary>
|
||||
public int AttackTime;
|
||||
|
||||
/// <summary>
|
||||
/// The release time.
|
||||
/// <remarks>This is in microseconds.</remarks>
|
||||
/// </summary>
|
||||
public int ReleaseTime;
|
||||
|
||||
/// <summary>
|
||||
/// The input gain.
|
||||
/// </summary>
|
||||
public float InputGain;
|
||||
|
||||
/// <summary>
|
||||
/// The attack coefficient.
|
||||
/// </summary>
|
||||
public float AttackCoefficient;
|
||||
|
||||
/// <summary>
|
||||
/// The release coefficient.
|
||||
/// </summary>
|
||||
public float ReleaseCoefficient;
|
||||
|
||||
/// <summary>
|
||||
/// The output gain.
|
||||
/// </summary>
|
||||
public float OutputGain;
|
||||
|
||||
/// <summary>
|
||||
/// The current usage status of the effect on the client side.
|
||||
/// </summary>
|
||||
public UsageState Status;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the makeup gain should be used.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool MakeupGainEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private Array2<byte> _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCount"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCount"/> is valid.</returns>
|
||||
public bool IsChannelCountValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCountMax"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCountMax"/> is valid.</returns>
|
||||
public bool IsChannelCountMaxValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCountMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/Ryujinx.Audio/Renderer/Parameter/Effect/DelayParameter.cs
Normal file
101
src/Ryujinx.Audio/Renderer/Parameter/Effect/DelayParameter.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.Delay"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct DelayParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of channels supported.
|
||||
/// </summary>
|
||||
public ushort ChannelCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public ushort ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum delay time in milliseconds.
|
||||
/// </summary>
|
||||
public uint DelayTimeMax;
|
||||
|
||||
/// <summary>
|
||||
/// The delay time in milliseconds.
|
||||
/// </summary>
|
||||
public uint DelayTime;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample rate. (Q15)
|
||||
/// </summary>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The input gain. (Q15)
|
||||
/// </summary>
|
||||
public uint InGain;
|
||||
|
||||
/// <summary>
|
||||
/// The feedback gain. (Q15)
|
||||
/// </summary>
|
||||
public uint FeedbackGain;
|
||||
|
||||
/// <summary>
|
||||
/// The output gain. (Q15)
|
||||
/// </summary>
|
||||
public uint OutGain;
|
||||
|
||||
/// <summary>
|
||||
/// The dry gain. (Q15)
|
||||
/// </summary>
|
||||
public uint DryGain;
|
||||
|
||||
/// <summary>
|
||||
/// The channel spread of the <see cref="FeedbackGain"/>. (Q15)
|
||||
/// </summary>
|
||||
public uint ChannelSpread;
|
||||
|
||||
/// <summary>
|
||||
/// The low pass amount. (Q15)
|
||||
/// </summary>
|
||||
public uint LowPassAmount;
|
||||
|
||||
/// <summary>
|
||||
/// The current usage status of the effect on the client side.
|
||||
/// </summary>
|
||||
public UsageState Status;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCount"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCount"/> is valid.</returns>
|
||||
public bool IsChannelCountValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCountMax"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCountMax"/> is valid.</returns>
|
||||
public bool IsChannelCountMaxValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCountMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
138
src/Ryujinx.Audio/Renderer/Parameter/Effect/LimiterParameter.cs
Normal file
138
src/Ryujinx.Audio/Renderer/Parameter/Effect/LimiterParameter.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.Limiter"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct LimiterParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of channels supported.
|
||||
/// </summary>
|
||||
public ushort ChannelCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public ushort ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample rate.
|
||||
/// </summary>
|
||||
/// <remarks>This is in kHz.</remarks>
|
||||
public int SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The look ahead max time.
|
||||
/// <remarks>This is in microseconds.</remarks>
|
||||
/// </summary>
|
||||
public int LookAheadTimeMax;
|
||||
|
||||
/// <summary>
|
||||
/// The attack time.
|
||||
/// <remarks>This is in microseconds.</remarks>
|
||||
/// </summary>
|
||||
public int AttackTime;
|
||||
|
||||
/// <summary>
|
||||
/// The release time.
|
||||
/// <remarks>This is in microseconds.</remarks>
|
||||
/// </summary>
|
||||
public int ReleaseTime;
|
||||
|
||||
/// <summary>
|
||||
/// The look ahead time.
|
||||
/// <remarks>This is in microseconds.</remarks>
|
||||
/// </summary>
|
||||
public int LookAheadTime;
|
||||
|
||||
/// <summary>
|
||||
/// The attack coefficient.
|
||||
/// </summary>
|
||||
public float AttackCoefficient;
|
||||
|
||||
/// <summary>
|
||||
/// The release coefficient.
|
||||
/// </summary>
|
||||
public float ReleaseCoefficient;
|
||||
|
||||
/// <summary>
|
||||
/// The threshold.
|
||||
/// </summary>
|
||||
public float Threshold;
|
||||
|
||||
/// <summary>
|
||||
/// The input gain.
|
||||
/// </summary>
|
||||
public float InputGain;
|
||||
|
||||
/// <summary>
|
||||
/// The output gain.
|
||||
/// </summary>
|
||||
public float OutputGain;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum samples stored in the delay buffer.
|
||||
/// </summary>
|
||||
public int DelayBufferSampleCountMin;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum samples stored in the delay buffer.
|
||||
/// </summary>
|
||||
public int DelayBufferSampleCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The current usage status of the effect on the client side.
|
||||
/// </summary>
|
||||
public UsageState Status;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the limiter effect should output statistics.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool StatisticsEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate to the DSP that the user did a statistics reset.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool StatisticsReset;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private byte _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCount"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCount"/> is valid.</returns>
|
||||
public bool IsChannelCountValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCountMax"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCountMax"/> is valid.</returns>
|
||||
public bool IsChannelCountMaxValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCountMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// Effect result state for <seealso cref="Common.EffectType.Limiter"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct LimiterStatistics
|
||||
{
|
||||
/// <summary>
|
||||
/// The max input sample value recorded by the limiter.
|
||||
/// </summary>
|
||||
public Array6<float> InputMax;
|
||||
|
||||
/// <summary>
|
||||
/// Compression gain min value.
|
||||
/// </summary>
|
||||
public Array6<float> CompressionGainMin;
|
||||
|
||||
/// <summary>
|
||||
/// Reset the statistics.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
InputMax.AsSpan().Fill(0.0f);
|
||||
CompressionGainMin.AsSpan().Fill(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
127
src/Ryujinx.Audio/Renderer/Parameter/Effect/Reverb3dParameter.cs
Normal file
127
src/Ryujinx.Audio/Renderer/Parameter/Effect/Reverb3dParameter.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.Reverb3d"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct Reverb3dParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of channels supported.
|
||||
/// </summary>
|
||||
public ushort ChannelCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public ushort ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private uint _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample rate.
|
||||
/// </summary>
|
||||
/// <remarks>This is in kHz.</remarks>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// Gain of the room high-frequency effect.
|
||||
/// </summary>
|
||||
public float RoomHf;
|
||||
|
||||
/// <summary>
|
||||
/// Reference high frequency.
|
||||
/// </summary>
|
||||
public float HfReference;
|
||||
|
||||
/// <summary>
|
||||
/// Reverberation decay time at low frequencies.
|
||||
/// </summary>
|
||||
public float DecayTime;
|
||||
|
||||
/// <summary>
|
||||
/// Ratio of the decay time at high frequencies to the decay time at low frequencies.
|
||||
/// </summary>
|
||||
public float HfDecayRatio;
|
||||
|
||||
/// <summary>
|
||||
/// Gain of the room effect.
|
||||
/// </summary>
|
||||
public float RoomGain;
|
||||
|
||||
/// <summary>
|
||||
/// Gain of the early reflections relative to <see cref="RoomGain"/>.
|
||||
/// </summary>
|
||||
public float ReflectionsGain;
|
||||
|
||||
/// <summary>
|
||||
/// Gain of the late reverberation relative to <see cref="RoomGain"/>.
|
||||
/// </summary>
|
||||
public float ReverbGain;
|
||||
|
||||
/// <summary>
|
||||
/// Echo density in the late reverberation decay.
|
||||
/// </summary>
|
||||
public float Diffusion;
|
||||
|
||||
/// <summary>
|
||||
/// Modal density in the late reverberation decay.
|
||||
/// </summary>
|
||||
public float ReflectionDelay;
|
||||
|
||||
/// <summary>
|
||||
/// Time limit between the early reflections and the late reverberation relative to the time of the first reflection.
|
||||
/// </summary>
|
||||
public float ReverbDelayTime;
|
||||
|
||||
/// <summary>
|
||||
/// Modal density in the late reverberation decay.
|
||||
/// </summary>
|
||||
public float Density;
|
||||
|
||||
/// <summary>
|
||||
/// The dry gain.
|
||||
/// </summary>
|
||||
public float DryGain;
|
||||
|
||||
/// <summary>
|
||||
/// The current usage status of the effect on the client side.
|
||||
/// </summary>
|
||||
public UsageState ParameterStatus;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCount"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCount"/> is valid.</returns>
|
||||
public bool IsChannelCountValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCountMax"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCountMax"/> is valid.</returns>
|
||||
public bool IsChannelCountMaxValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCountMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
119
src/Ryujinx.Audio/Renderer/Parameter/Effect/ReverbParameter.cs
Normal file
119
src/Ryujinx.Audio/Renderer/Parameter/Effect/ReverbParameter.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Audio.Renderer.Server.Effect;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IEffectInParameter.SpecificData"/> for <see cref="Common.EffectType.Reverb"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ReverbParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The input channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of channels supported.
|
||||
/// </summary>
|
||||
public ushort ChannelCountMax;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public ushort ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample rate. (Q15)
|
||||
/// </summary>
|
||||
/// <remarks>This is in kHz.</remarks>
|
||||
public int SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The early mode to use.
|
||||
/// </summary>
|
||||
public ReverbEarlyMode EarlyMode;
|
||||
|
||||
/// <summary>
|
||||
/// The gain to apply to the result of the early reflection. (Q15)
|
||||
/// </summary>
|
||||
public int EarlyGain;
|
||||
|
||||
/// <summary>
|
||||
/// The pre-delay time in milliseconds. (Q15)
|
||||
/// </summary>
|
||||
public int PreDelayTime;
|
||||
|
||||
/// <summary>
|
||||
/// The late mode to use.
|
||||
/// </summary>
|
||||
public ReverbLateMode LateMode;
|
||||
|
||||
/// <summary>
|
||||
/// The gain to apply to the result of the late reflection. (Q15)
|
||||
/// </summary>
|
||||
public int LateGain;
|
||||
|
||||
/// <summary>
|
||||
/// The decay time. (Q15)
|
||||
/// </summary>
|
||||
public int DecayTime;
|
||||
|
||||
/// <summary>
|
||||
/// The high frequency decay ratio. (Q15)
|
||||
/// </summary>
|
||||
/// <remarks>If <see cref="HighFrequencyDecayRatio"/> >= 0.995f, it is considered disabled.</remarks>
|
||||
public int HighFrequencyDecayRatio;
|
||||
|
||||
/// <summary>
|
||||
/// The coloration of the decay. (Q15)
|
||||
/// </summary>
|
||||
public int Coloration;
|
||||
|
||||
/// <summary>
|
||||
/// The reverb gain. (Q15)
|
||||
/// </summary>
|
||||
public int ReverbGain;
|
||||
|
||||
/// <summary>
|
||||
/// The output gain. (Q15)
|
||||
/// </summary>
|
||||
public int OutGain;
|
||||
|
||||
/// <summary>
|
||||
/// The dry gain. (Q15)
|
||||
/// </summary>
|
||||
public int DryGain;
|
||||
|
||||
/// <summary>
|
||||
/// The current usage status of the effect on the client side.
|
||||
/// </summary>
|
||||
public UsageState Status;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCount"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCount"/> is valid.</returns>
|
||||
public bool IsChannelCountValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="ChannelCountMax"/> is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the <see cref="ChannelCountMax"/> is valid.</returns>
|
||||
public bool IsChannelCountMaxValid()
|
||||
{
|
||||
return EffectInParameterVersion1.IsChannelCountValid(ChannelCountMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for an effect version 1.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct EffectInParameterVersion1 : IEffectInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the effect.
|
||||
/// </summary>
|
||||
public EffectType Type;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the effect is new.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsNew;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the effect must be active.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private byte _reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The target mix id of the effect.
|
||||
/// </summary>
|
||||
public int MixId;
|
||||
|
||||
/// <summary>
|
||||
/// Address of the processing workbuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
|
||||
public ulong BufferBase;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the processing workbuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
|
||||
public ulong BufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// Position of the effect while processing effects.
|
||||
/// </summary>
|
||||
public uint ProcessingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private uint _reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Specific data storage.
|
||||
/// </summary>
|
||||
private SpecificDataStruct _specificDataStart;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0xA0, Pack = 1)]
|
||||
private struct SpecificDataStruct { }
|
||||
|
||||
public Span<byte> SpecificData => SpanHelpers.AsSpan<SpecificDataStruct, byte>(ref _specificDataStart);
|
||||
|
||||
EffectType IEffectInParameter.Type => Type;
|
||||
|
||||
bool IEffectInParameter.IsNew => IsNew;
|
||||
|
||||
bool IEffectInParameter.IsEnabled => IsEnabled;
|
||||
|
||||
int IEffectInParameter.MixId => MixId;
|
||||
|
||||
ulong IEffectInParameter.BufferBase => BufferBase;
|
||||
|
||||
ulong IEffectInParameter.BufferSize => BufferSize;
|
||||
|
||||
uint IEffectInParameter.ProcessingOrder => ProcessingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given channel count is valid.
|
||||
/// </summary>
|
||||
/// <param name="channelCount">The channel count to check</param>
|
||||
/// <returns>Returns true if the channel count is valid.</returns>
|
||||
public static bool IsChannelCountValid(int channelCount)
|
||||
{
|
||||
return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for an effect version 2. (added with REV9)
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct EffectInParameterVersion2 : IEffectInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the effect.
|
||||
/// </summary>
|
||||
public EffectType Type;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the effect is new.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsNew;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the effect must be active.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private byte _reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The target mix id of the effect.
|
||||
/// </summary>
|
||||
public int MixId;
|
||||
|
||||
/// <summary>
|
||||
/// Address of the processing workbuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
|
||||
public ulong BufferBase;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the processing workbuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
|
||||
public ulong BufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// Position of the effect while processing effects.
|
||||
/// </summary>
|
||||
public uint ProcessingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private uint _reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Specific data storage.
|
||||
/// </summary>
|
||||
private SpecificDataStruct _specificDataStart;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0xA0, Pack = 1)]
|
||||
private struct SpecificDataStruct { }
|
||||
|
||||
public Span<byte> SpecificData => SpanHelpers.AsSpan<SpecificDataStruct, byte>(ref _specificDataStart);
|
||||
|
||||
EffectType IEffectInParameter.Type => Type;
|
||||
|
||||
bool IEffectInParameter.IsNew => IsNew;
|
||||
|
||||
bool IEffectInParameter.IsEnabled => IsEnabled;
|
||||
|
||||
int IEffectInParameter.MixId => MixId;
|
||||
|
||||
ulong IEffectInParameter.BufferBase => BufferBase;
|
||||
|
||||
ulong IEffectInParameter.BufferSize => BufferSize;
|
||||
|
||||
uint IEffectInParameter.ProcessingOrder => ProcessingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given channel count is valid.
|
||||
/// </summary>
|
||||
/// <param name="channelCount">The channel count to check</param>
|
||||
/// <returns>Returns true if the channel count is valid.</returns>
|
||||
public static bool IsChannelCountValid(int channelCount)
|
||||
{
|
||||
return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information for an effect version 1.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct EffectOutStatusVersion1 : IEffectOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Current effect state.
|
||||
/// </summary>
|
||||
public EffectState State;
|
||||
|
||||
/// <summary>
|
||||
/// Unused/Reserved.
|
||||
/// </summary>
|
||||
private unsafe fixed byte _reserved[15];
|
||||
|
||||
EffectState IEffectOutStatus.State { get => State; set => State = value; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information for an effect version 2. (added with REV9)
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct EffectOutStatusVersion2 : IEffectOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Current effect state.
|
||||
/// </summary>
|
||||
public EffectState State;
|
||||
|
||||
/// <summary>
|
||||
/// Unused/Reserved.
|
||||
/// </summary>
|
||||
private unsafe fixed byte _reserved[15];
|
||||
|
||||
/// <summary>
|
||||
/// Current result state.
|
||||
/// </summary>
|
||||
public EffectResultState ResultState;
|
||||
|
||||
EffectState IEffectOutStatus.State { get => State; set => State = value; }
|
||||
}
|
||||
}
|
||||
26
src/Ryujinx.Audio/Renderer/Parameter/EffectResultState.cs
Normal file
26
src/Ryujinx.Audio/Renderer/Parameter/EffectResultState.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Effect result state (added in REV9).
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct EffectResultState
|
||||
{
|
||||
/// <summary>
|
||||
/// Specific data storage.
|
||||
/// </summary>
|
||||
private SpecificDataStruct _specificDataStart;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x80, Pack = 1)]
|
||||
private struct SpecificDataStruct { }
|
||||
|
||||
/// <summary>
|
||||
/// Specific data changing depending of the type of effect. See also the <see cref="Effect"/> namespace.
|
||||
/// </summary>
|
||||
public Span<byte> SpecificData => SpanHelpers.AsSpan<SpecificDataStruct, byte>(ref _specificDataStart);
|
||||
}
|
||||
}
|
||||
18
src/Ryujinx.Audio/Renderer/Parameter/EffectState.cs
Normal file
18
src/Ryujinx.Audio/Renderer/Parameter/EffectState.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The state of an effect.
|
||||
/// </summary>
|
||||
public enum EffectState : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// The effect is enabled.
|
||||
/// </summary>
|
||||
Enabled = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The effect is disabled.
|
||||
/// </summary>
|
||||
Disabled = 4
|
||||
}
|
||||
}
|
||||
53
src/Ryujinx.Audio/Renderer/Parameter/IEffectInParameter.cs
Normal file
53
src/Ryujinx.Audio/Renderer/Parameter/IEffectInParameter.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic interface to represent input information for an effect.
|
||||
/// </summary>
|
||||
public interface IEffectInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the effect.
|
||||
/// </summary>
|
||||
EffectType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the effect is new.
|
||||
/// </summary>
|
||||
bool IsNew { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the effect must be active.
|
||||
/// </summary>
|
||||
bool IsEnabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The target mix id of the effect.
|
||||
/// </summary>
|
||||
int MixId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Address of the processing workbuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
|
||||
ulong BufferBase { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the processing workbuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
|
||||
ulong BufferSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Position of the effect while processing effects.
|
||||
/// </summary>
|
||||
uint ProcessingOrder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specific data changing depending of the <see cref="Type"/>. See also the <see cref="Effect"/> namespace.
|
||||
/// </summary>
|
||||
Span<byte> SpecificData { get; }
|
||||
}
|
||||
}
|
||||
13
src/Ryujinx.Audio/Renderer/Parameter/IEffectOutStatus.cs
Normal file
13
src/Ryujinx.Audio/Renderer/Parameter/IEffectOutStatus.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic interface to represent output information for an effect.
|
||||
/// </summary>
|
||||
public interface IEffectOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Current effect state.
|
||||
/// </summary>
|
||||
EffectState State { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using System.Runtime.InteropServices;
|
||||
using CpuAddress = System.UInt64;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for a memory pool.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MemoryPoolInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The CPU address used by the memory pool.
|
||||
/// </summary>
|
||||
public CpuAddress CpuAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The size used by the memory pool.
|
||||
/// </summary>
|
||||
public ulong Size;
|
||||
|
||||
/// <summary>
|
||||
/// The target state the user wants.
|
||||
/// </summary>
|
||||
public MemoryPoolUserState State;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved[3];
|
||||
}
|
||||
}
|
||||
22
src/Ryujinx.Audio/Renderer/Parameter/MemoryPoolOutStatus.cs
Normal file
22
src/Ryujinx.Audio/Renderer/Parameter/MemoryPoolOutStatus.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information for a memory pool.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MemoryPoolOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The current server memory pool state.
|
||||
/// </summary>
|
||||
public MemoryPoolUserState State;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved[3];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information header for mix updates on REV7 and later
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MixInParameterDirtyOnlyUpdate
|
||||
{
|
||||
/// <summary>
|
||||
/// Magic of the header
|
||||
/// </summary>
|
||||
/// <remarks>Never checked on hardware.</remarks>
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// The count of <see cref="MixParameter"/> following this header.
|
||||
/// </summary>
|
||||
public uint MixCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed byte _reserved[24];
|
||||
}
|
||||
}
|
||||
95
src/Ryujinx.Audio/Renderer/Parameter/MixParameter.cs
Normal file
95
src/Ryujinx.Audio/Renderer/Parameter/MixParameter.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for a mix.
|
||||
/// </summary>
|
||||
/// <remarks>Also used on the client side for mix tracking.</remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MixParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Base volume of the mix.
|
||||
/// </summary>
|
||||
public float Volume;
|
||||
|
||||
/// <summary>
|
||||
/// Target sample rate of the mix.
|
||||
/// </summary>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// Target buffer count.
|
||||
/// </summary>
|
||||
public uint BufferCount;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if in use.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsUsed;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if it was changed.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsDirty;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private ushort _reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The id of the mix.
|
||||
/// </summary>
|
||||
public int MixId;
|
||||
|
||||
/// <summary>
|
||||
/// The effect count. (client side)
|
||||
/// </summary>
|
||||
public uint EffectCount;
|
||||
|
||||
/// <summary>
|
||||
/// The mix node id.
|
||||
/// </summary>
|
||||
public int NodeId;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private ulong _reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Mix buffer volumes storage.
|
||||
/// </summary>
|
||||
private MixVolumeArray _mixBufferVolumeArray;
|
||||
|
||||
/// <summary>
|
||||
/// The mix to output the result of this mix.
|
||||
/// </summary>
|
||||
public int DestinationMixId;
|
||||
|
||||
/// <summary>
|
||||
/// The splitter to output the result of this mix.
|
||||
/// </summary>
|
||||
public uint DestinationSplitterId;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private uint _reserved3;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 4 * Constants.MixBufferCountMax * Constants.MixBufferCountMax, Pack = 1)]
|
||||
private struct MixVolumeArray { }
|
||||
|
||||
/// <summary>
|
||||
/// Mix buffer volumes.
|
||||
/// </summary>
|
||||
/// <remarks>Used when no splitter id is specified.</remarks>
|
||||
public Span<float> MixBufferVolume => SpanHelpers.AsSpan<MixVolumeArray, float>(ref _mixBufferVolumeArray);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Performance
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for performance monitoring.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct PerformanceInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The target node id to monitor performance on.
|
||||
/// </summary>
|
||||
public int TargetNodeId;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved[3];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Performance
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information for performance monitoring.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct PerformanceOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the total size output to the performance buffer.
|
||||
/// </summary>
|
||||
public uint HistorySize;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved[3];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Renderer output information on REV5 and later.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct RendererInfoOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The count of updates sent to the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public ulong ElapsedFrameCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/Unused.
|
||||
/// </summary>
|
||||
private ulong _reserved;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using CpuAddress = System.UInt64;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Sink
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="SinkInParameter.SpecificData"/> for <see cref="SinkType.CircularBuffer"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct CircularBufferParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The CPU address of the user circular buffer.
|
||||
/// </summary>
|
||||
public CpuAddress BufferAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the user circular buffer.
|
||||
/// </summary>
|
||||
public uint BufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// The total count of channels to output to the circular buffer.
|
||||
/// </summary>
|
||||
public uint InputCount;
|
||||
|
||||
/// <summary>
|
||||
/// The target sample count to output per update in the circular buffer.
|
||||
/// </summary>
|
||||
public uint SampleCount;
|
||||
|
||||
/// <summary>
|
||||
/// Last read offset on the CPU side.
|
||||
/// </summary>
|
||||
public uint LastReadOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The target <see cref="SampleFormat"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Only <see cref="SampleFormat.PcmInt16"/> is supported.</remarks>
|
||||
public SampleFormat SampleFormat;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private unsafe fixed byte _reserved1[3];
|
||||
|
||||
/// <summary>
|
||||
/// The input channels index that will be used.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private ushort _reserved2;
|
||||
}
|
||||
}
|
||||
58
src/Ryujinx.Audio/Renderer/Parameter/Sink/DeviceParameter.cs
Normal file
58
src/Ryujinx.Audio/Renderer/Parameter/Sink/DeviceParameter.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter.Sink
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="SinkInParameter.SpecificData"/> for <see cref="Common.SinkType.Device"/>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct DeviceParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Device name storage.
|
||||
/// </summary>
|
||||
private DeviceNameStruct _deviceName;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private byte _padding;
|
||||
|
||||
/// <summary>
|
||||
/// The total count of channels to output to the device.
|
||||
/// </summary>
|
||||
public uint InputCount;
|
||||
|
||||
/// <summary>
|
||||
/// The input channels index that will be used.
|
||||
/// </summary>
|
||||
public Array6<byte> Input;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private byte _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the user controls Surround to Stereo downmixing coefficients.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool DownMixParameterEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// The user Surround to Stereo downmixing coefficients.
|
||||
/// </summary>
|
||||
public Array4<float> DownMixParameter;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0xFF, Pack = 1)]
|
||||
private struct DeviceNameStruct { }
|
||||
|
||||
/// <summary>
|
||||
/// The output device name.
|
||||
/// </summary>
|
||||
public Span<byte> DeviceName => SpanHelpers.AsSpan<DeviceNameStruct, byte>(ref _deviceName);
|
||||
}
|
||||
}
|
||||
53
src/Ryujinx.Audio/Renderer/Parameter/SinkInParameter.cs
Normal file
53
src/Ryujinx.Audio/Renderer/Parameter/SinkInParameter.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for a sink.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SinkInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the sink.
|
||||
/// </summary>
|
||||
public SinkType Type;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the sink is used.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsUsed;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private ushort _reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The node id of the sink.
|
||||
/// </summary>
|
||||
public int NodeId;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private unsafe fixed ulong _reserved2[3];
|
||||
|
||||
/// <summary>
|
||||
/// Specific data storage.
|
||||
/// </summary>
|
||||
private SpecificDataStruct _specificDataStart;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x120, Pack = 1)]
|
||||
private struct SpecificDataStruct { }
|
||||
|
||||
/// <summary>
|
||||
/// Specific data changing depending of the <see cref="Type"/>. See also the <see cref="Sink"/> namespace.
|
||||
/// </summary>
|
||||
public Span<byte> SpecificData => SpanHelpers.AsSpan<SpecificDataStruct, byte>(ref _specificDataStart);
|
||||
}
|
||||
}
|
||||
26
src/Ryujinx.Audio/Renderer/Parameter/SinkOutStatus.cs
Normal file
26
src/Ryujinx.Audio/Renderer/Parameter/SinkOutStatus.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information for a sink.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SinkOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Last written offset if the sink type is <see cref="Common.SinkType.CircularBuffer"/>.
|
||||
/// </summary>
|
||||
public uint LastWrittenOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private uint _padding;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private unsafe fixed ulong _reserved[3];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input header for a splitter destination update.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SplitterDestinationInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Magic of the input header.
|
||||
/// </summary>
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Target splitter destination data id.
|
||||
/// </summary>
|
||||
public int Id;
|
||||
|
||||
/// <summary>
|
||||
/// Mix buffer volumes storage.
|
||||
/// </summary>
|
||||
private MixArray _mixBufferVolume;
|
||||
|
||||
/// <summary>
|
||||
/// The mix to output the result of the splitter.
|
||||
/// </summary>
|
||||
public int DestinationId;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if in use.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsUsed;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/padding.
|
||||
/// </summary>
|
||||
private unsafe fixed byte _reserved[3];
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 4 * Constants.MixBufferCountMax, Pack = 1)]
|
||||
private struct MixArray { }
|
||||
|
||||
/// <summary>
|
||||
/// Mix buffer volumes.
|
||||
/// </summary>
|
||||
/// <remarks>Used when a splitter id is specified in the mix.</remarks>
|
||||
public Span<float> MixBufferVolume => SpanHelpers.AsSpan<MixArray, float>(ref _mixBufferVolume);
|
||||
|
||||
/// <summary>
|
||||
/// The expected constant of any input header.
|
||||
/// </summary>
|
||||
private const uint ValidMagic = 0x44444E53;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the magic is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the magic is valid.</returns>
|
||||
public bool IsMagicValid()
|
||||
{
|
||||
return Magic == ValidMagic;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/Ryujinx.Audio/Renderer/Parameter/SplitterInParameter.cs
Normal file
46
src/Ryujinx.Audio/Renderer/Parameter/SplitterInParameter.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input header for a splitter state update.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SplitterInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Magic of the input header.
|
||||
/// </summary>
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Target splitter id.
|
||||
/// </summary>
|
||||
public int Id;
|
||||
|
||||
/// <summary>
|
||||
/// Target sample rate to use on the splitter.
|
||||
/// </summary>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// Count of splitter destinations.
|
||||
/// </summary>
|
||||
/// <remarks>Splitter destination ids are defined right after this header.</remarks>
|
||||
public int DestinationCount;
|
||||
|
||||
/// <summary>
|
||||
/// The expected constant of any input header.
|
||||
/// </summary>
|
||||
private const uint ValidMagic = 0x49444E53;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the magic is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the magic is valid.</returns>
|
||||
public bool IsMagicValid()
|
||||
{
|
||||
return Magic == ValidMagic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input header for splitter update.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SplitterInParameterHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Magic of the input header.
|
||||
/// </summary>
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// The count of <see cref="SplitterInParameter"/> after the header.
|
||||
/// </summary>
|
||||
public uint SplitterCount;
|
||||
|
||||
/// <summary>
|
||||
/// The count of splitter destinations after the header and splitter info.
|
||||
/// </summary>
|
||||
public uint SplitterDestinationCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved[5];
|
||||
|
||||
/// <summary>
|
||||
/// The expected constant of any input splitter header.
|
||||
/// </summary>
|
||||
private const uint ValidMagic = 0x48444E53;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the magic is valid.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the magic is valid.</returns>
|
||||
public bool IsMagicValid()
|
||||
{
|
||||
return Magic == ValidMagic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for a voice channel resources.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x70, Pack = 1)]
|
||||
public struct VoiceChannelResourceInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the voice channel resource.
|
||||
/// </summary>
|
||||
public uint Id;
|
||||
|
||||
/// <summary>
|
||||
/// Mix volumes for the voice channel resource.
|
||||
/// </summary>
|
||||
public Array24<float> Mix;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the voice channel resource is used.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsUsed;
|
||||
}
|
||||
}
|
||||
344
src/Ryujinx.Audio/Renderer/Parameter/VoiceInParameter.cs
Normal file
344
src/Ryujinx.Audio/Renderer/Parameter/VoiceInParameter.cs
Normal file
@@ -0,0 +1,344 @@
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Input information for a voice.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x170, Pack = 1)]
|
||||
public struct VoiceInParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Id of the voice.
|
||||
/// </summary>
|
||||
public int Id;
|
||||
|
||||
/// <summary>
|
||||
/// Node id of the voice.
|
||||
/// </summary>
|
||||
public int NodeId;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the voice is new.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsNew;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if the voice is used.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool InUse;
|
||||
|
||||
/// <summary>
|
||||
/// The voice <see cref="PlayState"/> wanted by the user.
|
||||
/// </summary>
|
||||
public PlayState PlayState;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SampleFormat"/> of the voice.
|
||||
/// </summary>
|
||||
public SampleFormat SampleFormat;
|
||||
|
||||
/// <summary>
|
||||
/// The sample rate of the voice.
|
||||
/// </summary>
|
||||
public uint SampleRate;
|
||||
|
||||
/// <summary>
|
||||
/// The priority of the voice.
|
||||
/// </summary>
|
||||
public uint Priority;
|
||||
|
||||
/// <summary>
|
||||
/// Target sorting position of the voice. (Used to sort voices with the same <see cref="Priority"/>)
|
||||
/// </summary>
|
||||
public uint SortingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// The total channel count used.
|
||||
/// </summary>
|
||||
public uint ChannelCount;
|
||||
|
||||
/// <summary>
|
||||
/// The pitch used on the voice.
|
||||
/// </summary>
|
||||
public float Pitch;
|
||||
|
||||
/// <summary>
|
||||
/// The output volume of the voice.
|
||||
/// </summary>
|
||||
public float Volume;
|
||||
|
||||
/// <summary>
|
||||
/// Biquad filters to apply to the output of the voice.
|
||||
/// </summary>
|
||||
public Array2<BiquadFilterParameter> BiquadFilters;
|
||||
|
||||
/// <summary>
|
||||
/// Total count of <see cref="WaveBufferInternal"/> of the voice.
|
||||
/// </summary>
|
||||
public uint WaveBuffersCount;
|
||||
|
||||
/// <summary>
|
||||
/// Current playing <see cref="WaveBufferInternal"/> of the voice.
|
||||
/// </summary>
|
||||
public uint WaveBuffersIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private uint _reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// User state address required by the data source.
|
||||
/// </summary>
|
||||
/// <remarks>Only used for <see cref="SampleFormat.Adpcm"/> as the address of the GC-ADPCM coefficients.</remarks>
|
||||
public ulong DataSourceStateAddress;
|
||||
|
||||
/// <summary>
|
||||
/// User state size required by the data source.
|
||||
/// </summary>
|
||||
/// <remarks>Only used for <see cref="SampleFormat.Adpcm"/> as the size of the GC-ADPCM coefficients.</remarks>
|
||||
public ulong DataSourceStateSize;
|
||||
|
||||
/// <summary>
|
||||
/// The target mix id of the voice.
|
||||
/// </summary>
|
||||
public int MixId;
|
||||
|
||||
/// <summary>
|
||||
/// The target splitter id of the voice.
|
||||
/// </summary>
|
||||
public uint SplitterId;
|
||||
|
||||
/// <summary>
|
||||
/// The wavebuffer parameters of this voice.
|
||||
/// </summary>
|
||||
public Array4<WaveBufferInternal> WaveBuffers;
|
||||
|
||||
/// <summary>
|
||||
/// The channel resource ids associated to the voice.
|
||||
/// </summary>
|
||||
public Array6<int> ChannelResourceIds;
|
||||
|
||||
/// <summary>
|
||||
/// Reset the voice drop flag during voice server update.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool ResetVoiceDropFlag;
|
||||
|
||||
/// <summary>
|
||||
/// Flush the amount of wavebuffer specified. This will result in the wavebuffer being skipped and marked played.
|
||||
/// </summary>
|
||||
/// <remarks>This was added on REV5.</remarks>
|
||||
public byte FlushWaveBufferCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private ushort _reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Change the behaviour of the voice.
|
||||
/// </summary>
|
||||
/// <remarks>This was added on REV5.</remarks>
|
||||
public DecodingBehaviour DecodingBehaviourFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Change the Sample Rate Conversion (SRC) quality of the voice.
|
||||
/// </summary>
|
||||
/// <remarks>This was added on REV8.</remarks>
|
||||
public SampleRateConversionQuality SrcQuality;
|
||||
|
||||
/// <summary>
|
||||
/// This was previously used for opus codec support on the Audio Renderer and was removed on REV3.
|
||||
/// </summary>
|
||||
public uint ExternalContext;
|
||||
|
||||
/// <summary>
|
||||
/// This was previously used for opus codec support on the Audio Renderer and was removed on REV3.
|
||||
/// </summary>
|
||||
public uint ExternalContextSize;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed uint _reserved3[2];
|
||||
|
||||
/// <summary>
|
||||
/// Input information for a voice wavebuffer.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x38, Pack = 1)]
|
||||
public struct WaveBufferInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Address of the wavebuffer data.
|
||||
/// </summary>
|
||||
public ulong Address;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the wavebuffer data.
|
||||
/// </summary>
|
||||
public ulong Size;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the first sample to play.
|
||||
/// </summary>
|
||||
public uint StartSampleOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the last sample to play.
|
||||
/// </summary>
|
||||
public uint EndSampleOffset;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the wavebuffer will loop when reaching <see cref="EndSampleOffset"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Starting with REV8, you can specify how many times to loop the wavebuffer (<see cref="LoopCount"/>) and where it should start and end when looping (<see cref="LoopFirstSampleOffset"/> and <see cref="LoopLastSampleOffset"/>)
|
||||
/// </remarks>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool ShouldLoop;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that this is the last wavebuffer to play of the voice.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsEndOfStream;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the server should update its internal state.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool SentToServer;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private byte _reserved;
|
||||
|
||||
/// <summary>
|
||||
/// If set to anything other than 0, specifies how many times to loop the wavebuffer.
|
||||
/// </summary>
|
||||
/// <remarks>This was added in REV8.</remarks>
|
||||
public int LoopCount;
|
||||
|
||||
/// <summary>
|
||||
/// Address of the context used by the sample decoder.
|
||||
/// </summary>
|
||||
/// <remarks>This is only currently used by <see cref="SampleFormat.Adpcm"/>.</remarks>
|
||||
public ulong ContextAddress;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the context used by the sample decoder.
|
||||
/// </summary>
|
||||
/// <remarks>This is only currently used by <see cref="SampleFormat.Adpcm"/>.</remarks>
|
||||
public ulong ContextSize;
|
||||
|
||||
/// <summary>
|
||||
/// If set to anything other than 0, specifies the offset of the first sample to play when looping.
|
||||
/// </summary>
|
||||
/// <remarks>This was added in REV8.</remarks>
|
||||
public uint LoopFirstSampleOffset;
|
||||
|
||||
/// <summary>
|
||||
/// If set to anything other than 0, specifies the offset of the last sample to play when looping.
|
||||
/// </summary>
|
||||
/// <remarks>This was added in REV8.</remarks>
|
||||
public uint LoopLastSampleOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the sample offsets are in a valid range for generic PCM.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The PCM sample type</typeparam>
|
||||
/// <returns>Returns true if the sample offset are in range of the size.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool IsSampleOffsetInRangeForPcm<T>() where T : unmanaged
|
||||
{
|
||||
uint dataTypeSize = (uint)Unsafe.SizeOf<T>();
|
||||
|
||||
return StartSampleOffset * dataTypeSize <= Size &&
|
||||
EndSampleOffset * dataTypeSize <= Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the sample offsets are in a valid range for the given <see cref="SampleFormat"/>.
|
||||
/// </summary>
|
||||
/// <param name="format">The target <see cref="SampleFormat"/></param>
|
||||
/// <returns>Returns true if the sample offset are in range of the size.</returns>
|
||||
public bool IsSampleOffsetValid(SampleFormat format)
|
||||
{
|
||||
bool result;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case SampleFormat.PcmInt16:
|
||||
result = IsSampleOffsetInRangeForPcm<ushort>();
|
||||
break;
|
||||
case SampleFormat.PcmFloat:
|
||||
result = IsSampleOffsetInRangeForPcm<float>();
|
||||
break;
|
||||
case SampleFormat.Adpcm:
|
||||
result = AdpcmHelper.GetAdpcmDataSize((int)StartSampleOffset) <= Size &&
|
||||
AdpcmHelper.GetAdpcmDataSize((int)EndSampleOffset) <= Size;
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"{format} not implemented!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag altering the behaviour of wavebuffer decoding.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DecodingBehaviour : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Default decoding behaviour.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Reset the played samples accumulator when looping.
|
||||
/// </summary>
|
||||
PlayedSampleCountResetWhenLooping = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Skip pitch and Sample Rate Conversion (SRC).
|
||||
/// </summary>
|
||||
SkipPitchAndSampleRateConversion = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the quality to use during Sample Rate Conversion (SRC) and pitch handling.
|
||||
/// </summary>
|
||||
/// <remarks>This was added in REV8.</remarks>
|
||||
public enum SampleRateConversionQuality : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Resample interpolating 4 samples per output sample.
|
||||
/// </summary>
|
||||
Default,
|
||||
|
||||
/// <summary>
|
||||
/// Resample interpolating 8 samples per output sample.
|
||||
/// </summary>
|
||||
High,
|
||||
|
||||
/// <summary>
|
||||
/// Resample interpolating 1 samples per output sample.
|
||||
/// </summary>
|
||||
Low
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/Ryujinx.Audio/Renderer/Parameter/VoiceOutStatus.cs
Normal file
35
src/Ryujinx.Audio/Renderer/Parameter/VoiceOutStatus.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Parameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Output information about a voice.
|
||||
/// </summary>
|
||||
/// <remarks>See <seealso cref="Server.StateUpdater.UpdateVoices(Server.Voice.VoiceContext, System.Memory{Server.MemoryPool.MemoryPoolState})"/></remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct VoiceOutStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The total amount of samples that was played.
|
||||
/// </summary>
|
||||
/// <remarks>This is reset to 0 when a <see cref="Common.WaveBuffer"/> finishes playing and <see cref="Common.WaveBuffer.IsEndOfStream"/> is set.</remarks>
|
||||
/// <remarks>This is reset to 0 when looping while <see cref="Parameter.VoiceInParameter.DecodingBehaviour.PlayedSampleCountResetWhenLooping"/> is set.</remarks>
|
||||
public ulong PlayedSampleCount;
|
||||
|
||||
/// <summary>
|
||||
/// The total amount of <see cref="WaveBuffer"/> consumed.
|
||||
/// </summary>
|
||||
public uint PlayedWaveBuffersCount;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the voice was dropped.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool VoiceDropFlag;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private unsafe fixed byte _reserved[3];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user