BiquadFilterHelper.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //
  2. // Copyright (c) 2019-2021 Ryujinx
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. //
  17. using Ryujinx.Audio.Renderer.Dsp.State;
  18. using Ryujinx.Audio.Renderer.Parameter;
  19. using System;
  20. using System.Runtime.CompilerServices;
  21. namespace Ryujinx.Audio.Renderer.Dsp
  22. {
  23. public static class BiquadFilterHelper
  24. {
  25. private const int FixedPointPrecisionForParameter = 14;
  26. /// <summary>
  27. /// Apply a single biquad filter.
  28. /// </summary>
  29. /// <remarks>This is implemented with a direct form 2.</remarks>
  30. /// <param name="parameter">The biquad filter parameter</param>
  31. /// <param name="state">The biquad filter state</param>
  32. /// <param name="outputBuffer">The output buffer to write the result</param>
  33. /// <param name="inputBuffer">The input buffer to write the result</param>
  34. /// <param name="sampleCount">The count of samples to process</param>
  35. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  36. public static void ProcessBiquadFilter(ref BiquadFilterParameter parameter, ref BiquadFilterState state, Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, uint sampleCount)
  37. {
  38. float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter);
  39. float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter);
  40. float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter);
  41. float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter);
  42. float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter);
  43. for (int i = 0; i < sampleCount; i++)
  44. {
  45. float input = inputBuffer[i];
  46. float output = input * a0 + state.State0;
  47. state.State0 = input * a1 + output * b1 + state.State1;
  48. state.State1 = input * a2 + output * b2;
  49. outputBuffer[i] = output;
  50. }
  51. }
  52. /// <summary>
  53. /// Apply multiple biquad filter.
  54. /// </summary>
  55. /// <remarks>This is implemented with a direct form 1.</remarks>
  56. /// <param name="parameters">The biquad filter parameter</param>
  57. /// <param name="states">The biquad filter state</param>
  58. /// <param name="outputBuffer">The output buffer to write the result</param>
  59. /// <param name="inputBuffer">The input buffer to write the result</param>
  60. /// <param name="sampleCount">The count of samples to process</param>
  61. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  62. public static void ProcessBiquadFilter(ReadOnlySpan<BiquadFilterParameter> parameters, Span<BiquadFilterState> states, Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, uint sampleCount)
  63. {
  64. for (int stageIndex = 0; stageIndex < parameters.Length; stageIndex++)
  65. {
  66. BiquadFilterParameter parameter = parameters[stageIndex];
  67. ref BiquadFilterState state = ref states[stageIndex];
  68. float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter);
  69. float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter);
  70. float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter);
  71. float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter);
  72. float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter);
  73. for (int i = 0; i < sampleCount; i++)
  74. {
  75. float input = inputBuffer[i];
  76. float output = input * a0 + state.State0 * a1 + state.State1 * a2 + state.State2 * b1 + state.State3 * b2;
  77. state.State1 = state.State0;
  78. state.State0 = input;
  79. state.State3 = state.State2;
  80. state.State2 = output;
  81. outputBuffer[i] = output;
  82. }
  83. }
  84. }
  85. }
  86. }