Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
f92650fcff | |||
712361f6e1 | |||
2232e4ae87 | |||
14ce9e1567 | |||
952d013c67 | |||
46c8129bf5 | |||
8cfec5de4b | |||
37b6e081da | |||
3c3bcd82fe | |||
a00c59a46c | |||
1825bd87b4 | |||
62f8ceb60b | |||
1a888ae087 | |||
84d0ca5645 | |||
31b8d413d5 | |||
6e02cac952 | |||
3a3380fa25 | |||
2d252db0a7 | |||
7f8a3541eb | |||
b34de74f81 | |||
5811d121df | |||
6eb85e846f | |||
c5bddfeab8 | |||
70ec5def9c | |||
7853faa334 | |||
b7fb474bfe | |||
2fa6413ed8 | |||
4523a73f75 | |||
f4c47f3c9a | |||
7d9a5feccb | |||
14ae4e276f | |||
3af42d6c7e | |||
bccf5e8b5a |
@ -197,12 +197,29 @@ namespace ARMeilleure.Signal
|
|||||||
// Only call tracking if in range.
|
// Only call tracking if in range.
|
||||||
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
|
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
|
||||||
|
|
||||||
context.Copy(inRegionLocal, Const(1));
|
|
||||||
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~PageMask));
|
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~PageMask));
|
||||||
|
|
||||||
// Call the tracking action, with the pointer's relative offset to the base address.
|
// Call the tracking action, with the pointer's relative offset to the base address.
|
||||||
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
|
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
|
||||||
context.Call(trackingActionPtr, OperandType.I32, offset, Const(PageSize), isWrite, Const(0));
|
|
||||||
|
context.Copy(inRegionLocal, Const(0));
|
||||||
|
|
||||||
|
Operand skipActionLabel = Label();
|
||||||
|
|
||||||
|
// Tracking action should be non-null to call it, otherwise assume false return.
|
||||||
|
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
|
||||||
|
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(PageSize), isWrite, Const(0));
|
||||||
|
context.Copy(inRegionLocal, result);
|
||||||
|
|
||||||
|
context.MarkLabel(skipActionLabel);
|
||||||
|
|
||||||
|
// If the tracking action returns false or does not exist, it might be an invalid access due to a partial overlap on Windows.
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
context.BranchIfTrue(endLabel, inRegionLocal);
|
||||||
|
|
||||||
|
context.Copy(inRegionLocal, WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context));
|
||||||
|
}
|
||||||
|
|
||||||
context.Branch(endLabel);
|
context.Branch(endLabel);
|
||||||
|
|
||||||
|
84
ARMeilleure/Signal/TestMethods.cs
Normal file
84
ARMeilleure/Signal/TestMethods.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using ARMeilleure.Translation;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
namespace ARMeilleure.Signal
|
||||||
|
{
|
||||||
|
public struct NativeWriteLoopState
|
||||||
|
{
|
||||||
|
public int Running;
|
||||||
|
public int Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestMethods
|
||||||
|
{
|
||||||
|
public delegate bool DebugPartialUnmap();
|
||||||
|
public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState);
|
||||||
|
public delegate void DebugNativeWriteLoop(IntPtr nativeWriteLoopPtr, IntPtr writePtr);
|
||||||
|
|
||||||
|
public static DebugPartialUnmap GenerateDebugPartialUnmap()
|
||||||
|
{
|
||||||
|
EmitterContext context = new EmitterContext();
|
||||||
|
|
||||||
|
var result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context);
|
||||||
|
|
||||||
|
context.Return(result);
|
||||||
|
|
||||||
|
// Compile and return the function.
|
||||||
|
|
||||||
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
|
|
||||||
|
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||||
|
|
||||||
|
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<DebugPartialUnmap>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(IntPtr structPtr)
|
||||||
|
{
|
||||||
|
EmitterContext context = new EmitterContext();
|
||||||
|
|
||||||
|
var result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1));
|
||||||
|
|
||||||
|
context.Return(result);
|
||||||
|
|
||||||
|
// Compile and return the function.
|
||||||
|
|
||||||
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
|
|
||||||
|
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||||
|
|
||||||
|
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<DebugThreadLocalMapGetOrReserve>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DebugNativeWriteLoop GenerateDebugNativeWriteLoop()
|
||||||
|
{
|
||||||
|
EmitterContext context = new EmitterContext();
|
||||||
|
|
||||||
|
// Loop a write to the target address until "running" is false.
|
||||||
|
|
||||||
|
Operand structPtr = context.Copy(context.LoadArgument(OperandType.I64, 0));
|
||||||
|
Operand writePtr = context.Copy(context.LoadArgument(OperandType.I64, 1));
|
||||||
|
|
||||||
|
Operand loopLabel = Label();
|
||||||
|
context.MarkLabel(loopLabel);
|
||||||
|
|
||||||
|
context.Store(writePtr, Const(12345));
|
||||||
|
|
||||||
|
Operand running = context.Load(OperandType.I32, structPtr);
|
||||||
|
|
||||||
|
context.BranchIfTrue(loopLabel, running);
|
||||||
|
|
||||||
|
context.Return();
|
||||||
|
|
||||||
|
// Compile and return the function.
|
||||||
|
|
||||||
|
ControlFlowGraph cfg = context.GetControlFlowGraph();
|
||||||
|
|
||||||
|
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||||
|
|
||||||
|
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map<DebugNativeWriteLoop>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
186
ARMeilleure/Signal/WindowsPartialUnmapHandler.cs
Normal file
186
ARMeilleure/Signal/WindowsPartialUnmapHandler.cs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using ARMeilleure.Translation;
|
||||||
|
using Ryujinx.Common.Memory.PartialUnmaps;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
namespace ARMeilleure.Signal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Methods to handle signals caused by partial unmaps. See the structs for C# implementations of the methods.
|
||||||
|
/// </summary>
|
||||||
|
internal static class WindowsPartialUnmapHandler
|
||||||
|
{
|
||||||
|
public static Operand EmitRetryFromAccessViolation(EmitterContext context)
|
||||||
|
{
|
||||||
|
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState;
|
||||||
|
IntPtr localCountsPtr = IntPtr.Add(partialRemapStatePtr, PartialUnmapState.LocalCountsOffset);
|
||||||
|
|
||||||
|
// Get the lock first.
|
||||||
|
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||||
|
|
||||||
|
IntPtr getCurrentThreadId = WindowsSignalHandlerRegistration.GetCurrentThreadIdFunc();
|
||||||
|
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
|
||||||
|
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
|
||||||
|
|
||||||
|
Operand endLabel = Label();
|
||||||
|
Operand retry = context.AllocateLocal(OperandType.I32);
|
||||||
|
Operand threadIndexValidLabel = Label();
|
||||||
|
|
||||||
|
context.BranchIfFalse(threadIndexValidLabel, context.ICompareEqual(threadIndex, Const(-1)));
|
||||||
|
|
||||||
|
context.Copy(retry, Const(1)); // Always retry when thread local cannot be allocated.
|
||||||
|
|
||||||
|
context.Branch(endLabel);
|
||||||
|
|
||||||
|
context.MarkLabel(threadIndexValidLabel);
|
||||||
|
|
||||||
|
Operand threadLocalPartialUnmapsPtr = EmitThreadLocalMapIntGetValuePtr(context, localCountsPtr, threadIndex);
|
||||||
|
Operand threadLocalPartialUnmaps = context.Load(OperandType.I32, threadLocalPartialUnmapsPtr);
|
||||||
|
Operand partialUnmapsCount = context.Load(OperandType.I32, Const((ulong)IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapsCountOffset)));
|
||||||
|
|
||||||
|
context.Copy(retry, context.ICompareNotEqual(threadLocalPartialUnmaps, partialUnmapsCount));
|
||||||
|
|
||||||
|
Operand noRetryLabel = Label();
|
||||||
|
|
||||||
|
context.BranchIfFalse(noRetryLabel, retry);
|
||||||
|
|
||||||
|
// if (retry) {
|
||||||
|
|
||||||
|
context.Store(threadLocalPartialUnmapsPtr, partialUnmapsCount);
|
||||||
|
|
||||||
|
context.Branch(endLabel);
|
||||||
|
|
||||||
|
context.MarkLabel(noRetryLabel);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
context.MarkLabel(endLabel);
|
||||||
|
|
||||||
|
// Finally, release the lock and return the retry value.
|
||||||
|
EmitNativeReaderLockRelease(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||||
|
|
||||||
|
return retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand EmitThreadLocalMapIntGetOrReserve(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand initialState)
|
||||||
|
{
|
||||||
|
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
|
||||||
|
|
||||||
|
Operand i = context.AllocateLocal(OperandType.I32);
|
||||||
|
|
||||||
|
context.Copy(i, Const(0));
|
||||||
|
|
||||||
|
// (Loop 1) Check all slots for a matching Thread ID (while also trying to allocate)
|
||||||
|
|
||||||
|
Operand endLabel = Label();
|
||||||
|
|
||||||
|
Operand loopLabel = Label();
|
||||||
|
context.MarkLabel(loopLabel);
|
||||||
|
|
||||||
|
Operand offset = context.Multiply(i, Const(sizeof(int)));
|
||||||
|
Operand idPtr = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset));
|
||||||
|
|
||||||
|
// Check that this slot has the thread ID.
|
||||||
|
Operand existingId = context.CompareAndSwap(idPtr, threadId, threadId);
|
||||||
|
|
||||||
|
// If it was already the thread ID, then we just need to return i.
|
||||||
|
context.BranchIfTrue(endLabel, context.ICompareEqual(existingId, threadId));
|
||||||
|
|
||||||
|
context.Copy(i, context.Add(i, Const(1)));
|
||||||
|
|
||||||
|
context.BranchIfTrue(loopLabel, context.ICompareLess(i, Const(ThreadLocalMap<int>.MapSize)));
|
||||||
|
|
||||||
|
// (Loop 2) Try take a slot that is 0 with our Thread ID.
|
||||||
|
|
||||||
|
context.Copy(i, Const(0)); // Reset i.
|
||||||
|
|
||||||
|
Operand loop2Label = Label();
|
||||||
|
context.MarkLabel(loop2Label);
|
||||||
|
|
||||||
|
Operand offset2 = context.Multiply(i, Const(sizeof(int)));
|
||||||
|
Operand idPtr2 = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset2));
|
||||||
|
|
||||||
|
// Try and swap in the thread id on top of 0.
|
||||||
|
Operand existingId2 = context.CompareAndSwap(idPtr2, Const(0), threadId);
|
||||||
|
|
||||||
|
Operand idNot0Label = Label();
|
||||||
|
|
||||||
|
// If it was 0, then we need to initialize the struct entry and return i.
|
||||||
|
context.BranchIfFalse(idNot0Label, context.ICompareEqual(existingId2, Const(0)));
|
||||||
|
|
||||||
|
Operand structsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
|
||||||
|
Operand structPtr = context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset2));
|
||||||
|
context.Store(structPtr, initialState);
|
||||||
|
|
||||||
|
context.Branch(endLabel);
|
||||||
|
|
||||||
|
context.MarkLabel(idNot0Label);
|
||||||
|
|
||||||
|
context.Copy(i, context.Add(i, Const(1)));
|
||||||
|
|
||||||
|
context.BranchIfTrue(loop2Label, context.ICompareLess(i, Const(ThreadLocalMap<int>.MapSize)));
|
||||||
|
|
||||||
|
context.Copy(i, Const(-1)); // Could not place the thread in the list.
|
||||||
|
|
||||||
|
context.MarkLabel(endLabel);
|
||||||
|
|
||||||
|
return context.Copy(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Operand EmitThreadLocalMapIntGetValuePtr(EmitterContext context, IntPtr threadLocalMapPtr, Operand index)
|
||||||
|
{
|
||||||
|
Operand offset = context.Multiply(index, Const(sizeof(int)));
|
||||||
|
Operand structsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
|
||||||
|
|
||||||
|
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitThreadLocalMapIntRelease(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand index)
|
||||||
|
{
|
||||||
|
Operand offset = context.Multiply(index, Const(sizeof(int)));
|
||||||
|
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
|
||||||
|
Operand idPtr = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset));
|
||||||
|
|
||||||
|
context.CompareAndSwap(idPtr, threadId, Const(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitAtomicAddI32(EmitterContext context, Operand ptr, Operand additive)
|
||||||
|
{
|
||||||
|
Operand loop = Label();
|
||||||
|
context.MarkLabel(loop);
|
||||||
|
|
||||||
|
Operand initial = context.Load(OperandType.I32, ptr);
|
||||||
|
Operand newValue = context.Add(initial, additive);
|
||||||
|
|
||||||
|
Operand replaced = context.CompareAndSwap(ptr, initial, newValue);
|
||||||
|
|
||||||
|
context.BranchIfFalse(loop, context.ICompareEqual(initial, replaced));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitNativeReaderLockAcquire(EmitterContext context, IntPtr nativeReaderLockPtr)
|
||||||
|
{
|
||||||
|
Operand writeLockPtr = Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.WriteLockOffset));
|
||||||
|
|
||||||
|
// Spin until we can acquire the write lock.
|
||||||
|
Operand spinLabel = Label();
|
||||||
|
context.MarkLabel(spinLabel);
|
||||||
|
|
||||||
|
// Old value must be 0 to continue (we gained the write lock)
|
||||||
|
context.BranchIfTrue(spinLabel, context.CompareAndSwap(writeLockPtr, Const(0), Const(1)));
|
||||||
|
|
||||||
|
// Increment reader count.
|
||||||
|
EmitAtomicAddI32(context, Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(1));
|
||||||
|
|
||||||
|
// Release write lock.
|
||||||
|
context.CompareAndSwap(writeLockPtr, Const(1), Const(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitNativeReaderLockRelease(EmitterContext context, IntPtr nativeReaderLockPtr)
|
||||||
|
{
|
||||||
|
// Decrement reader count.
|
||||||
|
EmitAtomicAddI32(context, Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Signal
|
namespace ARMeilleure.Signal
|
||||||
{
|
{
|
||||||
class WindowsSignalHandlerRegistration
|
unsafe class WindowsSignalHandlerRegistration
|
||||||
{
|
{
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
private static extern IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
|
private static extern IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
|
||||||
@ -11,6 +12,14 @@ namespace ARMeilleure.Signal
|
|||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
private static extern ulong RemoveVectoredExceptionHandler(IntPtr handle);
|
private static extern ulong RemoveVectoredExceptionHandler(IntPtr handle);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
|
||||||
|
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
|
||||||
|
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
||||||
|
|
||||||
|
private static IntPtr _getCurrentThreadIdPtr;
|
||||||
|
|
||||||
public static IntPtr RegisterExceptionHandler(IntPtr action)
|
public static IntPtr RegisterExceptionHandler(IntPtr action)
|
||||||
{
|
{
|
||||||
return AddVectoredExceptionHandler(1, action);
|
return AddVectoredExceptionHandler(1, action);
|
||||||
@ -20,5 +29,17 @@ namespace ARMeilleure.Signal
|
|||||||
{
|
{
|
||||||
return RemoveVectoredExceptionHandler(handle) != 0;
|
return RemoveVectoredExceptionHandler(handle) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetCurrentThreadIdFunc()
|
||||||
|
{
|
||||||
|
if (_getCurrentThreadIdPtr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
IntPtr handle = LoadLibrary("kernel32.dll");
|
||||||
|
|
||||||
|
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
|
||||||
|
}
|
||||||
|
|
||||||
|
return _getCurrentThreadIdPtr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,4 +129,4 @@ namespace Ryujinx.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,4 +23,4 @@ namespace Ryujinx.Audio.Backends.Common
|
|||||||
return bufferSize / GetSampleSize(format) / channelCount;
|
return bufferSize / GetSampleSize(format) / channelCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -163,4 +163,4 @@ namespace Ryujinx.Audio.Backends.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,4 +76,4 @@ namespace Ryujinx.Audio.Backends.Common
|
|||||||
|
|
||||||
public virtual void UnregisterBuffer(AudioBuffer buffer) { }
|
public virtual void UnregisterBuffer(AudioBuffer buffer) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -133,4 +133,4 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
return direction == Direction.Input || direction == Direction.Output;
|
return direction == Direction.Input || direction == Direction.Output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -81,7 +81,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
{
|
{
|
||||||
BufferTag = buffer.BufferTag,
|
BufferTag = buffer.BufferTag,
|
||||||
DataPointer = buffer.DataPointer,
|
DataPointer = buffer.DataPointer,
|
||||||
DataSize = (ulong)downmixedBuffer.Length
|
DataSize = (ulong)downmixedBuffer.Length
|
||||||
};
|
};
|
||||||
|
|
||||||
bool result = _realSession.RegisterBuffer(fakeBuffer, downmixedBuffer);
|
bool result = _realSession.RegisterBuffer(fakeBuffer, downmixedBuffer);
|
||||||
@ -120,4 +120,4 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
return _realSession.WasBufferFullyConsumed(buffer);
|
return _realSession.WasBufferFullyConsumed(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,11 +24,11 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
public short Right;
|
public short Right;
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int Q15Bits = 16;
|
private const int Q15Bits = 16;
|
||||||
private const int RawQ15One = 1 << Q15Bits;
|
private const int RawQ15One = 1 << Q15Bits;
|
||||||
private const int RawQ15HalfOne = (int)(0.5f * RawQ15One);
|
private const int RawQ15HalfOne = (int)(0.5f * RawQ15One);
|
||||||
private const int Minus3dBInQ15 = (int)(0.707f * RawQ15One);
|
private const int Minus3dBInQ15 = (int)(0.707f * RawQ15One);
|
||||||
private const int Minus6dBInQ15 = (int)(0.501f * RawQ15One);
|
private const int Minus6dBInQ15 = (int)(0.501f * RawQ15One);
|
||||||
private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
|
private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
|
||||||
|
|
||||||
private static readonly int[] DefaultSurroundToStereoCoefficients = new int[4]
|
private static readonly int[] DefaultSurroundToStereoCoefficients = new int[4]
|
||||||
@ -46,8 +46,8 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
};
|
};
|
||||||
|
|
||||||
private const int SurroundChannelCount = 6;
|
private const int SurroundChannelCount = 6;
|
||||||
private const int StereoChannelCount = 2;
|
private const int StereoChannelCount = 2;
|
||||||
private const int MonoChannelCount = 1;
|
private const int MonoChannelCount = 1;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ReadOnlySpan<Channel51FormatPCM16> GetSurroundBuffer(ReadOnlySpan<short> data)
|
private static ReadOnlySpan<Channel51FormatPCM16> GetSurroundBuffer(ReadOnlySpan<short> data)
|
||||||
@ -86,7 +86,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
{
|
{
|
||||||
Channel51FormatPCM16 channel = channels[i];
|
Channel51FormatPCM16 channel = channels[i];
|
||||||
|
|
||||||
downmixedBuffer[i * 2] = DownMixSurroundToStereo(coefficients, channel.BackLeft, channel.LowFrequency, channel.FrontCenter, channel.FrontLeft);
|
downmixedBuffer[i * 2] = DownMixSurroundToStereo(coefficients, channel.BackLeft, channel.LowFrequency, channel.FrontCenter, channel.FrontLeft);
|
||||||
downmixedBuffer[i * 2 + 1] = DownMixSurroundToStereo(coefficients, channel.BackRight, channel.LowFrequency, channel.FrontCenter, channel.FrontRight);
|
downmixedBuffer[i * 2 + 1] = DownMixSurroundToStereo(coefficients, channel.BackRight, channel.LowFrequency, channel.FrontCenter, channel.FrontRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,4 +122,4 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
|||||||
return DownMixSurroundToStereo(DefaultSurroundToStereoCoefficients, data);
|
return DownMixSurroundToStereo(DefaultSurroundToStereoCoefficients, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -84,4 +84,4 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
return channelCount == 1 || channelCount == 2 || channelCount == 6;
|
return channelCount == 1 || channelCount == 2 || channelCount == 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,4 +64,4 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,4 +34,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] Data;
|
public byte[] Data;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -513,4 +513,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,4 +15,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Stopped
|
Stopped
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,4 +26,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private ushort _reserved;
|
private ushort _reserved;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,4 +34,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AudioDeviceState AudioOutState;
|
public AudioDeviceState AudioOutState;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,4 +33,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong DataOffset;
|
public ulong DataOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,4 +40,4 @@ namespace Ryujinx.Audio.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Adpcm = 6
|
Adpcm = 6
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -172,4 +172,4 @@ namespace Ryujinx.Audio
|
|||||||
0.707f,
|
0.707f,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -214,9 +214,9 @@ namespace Ryujinx.Audio.Input
|
|||||||
outputDeviceName = audioIn.DeviceName;
|
outputDeviceName = audioIn.DeviceName;
|
||||||
outputConfiguration = new AudioOutputConfiguration
|
outputConfiguration = new AudioOutputConfiguration
|
||||||
{
|
{
|
||||||
ChannelCount = audioIn.ChannelCount,
|
ChannelCount = audioIn.ChannelCount,
|
||||||
SampleFormat = audioIn.SampleFormat,
|
SampleFormat = audioIn.SampleFormat,
|
||||||
SampleRate = audioIn.SampleRate,
|
SampleRate = audioIn.SampleRate,
|
||||||
AudioOutState = audioIn.GetState(),
|
AudioOutState = audioIn.GetState(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -263,4 +263,4 @@ namespace Ryujinx.Audio.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -389,4 +389,4 @@ namespace Ryujinx.Audio.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,8 +32,8 @@ namespace Ryujinx.Audio.Integration
|
|||||||
_session.QueueBuffer(new AudioBuffer
|
_session.QueueBuffer(new AudioBuffer
|
||||||
{
|
{
|
||||||
DataPointer = _currentBufferTag++,
|
DataPointer = _currentBufferTag++,
|
||||||
Data = _buffer,
|
Data = _buffer,
|
||||||
DataSize = (ulong)_buffer.Length,
|
DataSize = (ulong)_buffer.Length,
|
||||||
});
|
});
|
||||||
|
|
||||||
_currentBufferTag = _currentBufferTag % 4;
|
_currentBufferTag = _currentBufferTag % 4;
|
||||||
@ -72,4 +72,4 @@ namespace Ryujinx.Audio.Integration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -52,4 +52,4 @@ namespace Ryujinx.Audio.Integration
|
|||||||
return channelCount != Constants.ChannelCountMax;
|
return channelCount != Constants.ChannelCountMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,4 +31,4 @@ namespace Ryujinx.Audio.Integration
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,4 +25,4 @@ namespace Ryujinx.Audio.Integration
|
|||||||
|
|
||||||
void PrepareToClose();
|
void PrepareToClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,4 +15,4 @@ namespace Ryujinx.Audio.Integration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void Clear();
|
void Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -209,9 +209,9 @@ namespace Ryujinx.Audio.Output
|
|||||||
outputDeviceName = audioOut.DeviceName;
|
outputDeviceName = audioOut.DeviceName;
|
||||||
outputConfiguration = new AudioOutputConfiguration
|
outputConfiguration = new AudioOutputConfiguration
|
||||||
{
|
{
|
||||||
ChannelCount = audioOut.ChannelCount,
|
ChannelCount = audioOut.ChannelCount,
|
||||||
SampleFormat = audioOut.SampleFormat,
|
SampleFormat = audioOut.SampleFormat,
|
||||||
SampleRate = audioOut.SampleRate,
|
SampleRate = audioOut.SampleRate,
|
||||||
AudioOutState = audioOut.GetState(),
|
AudioOutState = audioOut.GetState(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -293,4 +293,4 @@ namespace Ryujinx.Audio.Output
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -169,7 +169,7 @@ namespace Ryujinx.Audio.Output
|
|||||||
}
|
}
|
||||||
|
|
||||||
SampleFormat = sampleFormat;
|
SampleFormat = sampleFormat;
|
||||||
SampleRate = Constants.TargetSampleRate;
|
SampleRate = Constants.TargetSampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -187,9 +187,9 @@ namespace Ryujinx.Audio.Output
|
|||||||
{
|
{
|
||||||
AudioBuffer buffer = new AudioBuffer
|
AudioBuffer buffer = new AudioBuffer
|
||||||
{
|
{
|
||||||
BufferTag = bufferTag,
|
BufferTag = bufferTag,
|
||||||
DataPointer = userBuffer.Data,
|
DataPointer = userBuffer.Data,
|
||||||
DataSize = userBuffer.DataSize
|
DataSize = userBuffer.DataSize
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_session.AppendBuffer(buffer))
|
if (_session.AppendBuffer(buffer))
|
||||||
@ -291,7 +291,7 @@ namespace Ryujinx.Audio.Output
|
|||||||
{
|
{
|
||||||
lock (_parentLock)
|
lock (_parentLock)
|
||||||
{
|
{
|
||||||
_session.SetVolume(volume);
|
_session.SetVolume(volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,4 +362,4 @@ namespace Ryujinx.Audio.Output
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,4 +10,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
public ulong ReturnBufferInfo;
|
public ulong ReturnBufferInfo;
|
||||||
public ulong ReturnBufferInfoBase;
|
public ulong ReturnBufferInfoBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -47,4 +47,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
public ulong ExtraErrorInfo;
|
public ulong ExtraErrorInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -147,4 +147,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
return _nodeCount;
|
return _nodeCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -50,4 +50,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
CaptureBuffer
|
CaptureBuffer
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,4 +40,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Released = 6
|
Released = 6
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,4 +25,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
return (nodeId >> 16) & 0xFFF;
|
return (nodeId >> 16) & 0xFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,4 +30,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Performance = 15
|
Performance = 15
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -226,4 +226,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,4 +16,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
Limiter,
|
Limiter,
|
||||||
CaptureBuffer
|
CaptureBuffer
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,4 +8,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
FinalMix,
|
FinalMix,
|
||||||
Sink
|
Sink
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,4 +20,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Pause
|
Pause
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,4 +30,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Disabled
|
Disabled
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -35,4 +35,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Limit = NoDelay
|
Limit = NoDelay
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,4 +20,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
CircularBuffer
|
CircularBuffer
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,4 +30,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
TotalSize = (uint)Unsafe.SizeOf<UpdateDataHeader>();
|
TotalSize = (uint)Unsafe.SizeOf<UpdateDataHeader>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -101,4 +101,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -79,4 +79,4 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private ushort _padding;
|
private ushort _padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
return Memory<byte>.Empty;
|
return Memory<byte>.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Memory<T> Allocate<T>(ulong count, int align) where T: unmanaged
|
public Memory<T> Allocate<T>(ulong count, int align) where T : unmanaged
|
||||||
{
|
{
|
||||||
Memory<byte> allocatedMemory = Allocate((ulong)Unsafe.SizeOf<T>() * count, align);
|
Memory<byte> allocatedMemory = Allocate((ulong)Unsafe.SizeOf<T>() * count, align);
|
||||||
|
|
||||||
@ -53,9 +53,9 @@ namespace Ryujinx.Audio.Renderer.Common
|
|||||||
return SpanMemoryManager<T>.Cast(allocatedMemory);
|
return SpanMemoryManager<T>.Cast(allocatedMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T: unmanaged
|
public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T : unmanaged
|
||||||
{
|
{
|
||||||
return BitUtils.AlignUp(currentSize, align) + (ulong)Unsafe.SizeOf<T>() * count;
|
return BitUtils.AlignUp(currentSize, align) + (ulong)Unsafe.SizeOf<T>() * count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -86,4 +86,4 @@ namespace Ryujinx.Audio.Renderer.Device
|
|||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,4 +24,4 @@ namespace Ryujinx.Audio.Renderer.Device
|
|||||||
Device = virtualDevice;
|
Device = virtualDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -59,4 +59,4 @@ namespace Ryujinx.Audio.Renderer.Device
|
|||||||
return virtualDeviceSession;
|
return virtualDeviceSession;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -199,4 +199,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
return decodedCount;
|
return decodedCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -268,4 +268,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -80,4 +80,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -72,4 +72,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -170,4 +170,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -49,4 +49,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
BiquadFilterHelper.ProcessBiquadFilter(ref _parameter, ref state, outputBuffer, inputBuffer, context.SampleCount);
|
BiquadFilterHelper.ProcessBiquadFilter(ref _parameter, ref state, outputBuffer, inputBuffer, context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -134,4 +134,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -74,4 +74,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,4 +21,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
context.ClearBuffers();
|
context.ClearBuffers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -153,4 +153,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
_buffersMemoryHandle.Dispose();
|
_buffersMemoryHandle.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,4 +33,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
GroupedBiquadFilter,
|
GroupedBiquadFilter,
|
||||||
CaptureBuffer
|
CaptureBuffer
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,4 +29,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
context.CopyBuffer(OutputBufferIndex, InputBufferIndex);
|
context.CopyBuffer(OutputBufferIndex, InputBufferIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -105,4 +105,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -87,7 +87,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
||||||
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
||||||
|
|
||||||
Matrix2x2 delayFeedback = new Matrix2x2(delayFeedbackBaseGain , delayFeedbackCrossGain,
|
Matrix2x2 delayFeedback = new Matrix2x2(delayFeedbackBaseGain, delayFeedbackCrossGain,
|
||||||
delayFeedbackCrossGain, delayFeedbackBaseGain);
|
delayFeedbackCrossGain, delayFeedbackBaseGain);
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
@ -124,10 +124,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
||||||
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
||||||
|
|
||||||
Matrix4x4 delayFeedback = new Matrix4x4(delayFeedbackBaseGain , delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f,
|
Matrix4x4 delayFeedback = new Matrix4x4(delayFeedbackBaseGain, delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f,
|
||||||
delayFeedbackCrossGain, delayFeedbackBaseGain , 0.0f , delayFeedbackCrossGain,
|
delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain,
|
||||||
delayFeedbackCrossGain, 0.0f , delayFeedbackBaseGain , delayFeedbackCrossGain,
|
delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain,
|
||||||
0.0f , delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain);
|
0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
@ -149,7 +149,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
};
|
};
|
||||||
|
|
||||||
Vector4 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;
|
Vector4 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;
|
||||||
|
|
||||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), channelCount);
|
state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), channelCount);
|
||||||
|
|
||||||
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
||||||
@ -171,12 +171,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
||||||
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
||||||
|
|
||||||
Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain , 0.0f , 0.0f , 0.0f , delayFeedbackCrossGain, delayFeedbackCrossGain,
|
Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain, 0.0f, 0.0f, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain,
|
||||||
0.0f , delayFeedbackBaseGain , 0.0f , delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f ,
|
0.0f, delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f,
|
||||||
delayFeedbackCrossGain, 0.0f , delayFeedbackBaseGain , delayFeedbackCrossGain, 0.0f , 0.0f ,
|
delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, 0.0f,
|
||||||
0.0f , delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain , 0.0f , 0.0f ,
|
0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, 0.0f,
|
||||||
delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f , 0.0f , delayFeedbackBaseGain , 0.0f ,
|
delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackBaseGain, 0.0f,
|
||||||
0.0f , 0.0f , 0.0f , 0.0f , 0.0f , feedbackGain);
|
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, feedbackGain);
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
for (int i = 0; i < sampleCount; i++)
|
||||||
{
|
{
|
||||||
@ -277,4 +277,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ProcessDelay(context, ref state);
|
ProcessDelay(context, ref state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -90,4 +90,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -54,4 +54,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -88,4 +88,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -65,4 +65,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
context.ClearBuffer(OutputBufferIndices[5]);
|
context.ClearBuffer(OutputBufferIndices[5]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -60,4 +60,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,4 +17,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -143,4 +143,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -162,4 +162,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -134,4 +134,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ProcessMix(outputBuffer, inputBuffer);
|
ProcessMix(outputBuffer, inputBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -65,4 +65,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
State.Span[0].LastSamples[LastSampleIndex] = ProcessMixRamp(outputBuffer, inputBuffer, (int)context.SampleCount);
|
State.Span[0].LastSamples[LastSampleIndex] = ProcessMixRamp(outputBuffer, inputBuffer, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -88,4 +88,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -71,4 +71,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -71,4 +71,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
DataSourceHelper.ProcessWaveBuffers(context.MemoryManager, outputBuffer, ref info, WaveBuffers, ref State.Span[0], context.SampleRate, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -44,4 +44,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -251,4 +251,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ProcessReverb3d(context, ref state);
|
ProcessReverb3d(context, ref state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -276,4 +276,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ProcessReverb(context, ref state);
|
ProcessReverb(context, ref state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -66,4 +66,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -134,4 +134,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ProcessVolume(outputBuffer, inputBuffer);
|
ProcessVolume(outputBuffer, inputBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -53,4 +53,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
ProcessVolumeRamp(outputBuffer, inputBuffer, (int)context.SampleCount);
|
ProcessVolumeRamp(outputBuffer, inputBuffer, (int)context.SampleCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -463,4 +463,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -49,4 +49,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
|||||||
return _delayLine.Tap(sampleIndex);
|
return _delayLine.Tap(sampleIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -75,4 +75,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
|||||||
return TapUnsafe(sampleIndex, -1);
|
return TapUnsafe(sampleIndex, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -73,4 +73,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
|||||||
return TapUnsafe(sampleIndex, -1);
|
return TapUnsafe(sampleIndex, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,4 +34,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
|||||||
return (uint)MathF.Round(sampleRate * delayTime);
|
return (uint)MathF.Round(sampleRate * delayTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,4 +30,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
return ToInt(value + half, qBits);
|
return ToInt(value + half, qBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,4 +64,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
return MathF.Sin(DegreesToRadians(value));
|
return MathF.Sin(DegreesToRadians(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -75,4 +75,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
return (short)value;
|
return (short)value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -627,4 +627,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,4 +9,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
public short History0;
|
public short History0;
|
||||||
public short History1;
|
public short History1;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -71,4 +71,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
public AuxiliaryBufferInfo CpuBufferInfo;
|
public AuxiliaryBufferInfo CpuBufferInfo;
|
||||||
public AuxiliaryBufferInfo DspBufferInfo;
|
public AuxiliaryBufferInfo DspBufferInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,4 +10,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
public float State2;
|
public float State2;
|
||||||
public float State3;
|
public float State3;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,4 +64,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,6 +25,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
UpdateParameter(ref parameter);
|
UpdateParameter(ref parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateParameter(ref LimiterParameter parameter) {}
|
public void UpdateParameter(ref LimiterParameter parameter) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -116,4 +116,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -201,4 +201,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user