CompatLayerHardwareDeviceSession.cs
1 using Ryujinx.Audio.Backends.Common; 2 using Ryujinx.Audio.Common; 3 using Ryujinx.Audio.Renderer.Dsp; 4 using System; 5 using System.Runtime.InteropServices; 6 7 namespace Ryujinx.Audio.Backends.CompatLayer 8 { 9 class CompatLayerHardwareDeviceSession : HardwareDeviceSessionOutputBase 10 { 11 private readonly HardwareDeviceSessionOutputBase _realSession; 12 private readonly SampleFormat _userSampleFormat; 13 private readonly uint _userChannelCount; 14 15 public CompatLayerHardwareDeviceSession(HardwareDeviceSessionOutputBase realSession, SampleFormat userSampleFormat, uint userChannelCount) : base(realSession.MemoryManager, realSession.RequestedSampleFormat, realSession.RequestedSampleRate, userChannelCount) 16 { 17 _realSession = realSession; 18 _userSampleFormat = userSampleFormat; 19 _userChannelCount = userChannelCount; 20 } 21 22 public override void Dispose() 23 { 24 _realSession.Dispose(); 25 } 26 27 public override ulong GetPlayedSampleCount() 28 { 29 return _realSession.GetPlayedSampleCount(); 30 } 31 32 public override float GetVolume() 33 { 34 return _realSession.GetVolume(); 35 } 36 37 public override void PrepareToClose() 38 { 39 _realSession.PrepareToClose(); 40 } 41 42 public override void QueueBuffer(AudioBuffer buffer) 43 { 44 SampleFormat realSampleFormat = _realSession.RequestedSampleFormat; 45 46 if (_userSampleFormat != realSampleFormat) 47 { 48 if (_userSampleFormat != SampleFormat.PcmInt16) 49 { 50 throw new NotImplementedException("Converting formats other than PCM16 is not supported."); 51 } 52 53 int userSampleCount = buffer.Data.Length / BackendHelper.GetSampleSize(_userSampleFormat); 54 55 ReadOnlySpan<short> samples = MemoryMarshal.Cast<byte, short>(buffer.Data); 56 byte[] convertedSamples = new byte[BackendHelper.GetSampleSize(realSampleFormat) * userSampleCount]; 57 58 switch (realSampleFormat) 59 { 60 case SampleFormat.PcmInt8: 61 PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples); 62 break; 63 case SampleFormat.PcmInt24: 64 PcmHelper.ConvertSampleToPcm24(convertedSamples, samples); 65 break; 66 case SampleFormat.PcmInt32: 67 PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(convertedSamples), samples); 68 break; 69 case SampleFormat.PcmFloat: 70 PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples); 71 break; 72 default: 73 throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented."); 74 } 75 76 buffer.Data = convertedSamples; 77 } 78 79 _realSession.QueueBuffer(buffer); 80 } 81 82 public override bool RegisterBuffer(AudioBuffer buffer, byte[] samples) 83 { 84 if (samples == null) 85 { 86 return false; 87 } 88 89 if (_userChannelCount != _realSession.RequestedChannelCount) 90 { 91 if (_userSampleFormat != SampleFormat.PcmInt16) 92 { 93 throw new NotImplementedException("Downmixing formats other than PCM16 is not supported."); 94 } 95 96 ReadOnlySpan<short> samplesPCM16 = MemoryMarshal.Cast<byte, short>(samples); 97 98 if (_userChannelCount == 6) 99 { 100 samplesPCM16 = Downmixing.DownMixSurroundToStereo(samplesPCM16); 101 102 if (_realSession.RequestedChannelCount == 1) 103 { 104 samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16); 105 } 106 } 107 else if (_userChannelCount == 2 && _realSession.RequestedChannelCount == 1) 108 { 109 samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16); 110 } 111 else 112 { 113 throw new NotImplementedException($"Downmixing from {_userChannelCount} to {_realSession.RequestedChannelCount} not implemented."); 114 } 115 116 samples = MemoryMarshal.Cast<short, byte>(samplesPCM16).ToArray(); 117 } 118 119 AudioBuffer fakeBuffer = new() 120 { 121 BufferTag = buffer.BufferTag, 122 DataPointer = buffer.DataPointer, 123 DataSize = (ulong)samples.Length, 124 }; 125 126 bool result = _realSession.RegisterBuffer(fakeBuffer, samples); 127 128 if (result) 129 { 130 buffer.Data = fakeBuffer.Data; 131 buffer.DataSize = fakeBuffer.DataSize; 132 } 133 134 return result; 135 } 136 137 public override void SetVolume(float volume) 138 { 139 _realSession.SetVolume(volume); 140 } 141 142 public override void Start() 143 { 144 _realSession.Start(); 145 } 146 147 public override void Stop() 148 { 149 _realSession.Stop(); 150 } 151 152 public override void UnregisterBuffer(AudioBuffer buffer) 153 { 154 _realSession.UnregisterBuffer(buffer); 155 } 156 157 public override bool WasBufferFullyConsumed(AudioBuffer buffer) 158 { 159 return _realSession.WasBufferFullyConsumed(buffer); 160 } 161 } 162 }