IHardwareOpusDecoderManager.cs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. namespace Ryujinx.HLE.HOS.Services.Aud
  2. {
  3. [Service("hwopus")]
  4. class IHardwareOpusDecoderManager : IpcService
  5. {
  6. public IHardwareOpusDecoderManager(ServiceCtx context) { }
  7. [Command(0)]
  8. // Initialize(bytes<8, 4>, u32, handle<copy>) -> object<nn::codec::detail::IHardwareOpusDecoder>
  9. public ResultCode Initialize(ServiceCtx context)
  10. {
  11. int sampleRate = context.RequestData.ReadInt32();
  12. int channelsCount = context.RequestData.ReadInt32();
  13. MakeObject(context, new IHardwareOpusDecoder(sampleRate, channelsCount));
  14. return ResultCode.Success;
  15. }
  16. [Command(1)]
  17. // GetWorkBufferSize(bytes<8, 4>) -> u32
  18. public ResultCode GetWorkBufferSize(ServiceCtx context)
  19. {
  20. // Note: The sample rate is ignored because it is fixed to 48KHz.
  21. int sampleRate = context.RequestData.ReadInt32();
  22. int channelsCount = context.RequestData.ReadInt32();
  23. context.ResponseData.Write(GetOpusDecoderSize(channelsCount));
  24. return ResultCode.Success;
  25. }
  26. private static int GetOpusDecoderSize(int channelsCount)
  27. {
  28. const int silkDecoderSize = 0x2198;
  29. if (channelsCount < 1 || channelsCount > 2)
  30. {
  31. return 0;
  32. }
  33. int celtDecoderSize = GetCeltDecoderSize(channelsCount);
  34. int opusDecoderSize = (channelsCount * 0x800 + 0x4807) & -0x800 | 0x50;
  35. return opusDecoderSize + silkDecoderSize + celtDecoderSize;
  36. }
  37. private static int GetCeltDecoderSize(int channelsCount)
  38. {
  39. const int decodeBufferSize = 0x2030;
  40. const int celtDecoderSize = 0x58;
  41. const int celtSigSize = 0x4;
  42. const int overlap = 120;
  43. const int eBandsCount = 21;
  44. return (decodeBufferSize + overlap * 4) * channelsCount +
  45. eBandsCount * 16 +
  46. celtDecoderSize +
  47. celtSigSize;
  48. }
  49. }
  50. }