aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Audio/Renderers/OpenAL
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Audio/Renderers/OpenAL')
-rw-r--r--Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs49
-rw-r--r--Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs8
2 files changed, 50 insertions, 7 deletions
diff --git a/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs b/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs
index ea5ce621..fe82fced 100644
--- a/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs
+++ b/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs
@@ -104,15 +104,24 @@ namespace Ryujinx.Audio
_context.Dispose();
}
+ public bool SupportsChannelCount(int channels)
+ {
+ // NOTE: OpenAL doesn't give us a way to know if the 5.1 setup is supported by hardware or actually emulated.
+ // TODO: find a way to determine hardware support.
+ return channels == 1 || channels == 2;
+ }
+
/// <summary>
/// Creates a new audio track with the specified parameters
/// </summary>
/// <param name="sampleRate">The requested sample rate</param>
- /// <param name="channels">The requested channels</param>
+ /// <param name="hardwareChannels">The requested hardware channels</param>
+ /// <param name="virtualChannels">The requested virtual channels</param>
/// <param name="callback">A <see cref="ReleaseCallback" /> that represents the delegate to invoke when a buffer has been released by the audio track</param>
- public int OpenTrack(int sampleRate, int channels, ReleaseCallback callback)
+ /// <returns>The created track's Track ID</returns>
+ public int OpenHardwareTrack(int sampleRate, int hardwareChannels, int virtualChannels, ReleaseCallback callback)
{
- OpenALAudioTrack track = new OpenALAudioTrack(sampleRate, GetALFormat(channels), callback);
+ OpenALAudioTrack track = new OpenALAudioTrack(sampleRate, GetALFormat(hardwareChannels), hardwareChannels, virtualChannels, callback);
for (int id = 0; id < MaxTracks; id++)
{
@@ -204,9 +213,37 @@ namespace Ryujinx.Audio
{
int bufferId = track.AppendBuffer(bufferTag);
- int size = buffer.Length * Marshal.SizeOf<T>();
-
- AL.BufferData(bufferId, track.Format, buffer, size, track.SampleRate);
+ // Do we need to downmix?
+ if (track.HardwareChannels != track.VirtualChannels)
+ {
+ short[] downmixedBuffer;
+
+ ReadOnlySpan<short> bufferPCM16 = MemoryMarshal.Cast<T, short>(buffer);
+
+ if (track.VirtualChannels == 6)
+ {
+ downmixedBuffer = Downmixing.DownMixSurroundToStereo(bufferPCM16);
+
+ if (track.HardwareChannels == 1)
+ {
+ downmixedBuffer = Downmixing.DownMixStereoToMono(downmixedBuffer);
+ }
+ }
+ else if (track.VirtualChannels == 2)
+ {
+ downmixedBuffer = Downmixing.DownMixStereoToMono(bufferPCM16);
+ }
+ else
+ {
+ throw new NotImplementedException($"Downmixing from {track.VirtualChannels} to {track.HardwareChannels} not implemented!");
+ }
+
+ AL.BufferData(bufferId, track.Format, downmixedBuffer, downmixedBuffer.Length * sizeof(ushort), track.SampleRate);
+ }
+ else
+ {
+ AL.BufferData(bufferId, track.Format, buffer, buffer.Length * sizeof(ushort), track.SampleRate);
+ }
AL.SourceQueueBuffer(track.SourceId, bufferId);
diff --git a/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs b/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs
index 8629dc96..2f150998 100644
--- a/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs
+++ b/Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs
@@ -12,6 +12,9 @@ namespace Ryujinx.Audio
public ALFormat Format { get; private set; }
public PlaybackState State { get; set; }
+ public int HardwareChannels { get; }
+ public int VirtualChannels { get; }
+
private ReleaseCallback _callback;
private ConcurrentDictionary<long, int> _buffers;
@@ -21,13 +24,16 @@ namespace Ryujinx.Audio
private bool _disposed;
- public OpenALAudioTrack(int sampleRate, ALFormat format, ReleaseCallback callback)
+ public OpenALAudioTrack(int sampleRate, ALFormat format, int hardwareChannels, int virtualChannels, ReleaseCallback callback)
{
SampleRate = sampleRate;
Format = format;
State = PlaybackState.Stopped;
SourceId = AL.GenSource();
+ HardwareChannels = hardwareChannels;
+ VirtualChannels = virtualChannels;
+
_callback = callback;
_buffers = new ConcurrentDictionary<long, int>();