Parcourir la source

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.
riperiperi il y a 4 ans
Parent
commit
7e9011673b
1 fichiers modifiés avec 28 ajouts et 5 suppressions
  1. 28 5
      Ryujinx.Audio/Renderer/Dsp/ResamplerHelper.cs

+ 28 - 5
Ryujinx.Audio/Renderer/Dsp/ResamplerHelper.cs

@@ -600,19 +600,42 @@ namespace Ryujinx.Audio.Renderer.Dsp
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         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 maxIndex = inputBuffer.Length - 1;
+            int cubicEnd = inputBuffer.Length - 3;
 
             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;
                 inputBufferIndex += (int)MathF.Truncate(fraction);