Use a basic cubic interpolation for the audren upsampler (#3129)
Before, it was selecting nearest neighbour, which sounded terrible. This is likely temporary til the upsampling algorithm used by the switch is reversed. Fixes bad audio in Skyward Sword HD.
This commit is contained in:
parent
741db8e43d
commit
7e9011673b
1 changed files with 28 additions and 5 deletions
|
@ -600,19 +600,42 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void ResampleForUpsampler(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float ratio, ref float fraction, int sampleCount)
|
public static void ResampleForUpsampler(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float ratio, ref float fraction, int sampleCount)
|
||||||
{
|
{
|
||||||
// TODO: use a bandwidth filter to have better resampling.
|
// Currently a simple cubic interpolation, assuming duplicated values at edges.
|
||||||
|
// TODO: Discover and use algorithm that the switch uses.
|
||||||
|
|
||||||
int inputBufferIndex = 0;
|
int inputBufferIndex = 0;
|
||||||
|
int maxIndex = inputBuffer.Length - 1;
|
||||||
|
int cubicEnd = inputBuffer.Length - 3;
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
{
|
{
|
||||||
float outputData = inputBuffer[inputBufferIndex];
|
float s0, s1, s2, s3;
|
||||||
|
|
||||||
if (fraction > 1.0f)
|
s1 = inputBuffer[inputBufferIndex];
|
||||||
|
|
||||||
|
if (inputBufferIndex == 0 || inputBufferIndex > cubicEnd)
|
||||||
{
|
{
|
||||||
outputData = inputBuffer[inputBufferIndex + 1];
|
// Clamp interplation values at the ends of the input buffer.
|
||||||
|
s0 = inputBuffer[Math.Max(0, inputBufferIndex - 1)];
|
||||||
|
s2 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 1)];
|
||||||
|
s3 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 2)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s0 = inputBuffer[inputBufferIndex - 1];
|
||||||
|
s2 = inputBuffer[inputBufferIndex + 1];
|
||||||
|
s3 = inputBuffer[inputBufferIndex + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
outputBuffer[i] = outputData;
|
float a = s3 - s2 - s0 + s1;
|
||||||
|
float b = s0 - s1 - a;
|
||||||
|
float c = s2 - s0;
|
||||||
|
float d = s1;
|
||||||
|
|
||||||
|
float f2 = fraction * fraction;
|
||||||
|
float f3 = f2 * fraction;
|
||||||
|
|
||||||
|
outputBuffer[i] = a * f3 + b * f2 + c * fraction + d;
|
||||||
|
|
||||||
fraction += ratio;
|
fraction += ratio;
|
||||||
inputBufferIndex += (int)MathF.Truncate(fraction);
|
inputBufferIndex += (int)MathF.Truncate(fraction);
|
||||||
|
|
Loading…
Reference in a new issue