BiquadFilterCommand.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. //
  2. // Copyright (c) 2019-2020 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. namespace Ryujinx.Audio.Renderer.Dsp.Command
  21. {
  22. public class BiquadFilterCommand : ICommand
  23. {
  24. public bool Enabled { get; set; }
  25. public int NodeId { get; }
  26. public CommandType CommandType => CommandType.BiquadFilter;
  27. public ulong EstimatedProcessingTime { get; set; }
  28. public BiquadFilterParameter Parameter { get; }
  29. public Memory<BiquadFilterState> BiquadFilterState { get; }
  30. public int InputBufferIndex { get; }
  31. public int OutputBufferIndex { get; }
  32. public bool NeedInitialization { get; }
  33. public BiquadFilterCommand(int baseIndex, ref BiquadFilterParameter filter, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, bool needInitialization, int nodeId)
  34. {
  35. Parameter = filter;
  36. BiquadFilterState = biquadFilterStateMemory;
  37. InputBufferIndex = baseIndex + inputBufferOffset;
  38. OutputBufferIndex = baseIndex + outputBufferOffset;
  39. NeedInitialization = needInitialization;
  40. Enabled = true;
  41. NodeId = nodeId;
  42. }
  43. private void ProcessBiquadFilter(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, uint sampleCount)
  44. {
  45. const int fixedPointPrecisionForParameter = 14;
  46. float a0 = FixedPointHelper.ToFloat(Parameter.Numerator[0], fixedPointPrecisionForParameter);
  47. float a1 = FixedPointHelper.ToFloat(Parameter.Numerator[1], fixedPointPrecisionForParameter);
  48. float a2 = FixedPointHelper.ToFloat(Parameter.Numerator[2], fixedPointPrecisionForParameter);
  49. float b1 = FixedPointHelper.ToFloat(Parameter.Denominator[0], fixedPointPrecisionForParameter);
  50. float b2 = FixedPointHelper.ToFloat(Parameter.Denominator[1], fixedPointPrecisionForParameter);
  51. ref BiquadFilterState state = ref BiquadFilterState.Span[0];
  52. for (int i = 0; i < sampleCount; i++)
  53. {
  54. float input = inputBuffer[i];
  55. float output = input * a0 + state.Z1;
  56. state.Z1 = input * a1 + output * b1 + state.Z2;
  57. state.Z2 = input * a2 + output * b2;
  58. outputBuffer[i] = output;
  59. }
  60. }
  61. public void Process(CommandList context)
  62. {
  63. Span<float> outputBuffer = context.GetBuffer(InputBufferIndex);
  64. if (NeedInitialization)
  65. {
  66. BiquadFilterState.Span[0] = new BiquadFilterState();
  67. }
  68. ProcessBiquadFilter(outputBuffer, outputBuffer, context.SampleCount);
  69. }
  70. }
  71. }