diff options
| author | 2022-07-16 23:48:45 +0100 | |
|---|---|---|
| committer | 2022-07-22 01:11:32 +0100 | |
| commit | 458da8a94877677f086f06cdeecf959ec4283a33 (patch) | |
| tree | 583166d77602ad90a0d552f37de8729ad80fd6c1 /src/audio_core/renderer/mix | |
| parent | Merge pull request #8598 from Link4565/recv-dontwait (diff) | |
| download | yuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.gz yuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.xz yuzu-458da8a94877677f086f06cdeecf959ec4283a33.zip | |
Project Andio
Diffstat (limited to 'src/audio_core/renderer/mix')
| -rw-r--r-- | src/audio_core/renderer/mix/mix_context.cpp | 141 | ||||
| -rw-r--r-- | src/audio_core/renderer/mix/mix_context.h | 124 | ||||
| -rw-r--r-- | src/audio_core/renderer/mix/mix_info.cpp | 120 | ||||
| -rw-r--r-- | src/audio_core/renderer/mix/mix_info.h | 124 |
4 files changed, 509 insertions, 0 deletions
diff --git a/src/audio_core/renderer/mix/mix_context.cpp b/src/audio_core/renderer/mix/mix_context.cpp new file mode 100644 index 000000000..2427c83ed --- /dev/null +++ b/src/audio_core/renderer/mix/mix_context.cpp | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <ranges> | ||
| 5 | |||
| 6 | #include "audio_core/renderer/mix/mix_context.h" | ||
| 7 | #include "audio_core/renderer/splitter/splitter_context.h" | ||
| 8 | |||
| 9 | namespace AudioCore::AudioRenderer { | ||
| 10 | |||
| 11 | void MixContext::Initialize(std::span<MixInfo*> sorted_mix_infos_, std::span<MixInfo> mix_infos_, | ||
| 12 | const u32 count_, std::span<s32> effect_process_order_buffer_, | ||
| 13 | const u32 effect_count_, std::span<u8> node_states_workbuffer, | ||
| 14 | const u64 node_buffer_size, std::span<u8> edge_matrix_workbuffer, | ||
| 15 | const u64 edge_matrix_size) { | ||
| 16 | count = count_; | ||
| 17 | sorted_mix_infos = sorted_mix_infos_; | ||
| 18 | mix_infos = mix_infos_; | ||
| 19 | effect_process_order_buffer = effect_process_order_buffer_; | ||
| 20 | effect_count = effect_count_; | ||
| 21 | |||
| 22 | if (node_states_workbuffer.size() > 0 && edge_matrix_workbuffer.size() > 0) { | ||
| 23 | node_states.Initialize(node_states_workbuffer, node_buffer_size, count); | ||
| 24 | edge_matrix.Initialize(edge_matrix_workbuffer, edge_matrix_size, count); | ||
| 25 | } | ||
| 26 | |||
| 27 | for (s32 i = 0; i < count; i++) { | ||
| 28 | sorted_mix_infos[i] = &mix_infos[i]; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | MixInfo* MixContext::GetSortedInfo(const s32 index) { | ||
| 33 | return sorted_mix_infos[index]; | ||
| 34 | } | ||
| 35 | |||
| 36 | void MixContext::SetSortedInfo(const s32 index, MixInfo& mix_info) { | ||
| 37 | sorted_mix_infos[index] = &mix_info; | ||
| 38 | } | ||
| 39 | |||
| 40 | MixInfo* MixContext::GetInfo(const s32 index) { | ||
| 41 | return &mix_infos[index]; | ||
| 42 | } | ||
| 43 | |||
| 44 | MixInfo* MixContext::GetFinalMixInfo() { | ||
| 45 | return &mix_infos[0]; | ||
| 46 | } | ||
| 47 | |||
| 48 | s32 MixContext::GetCount() const { | ||
| 49 | return count; | ||
| 50 | } | ||
| 51 | |||
| 52 | void MixContext::UpdateDistancesFromFinalMix() { | ||
| 53 | for (s32 i = 0; i < count; i++) { | ||
| 54 | mix_infos[i].distance_from_final_mix = InvalidDistanceFromFinalMix; | ||
| 55 | } | ||
| 56 | |||
| 57 | for (s32 i = 0; i < count; i++) { | ||
| 58 | auto& mix_info{mix_infos[i]}; | ||
| 59 | sorted_mix_infos[i] = &mix_info; | ||
| 60 | |||
| 61 | if (!mix_info.in_use) { | ||
| 62 | continue; | ||
| 63 | } | ||
| 64 | |||
| 65 | auto mix_id{mix_info.mix_id}; | ||
| 66 | auto distance_to_final_mix{FinalMixId}; | ||
| 67 | |||
| 68 | while (distance_to_final_mix < count) { | ||
| 69 | if (mix_id == FinalMixId) { | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | |||
| 73 | if (mix_id == UnusedMixId) { | ||
| 74 | distance_to_final_mix = InvalidDistanceFromFinalMix; | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | |||
| 78 | auto distance_from_final_mix{mix_infos[mix_id].distance_from_final_mix}; | ||
| 79 | if (distance_from_final_mix != InvalidDistanceFromFinalMix) { | ||
| 80 | distance_to_final_mix = distance_from_final_mix + 1; | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | distance_to_final_mix++; | ||
| 85 | mix_id = mix_infos[mix_id].dst_mix_id; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (distance_to_final_mix >= count) { | ||
| 89 | distance_to_final_mix = InvalidDistanceFromFinalMix; | ||
| 90 | } | ||
| 91 | mix_info.distance_from_final_mix = distance_to_final_mix; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | void MixContext::SortInfo() { | ||
| 96 | UpdateDistancesFromFinalMix(); | ||
| 97 | |||
| 98 | std::ranges::sort(sorted_mix_infos, [](const MixInfo* lhs, const MixInfo* rhs) { | ||
| 99 | return lhs->distance_from_final_mix > rhs->distance_from_final_mix; | ||
| 100 | }); | ||
| 101 | |||
| 102 | CalcMixBufferOffset(); | ||
| 103 | } | ||
| 104 | |||
| 105 | void MixContext::CalcMixBufferOffset() { | ||
| 106 | s16 offset{0}; | ||
| 107 | for (s32 i = 0; i < count; i++) { | ||
| 108 | auto mix_info{sorted_mix_infos[i]}; | ||
| 109 | if (mix_info->in_use) { | ||
| 110 | const auto buffer_count{mix_info->buffer_count}; | ||
| 111 | mix_info->buffer_offset = offset; | ||
| 112 | offset += buffer_count; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | bool MixContext::TSortInfo(const SplitterContext& splitter_context) { | ||
| 118 | if (!splitter_context.UsingSplitter()) { | ||
| 119 | CalcMixBufferOffset(); | ||
| 120 | return true; | ||
| 121 | } | ||
| 122 | |||
| 123 | if (!node_states.Tsort(edge_matrix)) { | ||
| 124 | return false; | ||
| 125 | } | ||
| 126 | |||
| 127 | std::vector<s32> sorted_results{node_states.GetSortedResuls()}; | ||
| 128 | const auto result_size{std::min(count, static_cast<s32>(sorted_results.size()))}; | ||
| 129 | for (s32 i = 0; i < result_size; i++) { | ||
| 130 | sorted_mix_infos[i] = &mix_infos[sorted_results[i]]; | ||
| 131 | } | ||
| 132 | |||
| 133 | CalcMixBufferOffset(); | ||
| 134 | return true; | ||
| 135 | } | ||
| 136 | |||
| 137 | EdgeMatrix& MixContext::GetEdgeMatrix() { | ||
| 138 | return edge_matrix; | ||
| 139 | } | ||
| 140 | |||
| 141 | } // namespace AudioCore::AudioRenderer | ||
diff --git a/src/audio_core/renderer/mix/mix_context.h b/src/audio_core/renderer/mix/mix_context.h new file mode 100644 index 000000000..da3aa2829 --- /dev/null +++ b/src/audio_core/renderer/mix/mix_context.h | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <span> | ||
| 7 | |||
| 8 | #include "audio_core/renderer/mix/mix_info.h" | ||
| 9 | #include "audio_core/renderer/nodes/edge_matrix.h" | ||
| 10 | #include "audio_core/renderer/nodes/node_states.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | namespace AudioCore::AudioRenderer { | ||
| 14 | class SplitterContext; | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Manages mixing states, sorting and building a node graph to describe a mix order. | ||
| 18 | */ | ||
| 19 | class MixContext { | ||
| 20 | public: | ||
| 21 | /** | ||
| 22 | * Initialize the mix context. | ||
| 23 | * | ||
| 24 | * @param sorted_mix_infos - Buffer for the sorted mix infos. | ||
| 25 | * @param mix_infos - Buffer for the mix infos. | ||
| 26 | * @param effect_process_order_buffer - Buffer for the effect process orders. | ||
| 27 | * @param effect_count - Number of effects in the buffer. | ||
| 28 | * @param node_states_workbuffer - Buffer for node states. | ||
| 29 | * @param node_buffer_size - Size of the node states buffer. | ||
| 30 | * @param edge_matrix_workbuffer - Buffer for edge matrix. | ||
| 31 | * @param edge_matrix_size - Size of the edge matrix buffer. | ||
| 32 | */ | ||
| 33 | void Initialize(std::span<MixInfo*> sorted_mix_infos, std::span<MixInfo> mix_infos, u32 count_, | ||
| 34 | std::span<s32> effect_process_order_buffer, u32 effect_count, | ||
| 35 | std::span<u8> node_states_workbuffer, u64 node_buffer_size, | ||
| 36 | std::span<u8> edge_matrix_workbuffer, u64 edge_matrix_size); | ||
| 37 | |||
| 38 | /** | ||
| 39 | * Get a sorted mix at the given index. | ||
| 40 | * | ||
| 41 | * @param index - Index of sorted mix. | ||
| 42 | * @return The sorted mix. | ||
| 43 | */ | ||
| 44 | MixInfo* GetSortedInfo(s32 index); | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Set the sorted info at the given index. | ||
| 48 | * | ||
| 49 | * @param index - Index of sorted mix. | ||
| 50 | * @param mix_info - The new mix for this index. | ||
| 51 | */ | ||
| 52 | void SetSortedInfo(s32 index, MixInfo& mix_info); | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Get a mix at the given index. | ||
| 56 | * | ||
| 57 | * @param index - Index of mix. | ||
| 58 | * @return The mix. | ||
| 59 | */ | ||
| 60 | MixInfo* GetInfo(s32 index); | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Get the final mix. | ||
| 64 | * | ||
| 65 | * @return The final mix. | ||
| 66 | */ | ||
| 67 | MixInfo* GetFinalMixInfo(); | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Get the current number of mixes. | ||
| 71 | * | ||
| 72 | * @return The number of active mixes. | ||
| 73 | */ | ||
| 74 | s32 GetCount() const; | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Update all of the mixes' distance from the final mix. | ||
| 78 | * Needs to be called after altering the mix graph. | ||
| 79 | */ | ||
| 80 | void UpdateDistancesFromFinalMix(); | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Non-splitter sort, sorts the sorted mixes based on their distance from the final mix. | ||
| 84 | */ | ||
| 85 | void SortInfo(); | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Re-calculate the mix buffer offsets for each mix after altering the mix. | ||
| 89 | */ | ||
| 90 | void CalcMixBufferOffset(); | ||
| 91 | |||
| 92 | /** | ||
| 93 | * Splitter sort, traverse the splitter node graph and sort the sorted mixes from results. | ||
| 94 | * | ||
| 95 | * @param splitter_context - Splitter context for the sort. | ||
| 96 | * @return True if the sort was successful, othewise false. | ||
| 97 | */ | ||
| 98 | bool TSortInfo(const SplitterContext& splitter_context); | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Get the edge matrix used for the mix graph. | ||
| 102 | * | ||
| 103 | * @return The edge matrix used. | ||
| 104 | */ | ||
| 105 | EdgeMatrix& GetEdgeMatrix(); | ||
| 106 | |||
| 107 | private: | ||
| 108 | /// Array of sorted mixes | ||
| 109 | std::span<MixInfo*> sorted_mix_infos{}; | ||
| 110 | /// Array of mixes | ||
| 111 | std::span<MixInfo> mix_infos{}; | ||
| 112 | /// Number of active mixes | ||
| 113 | s32 count{}; | ||
| 114 | /// Array of effect process orderings | ||
| 115 | std::span<s32> effect_process_order_buffer{}; | ||
| 116 | /// Number of effects in the process ordering buffer | ||
| 117 | u64 effect_count{}; | ||
| 118 | /// Node states used in splitter sort | ||
| 119 | NodeStates node_states{}; | ||
| 120 | /// Edge matrix for connected nodes used in splitter sort | ||
| 121 | EdgeMatrix edge_matrix{}; | ||
| 122 | }; | ||
| 123 | |||
| 124 | } // namespace AudioCore::AudioRenderer | ||
diff --git a/src/audio_core/renderer/mix/mix_info.cpp b/src/audio_core/renderer/mix/mix_info.cpp new file mode 100644 index 000000000..cc18e57ee --- /dev/null +++ b/src/audio_core/renderer/mix/mix_info.cpp | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "audio_core/renderer/behavior/behavior_info.h" | ||
| 5 | #include "audio_core/renderer/effect/effect_context.h" | ||
| 6 | #include "audio_core/renderer/mix/mix_info.h" | ||
| 7 | #include "audio_core/renderer/nodes/edge_matrix.h" | ||
| 8 | #include "audio_core/renderer/splitter/splitter_context.h" | ||
| 9 | |||
| 10 | namespace AudioCore::AudioRenderer { | ||
| 11 | |||
| 12 | MixInfo::MixInfo(std::span<s32> effect_order_buffer_, s32 effect_count_, BehaviorInfo& behavior) | ||
| 13 | : effect_order_buffer{effect_order_buffer_}, effect_count{effect_count_}, | ||
| 14 | long_size_pre_delay_supported{behavior.IsLongSizePreDelaySupported()} { | ||
| 15 | ClearEffectProcessingOrder(); | ||
| 16 | } | ||
| 17 | |||
| 18 | void MixInfo::Cleanup() { | ||
| 19 | mix_id = UnusedMixId; | ||
| 20 | dst_mix_id = UnusedMixId; | ||
| 21 | dst_splitter_id = UnusedSplitterId; | ||
| 22 | } | ||
| 23 | |||
| 24 | void MixInfo::ClearEffectProcessingOrder() { | ||
| 25 | for (s32 i = 0; i < effect_count; i++) { | ||
| 26 | effect_order_buffer[i] = -1; | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | bool MixInfo::Update(EdgeMatrix& edge_matrix, const InParameter& in_params, | ||
| 31 | EffectContext& effect_context, SplitterContext& splitter_context, | ||
| 32 | const BehaviorInfo& behavior) { | ||
| 33 | volume = in_params.volume; | ||
| 34 | sample_rate = in_params.sample_rate; | ||
| 35 | buffer_count = static_cast<s16>(in_params.buffer_count); | ||
| 36 | in_use = in_params.in_use; | ||
| 37 | mix_id = in_params.mix_id; | ||
| 38 | node_id = in_params.node_id; | ||
| 39 | mix_volumes = in_params.mix_volumes; | ||
| 40 | |||
| 41 | bool sort_required{false}; | ||
| 42 | if (behavior.IsSplitterSupported()) { | ||
| 43 | sort_required = UpdateConnection(edge_matrix, in_params, splitter_context); | ||
| 44 | } else { | ||
| 45 | if (dst_mix_id != in_params.dest_mix_id) { | ||
| 46 | dst_mix_id = in_params.dest_mix_id; | ||
| 47 | sort_required = true; | ||
| 48 | } | ||
| 49 | dst_splitter_id = UnusedSplitterId; | ||
| 50 | } | ||
| 51 | |||
| 52 | ClearEffectProcessingOrder(); | ||
| 53 | |||
| 54 | // Check all effects, and set their order if they belong to this mix. | ||
| 55 | const auto count{effect_context.GetCount()}; | ||
| 56 | for (u32 i = 0; i < count; i++) { | ||
| 57 | const auto& info{effect_context.GetInfo(i)}; | ||
| 58 | if (mix_id == info.GetMixId()) { | ||
| 59 | const auto processing_order{info.GetProcessingOrder()}; | ||
| 60 | if (processing_order > effect_count) { | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | effect_order_buffer[processing_order] = i; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | return sort_required; | ||
| 68 | } | ||
| 69 | |||
| 70 | bool MixInfo::UpdateConnection(EdgeMatrix& edge_matrix, const InParameter& in_params, | ||
| 71 | SplitterContext& splitter_context) { | ||
| 72 | auto has_new_connection{false}; | ||
| 73 | if (dst_splitter_id != UnusedSplitterId) { | ||
| 74 | auto& splitter_info{splitter_context.GetInfo(dst_splitter_id)}; | ||
| 75 | has_new_connection = splitter_info.HasNewConnection(); | ||
| 76 | } | ||
| 77 | |||
| 78 | // Check if this mix matches the input parameters. | ||
| 79 | // If everything is the same, don't bother updating. | ||
| 80 | if (dst_mix_id == in_params.dest_mix_id && dst_splitter_id == in_params.dest_splitter_id && | ||
| 81 | !has_new_connection) { | ||
| 82 | return false; | ||
| 83 | } | ||
| 84 | |||
| 85 | // Reset the mix in the graph, as we're about to update it. | ||
| 86 | edge_matrix.RemoveEdges(mix_id); | ||
| 87 | |||
| 88 | if (in_params.dest_mix_id == UnusedMixId) { | ||
| 89 | if (in_params.dest_splitter_id != UnusedSplitterId) { | ||
| 90 | // If the splitter is used, connect this mix to each active destination. | ||
| 91 | auto& splitter_info{splitter_context.GetInfo(in_params.dest_splitter_id)}; | ||
| 92 | auto const destination_count{splitter_info.GetDestinationCount()}; | ||
| 93 | |||
| 94 | for (u32 i = 0; i < destination_count; i++) { | ||
| 95 | auto destination{ | ||
| 96 | splitter_context.GetDesintationData(in_params.dest_splitter_id, i)}; | ||
| 97 | |||
| 98 | if (destination) { | ||
| 99 | const auto destination_id{destination->GetMixId()}; | ||
| 100 | if (destination_id != UnusedMixId) { | ||
| 101 | edge_matrix.Connect(mix_id, destination_id); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } else { | ||
| 107 | // If the splitter is not used, only connect this mix to its destination. | ||
| 108 | edge_matrix.Connect(mix_id, in_params.dest_mix_id); | ||
| 109 | } | ||
| 110 | |||
| 111 | dst_mix_id = in_params.dest_mix_id; | ||
| 112 | dst_splitter_id = in_params.dest_splitter_id; | ||
| 113 | return true; | ||
| 114 | } | ||
| 115 | |||
| 116 | bool MixInfo::HasAnyConnection() const { | ||
| 117 | return dst_mix_id != UnusedMixId || dst_splitter_id != UnusedSplitterId; | ||
| 118 | } | ||
| 119 | |||
| 120 | } // namespace AudioCore::AudioRenderer | ||
diff --git a/src/audio_core/renderer/mix/mix_info.h b/src/audio_core/renderer/mix/mix_info.h new file mode 100644 index 000000000..b5fa4c0c7 --- /dev/null +++ b/src/audio_core/renderer/mix/mix_info.h | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | |||
| 9 | #include "audio_core/common/common.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | namespace AudioCore::AudioRenderer { | ||
| 13 | class EdgeMatrix; | ||
| 14 | class SplitterContext; | ||
| 15 | class EffectContext; | ||
| 16 | class BehaviorInfo; | ||
| 17 | |||
| 18 | /** | ||
| 19 | * A single mix, which may feed through other mixes in a chain until reaching the final output mix. | ||
| 20 | */ | ||
| 21 | class MixInfo { | ||
| 22 | public: | ||
| 23 | struct InParameter { | ||
| 24 | /* 0x000 */ f32 volume; | ||
| 25 | /* 0x004 */ u32 sample_rate; | ||
| 26 | /* 0x008 */ u32 buffer_count; | ||
| 27 | /* 0x00C */ bool in_use; | ||
| 28 | /* 0x00D */ bool is_dirty; | ||
| 29 | /* 0x010 */ s32 mix_id; | ||
| 30 | /* 0x014 */ u32 effect_count; | ||
| 31 | /* 0x018 */ s32 node_id; | ||
| 32 | /* 0x01C */ char unk01C[0x8]; | ||
| 33 | /* 0x024 */ std::array<std::array<f32, MaxMixBuffers>, MaxMixBuffers> mix_volumes; | ||
| 34 | /* 0x924 */ s32 dest_mix_id; | ||
| 35 | /* 0x928 */ s32 dest_splitter_id; | ||
| 36 | /* 0x92C */ char unk92C[0x4]; | ||
| 37 | }; | ||
| 38 | static_assert(sizeof(InParameter) == 0x930, "MixInfo::InParameter has the wrong size!"); | ||
| 39 | |||
| 40 | struct InDirtyParameter { | ||
| 41 | /* 0x00 */ u32 magic; | ||
| 42 | /* 0x04 */ s32 count; | ||
| 43 | /* 0x08 */ char unk08[0x18]; | ||
| 44 | }; | ||
| 45 | static_assert(sizeof(InDirtyParameter) == 0x20, | ||
| 46 | "MixInfo::InDirtyParameter has the wrong size!"); | ||
| 47 | |||
| 48 | MixInfo(std::span<s32> effect_order_buffer, s32 effect_count, BehaviorInfo& behavior); | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Clean up the mix, resetting it to a default state. | ||
| 52 | */ | ||
| 53 | void Cleanup(); | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Clear the effect process order for all effects in this mix. | ||
| 57 | */ | ||
| 58 | void ClearEffectProcessingOrder(); | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Update the mix according to the given parameters. | ||
| 62 | * | ||
| 63 | * @param edge_matrix - Updated with new splitter node connections, if supported. | ||
| 64 | * @param in_params - Input parameters. | ||
| 65 | * @param effect_context - Used to update the effect orderings. | ||
| 66 | * @param splitter_context - Used to update the mix graph if supported. | ||
| 67 | * @param behavior - Used for checking which features are supported. | ||
| 68 | * @return True if the mix was updated and a sort is required, otherwise false. | ||
| 69 | */ | ||
| 70 | bool Update(EdgeMatrix& edge_matrix, const InParameter& in_params, | ||
| 71 | EffectContext& effect_context, SplitterContext& splitter_context, | ||
| 72 | const BehaviorInfo& behavior); | ||
| 73 | |||
| 74 | /** | ||
| 75 | * Update the mix's connection in the node graph according to the given parameters. | ||
| 76 | * | ||
| 77 | * @param edge_matrix - Updated with new splitter node connections, if supported. | ||
| 78 | * @param in_params - Input parameters. | ||
| 79 | * @param splitter_context - Used to update the mix graph if supported. | ||
| 80 | * @return True if the mix was updated and a sort is required, otherwise false. | ||
| 81 | */ | ||
| 82 | bool UpdateConnection(EdgeMatrix& edge_matrix, const InParameter& in_params, | ||
| 83 | SplitterContext& splitter_context); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Check if this mix is connected to any other. | ||
| 87 | * | ||
| 88 | * @return True if the mix has a connection, otherwise false. | ||
| 89 | */ | ||
| 90 | bool HasAnyConnection() const; | ||
| 91 | |||
| 92 | /// Volume of this mix | ||
| 93 | f32 volume{}; | ||
| 94 | /// Sample rate of this mix | ||
| 95 | u32 sample_rate{}; | ||
| 96 | /// Number of buffers in this mix | ||
| 97 | s16 buffer_count{}; | ||
| 98 | /// Is this mix in use? | ||
| 99 | bool in_use{}; | ||
| 100 | /// Is this mix enabled? | ||
| 101 | bool enabled{}; | ||
| 102 | /// Id of this mix | ||
| 103 | s32 mix_id{UnusedMixId}; | ||
| 104 | /// Node id of this mix | ||
| 105 | s32 node_id{}; | ||
| 106 | /// Buffer offset for this mix | ||
| 107 | s16 buffer_offset{}; | ||
| 108 | /// Distance to the final mix | ||
| 109 | s32 distance_from_final_mix{InvalidDistanceFromFinalMix}; | ||
| 110 | /// Array of effect orderings of all effects in this mix | ||
| 111 | std::span<s32> effect_order_buffer; | ||
| 112 | /// Number of effects in this mix | ||
| 113 | const s32 effect_count; | ||
| 114 | /// Id for next mix in the chain | ||
| 115 | s32 dst_mix_id{UnusedMixId}; | ||
| 116 | /// Mixing volumes for this mix used when this mix is chained with another | ||
| 117 | std::array<std::array<f32, MaxMixBuffers>, MaxMixBuffers> mix_volumes{}; | ||
| 118 | /// Id for next mix in the graph when splitter is used | ||
| 119 | s32 dst_splitter_id{UnusedSplitterId}; | ||
| 120 | /// Is a longer pre-delay time supported for the reverb effect? | ||
| 121 | const bool long_size_pre_delay_supported; | ||
| 122 | }; | ||
| 123 | |||
| 124 | } // namespace AudioCore::AudioRenderer | ||