mix_context.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <ranges>
  4. #include "audio_core/renderer/mix/mix_context.h"
  5. #include "audio_core/renderer/splitter/splitter_context.h"
  6. #include "common/polyfill_ranges.h"
  7. namespace AudioCore::AudioRenderer {
  8. void MixContext::Initialize(std::span<MixInfo*> sorted_mix_infos_, std::span<MixInfo> mix_infos_,
  9. const u32 count_, std::span<s32> effect_process_order_buffer_,
  10. const u32 effect_count_, std::span<u8> node_states_workbuffer,
  11. const u64 node_buffer_size, std::span<u8> edge_matrix_workbuffer,
  12. const u64 edge_matrix_size) {
  13. count = count_;
  14. sorted_mix_infos = sorted_mix_infos_;
  15. mix_infos = mix_infos_;
  16. effect_process_order_buffer = effect_process_order_buffer_;
  17. effect_count = effect_count_;
  18. if (node_states_workbuffer.size() > 0 && edge_matrix_workbuffer.size() > 0) {
  19. node_states.Initialize(node_states_workbuffer, node_buffer_size, count);
  20. edge_matrix.Initialize(edge_matrix_workbuffer, edge_matrix_size, count);
  21. }
  22. for (s32 i = 0; i < count; i++) {
  23. sorted_mix_infos[i] = &mix_infos[i];
  24. }
  25. }
  26. MixInfo* MixContext::GetSortedInfo(const s32 index) {
  27. return sorted_mix_infos[index];
  28. }
  29. void MixContext::SetSortedInfo(const s32 index, MixInfo& mix_info) {
  30. sorted_mix_infos[index] = &mix_info;
  31. }
  32. MixInfo* MixContext::GetInfo(const s32 index) {
  33. return &mix_infos[index];
  34. }
  35. MixInfo* MixContext::GetFinalMixInfo() {
  36. return &mix_infos[0];
  37. }
  38. s32 MixContext::GetCount() const {
  39. return count;
  40. }
  41. void MixContext::UpdateDistancesFromFinalMix() {
  42. for (s32 i = 0; i < count; i++) {
  43. mix_infos[i].distance_from_final_mix = InvalidDistanceFromFinalMix;
  44. }
  45. for (s32 i = 0; i < count; i++) {
  46. auto& mix_info{mix_infos[i]};
  47. sorted_mix_infos[i] = &mix_info;
  48. if (!mix_info.in_use) {
  49. continue;
  50. }
  51. auto mix_id{mix_info.mix_id};
  52. auto distance_to_final_mix{FinalMixId};
  53. while (distance_to_final_mix < count) {
  54. if (mix_id == FinalMixId) {
  55. break;
  56. }
  57. if (mix_id == UnusedMixId) {
  58. distance_to_final_mix = InvalidDistanceFromFinalMix;
  59. break;
  60. }
  61. auto distance_from_final_mix{mix_infos[mix_id].distance_from_final_mix};
  62. if (distance_from_final_mix != InvalidDistanceFromFinalMix) {
  63. distance_to_final_mix = distance_from_final_mix + 1;
  64. break;
  65. }
  66. distance_to_final_mix++;
  67. mix_id = mix_infos[mix_id].dst_mix_id;
  68. }
  69. if (distance_to_final_mix >= count) {
  70. distance_to_final_mix = InvalidDistanceFromFinalMix;
  71. }
  72. mix_info.distance_from_final_mix = distance_to_final_mix;
  73. }
  74. }
  75. void MixContext::SortInfo() {
  76. UpdateDistancesFromFinalMix();
  77. std::ranges::sort(sorted_mix_infos, [](const MixInfo* lhs, const MixInfo* rhs) {
  78. return lhs->distance_from_final_mix > rhs->distance_from_final_mix;
  79. });
  80. CalcMixBufferOffset();
  81. }
  82. void MixContext::CalcMixBufferOffset() {
  83. s16 offset{0};
  84. for (s32 i = 0; i < count; i++) {
  85. auto mix_info{sorted_mix_infos[i]};
  86. if (mix_info->in_use) {
  87. const auto buffer_count{mix_info->buffer_count};
  88. mix_info->buffer_offset = offset;
  89. offset += buffer_count;
  90. }
  91. }
  92. }
  93. bool MixContext::TSortInfo(const SplitterContext& splitter_context) {
  94. if (!splitter_context.UsingSplitter()) {
  95. CalcMixBufferOffset();
  96. return true;
  97. }
  98. if (!node_states.Tsort(edge_matrix)) {
  99. return false;
  100. }
  101. std::vector<s32> sorted_results{node_states.GetSortedResuls()};
  102. const auto result_size{std::min(count, static_cast<s32>(sorted_results.size()))};
  103. for (s32 i = 0; i < result_size; i++) {
  104. sorted_mix_infos[i] = &mix_infos[sorted_results[i]];
  105. }
  106. CalcMixBufferOffset();
  107. return true;
  108. }
  109. EdgeMatrix& MixContext::GetEdgeMatrix() {
  110. return edge_matrix;
  111. }
  112. } // namespace AudioCore::AudioRenderer