CircularBufferSinkCommand.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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.Parameter.Sink;
  18. using Ryujinx.Audio.Renderer.Server.MemoryPool;
  19. using System;
  20. using System.Diagnostics;
  21. namespace Ryujinx.Audio.Renderer.Dsp.Command
  22. {
  23. public class CircularBufferSinkCommand : ICommand
  24. {
  25. public bool Enabled { get; set; }
  26. public int NodeId { get; }
  27. public CommandType CommandType => CommandType.CircularBufferSink;
  28. public ulong EstimatedProcessingTime { get; set; }
  29. public ushort[] Input { get; }
  30. public uint InputCount { get; }
  31. public ulong CircularBuffer { get; }
  32. public ulong CircularBufferSize { get; }
  33. public ulong CurrentOffset { get; }
  34. public CircularBufferSinkCommand(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId)
  35. {
  36. Enabled = true;
  37. NodeId = nodeId;
  38. Input = new ushort[RendererConstants.ChannelCountMax];
  39. InputCount = parameter.InputCount;
  40. for (int i = 0; i < InputCount; i++)
  41. {
  42. Input[i] = (ushort)(bufferOffset + parameter.Input[i]);
  43. }
  44. CircularBuffer = circularBufferAddressInfo.GetReference(true);
  45. CircularBufferSize = parameter.BufferSize;
  46. CurrentOffset = currentOffset;
  47. Debug.Assert(CircularBuffer != 0);
  48. }
  49. public void Process(CommandList context)
  50. {
  51. const int targetChannelCount = 2;
  52. ulong currentOffset = CurrentOffset;
  53. if (CircularBufferSize > 0)
  54. {
  55. for (int i = 0; i < InputCount; i++)
  56. {
  57. ReadOnlySpan<float> inputBuffer = context.GetBuffer(Input[i]);
  58. ulong targetOffset = CircularBuffer + currentOffset;
  59. for (int y = 0; y < context.SampleCount; y++)
  60. {
  61. context.MemoryManager.Write(targetOffset + (ulong)y * targetChannelCount, PcmHelper.Saturate(inputBuffer[y]));
  62. }
  63. currentOffset += context.SampleCount * targetChannelCount;
  64. if (currentOffset >= CircularBufferSize)
  65. {
  66. currentOffset = 0;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. }