diff options
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | Ryujinx/Cpu/AOpCodeTable.cs | 8 | ||||
| -rw-r--r-- | Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs | 6 | ||||
| -rw-r--r-- | Ryujinx/Cpu/Instruction/AInstEmitAlu.cs | 54 | ||||
| -rw-r--r-- | Ryujinx/Cpu/Instruction/AInstEmitScalar.cs | 45 | ||||
| -rw-r--r-- | Ryujinx/Cpu/Instruction/AInstEmitSimd.cs | 2 | ||||
| -rw-r--r-- | Ryujinx/OsHle/Ipc/IpcHandler.cs | 12 | ||||
| -rw-r--r-- | Ryujinx/OsHle/Objects/AudIAudioOut.cs | 166 | ||||
| -rw-r--r-- | Ryujinx/OsHle/Objects/AudIAudioRenderer.cs | 20 | ||||
| -rw-r--r-- | Ryujinx/OsHle/Services/ServiceAud.cs | 19 |
10 files changed, 324 insertions, 11 deletions
@@ -8,3 +8,6 @@ Contributions are always welcome. To run this emulator, you need the .NET Core 2.0 (or higher) SDK. Run `dotnet run -c Release -- game.nro` inside the Ryujinx solution folder. + +Audio is partially supported (glitched) on Windows, you need to install the OpenAL Core SDK : +https://openal.org/downloads/OpenAL11CoreSDK.zip diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index 1f770c6a..a7deb2c7 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -10,6 +10,7 @@ namespace ChocolArm64 { #region "OpCode Table" //Integer + Set("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc, typeof(AOpCodeAluRs)); Set("x0010001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm)); Set("x0001011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs)); Set("x0001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx)); @@ -85,6 +86,7 @@ namespace ChocolArm64 Set("x101101011000000000010xxxxxxxxxx", AInstEmit.Rev32, typeof(AOpCodeAlu)); Set("1101101011000000000011xxxxxxxxxx", AInstEmit.Rev64, typeof(AOpCodeAlu)); Set("x0011010110xxxxx001011xxxxxxxxxx", AInstEmit.Rorv, typeof(AOpCodeAluRs)); + Set("x1011010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbc, typeof(AOpCodeAluRs)); Set("x00100110xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm)); Set("x0011010110xxxxx000011xxxxxxxxxx", AInstEmit.Sdiv, typeof(AOpCodeAluRs)); Set("10011011001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smaddl, typeof(AOpCodeMul)); @@ -144,6 +146,7 @@ namespace ChocolArm64 Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond)); Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg)); + Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond)); Set("00011110xx10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd)); Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_S, typeof(AOpCodeSimdCvt)); @@ -156,18 +159,21 @@ namespace ChocolArm64 Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Fix, typeof(AOpCodeSimdCvt)); Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Fix, typeof(AOpCodeSimdCvt)); Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg)); + Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); Set("0x0011100x1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); Set("0x0011111<<xxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Vs, typeof(AOpCodeSimdRegElem)); - Set("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimdFmov)); + Set("00011110xx100000010000xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimd)); + Set("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_Si, typeof(AOpCodeSimdFmov)); Set("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm)); Set("x0011110xx100110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi, typeof(AOpCodeSimdCvt)); Set("x0011110xx100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt)); Set("x0011110xx101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt)); Set("x0011110xx101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt)); + Set("00011111xx0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg)); Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Vs, typeof(AOpCodeSimdRegElem)); diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs index d3a8b76a..10a4aff8 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs @@ -4,13 +4,15 @@ namespace ChocolArm64.Decoder { class AOpCodeSimdReg : AOpCodeSimd { - public int Rm { get; private set; } public bool Bit3 { get; private set; } + public int Ra { get; private set; } + public int Rm { get; private set; } public AOpCodeSimdReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { - Rm = (OpCode >> 16) & 0x1f; Bit3 = ((OpCode >> 3) & 0x1) != 0; + Ra = (OpCode >> 10) & 0x1f; + Rm = (OpCode >> 16) & 0x1f; } } }
\ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs index f963f6f7..ac9c43c3 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs @@ -1,6 +1,8 @@ using ChocolArm64.Decoder; using ChocolArm64.State; using ChocolArm64.Translation; +using System; +using System.Reflection; using System.Reflection.Emit; using static ChocolArm64.Instruction.AInstEmitAluHelper; @@ -9,6 +11,30 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { + public static void Adc(AILEmitterCtx Context) + { + EmitDataLoadOpers(Context); + + Context.Emit(OpCodes.Add); + + Context.EmitLdflg((int)APState.CBit); + + Type[] MthdTypes = new Type[] { typeof(bool) }; + + MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes); + + Context.EmitCall(MthdInfo); + + if (Context.CurrOp.RegisterSize != ARegisterSize.Int32) + { + Context.Emit(OpCodes.Conv_I8); + } + + Context.Emit(OpCodes.Add); + + EmitDataStore(Context); + } + public static void Add(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Add); public static void Adds(AILEmitterCtx Context) @@ -105,6 +131,34 @@ namespace ChocolArm64.Instruction public static void Lslv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shl); public static void Lsrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr_Un); + public static void Sbc(AILEmitterCtx Context) + { + EmitDataLoadOpers(Context); + + Context.Emit(OpCodes.Sub); + + Context.EmitLdflg((int)APState.CBit); + + Type[] MthdTypes = new Type[] { typeof(bool) }; + + MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes); + + Context.EmitCall(MthdInfo); + + Context.EmitLdc_I4(1); + + Context.Emit(OpCodes.Xor); + + if (Context.CurrOp.RegisterSize != ARegisterSize.Int32) + { + Context.Emit(OpCodes.Conv_I8); + } + + Context.Emit(OpCodes.Sub); + + EmitDataStore(Context); + } + public static void Sub(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Sub); public static void Subs(AILEmitterCtx Context) diff --git a/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs b/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs index 5085c224..ab4c2fd2 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs @@ -169,6 +169,12 @@ namespace ChocolArm64.Instruction Context.MarkLabel(LblNotNaN); } + public static void Fcmpe_S(AILEmitterCtx Context) + { + //TODO: Raise exception if value is NaN, how to handle exceptions? + Fcmp_S(Context); + } + public static void Fcsel_S(AILEmitterCtx Context) { AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp; @@ -252,6 +258,20 @@ namespace ChocolArm64.Instruction public static void Fdiv_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Div); + public static void Fmadd_S(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + Context.EmitLdvecsf(Op.Ra); + Context.EmitLdvecsf(Op.Rn); + Context.EmitLdvecsf(Op.Rm); + + Context.Emit(OpCodes.Mul); + Context.Emit(OpCodes.Add); + + Context.EmitStvecsf(Op.Rd); + } + public static void Fmax_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Max)); public static void Fmin_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Min)); @@ -260,6 +280,14 @@ namespace ChocolArm64.Instruction public static void Fmov_S(AILEmitterCtx Context) { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + Context.EmitLdvecsf(Op.Rn); + Context.EmitStvecsf(Op.Rd); + } + + public static void Fmov_Si(AILEmitterCtx Context) + { AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp; Context.EmitLdc_I8(Op.Imm); @@ -313,6 +341,23 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } + public static void Fmsub_S(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + Context.EmitLdvecsf(Op.Ra); + Context.EmitLdvecsf(Op.Rn); + + Context.Emit(OpCodes.Neg); + + Context.EmitLdvecsf(Op.Rm); + + Context.Emit(OpCodes.Mul); + Context.Emit(OpCodes.Sub); + + Context.EmitStvecsf(Op.Rd); + } + public static void Fmul_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Mul); public static void Fneg_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Neg); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs index ccf0e357..8d4ade3a 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs @@ -273,7 +273,7 @@ namespace ChocolArm64.Instruction AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp; Context.EmitLdvec(Op.Rd); - Context.EmitLdintzr(Op.Rn); + Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4(Op.SrcIndex); Context.EmitLdc_I4(Op.DstIndex); Context.EmitLdc_I4(Op.Size); diff --git a/Ryujinx/OsHle/Ipc/IpcHandler.cs b/Ryujinx/OsHle/Ipc/IpcHandler.cs index 50968014..4e57889a 100644 --- a/Ryujinx/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx/OsHle/Ipc/IpcHandler.cs @@ -127,8 +127,20 @@ namespace Ryujinx.OsHle.Ipc //IAudioRenderer { (typeof(AudIAudioRenderer), 4), AudIAudioRenderer.RequestUpdateAudioRenderer }, { (typeof(AudIAudioRenderer), 5), AudIAudioRenderer.StartAudioRenderer }, + { (typeof(AudIAudioRenderer), 6), AudIAudioRenderer.StopAudioRenderer }, { (typeof(AudIAudioRenderer), 7), AudIAudioRenderer.QuerySystemEvent }, + //IAudioOut + { (typeof(AudIAudioOut), 0), AudIAudioOut.GetAudioOutState }, + { (typeof(AudIAudioOut), 1), AudIAudioOut.StartAudioOut }, + { (typeof(AudIAudioOut), 2), AudIAudioOut.StopAudioOut }, + { (typeof(AudIAudioOut), 3), AudIAudioOut.AppendAudioOutBuffer }, + { (typeof(AudIAudioOut), 4), AudIAudioOut.RegisterBufferEvent }, + { (typeof(AudIAudioOut), 5), AudIAudioOut.GetReleasedAudioOutBuffer }, + { (typeof(AudIAudioOut), 6), AudIAudioOut.ContainsAudioOutBuffer }, + { (typeof(AudIAudioOut), 7), AudIAudioOut.AppendAudioOutBuffer_ex }, + { (typeof(AudIAudioOut), 8), AudIAudioOut.GetReleasedAudioOutBuffer_ex }, + //IFile { (typeof(FspSrvIFile), 0), FspSrvIFile.Read }, { (typeof(FspSrvIFile), 1), FspSrvIFile.Write }, diff --git a/Ryujinx/OsHle/Objects/AudIAudioOut.cs b/Ryujinx/OsHle/Objects/AudIAudioOut.cs new file mode 100644 index 00000000..965e840d --- /dev/null +++ b/Ryujinx/OsHle/Objects/AudIAudioOut.cs @@ -0,0 +1,166 @@ +using ChocolArm64.Memory; +using Ryujinx.OsHle.Handles; +using Ryujinx.OsHle.Ipc; +using static Ryujinx.OsHle.Objects.ObjHelper; + +using System; +using System.Collections.Generic; +using System.IO; + +using OpenTK.Audio; +using OpenTK.Audio.OpenAL; + +namespace Ryujinx.OsHle.Objects +{ + class AudIAudioOut + { + enum AudioOutState + { + Started, + Stopped + }; + + //IAudioOut + private static AudioOutState State = AudioOutState.Stopped; + private static List<long> KeysQueue = new List<long>(); + + //OpenAL + private static bool OpenALInstalled = true; + private static AudioContext AudioCtx; + private static int Source; + private static int Buffer; + + //Return State of IAudioOut + public static long GetAudioOutState(ServiceCtx Context) + { + Context.ResponseData.Write((int)State); + + return 0; + } + + public static long StartAudioOut(ServiceCtx Context) + { + if (State == AudioOutState.Stopped) + { + State = AudioOutState.Started; + + try + { + AudioCtx = new AudioContext(); //Create the audio context + } + catch (Exception ex) + { + Console.WriteLine("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 static 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 static long AppendAudioOutBuffer(ServiceCtx Context) + { + long BufferId = Context.RequestData.ReadInt64(); + + KeysQueue.Insert(0, BufferId); + + byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, 0x28); + using (MemoryStream MS = new MemoryStream(AudioOutBuffer)) + { + BinaryReader Reader = new BinaryReader(MS); + long PointerToSampleDataPointer = Reader.ReadInt64(); + long PointerToSampleData = Reader.ReadInt64(); + long CapacitySampleBuffer = Reader.ReadInt64(); + long SizeDataSampleBuffer = Reader.ReadInt64(); + long Unknown = Reader.ReadInt64(); + + byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerToSampleData, (int)SizeDataSampleBuffer); + + 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 static long RegisterBufferEvent(ServiceCtx Context) + { + int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); + + return 0; + } + + public static long GetReleasedAudioOutBuffer(ServiceCtx Context) + { + long TempKey = 0; + + if (KeysQueue.Count > 0) + { + TempKey = KeysQueue[KeysQueue.Count - 1]; + KeysQueue.Remove(KeysQueue[KeysQueue.Count - 1]); + } + + AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, System.BitConverter.GetBytes(TempKey)); + + Context.ResponseData.Write((int)TempKey); + + 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 static long ContainsAudioOutBuffer(ServiceCtx Context) + { + return 0; + } + + public static long AppendAudioOutBuffer_ex(ServiceCtx Context) + { + return 0; + } + + public static long GetReleasedAudioOutBuffer_ex(ServiceCtx Context) + { + return 0; + } + } +} diff --git a/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs b/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs index 84ac4e04..35a5b82d 100644 --- a/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs +++ b/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs @@ -1,15 +1,20 @@ +using Ryujinx.OsHle.Handles; +using Ryujinx.OsHle.Ipc; + namespace Ryujinx.OsHle.Objects { class AudIAudioRenderer { public static 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 + 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? @@ -28,8 +33,17 @@ namespace Ryujinx.OsHle.Objects return 0; } + public static long StopAudioRenderer(ServiceCtx Context) + { + return 0; + } + public static long QuerySystemEvent(ServiceCtx Context) { + int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); + return 0; } } diff --git a/Ryujinx/OsHle/Services/ServiceAud.cs b/Ryujinx/OsHle/Services/ServiceAud.cs index 96e7e548..18401ae9 100644 --- a/Ryujinx/OsHle/Services/ServiceAud.cs +++ b/Ryujinx/OsHle/Services/ServiceAud.cs @@ -21,10 +21,21 @@ namespace Ryujinx.OsHle.Services public static long AudOutOpenAudioOut(ServiceCtx Context) { - Context.ResponseData.Write(48000); - Context.ResponseData.Write(2); - Context.ResponseData.Write(2); - Context.ResponseData.Write(0); + MakeObject(Context, new AudIAudioOut()); + + Context.ResponseData.Write(48000); //Sample Rate + Context.ResponseData.Write(2); //Channel Count + Context.ResponseData.Write(2); //PCM Format + /* + 0 - Invalid + 1 - INT8 + 2 - INT16 + 3 - INT24 + 4 - INT32 + 5 - PCM Float + 6 - ADPCM + */ + Context.ResponseData.Write(0); //Unknown return 0; } |
