aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs')
-rw-r--r--Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs166
1 files changed, 166 insertions, 0 deletions
diff --git a/Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs b/Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs
new file mode 100644
index 00000000..694bf1ae
--- /dev/null
+++ b/Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs
@@ -0,0 +1,166 @@
+//
+// Copyright (c) 2019-2020 Ryujinx
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+//
+
+using Ryujinx.Audio.Renderer.Common;
+using Ryujinx.Audio.Renderer.Utils;
+using System;
+using System.Diagnostics;
+
+namespace Ryujinx.Audio.Renderer.Server.Voice
+{
+ /// <summary>
+ /// Voice context.
+ /// </summary>
+ public class VoiceContext
+ {
+ /// <summary>
+ /// Storage of the sorted indices to <see cref="VoiceState"/>.
+ /// </summary>
+ private Memory<int> _sortedVoices;
+
+ /// <summary>
+ /// Storage for <see cref="VoiceState"/>.
+ /// </summary>
+ private Memory<VoiceState> _voices;
+
+ /// <summary>
+ /// Storage for <see cref="VoiceChannelResource"/>.
+ /// </summary>
+ private Memory<VoiceChannelResource> _voiceChannelResources;
+
+ /// <summary>
+ /// Storage for <see cref="VoiceUpdateState"/> that are used during audio renderer server updates.
+ /// </summary>
+ private Memory<VoiceUpdateState> _voiceUpdateStatesCpu;
+
+ /// <summary>
+ /// Storage for <see cref="VoiceUpdateState"/> for the <see cref="Dsp.AudioProcessor"/>.
+ /// </summary>
+ private Memory<VoiceUpdateState> _voiceUpdateStatesDsp;
+
+ /// <summary>
+ /// The total voice count.
+ /// </summary>
+ private uint _voiceCount;
+
+ public void Initialize(Memory<int> sortedVoices, Memory<VoiceState> voices, Memory<VoiceChannelResource> voiceChannelResources, Memory<VoiceUpdateState> voiceUpdateStatesCpu, Memory<VoiceUpdateState> voiceUpdateStatesDsp, uint voiceCount)
+ {
+ _sortedVoices = sortedVoices;
+ _voices = voices;
+ _voiceChannelResources = voiceChannelResources;
+ _voiceUpdateStatesCpu = voiceUpdateStatesCpu;
+ _voiceUpdateStatesDsp = voiceUpdateStatesDsp;
+ _voiceCount = voiceCount;
+ }
+
+ /// <summary>
+ /// Get the total voice count.
+ /// </summary>
+ /// <returns>The total voice count.</returns>
+ public uint GetCount()
+ {
+ return _voiceCount;
+ }
+
+ /// <summary>
+ /// Get a reference to a <see cref="VoiceChannelResource"/> at the given <paramref name="id"/>.
+ /// </summary>
+ /// <param name="id">The index to use.</param>
+ /// <returns>A reference to a <see cref="VoiceChannelResource"/> at the given <paramref name="id"/>.</returns>
+ public ref VoiceChannelResource GetChannelResource(int id)
+ {
+ return ref SpanIOHelper.GetFromMemory(_voiceChannelResources, id, _voiceCount);
+ }
+
+ /// <summary>
+ /// Get a <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.
+ /// </summary>
+ /// <param name="id">The index to use.</param>
+ /// <returns>A <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.</returns>
+ /// <remarks>The returned <see cref="Memory{VoiceUpdateState}"/> should only be used when updating the server state.</remarks>
+ public Memory<VoiceUpdateState> GetUpdateStateForCpu(int id)
+ {
+ return SpanIOHelper.GetMemory(_voiceUpdateStatesCpu, id, _voiceCount);
+ }
+
+ /// <summary>
+ /// Get a <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.
+ /// </summary>
+ /// <param name="id">The index to use.</param>
+ /// <returns>A <see cref="Memory{VoiceUpdateState}"/> at the given <paramref name="id"/>.</returns>
+ /// <remarks>The returned <see cref="Memory{VoiceUpdateState}"/> should only be used in the context of processing on the <see cref="Dsp.AudioProcessor"/>.</remarks>
+ public Memory<VoiceUpdateState> GetUpdateStateForDsp(int id)
+ {
+ return SpanIOHelper.GetMemory(_voiceUpdateStatesDsp, id, _voiceCount);
+ }
+
+ /// <summary>
+ /// Get a reference to a <see cref="VoiceState"/> at the given <paramref name="id"/>.
+ /// </summary>
+ /// <param name="id">The index to use.</param>
+ /// <returns>A reference to a <see cref="VoiceState"/> at the given <paramref name="id"/>.</returns>
+ public ref VoiceState GetState(int id)
+ {
+ return ref SpanIOHelper.GetFromMemory(_voices, id, _voiceCount);
+ }
+
+ public ref VoiceState GetSortedState(int id)
+ {
+ Debug.Assert(id >= 0 && id < _voiceCount);
+
+ return ref GetState(_sortedVoices.Span[id]);
+ }
+
+ /// <summary>
+ /// Update internal state during command generation.
+ /// </summary>
+ public void UpdateForCommandGeneration()
+ {
+ _voiceUpdateStatesDsp.CopyTo(_voiceUpdateStatesCpu);
+ }
+
+ /// <summary>
+ /// Sort the internal voices by priority and sorting order (if the priorities match).
+ /// </summary>
+ public void Sort()
+ {
+ for (int i = 0; i < _voiceCount; i++)
+ {
+ _sortedVoices.Span[i] = i;
+ }
+
+ int[] sortedVoicesTemp = _sortedVoices.Slice(0, (int)GetCount()).ToArray();
+
+ Array.Sort(sortedVoicesTemp, (a, b) =>
+ {
+ ref VoiceState aState = ref GetState(a);
+ ref VoiceState bState = ref GetState(b);
+
+ int result = aState.Priority.CompareTo(bState.Priority);
+
+ if (result == 0)
+ {
+ return aState.SortingOrder.CompareTo(bState.SortingOrder);
+ }
+
+ return result;
+ });
+
+ sortedVoicesTemp.AsSpan().CopyTo(_sortedVoices.Span);
+ }
+ }
+}