VoiceContext.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using Ryujinx.Audio.Renderer.Common;
  2. using Ryujinx.Audio.Renderer.Utils;
  3. using System;
  4. using System.Diagnostics;
  5. namespace Ryujinx.Audio.Renderer.Server.Voice
  6. {
  7. /// <summary>
  8. /// Voice context.
  9. /// </summary>
  10. public class VoiceContext
  11. {
  12. /// <summary>
  13. /// Storage of the sorted indices to <see cref="VoiceState"/>.
  14. /// </summary>
  15. private Memory<int> _sortedVoices;
  16. /// <summary>
  17. /// Storage for <see cref="VoiceState"/>.
  18. /// </summary>
  19. private Memory<VoiceState> _voices;
  20. /// <summary>
  21. /// Storage for <see cref="VoiceChannelResource"/>.
  22. /// </summary>
  23. private Memory<VoiceChannelResource> _voiceChannelResources;
  24. /// <summary>
  25. /// Storage for <see cref="VoiceUpdateState"/> that are used during audio renderer server updates.
  26. /// </summary>
  27. private Memory<VoiceUpdateState> _voiceUpdateStatesCpu;
  28. /// <summary>
  29. /// Storage for <see cref="VoiceUpdateState"/> for the <see cref="Dsp.AudioProcessor"/>.
  30. /// </summary>
  31. private Memory<VoiceUpdateState> _voiceUpdateStatesDsp;
  32. /// <summary>
  33. /// The total voice count.
  34. /// </summary>
  35. private uint _voiceCount;
  36. public void Initialize(Memory<int> sortedVoices, Memory<VoiceState> voices, Memory<VoiceChannelResource> voiceChannelResources, Memory<VoiceUpdateState> voiceUpdateStatesCpu, Memory<VoiceUpdateState> voiceUpdateStatesDsp, uint voiceCount)
  37. {
  38. _sortedVoices = sortedVoices;
  39. _voices = voices;
  40. _voiceChannelResources = voiceChannelResources;
  41. _voiceUpdateStatesCpu = voiceUpdateStatesCpu;
  42. _voiceUpdateStatesDsp = voiceUpdateStatesDsp;
  43. _voiceCount = voiceCount;
  44. }
  45. /// <summary>
  46. /// Get the total voice count.
  47. /// </summary>
  48. /// <returns>The total voice count.</returns>
  49. public uint GetCount()
  50. {
  51. return _voiceCount;
  52. }
  53. /// <summary>
  54. /// Get a reference to a <see cref="VoiceChannelResource"/> at the given <paramref name="id"/>.
  55. /// </summary>
  56. /// <param name="id">The index to use.</param>
  57. /// <returns>A reference to a <see cref="VoiceChannelResource"/> at the given <paramref name="id"/>.</returns>
  58. public ref VoiceChannelResource GetChannelResource(int id)
  59. {
  60. return ref SpanIOHelper.GetFromMemory(_voiceChannelResources, id, _voiceCount);
  61. }
  62. /// <summary>
  63. /// Get a <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.
  64. /// </summary>
  65. /// <param name="id">The index to use.</param>
  66. /// <returns>A <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.</returns>
  67. /// <remarks>The returned <see cref="Memory{VoiceUpdateState}"/> should only be used when updating the server state.</remarks>
  68. public Memory<VoiceUpdateState> GetUpdateStateForCpu(int id)
  69. {
  70. return SpanIOHelper.GetMemory(_voiceUpdateStatesCpu, id, _voiceCount);
  71. }
  72. /// <summary>
  73. /// Get a <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.
  74. /// </summary>
  75. /// <param name="id">The index to use.</param>
  76. /// <returns>A <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.</returns>
  77. /// <remarks>The returned <see cref="Memory{VoiceUpdateState}"/> should only be used in the context of processing on the <see cref="Dsp.AudioProcessor"/>.</remarks>
  78. public Memory<VoiceUpdateState> GetUpdateStateForDsp(int id)
  79. {
  80. return SpanIOHelper.GetMemory(_voiceUpdateStatesDsp, id, _voiceCount);
  81. }
  82. /// <summary>
  83. /// Get a reference to a <see cref="VoiceState"/> at the given <paramref name="id"/>.
  84. /// </summary>
  85. /// <param name="id">The index to use.</param>
  86. /// <returns>A reference to a <see cref="VoiceState"/> at the given <paramref name="id"/>.</returns>
  87. public ref VoiceState GetState(int id)
  88. {
  89. return ref SpanIOHelper.GetFromMemory(_voices, id, _voiceCount);
  90. }
  91. public ref VoiceState GetSortedState(int id)
  92. {
  93. Debug.Assert(id >= 0 && id < _voiceCount);
  94. return ref GetState(_sortedVoices.Span[id]);
  95. }
  96. /// <summary>
  97. /// Update internal state during command generation.
  98. /// </summary>
  99. public void UpdateForCommandGeneration()
  100. {
  101. _voiceUpdateStatesDsp.CopyTo(_voiceUpdateStatesCpu);
  102. }
  103. /// <summary>
  104. /// Sort the internal voices by priority and sorting order (if the priorities match).
  105. /// </summary>
  106. public void Sort()
  107. {
  108. for (int i = 0; i < _voiceCount; i++)
  109. {
  110. _sortedVoices.Span[i] = i;
  111. }
  112. int[] sortedVoicesTemp = _sortedVoices.Slice(0, (int)GetCount()).ToArray();
  113. Array.Sort(sortedVoicesTemp, (a, b) =>
  114. {
  115. ref VoiceState aState = ref GetState(a);
  116. ref VoiceState bState = ref GetState(b);
  117. int result = aState.Priority.CompareTo(bState.Priority);
  118. if (result == 0)
  119. {
  120. return aState.SortingOrder.CompareTo(bState.SortingOrder);
  121. }
  122. return result;
  123. });
  124. sortedVoicesTemp.AsSpan().CopyTo(_sortedVoices.Span);
  125. }
  126. }
  127. }