aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-11-17 01:36:49 -0200
committerAc_K <Acoustik666@gmail.com>2018-11-17 04:36:49 +0100
commitb833183ef640934e82106cb91f7ced65d81e3b07 (patch)
tree9d0f7c8008e5d65d86550d66a11d1662e36a2e21 /Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs
parent5829e36a5cf5c1586dc8ebb5b52f99b7f61605b6 (diff)
HwOpus service implementation (#201)
* Started to implement the hwopus service * Write outputs on decode method, some basic error handling * Fix buffer size read from header and check * Fix order of values
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs')
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs91
1 files changed, 91 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs b/Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs
new file mode 100644
index 00000000..a71b8602
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs
@@ -0,0 +1,91 @@
+using Concentus.Structs;
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+using static Ryujinx.HLE.HOS.ErrorCode;
+
+namespace Ryujinx.HLE.HOS.Services.Aud
+{
+ class IHardwareOpusDecoder : IpcService
+ {
+ private const int FixedSampleRate = 48000;
+
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private int SampleRate;
+ private int ChannelsCount;
+
+ private OpusDecoder Decoder;
+
+ public IHardwareOpusDecoder(int SampleRate, int ChannelsCount)
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, DecodeInterleaved },
+ { 4, DecodeInterleavedWithPerf }
+ };
+
+ this.SampleRate = SampleRate;
+ this.ChannelsCount = ChannelsCount;
+
+ Decoder = new OpusDecoder(FixedSampleRate, ChannelsCount);
+ }
+
+ public long DecodeInterleavedWithPerf(ServiceCtx Context)
+ {
+ long Result = DecodeInterleaved(Context);
+
+ //TODO: Figure out what this value is.
+ //According to switchbrew, it is now used.
+ Context.ResponseData.Write(0L);
+
+ return Result;
+ }
+
+ public long DecodeInterleaved(ServiceCtx Context)
+ {
+ long InPosition = Context.Request.SendBuff[0].Position;
+ long InSize = Context.Request.SendBuff[0].Size;
+
+ if (InSize < 8)
+ {
+ return MakeError(ErrorModule.Audio, AudErr.OpusInvalidInput);
+ }
+
+ long OutPosition = Context.Request.ReceiveBuff[0].Position;
+ long OutSize = Context.Request.ReceiveBuff[0].Size;
+
+ byte[] OpusData = Context.Memory.ReadBytes(InPosition, InSize);
+
+ int Processed = ((OpusData[0] << 24) |
+ (OpusData[1] << 16) |
+ (OpusData[2] << 8) |
+ (OpusData[3] << 0)) + 8;
+
+ if ((uint)Processed > (ulong)InSize)
+ {
+ return MakeError(ErrorModule.Audio, AudErr.OpusInvalidInput);
+ }
+
+ short[] Pcm = new short[OutSize / 2];
+
+ int FrameSize = Pcm.Length / (ChannelsCount * 2);
+
+ int Samples = Decoder.Decode(OpusData, 0, OpusData.Length, Pcm, 0, FrameSize);
+
+ foreach (short Sample in Pcm)
+ {
+ Context.Memory.WriteInt16(OutPosition, Sample);
+
+ OutPosition += 2;
+ }
+
+ Context.ResponseData.Write(Processed);
+ Context.ResponseData.Write(Samples);
+
+ return 0;
+ }
+ }
+}