FloatingPointHelper.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System;
  2. using System.Reflection.Metadata;
  3. using System.Runtime.CompilerServices;
  4. namespace Ryujinx.Audio.Renderer.Dsp
  5. {
  6. public static class FloatingPointHelper
  7. {
  8. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  9. public static float MultiplyRoundDown(float a, float b)
  10. {
  11. return RoundDown(a * b);
  12. }
  13. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  14. public static float RoundDown(float a)
  15. {
  16. return MathF.Round(a, 0);
  17. }
  18. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  19. public static float RoundUp(float a)
  20. {
  21. return MathF.Round(a);
  22. }
  23. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  24. public static float MultiplyRoundUp(float a, float b)
  25. {
  26. return RoundUp(a * b);
  27. }
  28. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  29. public static float Pow10(float x)
  30. {
  31. // NOTE: Nintendo implementation uses Q15 and a LUT for this, we don't.
  32. // As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
  33. if (x >= 0.0f)
  34. {
  35. return 1.0f;
  36. }
  37. else if (x <= -5.3f)
  38. {
  39. return 0.0f;
  40. }
  41. return MathF.Pow(10, x);
  42. }
  43. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  44. public static float Log10(float x)
  45. {
  46. // NOTE: Nintendo uses an approximation of log10, we don't.
  47. // As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
  48. return MathF.Pow(10, MathF.Max(x, 1.0e-10f));
  49. }
  50. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  51. public static float MeanSquare(ReadOnlySpan<float> inputs)
  52. {
  53. float res = 0.0f;
  54. foreach (float input in inputs)
  55. {
  56. res += (input * input);
  57. }
  58. res /= inputs.Length;
  59. return res;
  60. }
  61. /// <summary>
  62. /// Map decibel to linear.
  63. /// </summary>
  64. /// <param name="db">The decibel value to convert</param>
  65. /// <returns>Converted linear value/returns>
  66. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  67. public static float DecibelToLinear(float db)
  68. {
  69. return MathF.Pow(10.0f, db / 20.0f);
  70. }
  71. /// <summary>
  72. /// Map decibel to linear in [0, 2] range.
  73. /// </summary>
  74. /// <param name="db">The decibel value to convert</param>
  75. /// <returns>Converted linear value in [0, 2] range</returns>
  76. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  77. public static float DecibelToLinearExtended(float db)
  78. {
  79. float tmp = MathF.Log2(DecibelToLinear(db));
  80. return MathF.Truncate(tmp) + MathF.Pow(2.0f, tmp - MathF.Truncate(tmp));
  81. }
  82. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  83. public static float DegreesToRadians(float degrees)
  84. {
  85. return degrees * MathF.PI / 180.0f;
  86. }
  87. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  88. public static float Cos(float value)
  89. {
  90. return MathF.Cos(DegreesToRadians(value));
  91. }
  92. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  93. public static float Sin(float value)
  94. {
  95. return MathF.Sin(DegreesToRadians(value));
  96. }
  97. }
  98. }