From 458da8a94877677f086f06cdeecf959ec4283a33 Mon Sep 17 00:00:00 2001 From: Kelebek1 Date: Sat, 16 Jul 2022 23:48:45 +0100 Subject: Project Andio --- .../renderer/splitter/splitter_context.h | 189 +++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/audio_core/renderer/splitter/splitter_context.h (limited to 'src/audio_core/renderer/splitter/splitter_context.h') diff --git a/src/audio_core/renderer/splitter/splitter_context.h b/src/audio_core/renderer/splitter/splitter_context.h new file mode 100644 index 000000000..cfd092b4f --- /dev/null +++ b/src/audio_core/renderer/splitter/splitter_context.h @@ -0,0 +1,189 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "audio_core/renderer/splitter/splitter_destinations_data.h" +#include "audio_core/renderer/splitter/splitter_info.h" +#include "common/common_types.h" + +namespace AudioCore { +struct AudioRendererParameterInternal; +class WorkbufferAllocator; + +namespace AudioRenderer { +class BehaviorInfo; + +/** + * The splitter allows much more control over how sound is mixed together. + * Previously, one mix can only connect to one other, and you may need + * more mixes (and duplicate processing) to achieve the same result. + * With the splitter, many-to-one and one-to-many mixing is possible. + * This was added in revision 2. + * Had a bug with incorrect numbers of destinations, fixed in revision 5. + */ +class SplitterContext { + struct InParameterHeader { + /* 0x00 */ u32 magic; // 'SNDH' + /* 0x04 */ s32 info_count; + /* 0x08 */ s32 destination_count; + /* 0x0C */ char unk0C[0x14]; + }; + static_assert(sizeof(InParameterHeader) == 0x20, + "SplitterContext::InParameterHeader has the wrong size!"); + +public: + /** + * Get a destination mix from the given splitter and destination index. + * + * @param splitter_id - Splitter index to get from. + * @param destination_id - Destination index within the splitter. + * @return Pointer to the found destination. May be nullptr. + */ + SplitterDestinationData* GetDesintationData(s32 splitter_id, s32 destination_id); + + /** + * Get a splitter from the given index. + * + * @param index - Index of the desired splitter. + * @return Splitter requested. + */ + SplitterInfo& GetInfo(s32 index); + + /** + * Get the total number of splitter destinations. + * + * @return Number of destiantions. + */ + u32 GetDataCount() const; + + /** + * Get the total number of splitters. + * + * @return Number of splitters. + */ + u32 GetInfoCount() const; + + /** + * Get a specific global destination. + * + * @param index - Index of the desired destination. + * @return The requested destination. + */ + SplitterDestinationData& GetData(u32 index); + + /** + * Check if the splitter is in use. + * + * @return True if any splitter or destination is in use, otherwise false. + */ + bool UsingSplitter() const; + + /** + * Mark all splitters as having new connections. + */ + void ClearAllNewConnectionFlag(); + + /** + * Initialize the context. + * + * @param behavior - Used to check for splitter support. + * @param params - Input parameters. + * @param allocator - Allocator used to allocate workbuffer memory. + */ + bool Initialize(const BehaviorInfo& behavior, const AudioRendererParameterInternal& params, + WorkbufferAllocator& allocator); + + /** + * Update the context. + * + * @param input - Input buffer with the new info, + * expected to point to a InParameterHeader. + * @param consumed_size - Output with the number of bytes consumed from input. + */ + bool Update(const u8* input, u32& consumed_size); + + /** + * Update the splitters. + * + * @param input - Input buffer with the new info. + * @param offset - Current offset within the input buffer, + * input + offset should point to a SplitterInfo::InParameter. + * @param splitter_count - Number of splitters in the input buffer. + * @return Number of bytes consumed in input. + */ + u32 UpdateInfo(const u8* input, u32 offset, u32 splitter_count); + + /** + * Update the splitters. + * + * @param input - Input buffer with the new info. + * @param offset - Current offset within the input buffer, + * input + offset should point to a + * SplitterDestinationData::InParameter. + * @param destination_count - Number of destinations in the input buffer. + * @return Number of bytes consumed in input. + */ + u32 UpdateData(const u8* input, u32 offset, u32 destination_count); + + /** + * Update the state of all destinations in all splitters. + */ + void UpdateInternalState(); + + /** + * Replace the given splitter's destinations with new ones. + * + * @param out_info - Splitter to recompose. + * @param info_header - Input parameters containing new destination ids. + */ + void RecomposeDestination(SplitterInfo& out_info, const SplitterInfo::InParameter* info_header); + + /** + * Old calculation for destinations, this is the thing the splitter bug fixes. + * Left for compatibility, and now min'd with the actual count to not bug. + * + * @return Number of splitter destinations. + */ + u32 GetDestCountPerInfoForCompat() const; + + /** + * Calculate the size of the required workbuffer for splitters and destinations. + * + * @param behavior - Used to check splitter features. + * @param params - Input parameters with splitter/destination counts. + * @return Required buffer size. + */ + static u64 CalcWorkBufferSize(const BehaviorInfo& behavior, + const AudioRendererParameterInternal& params); + +private: + /** + * Setup the context. + * + * @param splitter_infos - Workbuffer for splitters. + * @param splitter_info_count - Number of splitters in the workbuffer. + * @param splitter_destinations - Workbuffer for splitter destinations. + * @param destination_count - Number of destinations in the workbuffer. + * @param splitter_bug_fixed - Is the splitter bug fixed? + */ + void Setup(std::span splitter_infos, u32 splitter_info_count, + SplitterDestinationData* splitter_destinations, u32 destination_count, + bool splitter_bug_fixed); + + /// Workbuffer for splitters + std::span splitter_infos{}; + /// Number of splitters in buffer + s32 info_count{}; + /// Workbuffer for destinations + SplitterDestinationData* splitter_destinations{}; + /// Number of destinations in buffer + s32 destinations_count{}; + /// Is the splitter bug fixed? + bool splitter_bug_fixed{}; +}; + +} // namespace AudioRenderer +} // namespace AudioCore -- cgit v1.2.3