diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-11-17 01:36:49 -0200 |
|---|---|---|
| committer | Ac_K <Acoustik666@gmail.com> | 2018-11-17 04:36:49 +0100 |
| commit | b833183ef640934e82106cb91f7ced65d81e3b07 (patch) | |
| tree | 9d0f7c8008e5d65d86550d66a11d1662e36a2e21 /Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoder.cs | |
| parent | 5829e36a5cf5c1586dc8ebb5b52f99b7f61605b6 (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.cs | 91 |
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; + } + } +} |
