Move solution and projects to src
This commit is contained in:
52
src/Ryujinx.Audio/Renderer/Dsp/Effect/DecayDelay.cs
Normal file
52
src/Ryujinx.Audio/Renderer/Dsp/Effect/DecayDelay.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
||||
{
|
||||
public class DecayDelay : IDelayLine
|
||||
{
|
||||
private readonly IDelayLine _delayLine;
|
||||
|
||||
public uint CurrentSampleCount => _delayLine.CurrentSampleCount;
|
||||
|
||||
public uint SampleCountMax => _delayLine.SampleCountMax;
|
||||
|
||||
private float _decayRate;
|
||||
|
||||
public DecayDelay(IDelayLine delayLine)
|
||||
{
|
||||
_decayRate = 0.0f;
|
||||
_delayLine = delayLine;
|
||||
}
|
||||
|
||||
public void SetDecayRate(float decayRate)
|
||||
{
|
||||
_decayRate = decayRate;
|
||||
}
|
||||
|
||||
public float Update(float value)
|
||||
{
|
||||
float delayLineValue = _delayLine.Read();
|
||||
float processedValue = value - (_decayRate * delayLineValue);
|
||||
|
||||
return _delayLine.Update(processedValue) + processedValue * _decayRate;
|
||||
}
|
||||
|
||||
public void SetDelay(float delayTime)
|
||||
{
|
||||
_delayLine.SetDelay(delayTime);
|
||||
}
|
||||
|
||||
public float Read()
|
||||
{
|
||||
return _delayLine.Read();
|
||||
}
|
||||
|
||||
public float TapUnsafe(uint sampleIndex, int offset)
|
||||
{
|
||||
return _delayLine.TapUnsafe(sampleIndex, offset);
|
||||
}
|
||||
|
||||
public float Tap(uint sampleIndex)
|
||||
{
|
||||
return _delayLine.Tap(sampleIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLine.cs
Normal file
78
src/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLine.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
||||
{
|
||||
public class DelayLine : IDelayLine
|
||||
{
|
||||
private float[] _workBuffer;
|
||||
private uint _sampleRate;
|
||||
private uint _currentSampleIndex;
|
||||
private uint _lastSampleIndex;
|
||||
|
||||
public uint CurrentSampleCount { get; private set; }
|
||||
public uint SampleCountMax { get; private set; }
|
||||
|
||||
public DelayLine(uint sampleRate, float delayTimeMax)
|
||||
{
|
||||
_sampleRate = sampleRate;
|
||||
SampleCountMax = IDelayLine.GetSampleCount(_sampleRate, delayTimeMax);
|
||||
_workBuffer = new float[SampleCountMax + 1];
|
||||
|
||||
SetDelay(delayTimeMax);
|
||||
}
|
||||
|
||||
private void ConfigureDelay(uint targetSampleCount)
|
||||
{
|
||||
CurrentSampleCount = Math.Min(SampleCountMax, targetSampleCount);
|
||||
_currentSampleIndex = 0;
|
||||
|
||||
if (CurrentSampleCount == 0)
|
||||
{
|
||||
_lastSampleIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastSampleIndex = CurrentSampleCount - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDelay(float delayTime)
|
||||
{
|
||||
ConfigureDelay(IDelayLine.GetSampleCount(_sampleRate, delayTime));
|
||||
}
|
||||
|
||||
public float Read()
|
||||
{
|
||||
return _workBuffer[_currentSampleIndex];
|
||||
}
|
||||
|
||||
public float Update(float value)
|
||||
{
|
||||
float output = Read();
|
||||
|
||||
_workBuffer[_currentSampleIndex++] = value;
|
||||
|
||||
if (_currentSampleIndex >= _lastSampleIndex)
|
||||
{
|
||||
_currentSampleIndex = 0;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public float TapUnsafe(uint sampleIndex, int offset)
|
||||
{
|
||||
return IDelayLine.Tap(_workBuffer, (int)_currentSampleIndex, (int)sampleIndex + offset, (int)CurrentSampleCount);
|
||||
}
|
||||
|
||||
public float Tap(uint sampleIndex)
|
||||
{
|
||||
if (sampleIndex >= CurrentSampleCount)
|
||||
{
|
||||
sampleIndex = CurrentSampleCount - 1;
|
||||
}
|
||||
|
||||
return TapUnsafe(sampleIndex, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLineReverb3d.cs
Normal file
76
src/Ryujinx.Audio/Renderer/Dsp/Effect/DelayLineReverb3d.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
||||
{
|
||||
public class DelayLine3d : IDelayLine
|
||||
{
|
||||
private float[] _workBuffer;
|
||||
private uint _sampleRate;
|
||||
private uint _currentSampleIndex;
|
||||
private uint _lastSampleIndex;
|
||||
|
||||
public uint CurrentSampleCount { get; private set; }
|
||||
public uint SampleCountMax { get; private set; }
|
||||
|
||||
public DelayLine3d(uint sampleRate, float delayTimeMax)
|
||||
{
|
||||
_sampleRate = sampleRate;
|
||||
SampleCountMax = IDelayLine.GetSampleCount(_sampleRate, delayTimeMax);
|
||||
_workBuffer = new float[SampleCountMax + 1];
|
||||
|
||||
SetDelay(delayTimeMax);
|
||||
}
|
||||
|
||||
private void ConfigureDelay(uint targetSampleCount)
|
||||
{
|
||||
if (SampleCountMax >= targetSampleCount)
|
||||
{
|
||||
CurrentSampleCount = targetSampleCount;
|
||||
_lastSampleIndex = (_currentSampleIndex + targetSampleCount) % (SampleCountMax + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDelay(float delayTime)
|
||||
{
|
||||
ConfigureDelay(IDelayLine.GetSampleCount(_sampleRate, delayTime));
|
||||
}
|
||||
|
||||
public float Read()
|
||||
{
|
||||
return _workBuffer[_currentSampleIndex];
|
||||
}
|
||||
|
||||
public float Update(float value)
|
||||
{
|
||||
Debug.Assert(!float.IsNaN(value) && !float.IsInfinity(value));
|
||||
|
||||
_workBuffer[_lastSampleIndex++] = value;
|
||||
|
||||
float output = Read();
|
||||
|
||||
_currentSampleIndex++;
|
||||
|
||||
if (_currentSampleIndex >= SampleCountMax)
|
||||
{
|
||||
_currentSampleIndex = 0;
|
||||
}
|
||||
|
||||
if (_lastSampleIndex >= SampleCountMax)
|
||||
{
|
||||
_lastSampleIndex = 0;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public float TapUnsafe(uint sampleIndex, int offset)
|
||||
{
|
||||
return IDelayLine.Tap(_workBuffer, (int)_lastSampleIndex, (int)sampleIndex + offset, (int)SampleCountMax + 1);
|
||||
}
|
||||
|
||||
public float Tap(uint sampleIndex)
|
||||
{
|
||||
return TapUnsafe(sampleIndex, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
||||
{
|
||||
public struct ExponentialMovingAverage
|
||||
{
|
||||
private float _mean;
|
||||
|
||||
public ExponentialMovingAverage(float mean)
|
||||
{
|
||||
_mean = mean;
|
||||
}
|
||||
|
||||
public float Read()
|
||||
{
|
||||
return _mean;
|
||||
}
|
||||
|
||||
public float Update(float value, float alpha)
|
||||
{
|
||||
_mean += alpha * (value - _mean);
|
||||
|
||||
return _mean;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Ryujinx.Audio/Renderer/Dsp/Effect/IDelayLine.cs
Normal file
37
src/Ryujinx.Audio/Renderer/Dsp/Effect/IDelayLine.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
||||
{
|
||||
public interface IDelayLine
|
||||
{
|
||||
uint CurrentSampleCount { get; }
|
||||
uint SampleCountMax { get; }
|
||||
|
||||
void SetDelay(float delayTime);
|
||||
float Read();
|
||||
float Update(float value);
|
||||
|
||||
float TapUnsafe(uint sampleIndex, int offset);
|
||||
float Tap(uint sampleIndex);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float Tap(Span<float> workBuffer, int baseIndex, int sampleIndex, int delaySampleCount)
|
||||
{
|
||||
int targetIndex = baseIndex - sampleIndex;
|
||||
|
||||
if (targetIndex < 0)
|
||||
{
|
||||
targetIndex += delaySampleCount;
|
||||
}
|
||||
|
||||
return workBuffer[targetIndex];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint GetSampleCount(uint sampleRate, float delayTime)
|
||||
{
|
||||
return (uint)MathF.Round(sampleRate * delayTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user