DeviceSinkCommand.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using Ryujinx.Audio.Integration;
  2. using Ryujinx.Audio.Renderer.Server.Sink;
  3. using System;
  4. using System.Runtime.CompilerServices;
  5. using System.Text;
  6. namespace Ryujinx.Audio.Renderer.Dsp.Command
  7. {
  8. public class DeviceSinkCommand : ICommand
  9. {
  10. public bool Enabled { get; set; }
  11. public int NodeId { get; }
  12. public CommandType CommandType => CommandType.DeviceSink;
  13. public uint EstimatedProcessingTime { get; set; }
  14. public string DeviceName { get; }
  15. public int SessionId { get; }
  16. public uint InputCount { get; }
  17. public ushort[] InputBufferIndices { get; }
  18. public Memory<float> Buffers { get; }
  19. public DeviceSinkCommand(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId)
  20. {
  21. Enabled = true;
  22. NodeId = nodeId;
  23. DeviceName = Encoding.ASCII.GetString(sink.Parameter.DeviceName).TrimEnd('\0');
  24. SessionId = sessionId;
  25. InputCount = sink.Parameter.InputCount;
  26. InputBufferIndices = new ushort[InputCount];
  27. for (int i = 0; i < Math.Min(InputCount, Constants.ChannelCountMax); i++)
  28. {
  29. InputBufferIndices[i] = (ushort)(bufferOffset + sink.Parameter.Input[i]);
  30. }
  31. if (sink.UpsamplerState != null)
  32. {
  33. Buffers = sink.UpsamplerState.OutputBuffer;
  34. }
  35. else
  36. {
  37. Buffers = buffers;
  38. }
  39. }
  40. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  41. private Span<float> GetBuffer(int index, int sampleCount)
  42. {
  43. return Buffers.Span.Slice(index * sampleCount, sampleCount);
  44. }
  45. public void Process(CommandList context)
  46. {
  47. IHardwareDevice device = context.OutputDevice;
  48. if (device.GetSampleRate() == Constants.TargetSampleRate)
  49. {
  50. int channelCount = (int)device.GetChannelCount();
  51. uint bufferCount = Math.Min(device.GetChannelCount(), InputCount);
  52. const int sampleCount = Constants.TargetSampleCount;
  53. short[] outputBuffer = new short[bufferCount * sampleCount];
  54. for (int i = 0; i < bufferCount; i++)
  55. {
  56. ReadOnlySpan<float> inputBuffer = GetBuffer(InputBufferIndices[i], sampleCount);
  57. for (int j = 0; j < sampleCount; j++)
  58. {
  59. outputBuffer[i + j * channelCount] = PcmHelper.Saturate(inputBuffer[j]);
  60. }
  61. }
  62. device.AppendBuffer(outputBuffer, InputCount);
  63. }
  64. else
  65. {
  66. // TODO: support resampling for device only supporting something different
  67. throw new NotImplementedException();
  68. }
  69. }
  70. }
  71. }