Move solution and projects to src

This commit is contained in:
TSR Berry 2023-04-08 01:22:00 +02:00 committed by Mary
parent cd124bda58
commit cee7121058
3466 changed files with 55 additions and 55 deletions

View file

@ -0,0 +1,9 @@
namespace Ryujinx.Audio.Backends.OpenAL
{
class OpenALAudioBuffer
{
public int BufferId;
public ulong DriverIdentifier;
public ulong SampleCount;
}
}

View file

@ -0,0 +1,167 @@
using OpenTK.Audio.OpenAL;
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
namespace Ryujinx.Audio.Backends.OpenAL
{
public class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
{
private readonly ALDevice _device;
private readonly ALContext _context;
private readonly ManualResetEvent _updateRequiredEvent;
private readonly ManualResetEvent _pauseEvent;
private readonly ConcurrentDictionary<OpenALHardwareDeviceSession, byte> _sessions;
private bool _stillRunning;
private Thread _updaterThread;
public OpenALHardwareDeviceDriver()
{
_device = ALC.OpenDevice("");
_context = ALC.CreateContext(_device, new ALContextAttributes());
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
_sessions = new ConcurrentDictionary<OpenALHardwareDeviceSession, byte>();
_stillRunning = true;
_updaterThread = new Thread(Update)
{
Name = "HardwareDeviceDriver.OpenAL"
};
_updaterThread.Start();
}
public static bool IsSupported
{
get
{
try
{
return ALC.GetStringList(GetEnumerationStringList.DeviceSpecifier).Any();
}
catch
{
return false;
}
}
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
{
if (channelCount == 0)
{
channelCount = 2;
}
if (sampleRate == 0)
{
sampleRate = Constants.TargetSampleRate;
}
if (direction != Direction.Output)
{
throw new ArgumentException($"{direction}");
}
else if (!SupportsChannelCount(channelCount))
{
throw new ArgumentException($"{channelCount}");
}
OpenALHardwareDeviceSession session = new OpenALHardwareDeviceSession(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
_sessions.TryAdd(session, 0);
return session;
}
internal bool Unregister(OpenALHardwareDeviceSession session)
{
return _sessions.TryRemove(session, out _);
}
public ManualResetEvent GetUpdateRequiredEvent()
{
return _updateRequiredEvent;
}
public ManualResetEvent GetPauseEvent()
{
return _pauseEvent;
}
private void Update()
{
ALC.MakeContextCurrent(_context);
while (_stillRunning)
{
bool updateRequired = false;
foreach (OpenALHardwareDeviceSession session in _sessions.Keys)
{
if (session.Update())
{
updateRequired = true;
}
}
if (updateRequired)
{
_updateRequiredEvent.Set();
}
// If it's not slept it will waste cycles.
Thread.Sleep(10);
}
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_stillRunning = false;
foreach (OpenALHardwareDeviceSession session in _sessions.Keys)
{
session.Dispose();
}
ALC.DestroyContext(_context);
ALC.CloseDevice(_device);
_pauseEvent.Dispose();
}
}
public bool SupportsSampleRate(uint sampleRate)
{
return true;
}
public bool SupportsSampleFormat(SampleFormat sampleFormat)
{
return true;
}
public bool SupportsChannelCount(uint channelCount)
{
return channelCount == 1 || channelCount == 2 || channelCount == 6;
}
public bool SupportsDirection(Direction direction)
{
return direction == Direction.Output;
}
}
}

View file

@ -0,0 +1,212 @@
using OpenTK.Audio.OpenAL;
using Ryujinx.Audio.Backends.Common;
using Ryujinx.Audio.Common;
using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Ryujinx.Audio.Backends.OpenAL
{
class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private OpenALHardwareDeviceDriver _driver;
private int _sourceId;
private ALFormat _targetFormat;
private bool _isActive;
private Queue<OpenALAudioBuffer> _queuedBuffers;
private ulong _playedSampleCount;
private object _lock = new object();
public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{
_driver = driver;
_queuedBuffers = new Queue<OpenALAudioBuffer>();
_sourceId = AL.GenSource();
_targetFormat = GetALFormat();
_isActive = false;
_playedSampleCount = 0;
SetVolume(requestedVolume);
}
private ALFormat GetALFormat()
{
switch (RequestedSampleFormat)
{
case SampleFormat.PcmInt16:
switch (RequestedChannelCount)
{
case 1:
return ALFormat.Mono16;
case 2:
return ALFormat.Stereo16;
case 6:
return ALFormat.Multi51Chn16Ext;
default:
throw new NotImplementedException($"Unsupported channel config {RequestedChannelCount}");
}
default:
throw new NotImplementedException($"Unsupported sample format {RequestedSampleFormat}");
}
}
public override void PrepareToClose() { }
private void StartIfNotPlaying()
{
AL.GetSource(_sourceId, ALGetSourcei.SourceState, out int stateInt);
ALSourceState State = (ALSourceState)stateInt;
if (State != ALSourceState.Playing)
{
AL.SourcePlay(_sourceId);
}
}
public override void QueueBuffer(AudioBuffer buffer)
{
lock (_lock)
{
OpenALAudioBuffer driverBuffer = new OpenALAudioBuffer
{
DriverIdentifier = buffer.DataPointer,
BufferId = AL.GenBuffer(),
SampleCount = GetSampleCount(buffer)
};
AL.BufferData(driverBuffer.BufferId, _targetFormat, buffer.Data, (int)RequestedSampleRate);
_queuedBuffers.Enqueue(driverBuffer);
AL.SourceQueueBuffer(_sourceId, driverBuffer.BufferId);
if (_isActive)
{
StartIfNotPlaying();
}
}
}
public override void SetVolume(float volume)
{
lock (_lock)
{
AL.Source(_sourceId, ALSourcef.Gain, volume);
}
}
public override float GetVolume()
{
AL.GetSource(_sourceId, ALSourcef.Gain, out float volume);
return volume;
}
public override void Start()
{
lock (_lock)
{
_isActive = true;
StartIfNotPlaying();
}
}
public override void Stop()
{
lock (_lock)
{
SetVolume(0.0f);
AL.SourceStop(_sourceId);
_isActive = false;
}
}
public override void UnregisterBuffer(AudioBuffer buffer) { }
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{
lock (_lock)
{
if (!_queuedBuffers.TryPeek(out OpenALAudioBuffer driverBuffer))
{
return true;
}
return driverBuffer.DriverIdentifier != buffer.DataPointer;
}
}
public override ulong GetPlayedSampleCount()
{
lock (_lock)
{
return _playedSampleCount;
}
}
public bool Update()
{
lock (_lock)
{
if (_isActive)
{
AL.GetSource(_sourceId, ALGetSourcei.BuffersProcessed, out int releasedCount);
if (releasedCount > 0)
{
int[] bufferIds = new int[releasedCount];
AL.SourceUnqueueBuffers(_sourceId, releasedCount, bufferIds);
int i = 0;
while (_queuedBuffers.TryPeek(out OpenALAudioBuffer buffer) && i < bufferIds.Length)
{
if (buffer.BufferId == bufferIds[i])
{
_playedSampleCount += buffer.SampleCount;
_queuedBuffers.TryDequeue(out _);
i++;
}
}
Debug.Assert(i == bufferIds.Length, "Unknown buffer ids found!");
AL.DeleteBuffers(bufferIds);
}
return releasedCount > 0;
}
return false;
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing && _driver.Unregister(this))
{
lock (_lock)
{
PrepareToClose();
Stop();
AL.DeleteSource(_sourceId);
}
}
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View file

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK.OpenAL" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
</ItemGroup>
</Project>