diff options
Diffstat (limited to 'src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs')
| -rw-r--r-- | src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRenderer.cs | 187 |
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); + } + } +} |
