splitter_context.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <stack>
  6. #include <vector>
  7. #include "audio_core/common.h"
  8. #include "common/common_funcs.h"
  9. #include "common/common_types.h"
  10. #include "common/swap.h"
  11. namespace AudioCore {
  12. class BehaviorInfo;
  13. class EdgeMatrix {
  14. public:
  15. EdgeMatrix();
  16. ~EdgeMatrix();
  17. void Initialize(std::size_t _node_count);
  18. bool Connected(s32 a, s32 b);
  19. void Connect(s32 a, s32 b);
  20. void Disconnect(s32 a, s32 b);
  21. void RemoveEdges(s32 edge);
  22. std::size_t GetNodeCount() const;
  23. private:
  24. void SetState(s32 a, s32 b, bool state);
  25. bool GetState(s32 a, s32 b);
  26. bool InRange(s32 a, s32 b) const;
  27. std::vector<bool> edge_matrix{};
  28. std::size_t node_count{};
  29. };
  30. class NodeStates {
  31. public:
  32. enum class State {
  33. NoState = 0,
  34. InFound = 1,
  35. InCompleted = 2,
  36. };
  37. // Looks to be a fixed size stack. Placed within the NodeStates class based on symbols
  38. class Stack {
  39. public:
  40. Stack();
  41. ~Stack();
  42. void Reset(std::size_t size);
  43. void push(s32 val);
  44. std::size_t Count() const;
  45. s32 top() const;
  46. s32 pop();
  47. private:
  48. std::vector<s32> stack{};
  49. std::size_t stack_size{};
  50. std::size_t stack_pos{};
  51. };
  52. NodeStates();
  53. ~NodeStates();
  54. void Initialize(std::size_t node_count_);
  55. bool Tsort(EdgeMatrix& edge_matrix);
  56. std::size_t GetIndexPos() const;
  57. const std::vector<s32>& GetIndexList() const;
  58. private:
  59. void PushTsortResult(s32 index);
  60. bool DepthFirstSearch(EdgeMatrix& edge_matrix);
  61. void ResetState();
  62. void UpdateState(State state, std::size_t i);
  63. State GetState(std::size_t i);
  64. std::size_t node_count{};
  65. std::vector<bool> was_node_found{};
  66. std::vector<bool> was_node_completed{};
  67. std::size_t index_pos{};
  68. std::vector<s32> index_list{};
  69. Stack index_stack{};
  70. };
  71. enum class SplitterMagic : u32_le {
  72. SplitterHeader = Common::MakeMagic('S', 'N', 'D', 'H'),
  73. DataHeader = Common::MakeMagic('S', 'N', 'D', 'D'),
  74. InfoHeader = Common::MakeMagic('S', 'N', 'D', 'I'),
  75. };
  76. class SplitterInfo {
  77. public:
  78. struct InHeader {
  79. SplitterMagic magic{};
  80. s32_le info_count{};
  81. s32_le data_count{};
  82. INSERT_PADDING_WORDS(5);
  83. };
  84. static_assert(sizeof(InHeader) == 0x20, "SplitterInfo::InHeader is an invalid size");
  85. struct InInfoPrams {
  86. SplitterMagic magic{};
  87. s32_le send_id{};
  88. s32_le sample_rate{};
  89. s32_le length{};
  90. s32_le resource_id_base{};
  91. };
  92. static_assert(sizeof(InInfoPrams) == 0x14, "SplitterInfo::InInfoPrams is an invalid size");
  93. struct InDestinationParams {
  94. SplitterMagic magic{};
  95. s32_le splitter_id{};
  96. std::array<float_le, AudioCommon::MAX_MIX_BUFFERS> mix_volumes{};
  97. s32_le mix_id{};
  98. bool in_use{};
  99. INSERT_PADDING_BYTES(3);
  100. };
  101. static_assert(sizeof(InDestinationParams) == 0x70,
  102. "SplitterInfo::InDestinationParams is an invalid size");
  103. };
  104. class ServerSplitterDestinationData {
  105. public:
  106. explicit ServerSplitterDestinationData(s32 id_);
  107. ~ServerSplitterDestinationData();
  108. void Update(SplitterInfo::InDestinationParams& header);
  109. ServerSplitterDestinationData* GetNextDestination();
  110. const ServerSplitterDestinationData* GetNextDestination() const;
  111. void SetNextDestination(ServerSplitterDestinationData* dest);
  112. bool ValidMixId() const;
  113. s32 GetMixId() const;
  114. bool IsConfigured() const;
  115. float GetMixVolume(std::size_t i) const;
  116. const std::array<float, AudioCommon::MAX_MIX_BUFFERS>& CurrentMixVolumes() const;
  117. const std::array<float, AudioCommon::MAX_MIX_BUFFERS>& LastMixVolumes() const;
  118. void MarkDirty();
  119. void UpdateInternalState();
  120. private:
  121. bool needs_update{};
  122. bool in_use{};
  123. s32 id{};
  124. s32 mix_id{};
  125. std::array<float, AudioCommon::MAX_MIX_BUFFERS> current_mix_volumes{};
  126. std::array<float, AudioCommon::MAX_MIX_BUFFERS> last_mix_volumes{};
  127. ServerSplitterDestinationData* next = nullptr;
  128. };
  129. class ServerSplitterInfo {
  130. public:
  131. explicit ServerSplitterInfo(s32 id_);
  132. ~ServerSplitterInfo();
  133. void InitializeInfos();
  134. void ClearNewConnectionFlag();
  135. std::size_t Update(SplitterInfo::InInfoPrams& header);
  136. ServerSplitterDestinationData* GetHead();
  137. const ServerSplitterDestinationData* GetHead() const;
  138. ServerSplitterDestinationData* GetData(std::size_t depth);
  139. const ServerSplitterDestinationData* GetData(std::size_t depth) const;
  140. bool HasNewConnection() const;
  141. s32 GetLength() const;
  142. void SetHead(ServerSplitterDestinationData* new_head);
  143. void SetHeadDepth(s32 length);
  144. private:
  145. s32 sample_rate{};
  146. s32 id{};
  147. s32 send_length{};
  148. ServerSplitterDestinationData* head = nullptr;
  149. bool new_connection{};
  150. };
  151. class SplitterContext {
  152. public:
  153. SplitterContext();
  154. ~SplitterContext();
  155. void Initialize(BehaviorInfo& behavior_info, std::size_t splitter_count,
  156. std::size_t data_count);
  157. bool Update(const std::vector<u8>& input, std::size_t& input_offset, std::size_t& bytes_read);
  158. bool UsingSplitter() const;
  159. ServerSplitterInfo& GetInfo(std::size_t i);
  160. const ServerSplitterInfo& GetInfo(std::size_t i) const;
  161. ServerSplitterDestinationData& GetData(std::size_t i);
  162. const ServerSplitterDestinationData& GetData(std::size_t i) const;
  163. ServerSplitterDestinationData* GetDestinationData(std::size_t info, std::size_t data);
  164. const ServerSplitterDestinationData* GetDestinationData(std::size_t info,
  165. std::size_t data) const;
  166. void UpdateInternalState();
  167. std::size_t GetInfoCount() const;
  168. std::size_t GetDataCount() const;
  169. private:
  170. void Setup(std::size_t info_count, std::size_t data_count, bool is_splitter_bug_fixed);
  171. bool UpdateInfo(const std::vector<u8>& input, std::size_t& input_offset,
  172. std::size_t& bytes_read, s32 in_splitter_count);
  173. bool UpdateData(const std::vector<u8>& input, std::size_t& input_offset,
  174. std::size_t& bytes_read, s32 in_data_count);
  175. bool RecomposeDestination(ServerSplitterInfo& info, SplitterInfo::InInfoPrams& header,
  176. const std::vector<u8>& input, const std::size_t& input_offset);
  177. std::vector<ServerSplitterInfo> infos{};
  178. std::vector<ServerSplitterDestinationData> datas{};
  179. std::size_t info_count{};
  180. std::size_t data_count{};
  181. bool bug_fixed{};
  182. };
  183. } // namespace AudioCore