using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Utils; using System; using System.Diagnostics; namespace Ryujinx.Audio.Renderer.Server.Voice { /// /// Voice context. /// public class VoiceContext { /// /// Storage of the sorted indices to . /// private Memory _sortedVoices; /// /// Storage for . /// private Memory _voices; /// /// Storage for . /// private Memory _voiceChannelResources; /// /// Storage for that are used during audio renderer server updates. /// private Memory _voiceStatesCpu; /// /// Storage for for the . /// private Memory _voiceStatesDsp; /// /// The total voice count. /// private uint _voiceCount; public void Initialize(Memory sortedVoices, Memory voices, Memory voiceChannelResources, Memory voiceStatesCpu, Memory voiceStatesDsp, uint voiceCount) { _sortedVoices = sortedVoices; _voices = voices; _voiceChannelResources = voiceChannelResources; _voiceStatesCpu = voiceStatesCpu; _voiceStatesDsp = voiceStatesDsp; _voiceCount = voiceCount; } /// /// Get the total voice count. /// /// The total voice count. public uint GetCount() { return _voiceCount; } /// /// Get a reference to a at the given . /// /// The index to use. /// A reference to a at the given . public ref VoiceChannelResource GetChannelResource(int id) { return ref SpanIOHelper.GetFromMemory(_voiceChannelResources, id, _voiceCount); } /// /// Get a at the given . /// /// The index to use. /// A at the given . /// The returned should only be used when updating the server state. public Memory GetUpdateStateForCpu(int id) { return SpanIOHelper.GetMemory(_voiceStatesCpu, id, _voiceCount); } /// /// Get a at the given . /// /// The index to use. /// A at the given . /// The returned should only be used in the context of processing on the . public Memory GetUpdateStateForDsp(int id) { return SpanIOHelper.GetMemory(_voiceStatesDsp, id, _voiceCount); } /// /// Get a reference to a at the given . /// /// The index to use. /// A reference to a at the given . public ref VoiceInfo GetState(int id) { return ref SpanIOHelper.GetFromMemory(_voices, id, _voiceCount); } public ref VoiceInfo GetSortedState(int id) { Debug.Assert(id >= 0 && id < _voiceCount); return ref GetState(_sortedVoices.Span[id]); } /// /// Update internal state during command generation. /// public void UpdateForCommandGeneration() { _voiceStatesDsp.CopyTo(_voiceStatesCpu); } /// /// Sort the internal voices by priority and sorting order (if the priorities match). /// public void Sort() { for (int i = 0; i < _voiceCount; i++) { _sortedVoices.Span[i] = i; } Span sortedVoicesTemp = _sortedVoices[..(int)_voiceCount].Span; sortedVoicesTemp.Sort((a, b) => { ref VoiceInfo aInfo = ref GetState(a); ref VoiceInfo bInfo = ref GetState(b); int result = aInfo.Priority.CompareTo(bInfo.Priority); if (result == 0) { return aInfo.SortingOrder.CompareTo(bInfo.SortingOrder); } return result; }); // sortedVoicesTemp.CopyTo(_sortedVoices.Span); } } }