aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs
diff options
context:
space:
mode:
authorMary <me@thog.eu>2021-02-26 01:11:56 +0100
committerGitHub <noreply@github.com>2021-02-26 01:11:56 +0100
commitf556c80d0230056335632b60c71f1567e177239e (patch)
tree748aa6be62b93a8e941e25dbd83f39e1dbb37035 /Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs
parent1c49089ff00fc87dc4872f135dc6a0d36169a970 (diff)
Haydn: Part 1 (#2007)
* Haydn: Part 1 Based on my reverse of audio 11.0.0. As always, core implementation under LGPLv3 for the same reasons as for Amadeus. This place the bases of a more flexible audio system while making audout & audin accurate. This have the following improvements: - Complete reimplementation of audout and audin. - Audin currently only have a dummy backend. - Dramatically reduce CPU usage by up to 50% in common cases (SoundIO and OpenAL). - Audio Renderer now can output to 5.1 devices when supported. - Audio Renderer init its backend on demand instead of keeping two up all the time. - All backends implementation are now in their own project. - Ryujinx.Audio.Renderer was renamed Ryujinx.Audio and was refactored because of this. As a note, games having issues with OpenAL haven't improved and will not because of OpenAL design (stopping when buffers finish playing causing possible audio "pops" when buffers are very small). * Update for latest hexkyz's edits on Switchbrew * audren: Rollback channel configuration changes * Address gdkchan's comments * Fix typo in OpenAL backend driver * Address last comments * Fix a nit * Address gdkchan's comments
Diffstat (limited to 'Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs')
-rw-r--r--Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs237
1 files changed, 0 insertions, 237 deletions
diff --git a/Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs b/Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs
deleted file mode 100644
index c928ec53..00000000
--- a/Ryujinx.Audio.Renderer/Server/Splitter/SplitterState.cs
+++ /dev/null
@@ -1,237 +0,0 @@
-//
-// Copyright (c) 2019-2021 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.Parameter;
-using System;
-using System.Buffers;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Audio.Renderer.Server.Splitter
-{
- /// <summary>
- /// Server state for a splitter.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Size = 0x20, Pack = Alignment)]
- public struct SplitterState
- {
- public const int Alignment = 0x10;
-
- /// <summary>
- /// The unique id of this <see cref="SplitterState"/>.
- /// </summary>
- public int Id;
-
- /// <summary>
- /// Target sample rate to use on the splitter.
- /// </summary>
- public uint SampleRate;
-
- /// <summary>
- /// Count of splitter destinations (<see cref="SplitterDestination"/>).
- /// </summary>
- public int DestinationCount;
-
- /// <summary>
- /// Set to true if the splitter has a new connection.
- /// </summary>
- [MarshalAs(UnmanagedType.I1)]
- public bool HasNewConnection;
-
- /// <summary>
- /// Linked list of <see cref="SplitterDestination"/>.
- /// </summary>
- private unsafe SplitterDestination* _destinationsData;
-
- /// <summary>
- /// Span to the first element of the linked list of <see cref="SplitterDestination"/>.
- /// </summary>
- public Span<SplitterDestination> Destinations
- {
- get
- {
- unsafe
- {
- return (IntPtr)_destinationsData != IntPtr.Zero ? new Span<SplitterDestination>(_destinationsData, 1) : Span<SplitterDestination>.Empty;
- }
- }
- }
-
- /// <summary>
- /// Create a new <see cref="SplitterState"/>.
- /// </summary>
- /// <param name="id">The unique id of this <see cref="SplitterState"/>.</param>
- public SplitterState(int id) : this()
- {
- Id = id;
- }
-
- public Span<SplitterDestination> GetData(int index)
- {
- int i = 0;
-
- Span<SplitterDestination> result = Destinations;
-
- while (i < index)
- {
- if (result.IsEmpty)
- {
- break;
- }
-
- result = result[0].Next;
- i++;
- }
-
- return result;
- }
-
- /// <summary>
- /// Clear the new connection flag.
- /// </summary>
- public void ClearNewConnectionFlag()
- {
- HasNewConnection = false;
- }
-
- /// <summary>
- /// Utility function to apply a given <see cref="SpanAction{T, TArg}"/> to all <see cref="Destinations"/>.
- /// </summary>
- /// <param name="action">The action to execute on each elements.</param>
- private void ForEachDestination(SpanAction<SplitterDestination, int> action)
- {
- Span<SplitterDestination> temp = Destinations;
-
- int i = 0;
-
- while (true)
- {
- if (temp.IsEmpty)
- {
- break;
- }
-
- Span<SplitterDestination> next = temp[0].Next;
-
- action.Invoke(temp, i++);
-
- temp = next;
- }
- }
-
- /// <summary>
- /// Update the <see cref="SplitterState"/> from user parameter.
- /// </summary>
- /// <param name="context">The splitter context.</param>
- /// <param name="parameter">The user parameter.</param>
- /// <param name="input">The raw input data after the <paramref name="parameter"/>.</param>
- public void Update(SplitterContext context, ref SplitterInParameter parameter, ReadOnlySpan<byte> input)
- {
- ClearLinks();
-
- int destinationCount;
-
- if (context.IsBugFixed)
- {
- destinationCount = parameter.DestinationCount;
- }
- else
- {
- destinationCount = Math.Min(context.GetDestinationCountPerStateForCompatibility(), parameter.DestinationCount);
- }
-
- if (destinationCount > 0)
- {
- ReadOnlySpan<int> destinationIds = MemoryMarshal.Cast<byte, int>(input);
-
- Memory<SplitterDestination> destination = context.GetDestinationMemory(destinationIds[0]);
-
- SetDestination(ref destination.Span[0]);
-
- DestinationCount = destinationCount;
-
- for (int i = 1; i < destinationCount; i++)
- {
- Memory<SplitterDestination> nextDestination = context.GetDestinationMemory(destinationIds[i]);
-
- destination.Span[0].Link(ref nextDestination.Span[0]);
- destination = nextDestination;
- }
- }
-
- Debug.Assert(parameter.Id == Id);
-
- if (parameter.Id == Id)
- {
- SampleRate = parameter.SampleRate;
- HasNewConnection = true;
- }
- }
-
- /// <summary>
- /// Set the head of the linked list of <see cref="Destinations"/>.
- /// </summary>
- /// <param name="newValue">A reference to a <see cref="SplitterDestination"/>.</param>
- public void SetDestination(ref SplitterDestination newValue)
- {
- unsafe
- {
- fixed (SplitterDestination* newValuePtr = &newValue)
- {
- _destinationsData = newValuePtr;
- }
- }
- }
-
- /// <summary>
- /// Update the internal state of this instance.
- /// </summary>
- public void UpdateInternalState()
- {
- ForEachDestination((destination, _) => destination[0].UpdateInternalState());
- }
-
- /// <summary>
- /// Clear all links from the <see cref="Destinations"/>.
- /// </summary>
- public void ClearLinks()
- {
- ForEachDestination((destination, _) => destination[0].Unlink());
-
- unsafe
- {
- _destinationsData = (SplitterDestination*)IntPtr.Zero;
- }
- }
-
- /// <summary>
- /// Initialize a given <see cref="Span{SplitterState}"/>.
- /// </summary>
- /// <param name="splitters">All the <see cref="SplitterState"/> to initialize.</param>
- public static void InitializeSplitters(Span<SplitterState> splitters)
- {
- foreach (ref SplitterState splitter in splitters)
- {
- unsafe
- {
- splitter._destinationsData = (SplitterDestination*)IntPtr.Zero;
- }
-
- splitter.DestinationCount = 0;
- }
- }
- }
-}