VoiceContext.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //
  2. // Copyright (c) 2019-2021 Ryujinx
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. //
  17. using Ryujinx.Audio.Renderer.Common;
  18. using Ryujinx.Audio.Renderer.Utils;
  19. using System;
  20. using System.Diagnostics;
  21. namespace Ryujinx.Audio.Renderer.Server.Voice
  22. {
  23. /// <summary>
  24. /// Voice context.
  25. /// </summary>
  26. public class VoiceContext
  27. {
  28. /// <summary>
  29. /// Storage of the sorted indices to <see cref="VoiceState"/>.
  30. /// </summary>
  31. private Memory<int> _sortedVoices;
  32. /// <summary>
  33. /// Storage for <see cref="VoiceState"/>.
  34. /// </summary>
  35. private Memory<VoiceState> _voices;
  36. /// <summary>
  37. /// Storage for <see cref="VoiceChannelResource"/>.
  38. /// </summary>
  39. private Memory<VoiceChannelResource> _voiceChannelResources;
  40. /// <summary>
  41. /// Storage for <see cref="VoiceUpdateState"/> that are used during audio renderer server updates.
  42. /// </summary>
  43. private Memory<VoiceUpdateState> _voiceUpdateStatesCpu;
  44. /// <summary>
  45. /// Storage for <see cref="VoiceUpdateState"/> for the <see cref="Dsp.AudioProcessor"/>.
  46. /// </summary>
  47. private Memory<VoiceUpdateState> _voiceUpdateStatesDsp;
  48. /// <summary>
  49. /// The total voice count.
  50. /// </summary>
  51. private uint _voiceCount;
  52. public void Initialize(Memory<int> sortedVoices, Memory<VoiceState> voices, Memory<VoiceChannelResource> voiceChannelResources, Memory<VoiceUpdateState> voiceUpdateStatesCpu, Memory<VoiceUpdateState> voiceUpdateStatesDsp, uint voiceCount)
  53. {
  54. _sortedVoices = sortedVoices;
  55. _voices = voices;
  56. _voiceChannelResources = voiceChannelResources;
  57. _voiceUpdateStatesCpu = voiceUpdateStatesCpu;
  58. _voiceUpdateStatesDsp = voiceUpdateStatesDsp;
  59. _voiceCount = voiceCount;
  60. }
  61. /// <summary>
  62. /// Get the total voice count.
  63. /// </summary>
  64. /// <returns>The total voice count.</returns>
  65. public uint GetCount()
  66. {
  67. return _voiceCount;
  68. }
  69. /// <summary>
  70. /// Get a reference to a <see cref="VoiceChannelResource"/> at the given <paramref name="id"/>.
  71. /// </summary>
  72. /// <param name="id">The index to use.</param>
  73. /// <returns>A reference to a <see cref="VoiceChannelResource"/> at the given <paramref name="id"/>.</returns>
  74. public ref VoiceChannelResource GetChannelResource(int id)
  75. {
  76. return ref SpanIOHelper.GetFromMemory(_voiceChannelResources, id, _voiceCount);
  77. }
  78. /// <summary>
  79. /// Get a <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.
  80. /// </summary>
  81. /// <param name="id">The index to use.</param>
  82. /// <returns>A <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.</returns>
  83. /// <remarks>The returned <see cref="Memory{VoiceUpdateState}"/> should only be used when updating the server state.</remarks>
  84. public Memory<VoiceUpdateState> GetUpdateStateForCpu(int id)
  85. {
  86. return SpanIOHelper.GetMemory(_voiceUpdateStatesCpu, id, _voiceCount);
  87. }
  88. /// <summary>
  89. /// Get a <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.
  90. /// </summary>
  91. /// <param name="id">The index to use.</param>
  92. /// <returns>A <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.</returns>
  93. /// <remarks>The returned <see cref="Memory{VoiceUpdateState}"/> should only be used in the context of processing on the <see cref="Dsp.AudioProcessor"/>.</remarks>
  94. public Memory<VoiceUpdateState> GetUpdateStateForDsp(int id)
  95. {
  96. return SpanIOHelper.GetMemory(_voiceUpdateStatesDsp, id, _voiceCount);
  97. }
  98. /// <summary>
  99. /// Get a reference to a <see cref="VoiceState"/> at the given <paramref name="id"/>.
  100. /// </summary>
  101. /// <param name="id">The index to use.</param>
  102. /// <returns>A reference to a <see cref="VoiceState"/> at the given <paramref name="id"/>.</returns>
  103. public ref VoiceState GetState(int id)
  104. {
  105. return ref SpanIOHelper.GetFromMemory(_voices, id, _voiceCount);
  106. }
  107. public ref VoiceState GetSortedState(int id)
  108. {
  109. Debug.Assert(id >= 0 && id < _voiceCount);
  110. return ref GetState(_sortedVoices.Span[id]);
  111. }
  112. /// <summary>
  113. /// Update internal state during command generation.
  114. /// </summary>
  115. public void UpdateForCommandGeneration()
  116. {
  117. _voiceUpdateStatesDsp.CopyTo(_voiceUpdateStatesCpu);
  118. }
  119. /// <summary>
  120. /// Sort the internal voices by priority and sorting order (if the priorities match).
  121. /// </summary>
  122. public void Sort()
  123. {
  124. for (int i = 0; i < _voiceCount; i++)
  125. {
  126. _sortedVoices.Span[i] = i;
  127. }
  128. int[] sortedVoicesTemp = _sortedVoices.Slice(0, (int)GetCount()).ToArray();
  129. Array.Sort(sortedVoicesTemp, (a, b) =>
  130. {
  131. ref VoiceState aState = ref GetState(a);
  132. ref VoiceState bState = ref GetState(b);
  133. int result = aState.Priority.CompareTo(bState.Priority);
  134. if (result == 0)
  135. {
  136. return aState.SortingOrder.CompareTo(bState.SortingOrder);
  137. }
  138. return result;
  139. });
  140. sortedVoicesTemp.AsSpan().CopyTo(_sortedVoices.Span);
  141. }
  142. }
  143. }