diff options
Diffstat (limited to 'Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs')
-rw-r--r-- | Ryujinx.Audio.Renderer/Server/Voice/VoiceContext.cs | 166 |
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); + } + } +} |