aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs')
-rw-r--r--src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs
new file mode 100644
index 00000000..776df641
--- /dev/null
+++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs
@@ -0,0 +1,187 @@
+using Ryujinx.Audio;
+using Ryujinx.Audio.Integration;
+using Ryujinx.Audio.Renderer.Server;
+using Ryujinx.Common.Memory;
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Sf;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using System;
+using System.Buffers;
+
+namespace Ryujinx.Horizon.Sdk.Audio.Detail
+{
+ partial class AudioRenderer : IAudioRenderer, IDisposable
+ {
+ private readonly AudioRenderSystem _renderSystem;
+ private int _workBufferHandle;
+ private int _processHandle;
+
+ public AudioRenderer(AudioRenderSystem renderSystem, int workBufferHandle, int processHandle)
+ {
+ _renderSystem = renderSystem;
+ _workBufferHandle = workBufferHandle;
+ _processHandle = processHandle;
+ }
+
+ [CmifCommand(0)]
+ public Result GetSampleRate(out int sampleRate)
+ {
+ sampleRate = (int)_renderSystem.GetSampleRate();
+
+ return Result.Success;
+ }
+
+ [CmifCommand(1)]
+ public Result GetSampleCount(out int sampleCount)
+ {
+ sampleCount = (int)_renderSystem.GetSampleCount();
+
+ return Result.Success;
+ }
+
+ [CmifCommand(2)]
+ public Result GetMixBufferCount(out int mixBufferCount)
+ {
+ mixBufferCount = (int)_renderSystem.GetMixBufferCount();
+
+ return Result.Success;
+ }
+
+ [CmifCommand(3)]
+ public Result GetState(out int state)
+ {
+ state = _renderSystem.IsActive() ? 0 : 1;
+
+ return Result.Success;
+ }
+
+ [CmifCommand(4)]
+ public Result RequestUpdate(
+ [Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span<byte> output,
+ [Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span<byte> performanceOutput,
+ [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> input)
+ {
+ using IMemoryOwner<byte> outputOwner = ByteMemoryPool.Rent(output.Length);
+ using IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.Rent(performanceOutput.Length);
+
+ Memory<byte> outputMemory = outputOwner.Memory;
+ Memory<byte> performanceOutputMemory = performanceOutputOwner.Memory;
+
+ using MemoryHandle outputHandle = outputMemory.Pin();
+ using MemoryHandle performanceOutputHandle = performanceOutputMemory.Pin();
+
+ Result result = new Result((int)_renderSystem.Update(outputMemory, performanceOutputMemory, input.ToArray()));
+
+ outputMemory.Span.CopyTo(output);
+ performanceOutputMemory.Span.CopyTo(performanceOutput);
+
+ return result;
+ }
+
+ [CmifCommand(5)]
+ public Result Start()
+ {
+ _renderSystem.Start();
+
+ return Result.Success;
+ }
+
+ [CmifCommand(6)]
+ public Result Stop()
+ {
+ _renderSystem.Stop();
+
+ return Result.Success;
+ }
+
+ [CmifCommand(7)]
+ public Result QuerySystemEvent([CopyHandle] out int eventHandle)
+ {
+ ResultCode rc = _renderSystem.QuerySystemEvent(out IWritableEvent systemEvent);
+
+ eventHandle = 0;
+
+ if (rc == ResultCode.Success && systemEvent is AudioEvent audioEvent)
+ {
+ eventHandle = audioEvent.GetReadableHandle();
+ }
+
+ return new Result((int)rc);
+ }
+
+ [CmifCommand(8)]
+ public Result SetRenderingTimeLimit(int percent)
+ {
+ _renderSystem.SetRenderingTimeLimitPercent((uint)percent);
+
+ return Result.Success;
+ }
+
+ [CmifCommand(9)]
+ public Result GetRenderingTimeLimit(out int percent)
+ {
+ percent = (int)_renderSystem.GetRenderingTimeLimit();
+
+ return Result.Success;
+ }
+
+ [CmifCommand(10)] // 3.0.0+
+ public Result RequestUpdateAuto(
+ [Buffer(HipcBufferFlags.Out | HipcBufferFlags.AutoSelect)] Span<byte> output,
+ [Buffer(HipcBufferFlags.Out | HipcBufferFlags.AutoSelect)] Span<byte> performanceOutput,
+ [Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] ReadOnlySpan<byte> input)
+ {
+ return RequestUpdate(output, performanceOutput, input);
+ }
+
+ [CmifCommand(11)] // 3.0.0+
+ public Result ExecuteAudioRendererRendering()
+ {
+ return new Result((int)_renderSystem.ExecuteAudioRendererRendering());
+ }
+
+ [CmifCommand(12)] // 15.0.0+
+ public Result SetVoiceDropParameter(float voiceDropParameter)
+ {
+ _renderSystem.SetVoiceDropParameter(voiceDropParameter);
+
+ return Result.Success;
+ }
+
+ [CmifCommand(13)] // 15.0.0+
+ public Result GetVoiceDropParameter(out float voiceDropParameter)
+ {
+ voiceDropParameter = _renderSystem.GetVoiceDropParameter();
+
+ return Result.Success;
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _renderSystem.Dispose();
+
+ if (_workBufferHandle != 0)
+ {
+ HorizonStatic.Syscall.CloseHandle(_workBufferHandle);
+
+ _workBufferHandle = 0;
+ }
+
+ if (_processHandle != 0)
+ {
+ HorizonStatic.Syscall.CloseHandle(_processHandle);
+
+ _processHandle = 0;
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}