IHardwareOpusDecoderManager.cs 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Ryujinx.Common;
  2. using Ryujinx.HLE.HOS.Services.Audio.HardwareOpusDecoderManager;
  3. using Ryujinx.HLE.HOS.Services.Audio.Types;
  4. namespace Ryujinx.HLE.HOS.Services.Audio
  5. {
  6. [Service("hwopus")]
  7. class IHardwareOpusDecoderManager : IpcService
  8. {
  9. public IHardwareOpusDecoderManager(ServiceCtx context) { }
  10. [CommandHipc(0)]
  11. // Initialize(bytes<8, 4>, u32, handle<copy>) -> object<nn::codec::detail::IHardwareOpusDecoder>
  12. public ResultCode Initialize(ServiceCtx context)
  13. {
  14. int sampleRate = context.RequestData.ReadInt32();
  15. int channelsCount = context.RequestData.ReadInt32();
  16. MakeObject(context, new IHardwareOpusDecoder(sampleRate, channelsCount));
  17. // Close transfer memory immediately as we don't use it.
  18. context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]);
  19. return ResultCode.Success;
  20. }
  21. [CommandHipc(1)]
  22. // GetWorkBufferSize(bytes<8, 4>) -> u32
  23. public ResultCode GetWorkBufferSize(ServiceCtx context)
  24. {
  25. // NOTE: The sample rate is ignored because it is fixed to 48KHz.
  26. int sampleRate = context.RequestData.ReadInt32();
  27. int channelsCount = context.RequestData.ReadInt32();
  28. context.ResponseData.Write(GetOpusDecoderSize(channelsCount));
  29. return ResultCode.Success;
  30. }
  31. [CommandHipc(4)] // 12.0.0+
  32. // InitializeEx(OpusParametersEx, u32, handle<copy>) -> object<nn::codec::detail::IHardwareOpusDecoder>
  33. public ResultCode InitializeEx(ServiceCtx context)
  34. {
  35. OpusParametersEx parameters = context.RequestData.ReadStruct<OpusParametersEx>();
  36. // UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result.
  37. MakeObject(context, new IHardwareOpusDecoder(parameters.SampleRate, parameters.ChannelCount));
  38. // Close transfer memory immediately as we don't use it.
  39. context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]);
  40. return ResultCode.Success;
  41. }
  42. [CommandHipc(5)] // 12.0.0+
  43. // GetWorkBufferSizeEx(OpusParametersEx) -> u32
  44. public ResultCode GetWorkBufferSizeEx(ServiceCtx context)
  45. {
  46. OpusParametersEx parameters = context.RequestData.ReadStruct<OpusParametersEx>();
  47. // NOTE: The sample rate is ignored because it is fixed to 48KHz.
  48. context.ResponseData.Write(GetOpusDecoderSize(parameters.ChannelCount));
  49. return ResultCode.Success;
  50. }
  51. private static int GetOpusDecoderSize(int channelsCount)
  52. {
  53. const int silkDecoderSize = 0x2198;
  54. if (channelsCount < 1 || channelsCount > 2)
  55. {
  56. return 0;
  57. }
  58. int celtDecoderSize = GetCeltDecoderSize(channelsCount);
  59. int opusDecoderSize = (channelsCount * 0x800 + 0x4807) & -0x800 | 0x50;
  60. return opusDecoderSize + silkDecoderSize + celtDecoderSize;
  61. }
  62. private static int GetCeltDecoderSize(int channelsCount)
  63. {
  64. const int decodeBufferSize = 0x2030;
  65. const int celtDecoderSize = 0x58;
  66. const int celtSigSize = 0x4;
  67. const int overlap = 120;
  68. const int eBandsCount = 21;
  69. return (decodeBufferSize + overlap * 4) * channelsCount +
  70. eBandsCount * 16 +
  71. celtDecoderSize +
  72. celtSigSize;
  73. }
  74. }
  75. }