MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferManager.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "BufferSpec.hpp"
5
6namespace MayaFlux::Nodes {
7class Node;
8}
9
10namespace MayaFlux::Buffers {
11
12class BufferProcessor;
13class BufferProcessingChain;
14class TokenUnitManager;
15class BufferAccessControl;
16class BufferProcessingControl;
17class BufferInputControl;
18class BufferSupplyMixing;
19
20/**
21 * @class BufferManager
22 * @brief Token-based multimodal buffer management system for unified data stream processing
23 *
24 * BufferManager serves as the central orchestrator for buffer processing in the MayaFlux engine,
25 * implementing a token-based architecture that enables seamless integration of different processing
26 * domains while maintaining proven audio processing patterns.
27 *
28 * **Architecture:**
29 * - **Token-Based Routing**: Operations use tokens to route to appropriate units
30 * - **Unified Interface**: Most operations work generically across domains, no audio_/graphics_ prefixes needed
31 * - **Delegating Facade**: Thin delegation layer over functional helper classes
32 * - **Functional Helpers**: Encapsulate specific concerns (TokenUnitManager, BufferAccessControl, etc.)
33 *
34 * This design scales to new domains without API explosion—just add token support.
35 */
36class MAYAFLUX_API BufferManager {
37public:
38 /**
39 * @brief Creates a new multimodal buffer manager
40 * @param default_out_channels Number of output channels for the default domain (default: 2)
41 * @param default_in_channels Number of input channels for the default domain (default: 0)
42 * @param default_buffer_size Buffer size for the default domain (default: 512)
43 * @param default_processing_token Primary processing domain (default: AUDIO_BACKEND)
44 */
46 uint32_t default_out_channels = 2,
47 uint32_t default_in_channels = 0,
48 uint32_t default_buffer_size = 512,
49 ProcessingToken default_audio_token = ProcessingToken::AUDIO_BACKEND,
50 ProcessingToken default_graphics_token = ProcessingToken::GRAPHICS_BACKEND);
51
53
54 // =========================================================================
55 // Processing and Token Management
56 // =========================================================================
57
58 /**
59 * @brief Processes all buffers for a specific token
60 * @param token Processing domain to process
61 * @param processing_units Number of processing units (samples for audio, frames for video)
62 */
63 void process_token(ProcessingToken token, uint32_t processing_units);
64
65 /**
66 * @brief Processes all active tokens with their configured processing units
67 */
68 void process_all_tokens();
69
70 /**
71 * @brief Processes a specific channel within a token domain
72 * @param token Processing domain
73 * @param channel Channel index (audio-specific)
74 * @param processing_units Number of processing units to process
75 * @param node_output_data Optional output data from a node
76 */
77 void process_channel(
79 uint32_t channel,
80 uint32_t processing_units,
81 const std::vector<double>& node_output_data = {});
82
83 /**
84 * @brief Gets all currently active processing tokens
85 * @return Vector of tokens that have active buffers
86 */
87 [[nodiscard]] std::vector<ProcessingToken> get_active_tokens() const;
88
89 /**
90 * @brief Registers a custom processor for an audio token domain
91 * @param token Processing domain to handle
92 * @param processor Function that processes all channels for this domain
93 */
94 void register_audio_token_processor(ProcessingToken token, RootAudioProcessingFunction processor);
95
96 /**
97 * @brief Gets the default processing token used by the manager
98 */
99 [[nodiscard]] ProcessingToken get_default_audio_token() const;
100
101 // =========================================================================
102 // Buffer Access (Token-Generic)
103 // =========================================================================
104
105 /**
106 * @brief Gets a root buffer for a specific token and channel (audio-specific due to channels)
107 * @param token Processing domain
108 * @param channel Channel index
109 * @return Shared pointer to the root audio buffer
110 */
111 std::shared_ptr<RootAudioBuffer> get_root_audio_buffer(
113 uint32_t channel = 0);
114
115 /**
116 * @brief Gets a root graphics buffer for a specific token
117 * @param token Processing domain
118 * @return Shared pointer to the root graphics buffer
119 */
120 std::shared_ptr<RootGraphicsBuffer> get_root_graphics_buffer(
122
123 /**
124 * @brief Gets data from a specific token and channel (audio-specific)
125 * @param token Processing domain
126 * @param channel Channel index
127 * @return Reference to the channel's data vector
128 */
129 std::vector<double>& get_buffer_data(ProcessingToken token, uint32_t channel);
130 [[nodiscard]] const std::vector<double>& get_buffer_data(ProcessingToken token, uint32_t channel) const;
131
132 /**
133 * @brief Gets the number of channels for a token (audio-specific)
134 * @param token Processing domain
135 * @return Number of channels
136 */
137 [[nodiscard]] uint32_t get_num_channels(ProcessingToken token) const;
138
139 /**
140 * @brief Gets the buffer size for a token
141 * @param token Processing domain
142 * @return Buffer size in processing units
143 */
144 [[nodiscard]] uint32_t get_buffer_size(ProcessingToken token) const;
145
146 /**
147 * @brief Resizes buffers for a token
148 * @param token Processing domain
149 * @param buffer_size New buffer size
150 */
151 void resize_buffers(ProcessingToken token, uint32_t buffer_size);
152
153 /**
154 * @brief Ensures minimum number of channels exist for an audio token
155 * @param token Processing domain
156 * @param channel_count Minimum number of channels
157 */
158 void ensure_channels(ProcessingToken token, uint32_t channel_count);
159
160 /**
161 * @brief Validates the number of channels and resizes buffers if necessary (audio-specific)
162 * @param token Processing domain
163 * @param num_channels Number of channels to validate
164 * @param buffer_size New buffer size to set
165 *
166 * This method ensures that the specified number of channels exists for the given token,
167 * resizing the root audio buffers accordingly.
168 */
169 void validate_num_channels(ProcessingToken token, uint32_t num_channels, uint32_t buffer_size)
170 {
171 ensure_channels(token, num_channels);
172 resize_buffers(token, buffer_size);
173 }
174
175 /**
176 * @brief Gets the processing chain for a token and channel (audio-specific)
177 * @param token Processing domain
178 * @param channel Channel index
179 * @return Shared pointer to the processing chain
180 */
181 std::shared_ptr<BufferProcessingChain> get_processing_chain(ProcessingToken token, uint32_t channel);
182
183 /**
184 * @brief Gets the global processing chain (applied to all tokens)
185 * @return Shared pointer to the global processing chain
186 */
187 std::shared_ptr<BufferProcessingChain> get_global_processing_chain();
188
189 // =========================================================================
190 // Buffer Management (Token-Generic via Dynamic Dispatch)
191 // =========================================================================
192
193 /**
194 * @brief Adds a buffer to a token and channel
195 * @param buffer Buffer to add (AudioBuffer or VKBuffer depending on token)
196 * @param token Processing domain
197 * @param channel Channel index (optional, used for audio)
198 */
199 void add_buffer(
200 const std::shared_ptr<Buffer>& buffer,
202 uint32_t channel = 0);
203
204 /**
205 * @brief Removes a buffer from a token
206 * @param buffer Buffer to remove
207 * @param token Processing domain
208 * @param channel Channel index (optional, used for audio)
209 */
210 void remove_buffer(
211 const std::shared_ptr<Buffer>& buffer,
213 uint32_t channel = 0);
214
215 /**
216 * @brief Gets buffers for a token (audio-specific due to channels)
217 * @param token Processing domain
218 * @param channel Channel index
219 * @return Const reference to vector of buffers
220 */
221 [[nodiscard]] const std::vector<std::shared_ptr<AudioBuffer>>& get_buffers(ProcessingToken token, uint32_t channel) const;
222
223 /**
224 * @brief Gets graphics buffers for a token
225 * @param token Processing domain
226 * @return Const reference to vector of VKBuffers
227 */
228 [[nodiscard]] const std::vector<std::shared_ptr<VKBuffer>>& get_graphics_buffers(ProcessingToken token) const;
229
230 /**
231 * @brief Gets graphics buffers filtered by usage
232 * @param usage VKBuffer usage type
233 * @param token Processing domain
234 * @return Vector of matching buffers
235 */
236 [[nodiscard]] std::vector<std::shared_ptr<VKBuffer>> get_buffers_by_usage(
237 VKBuffer::Usage usage,
238 ProcessingToken token) const;
239
240 /**
241 * @brief Creates a specialized audio buffer and adds it to the specified token/channel
242 * @tparam BufferType Type of buffer to create (must be compatible with token)
243 * @tparam Args Constructor argument types
244 * @param token Processing domain
245 * @param channel Channel index
246 * @param args Constructor arguments
247 * @return Shared pointer to the created buffer
248 */
249 template <typename BufferType, typename... Args>
250 std::shared_ptr<BufferType> create_audio_buffer(ProcessingToken token, uint32_t channel, Args&&... args)
251 {
252 auto& unit = m_unit_manager->ensure_and_get_audio_unit(token, channel);
253 auto buffer = std::make_shared<BufferType>(channel, unit.buffer_size, std::forward<Args>(args)...);
254
255 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
256 add_buffer(audio_buffer, token, channel);
257 }
258
259 return buffer;
260 }
261
262 /**
263 * @brief Creates a specialized vulkan buffer and adds it to the specified token/channel
264 * @tparam BufferType Type of buffer to create (must be compatible with token)
265 * @tparam Args Constructor argument types
266 * @param token Processing domain
267 * @param args Constructor arguments
268 * @return Shared pointer to the created buffer
269 */
270 template <typename BufferType, typename... Args>
271 std::shared_ptr<BufferType> create_graphics_buffer(ProcessingToken token, Args&&... args)
272 {
273 auto& unit = m_unit_manager->get_or_create_graphics_unit(token);
274 auto buffer = std::make_shared<BufferType>(std::forward<Args>(args)...);
275
276 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
277 add_buffer(vk_buffer, token);
278 }
279
280 return buffer;
281 }
282
283 // =========================================================================
284 // Processor Management (Token-Generic)
285 // =========================================================================
286
287 /**
288 * @brief Adds a processor to a buffer
289 * @param processor Processor to add
290 * @param buffer Target buffer (dispatches based on type)
291 */
292 void add_processor(
293 const std::shared_ptr<BufferProcessor>& processor,
294 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::AUDIO_BACKEND);
295
296 /**
297 * @brief Adds a processor to a token and channel (audio-specific)
298 * @param processor Processor to add
299 * @param token Processing domain
300 * @param channel Channel index
301 */
302 void add_processor(
303 const std::shared_ptr<BufferProcessor>& processor,
305 uint32_t channel);
306
307 /**
308 * @brief Adds a processor to all channels in a token (audio-specific)
309 * @param processor Processor to add
310 * @param token Processing domain
311 */
312 void add_processor(
313 const std::shared_ptr<BufferProcessor>& processor,
315
316 /**
317 * @brief Removes a processor from a buffer
318 * @param processor Processor to remove
319 * @param buffer Target buffer
320 */
321 void remove_processor(
322 const std::shared_ptr<BufferProcessor>& processor,
323 const std::shared_ptr<Buffer>& buffer);
324
325 /**
326 * @brief Removes a processor from a token and channel (audio-specific)
327 * @param processor Processor to remove
328 * @param token Processing domain
329 * @param channel Channel index
330 */
331 void remove_processor_from_channel(
332 const std::shared_ptr<BufferProcessor>& processor,
334 uint32_t channel);
335
336 /**
337 * @brief Removes a processor from all channels in a token (audio-specific)
338 * @param processor Processor to remove
339 * @param token Processing domain
340 */
341 void remove_processor_from_token(
342 const std::shared_ptr<BufferProcessor>& processor,
344
345 /**
346 * @brief Sets a final processor for a token (audio-specific)
347 * @param processor Final processor to apply
348 * @param token Processing domain
349 */
350 void set_final_processor(
351 const std::shared_ptr<BufferProcessor>& processor,
353
354 // =========================================================================
355 // Quick Processing (Audio-Specific)
356 // =========================================================================
357
358 std::shared_ptr<BufferProcessor> attach_quick_process(
359 BufferProcessingFunction processor,
360 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::AUDIO_BACKEND);
361
362 std::shared_ptr<BufferProcessor> attach_quick_process(
363 BufferProcessingFunction processor,
365 uint32_t channel);
366
367 std::shared_ptr<BufferProcessor> attach_quick_process(
368 BufferProcessingFunction processor,
370
371 // =========================================================================
372 // Node Connection (Audio-Specific)
373 // =========================================================================
374
376 const std::shared_ptr<Nodes::Node>& node,
378 uint32_t channel,
379 float mix = 0.5F,
380 bool clear_before = false);
381
383 const std::shared_ptr<Nodes::Node>& node,
384 const std::shared_ptr<AudioBuffer>& buffer,
385 float mix = 0.5F,
386 bool clear_before = true);
387
388 // =========================================================================
389 // Data I/O (Audio-Specific)
390 // =========================================================================
391
392 void fill_from_interleaved(
393 const double* interleaved_data,
394 uint32_t num_frames,
396 uint32_t num_channels);
397
398 void fill_interleaved(
399 double* interleaved_data,
400 uint32_t num_frames,
402 uint32_t num_channels) const;
403
404 std::vector<std::shared_ptr<AudioBuffer>> clone_buffer_for_channels(
405 const std::shared_ptr<AudioBuffer>& buffer,
406 const std::vector<uint32_t>& channels,
408
409 // =========================================================================
410 // Input Handling (Audio-Specific)
411 // =========================================================================
412
413 void process_input(double* input_data, uint32_t num_channels, uint32_t num_frames);
414
415 void register_input_listener(const std::shared_ptr<AudioBuffer>& buffer, uint32_t channel);
416
417 void unregister_input_listener(const std::shared_ptr<AudioBuffer>& buffer, uint32_t channel);
418
419 // =========================================================================
420 // Buffer Supply/Mixing (Audio-Specific)
421 // =========================================================================
422
423 bool supply_buffer_to(
424 const std::shared_ptr<AudioBuffer>& buffer,
426 uint32_t channel,
427 double mix = 1.0);
428
429 bool remove_supplied_buffer(
430 const std::shared_ptr<AudioBuffer>& buffer,
432 uint32_t channel);
433
434 // =========================================================================
435 // Utility
436 // =========================================================================
437
438 void initialize_buffer_service();
439
440 /**
441 * @brief Terminates all active buffers, clearing their data
442 */
443 void terminate_active_buffers();
444
445private:
446 void process_audio_token_default(ProcessingToken token, uint32_t processing_units);
447
448 void process_graphics_token_default(ProcessingToken token, uint32_t processing_units);
449
450 /// Token/unit storage and lifecycle
451 std::unique_ptr<TokenUnitManager> m_unit_manager;
452
453 /// Buffer and unit access operations
454 std::unique_ptr<BufferAccessControl> m_access_control;
455
456 /// Processor attachment/removal operations
457 std::unique_ptr<BufferProcessingControl> m_processor_control;
458
459 /// Audio input management
460 std::unique_ptr<BufferInputControl> m_input_control;
461
462 /// Buffer supply and mixing operations
463 std::unique_ptr<BufferSupplyMixing> m_supply_mixing;
464
465 /// Global processing chain applied to all tokens
466 std::shared_ptr<BufferProcessingChain> m_global_processing_chain;
467};
468
469} // namespace MayaFlux::Buffers
static MayaFlux::Nodes::ProcessingToken token
Definition Timers.cpp:8
std::shared_ptr< BufferProcessingChain > m_global_processing_chain
Global processing chain applied to all tokens.
std::unique_ptr< TokenUnitManager > m_unit_manager
Token/unit storage and lifecycle.
std::shared_ptr< BufferType > create_graphics_buffer(ProcessingToken token, Args &&... args)
Creates a specialized vulkan buffer and adds it to the specified token/channel.
std::unique_ptr< BufferInputControl > m_input_control
Audio input management.
std::unique_ptr< BufferProcessingControl > m_processor_control
Processor attachment/removal operations.
void validate_num_channels(ProcessingToken token, uint32_t num_channels, uint32_t buffer_size)
Validates the number of channels and resizes buffers if necessary (audio-specific)
std::shared_ptr< BufferType > create_audio_buffer(ProcessingToken token, uint32_t channel, Args &&... args)
Creates a specialized audio buffer and adds it to the specified token/channel.
std::unique_ptr< BufferSupplyMixing > m_supply_mixing
Buffer supply and mixing operations.
std::unique_ptr< BufferAccessControl > m_access_control
Buffer and unit access operations.
Token-based multimodal buffer management system for unified data stream processing.
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
std::variant< AudioProcessingFunction, GraphicsProcessingFunction > BufferProcessingFunction
std::function< void(std::vector< std::shared_ptr< RootAudioBuffer > > &, uint32_t)> RootAudioProcessingFunction
Contains the node-based computational processing system components.
Definition Chronie.hpp:5
void connect_node_to_buffer(const std::shared_ptr< Nodes::Node > &node, const std::shared_ptr< Buffers::AudioBuffer > &buffer, float mix, bool clear_before)
Connects a node to a specific buffer.
Definition Graph.cpp:117
void add_processor(const std::shared_ptr< Buffers::BufferProcessor > &processor, const std::shared_ptr< Buffers::Buffer > &buffer, Buffers::ProcessingToken token)
Adds a processor to a specific buffer.
Definition Graph.cpp:86
Buffers::RootAudioBuffer & get_root_audio_buffer(uint32_t channel)
Gets the audio buffer for a specific channel.
Definition Graph.cpp:106
std::shared_ptr< Buffers::BufferProcessor > attach_quick_process(Buffers::BufferProcessingFunction processor, const std::shared_ptr< Buffers::AudioBuffer > &buffer)
Attaches a processing function to a specific buffer.
Definition Graph.cpp:140
void connect_node_to_channel(const std::shared_ptr< Nodes::Node > &node, uint32_t channel_index, float mix, bool clear_before)
Connects a node to a specific output channel.
Definition Graph.cpp:111