CompatLayerHardwareDeviceSession.cs 5.4 KB

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