IAudioRendererManager.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using Ryujinx.Audio;
  2. using Ryujinx.Common;
  3. using Ryujinx.Common.Logging;
  4. using Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager;
  5. namespace Ryujinx.HLE.HOS.Services.Audio
  6. {
  7. [Service("audren:u")]
  8. class IAudioRendererManager : IpcService
  9. {
  10. public IAudioRendererManager(ServiceCtx context) { }
  11. [Command(0)]
  12. // OpenAudioRenderer(nn::audio::detail::AudioRendererParameterInternal, u64, nn::applet::AppletResourceUserId, pid, handle<copy>, handle<copy>)
  13. // -> object<nn::audio::detail::IAudioRenderer>
  14. public ResultCode OpenAudioRenderer(ServiceCtx context)
  15. {
  16. IAalOutput audioOut = context.Device.AudioOut;
  17. AudioRendererParameter Params = GetAudioRendererParameter(context);
  18. MakeObject(context, new IAudioRenderer(
  19. context.Device.System,
  20. context.Memory,
  21. audioOut,
  22. Params));
  23. return ResultCode.Success;
  24. }
  25. [Command(1)]
  26. // GetWorkBufferSize(nn::audio::detail::AudioRendererParameterInternal) -> u64
  27. public ResultCode GetAudioRendererWorkBufferSize(ServiceCtx context)
  28. {
  29. AudioRendererParameter parameters = GetAudioRendererParameter(context);
  30. if (AudioRendererCommon.CheckValidRevision(parameters))
  31. {
  32. BehaviorInfo behaviorInfo = new BehaviorInfo();
  33. behaviorInfo.SetUserLibRevision(parameters.Revision);
  34. long size;
  35. int totalMixCount = parameters.SubMixCount + 1;
  36. size = BitUtils.AlignUp(parameters.MixBufferCount * 4, AudioRendererConsts.BufferAlignment) +
  37. parameters.SubMixCount * 0x400 +
  38. totalMixCount * 0x940 +
  39. parameters.VoiceCount * 0x3F0 +
  40. BitUtils.AlignUp(totalMixCount * 8, 16) +
  41. BitUtils.AlignUp(parameters.VoiceCount * 8, 16) +
  42. BitUtils.AlignUp(((parameters.SinkCount + parameters.SubMixCount) * 0x3C0 + parameters.SampleCount * 4) *
  43. (parameters.MixBufferCount + 6), AudioRendererConsts.BufferAlignment) +
  44. (parameters.SinkCount + parameters.SubMixCount) * 0x2C0 +
  45. (parameters.EffectCount + parameters.VoiceCount * 4) * 0x30 +
  46. 0x50;
  47. if (behaviorInfo.IsSplitterSupported())
  48. {
  49. size += BitUtils.AlignUp(NodeStates.GetWorkBufferSize(totalMixCount) + EdgeMatrix.GetWorkBufferSize(totalMixCount), 16);
  50. }
  51. size = parameters.SinkCount * 0x170 +
  52. (parameters.SinkCount + parameters.SubMixCount) * 0x280 +
  53. parameters.EffectCount * 0x4C0 +
  54. ((size + SplitterContext.CalcWorkBufferSize(behaviorInfo, parameters) + 0x30 * parameters.EffectCount + (4 * parameters.VoiceCount) + 0x8F) & ~0x3FL) +
  55. ((parameters.VoiceCount << 8) | 0x40);
  56. if (parameters.PerformanceManagerCount >= 1)
  57. {
  58. size += (PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(behaviorInfo, parameters) *
  59. (parameters.PerformanceManagerCount + 1) + 0xFF) & ~0x3FL;
  60. }
  61. if (behaviorInfo.IsVariadicCommandBufferSizeSupported())
  62. {
  63. size += CommandGenerator.CalculateCommandBufferSize(parameters) + 0x7E;
  64. }
  65. else
  66. {
  67. size += 0x1807E;
  68. }
  69. size = BitUtils.AlignUp(size, 0x1000);
  70. context.ResponseData.Write(size);
  71. Logger.PrintDebug(LogClass.ServiceAudio, $"WorkBufferSize is 0x{size:x16}.");
  72. return ResultCode.Success;
  73. }
  74. else
  75. {
  76. context.ResponseData.Write(0L);
  77. Logger.PrintWarning(LogClass.ServiceAudio, $"Library Revision REV{AudioRendererCommon.GetRevisionVersion(parameters.Revision)} is not supported!");
  78. return ResultCode.UnsupportedRevision;
  79. }
  80. }
  81. private AudioRendererParameter GetAudioRendererParameter(ServiceCtx context)
  82. {
  83. AudioRendererParameter Params = new AudioRendererParameter
  84. {
  85. SampleRate = context.RequestData.ReadInt32(),
  86. SampleCount = context.RequestData.ReadInt32(),
  87. MixBufferCount = context.RequestData.ReadInt32(),
  88. SubMixCount = context.RequestData.ReadInt32(),
  89. VoiceCount = context.RequestData.ReadInt32(),
  90. SinkCount = context.RequestData.ReadInt32(),
  91. EffectCount = context.RequestData.ReadInt32(),
  92. PerformanceManagerCount = context.RequestData.ReadInt32(),
  93. VoiceDropEnable = context.RequestData.ReadInt32(),
  94. SplitterCount = context.RequestData.ReadInt32(),
  95. SplitterDestinationDataCount = context.RequestData.ReadInt32(),
  96. Unknown2C = context.RequestData.ReadInt32(),
  97. Revision = context.RequestData.ReadInt32()
  98. };
  99. return Params;
  100. }
  101. [Command(2)]
  102. // GetAudioDeviceService(nn::applet::AppletResourceUserId) -> object<nn::audio::detail::IAudioDevice>
  103. public ResultCode GetAudioDeviceService(ServiceCtx context)
  104. {
  105. long appletResourceUserId = context.RequestData.ReadInt64();
  106. MakeObject(context, new IAudioDevice(context.Device.System));
  107. return ResultCode.Success;
  108. }
  109. [Command(4)] // 4.0.0+
  110. // GetAudioDeviceServiceWithRevisionInfo(u32 revision_info, nn::applet::AppletResourceUserId) -> object<nn::audio::detail::IAudioDevice>
  111. public ResultCode GetAudioDeviceServiceWithRevisionInfo(ServiceCtx context)
  112. {
  113. int revisionInfo = context.RequestData.ReadInt32();
  114. long appletResourceUserId = context.RequestData.ReadInt64();
  115. Logger.PrintStub(LogClass.ServiceAudio, new { appletResourceUserId, revisionInfo });
  116. return GetAudioDeviceService(context);
  117. }
  118. }
  119. }