aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core/OsHle/Objects/Aud
diff options
context:
space:
mode:
authoremmauss <emmausssss@gmail.com>2018-02-20 22:09:23 +0200
committergdkchan <gab.dark.100@gmail.com>2018-02-20 17:09:23 -0300
commit62b827f474f0aa2152dd339fcc7cf31084e16a0b (patch)
tree0e5c55b341aee4db0ccb841a084f253ec5e05657 /Ryujinx.Core/OsHle/Objects/Aud
parentcb665bb715834526d73c9469d16114b287faaecd (diff)
Split main project into core,graphics and chocolarm4 subproject (#29)
Diffstat (limited to 'Ryujinx.Core/OsHle/Objects/Aud')
-rw-r--r--Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs180
-rw-r--r--Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs66
2 files changed, 246 insertions, 0 deletions
diff --git a/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs
new file mode 100644
index 00000000..061c6376
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs
@@ -0,0 +1,180 @@
+using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Ipc;
+using OpenTK.Audio;
+using OpenTK.Audio.OpenAL;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.Core.OsHle.Objects.Aud
+{
+ class IAudioOut : IIpcInterface
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IAudioOut()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, GetAudioOutState },
+ { 1, StartAudioOut },
+ { 2, StopAudioOut },
+ { 3, AppendAudioOutBuffer },
+ { 4, RegisterBufferEvent },
+ { 5, GetReleasedAudioOutBuffer },
+ { 6, ContainsAudioOutBuffer },
+ { 7, AppendAudioOutBuffer_ex },
+ { 8, GetReleasedAudioOutBuffer_ex }
+ };
+ }
+
+ enum AudioOutState
+ {
+ Started,
+ Stopped
+ };
+
+ //IAudioOut
+ private AudioOutState State = AudioOutState.Stopped;
+ private Queue<long> KeysQueue = new Queue<long>();
+
+ //OpenAL
+ private bool OpenALInstalled = true;
+ private AudioContext AudioCtx;
+ private int Source;
+ private int Buffer;
+
+ //Return State of IAudioOut
+ public long GetAudioOutState(ServiceCtx Context)
+ {
+ Context.ResponseData.Write((int)State);
+
+ return 0;
+ }
+
+ public long StartAudioOut(ServiceCtx Context)
+ {
+ if (State == AudioOutState.Stopped)
+ {
+ State = AudioOutState.Started;
+
+ try
+ {
+ AudioCtx = new AudioContext(); //Create the audio context
+ }
+ catch (Exception)
+ {
+ Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!");
+ OpenALInstalled = false;
+ }
+
+ if (OpenALInstalled) AL.Listener(ALListenerf.Gain, (float)8.0); //Add more gain to it
+ }
+
+ return 0;
+ }
+
+ public long StopAudioOut(ServiceCtx Context)
+ {
+ if (State == AudioOutState.Started)
+ {
+ if (OpenALInstalled)
+ {
+ if (AudioCtx == null) //Needed to call the instance of AudioContext()
+ return 0;
+
+ AL.SourceStop(Source);
+ AL.DeleteSource(Source);
+ }
+ State = AudioOutState.Stopped;
+ }
+
+ return 0;
+ }
+
+ public long AppendAudioOutBuffer(ServiceCtx Context)
+ {
+ long BufferId = Context.RequestData.ReadInt64();
+
+ KeysQueue.Enqueue(BufferId);
+
+ byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, sizeof(long) * 5);
+ using (MemoryStream MS = new MemoryStream(AudioOutBuffer))
+ {
+ BinaryReader Reader = new BinaryReader(MS);
+ long PointerNextBuffer = Reader.ReadInt64();
+ long PointerSampleBuffer = Reader.ReadInt64();
+ long CapacitySampleBuffer = Reader.ReadInt64();
+ long SizeDataInSampleBuffer = Reader.ReadInt64();
+ long OffsetDataInSampleBuffer = Reader.ReadInt64();
+
+ byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerSampleBuffer + OffsetDataInSampleBuffer, (int)SizeDataInSampleBuffer);
+
+ if (OpenALInstalled)
+ {
+ if (AudioCtx == null) //Needed to call the instance of AudioContext()
+ return 0;
+
+ Buffer = AL.GenBuffer();
+ AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000);
+
+ Source = AL.GenSource();
+ AL.SourceQueueBuffer(Source, Buffer);
+ }
+ }
+
+ return 0;
+ }
+
+ public long RegisterBufferEvent(ServiceCtx Context)
+ {
+ int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent());
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ return 0;
+ }
+
+ public long GetReleasedAudioOutBuffer(ServiceCtx Context)
+ {
+ long TempKey = 0;
+
+ if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue();
+
+ AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey));
+
+ int ReleasedBuffersCount = 1;
+ Context.ResponseData.Write(ReleasedBuffersCount);
+
+ if (OpenALInstalled)
+ {
+ if (AudioCtx == null) //Needed to call the instance of AudioContext()
+ return 0;
+
+ AL.SourcePlay(Source);
+ int[] FreeBuffers = AL.SourceUnqueueBuffers(Source, 1);
+ AL.DeleteBuffers(FreeBuffers);
+ }
+
+ return 0;
+ }
+
+ public long ContainsAudioOutBuffer(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public long AppendAudioOutBuffer_ex(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public long GetReleasedAudioOutBuffer_ex(ServiceCtx Context)
+ {
+ return 0;
+ }
+ }
+}
diff --git a/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs
new file mode 100644
index 00000000..05356477
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs
@@ -0,0 +1,66 @@
+using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.Core.OsHle.Objects.Aud
+{
+ class IAudioRenderer : IIpcInterface
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IAudioRenderer()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 4, RequestUpdateAudioRenderer },
+ { 5, StartAudioRenderer },
+ { 6, StopAudioRenderer },
+ { 7, QuerySystemEvent }
+ };
+ }
+
+ public long RequestUpdateAudioRenderer(ServiceCtx Context)
+ {
+ //(buffer<unknown, 5, 0>) -> (buffer<unknown, 6, 0>, buffer<unknown, 6, 0>)
+
+ long Position = Context.Request.ReceiveBuff[0].Position;
+
+ //0x40 bytes header
+ Context.Memory.WriteInt32(Position + 0x4, 0xb0); //Behavior Out State Size? (note: this is the last section)
+ Context.Memory.WriteInt32(Position + 0x8, 0x18e0); //Memory Pool Out State Size?
+ Context.Memory.WriteInt32(Position + 0xc, 0x600); //Voice Out State Size?
+ Context.Memory.WriteInt32(Position + 0x14, 0xe0); //Effect Out State Size?
+ Context.Memory.WriteInt32(Position + 0x1c, 0x20); //Sink Out State Size?
+ Context.Memory.WriteInt32(Position + 0x20, 0x10); //Performance Out State Size?
+ Context.Memory.WriteInt32(Position + 0x3c, 0x20e0); //Total Size (including 0x40 bytes header)
+
+ for (int Offset = 0x40; Offset < 0x40 + 0x18e0; Offset += 0x10)
+ {
+ Context.Memory.WriteInt32(Position + Offset, 5);
+ }
+
+ return 0;
+ }
+
+ public long StartAudioRenderer(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public long StopAudioRenderer(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public long QuerySystemEvent(ServiceCtx Context)
+ {
+ int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent());
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file