IHardwareOpusDecoder.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using Ryujinx.HLE.HOS.Services.Audio.Types;
  2. using System;
  3. using System.Runtime.InteropServices;
  4. namespace Ryujinx.HLE.HOS.Services.Audio.HardwareOpusDecoderManager
  5. {
  6. class IHardwareOpusDecoder : IpcService
  7. {
  8. private readonly IDecoder _decoder;
  9. private readonly OpusDecoderFlags _flags;
  10. public IHardwareOpusDecoder(int sampleRate, int channelsCount, OpusDecoderFlags flags)
  11. {
  12. _decoder = new Decoder(sampleRate, channelsCount);
  13. _flags = flags;
  14. }
  15. public IHardwareOpusDecoder(int sampleRate, int channelsCount, int streams, int coupledStreams, OpusDecoderFlags flags, byte[] mapping)
  16. {
  17. _decoder = new MultiSampleDecoder(sampleRate, channelsCount, streams, coupledStreams, mapping);
  18. _flags = flags;
  19. }
  20. [CommandHipc(0)]
  21. // DecodeInterleavedOld(buffer<unknown, 5>) -> (u32, u32, buffer<unknown, 6>)
  22. public ResultCode DecodeInterleavedOld(ServiceCtx context)
  23. {
  24. return DecodeInterleavedInternal(context, OpusDecoderFlags.None, reset: false, withPerf: false);
  25. }
  26. [CommandHipc(2)]
  27. // DecodeInterleavedForMultiStreamOld(buffer<unknown, 5>) -> (u32, u32, buffer<unknown, 6>)
  28. public ResultCode DecodeInterleavedForMultiStreamOld(ServiceCtx context)
  29. {
  30. return DecodeInterleavedInternal(context, OpusDecoderFlags.None, reset: false, withPerf: false);
  31. }
  32. [CommandHipc(4)] // 6.0.0+
  33. // DecodeInterleavedWithPerfOld(buffer<unknown, 5>) -> (u32, u32, u64, buffer<unknown, 0x46>)
  34. public ResultCode DecodeInterleavedWithPerfOld(ServiceCtx context)
  35. {
  36. return DecodeInterleavedInternal(context, OpusDecoderFlags.None, reset: false, withPerf: true);
  37. }
  38. [CommandHipc(5)] // 6.0.0+
  39. // DecodeInterleavedForMultiStreamWithPerfOld(buffer<unknown, 5>) -> (u32, u32, u64, buffer<unknown, 0x46>)
  40. public ResultCode DecodeInterleavedForMultiStreamWithPerfOld(ServiceCtx context)
  41. {
  42. return DecodeInterleavedInternal(context, OpusDecoderFlags.None, reset: false, withPerf: true);
  43. }
  44. [CommandHipc(6)] // 6.0.0+
  45. // DecodeInterleavedWithPerfAndResetOld(bool reset, buffer<unknown, 5>) -> (u32, u32, u64, buffer<unknown, 0x46>)
  46. public ResultCode DecodeInterleavedWithPerfAndResetOld(ServiceCtx context)
  47. {
  48. bool reset = context.RequestData.ReadBoolean();
  49. return DecodeInterleavedInternal(context, OpusDecoderFlags.None, reset, withPerf: true);
  50. }
  51. [CommandHipc(7)] // 6.0.0+
  52. // DecodeInterleavedForMultiStreamWithPerfAndResetOld(bool reset, buffer<unknown, 5>) -> (u32, u32, u64, buffer<unknown, 0x46>)
  53. public ResultCode DecodeInterleavedForMultiStreamWithPerfAndResetOld(ServiceCtx context)
  54. {
  55. bool reset = context.RequestData.ReadBoolean();
  56. return DecodeInterleavedInternal(context, OpusDecoderFlags.None, reset, withPerf: true);
  57. }
  58. [CommandHipc(8)] // 7.0.0+
  59. // DecodeInterleaved(bool reset, buffer<unknown, 0x45>) -> (u32, u32, u64, buffer<unknown, 0x46>)
  60. public ResultCode DecodeInterleaved(ServiceCtx context)
  61. {
  62. bool reset = context.RequestData.ReadBoolean();
  63. return DecodeInterleavedInternal(context, _flags, reset, withPerf: true);
  64. }
  65. [CommandHipc(9)] // 7.0.0+
  66. // DecodeInterleavedForMultiStream(bool reset, buffer<unknown, 0x45>) -> (u32, u32, u64, buffer<unknown, 0x46>)
  67. public ResultCode DecodeInterleavedForMultiStream(ServiceCtx context)
  68. {
  69. bool reset = context.RequestData.ReadBoolean();
  70. return DecodeInterleavedInternal(context, _flags, reset, withPerf: true);
  71. }
  72. private ResultCode DecodeInterleavedInternal(ServiceCtx context, OpusDecoderFlags flags, bool reset, bool withPerf)
  73. {
  74. ulong inPosition = context.Request.SendBuff[0].Position;
  75. ulong inSize = context.Request.SendBuff[0].Size;
  76. ulong outputPosition = context.Request.ReceiveBuff[0].Position;
  77. ulong outputSize = context.Request.ReceiveBuff[0].Size;
  78. ReadOnlySpan<byte> input = context.Memory.GetSpan(inPosition, (int)inSize);
  79. ResultCode result = _decoder.DecodeInterleaved(reset, input, out short[] outPcmData, outputSize, out uint outConsumed, out int outSamples);
  80. if (result == ResultCode.Success)
  81. {
  82. context.Memory.Write(outputPosition, MemoryMarshal.Cast<short, byte>(outPcmData.AsSpan()));
  83. context.ResponseData.Write(outConsumed);
  84. context.ResponseData.Write(outSamples);
  85. if (withPerf)
  86. {
  87. // This is the time the DSP took to process the request, TODO: fill this.
  88. context.ResponseData.Write(0UL);
  89. }
  90. }
  91. return result;
  92. }
  93. }
  94. }