MayaFlux 0.3.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_sample_rate Sample rate for the default domain (default: 48000)
43 * @param default_buffer_size Buffer size for the default domain (default: 512)
44 * @param default_processing_token Primary processing domain (default: AUDIO_BACKEND)
45 */
47 uint32_t default_out_channels = 2,
48 uint32_t default_in_channels = 0,
49 uint64_t default_sample_rate = 48000,
50 uint32_t default_buffer_size = 512,
51 ProcessingToken default_audio_token = ProcessingToken::AUDIO_BACKEND,
52 ProcessingToken default_graphics_token = ProcessingToken::GRAPHICS_BACKEND);
53
55
56 // =========================================================================
57 // Processing and Token Management
58 // =========================================================================
59
60 /**
61 * @brief Processes all buffers for a specific token
62 * @param token Processing domain to process
63 * @param processing_units Number of processing units (samples for audio, frames for video)
64 */
65 void process_token(ProcessingToken token, uint32_t processing_units);
66
67 /**
68 * @brief Processes all active tokens with their configured processing units
69 */
70 void process_all_tokens();
71
72 /**
73 * @brief Processes a specific channel within a token domain
74 * @param token Processing domain
75 * @param channel Channel index (audio-specific)
76 * @param processing_units Number of processing units to process
77 * @param node_output_data Optional output data from a node
78 */
79 void process_channel(
80 ProcessingToken token,
81 uint32_t channel,
82 uint32_t processing_units,
83 const std::vector<double>& node_output_data = {});
84
85 /**
86 * @brief Gets all currently active processing tokens
87 * @return Vector of tokens that have active buffers
88 */
89 [[nodiscard]] std::vector<ProcessingToken> get_active_tokens() const;
90
91 /**
92 * @brief Registers a custom processor for an audio token domain
93 * @param token Processing domain to handle
94 * @param processor Function that processes all channels for this domain
95 */
96 void register_audio_token_processor(ProcessingToken token, RootAudioProcessingFunction processor);
97
98 /**
99 * @brief Gets the default processing token used by the manager
100 */
101 [[nodiscard]] ProcessingToken get_default_audio_token() const;
102
103 // =========================================================================
104 // Buffer Access (Token-Generic)
105 // =========================================================================
106
107 /**
108 * @brief Gets a root buffer for a specific token and channel (audio-specific due to channels)
109 * @param token Processing domain
110 * @param channel Channel index
111 * @return Shared pointer to the root audio buffer
112 */
113 std::shared_ptr<RootAudioBuffer> get_root_audio_buffer(
114 ProcessingToken token,
115 uint32_t channel = 0);
116
117 /**
118 * @brief Gets a root graphics buffer for a specific token
119 * @param token Processing domain
120 * @return Shared pointer to the root graphics buffer
121 */
122 std::shared_ptr<RootGraphicsBuffer> get_root_graphics_buffer(
123 ProcessingToken token);
124
125 /**
126 * @brief Gets data from a specific token and channel (audio-specific)
127 * @param token Processing domain
128 * @param channel Channel index
129 * @return Reference to the channel's data vector
130 */
131 std::vector<double>& get_buffer_data(ProcessingToken token, uint32_t channel);
132 [[nodiscard]] const std::vector<double>& get_buffer_data(ProcessingToken token, uint32_t channel) const;
133
134 /**
135 * @brief Gets the number of channels for a token (audio-specific)
136 * @param token Processing domain
137 * @return Number of channels
138 */
139 [[nodiscard]] uint32_t get_num_channels(ProcessingToken token) const;
140
141 /**
142 * @brief Gets the buffer size for a token
143 * @param token Processing domain
144 * @return Buffer size in processing units
145 */
146 [[nodiscard]] uint32_t get_buffer_size(ProcessingToken token) const;
147
148 /**
149 * @brief Resizes buffers for a token
150 * @param token Processing domain
151 * @param buffer_size New buffer size
152 */
153 void resize_buffers(ProcessingToken token, uint32_t buffer_size);
154
155 /**
156 * @brief Ensures minimum number of channels exist for an audio token
157 * @param token Processing domain
158 * @param channel_count Minimum number of channels
159 */
160 void ensure_channels(ProcessingToken token, uint32_t channel_count);
161
162 /**
163 * @brief Validates the number of channels and resizes buffers if necessary (audio-specific)
164 * @param token Processing domain
165 * @param num_channels Number of channels to validate
166 * @param buffer_size New buffer size to set
167 *
168 * This method ensures that the specified number of channels exists for the given token,
169 * resizing the root audio buffers accordingly.
170 */
171 void validate_num_channels(ProcessingToken token, uint32_t num_channels, uint32_t buffer_size)
172 {
173 ensure_channels(token, num_channels);
174 resize_buffers(token, buffer_size);
175 }
176
177 /**
178 * @brief Gets the processing chain for a token and channel (audio-specific)
179 * @param token Processing domain
180 * @param channel Channel index
181 * @return Shared pointer to the processing chain
182 */
183 std::shared_ptr<BufferProcessingChain> get_processing_chain(ProcessingToken token, uint32_t channel);
184
185 /**
186 * @brief Gets the global processing chain (applied to all tokens)
187 * @return Shared pointer to the global processing chain
188 */
189 std::shared_ptr<BufferProcessingChain> get_global_processing_chain();
190
191 // =========================================================================
192 // Buffer Management (Token-Generic via Dynamic Dispatch)
193 // =========================================================================
194
195 /**
196 * @brief Adds a buffer to a token and channel
197 * @param buffer Buffer to add (AudioBuffer or VKBuffer depending on token)
198 * @param token Processing domain
199 * @param channel Channel index (optional, used for audio)
200 */
201 void add_buffer(
202 const std::shared_ptr<Buffer>& buffer,
203 ProcessingToken token,
204 uint32_t channel = 0);
205
206 /**
207 * @brief Removes a buffer from a token
208 * @param buffer Buffer to remove
209 * @param token Processing domain
210 * @param channel Channel index (optional, used for audio)
211 */
212 void remove_buffer(
213 const std::shared_ptr<Buffer>& buffer,
214 ProcessingToken token,
215 uint32_t channel = 0);
216
217 /**
218 * @brief Gets buffers for a token (audio-specific due to channels)
219 * @param token Processing domain
220 * @param channel Channel index
221 * @return Const reference to vector of buffers
222 */
223 [[nodiscard]] const std::vector<std::shared_ptr<AudioBuffer>>& get_buffers(ProcessingToken token, uint32_t channel) const;
224
225 /**
226 * @brief Gets graphics buffers for a token
227 * @param token Processing domain
228 * @return Const reference to vector of VKBuffers
229 */
230 [[nodiscard]] const std::vector<std::shared_ptr<VKBuffer>>& get_graphics_buffers(ProcessingToken token) const;
231
232 /**
233 * @brief Gets graphics buffers filtered by usage
234 * @param usage VKBuffer usage type
235 * @param token Processing domain
236 * @return Vector of matching buffers
237 */
238 [[nodiscard]] std::vector<std::shared_ptr<VKBuffer>> get_buffers_by_usage(
239 VKBuffer::Usage usage,
240 ProcessingToken token) const;
241
242 /**
243 * @brief Creates a specialized audio buffer and adds it to the specified token/channel
244 * @tparam BufferType Type of buffer to create (must be compatible with token)
245 * @tparam Args Constructor argument types
246 * @param token Processing domain
247 * @param channel Channel index
248 * @param args Constructor arguments
249 * @return Shared pointer to the created buffer
250 */
251 template <typename BufferType, typename... Args>
252 std::shared_ptr<BufferType> create_audio_buffer(ProcessingToken token, uint32_t channel, Args&&... args)
253 {
254 auto& unit = m_unit_manager->ensure_and_get_audio_unit(token, channel);
255 auto buffer = std::make_shared<BufferType>(channel, unit.buffer_size, std::forward<Args>(args)...);
256
257 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
258 add_buffer(audio_buffer, token, channel);
259 }
260
261 return buffer;
262 }
263
264 /**
265 * @brief Creates a specialized vulkan buffer and adds it to the specified token/channel
266 * @tparam BufferType Type of buffer to create (must be compatible with token)
267 * @tparam Args Constructor argument types
268 * @param token Processing domain
269 * @param args Constructor arguments
270 * @return Shared pointer to the created buffer
271 */
272 template <typename BufferType, typename... Args>
273 std::shared_ptr<BufferType> create_graphics_buffer(ProcessingToken token, Args&&... args)
274 {
275 auto& unit = m_unit_manager->get_or_create_graphics_unit(token);
276 auto buffer = std::make_shared<BufferType>(std::forward<Args>(args)...);
277
278 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
279 add_buffer(vk_buffer, token);
280 }
281
282 return buffer;
283 }
284
285 // =========================================================================
286 // Processor Management (Token-Generic)
287 // =========================================================================
288
289 /**
290 * @brief Adds a processor to a buffer
291 * @param processor Processor to add
292 * @param buffer Target buffer (dispatches based on type)
293 */
294 void add_processor(
295 const std::shared_ptr<BufferProcessor>& processor,
296 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::AUDIO_BACKEND);
297
298 /**
299 * @brief Adds a processor to a token and channel (audio-specific)
300 * @param processor Processor to add
301 * @param token Processing domain
302 * @param channel Channel index
303 */
304 void add_processor(
305 const std::shared_ptr<BufferProcessor>& processor,
306 ProcessingToken token,
307 uint32_t channel);
308
309 /**
310 * @brief Adds a processor to all channels in a token (audio-specific)
311 * @param processor Processor to add
312 * @param token Processing domain
313 */
314 void add_processor(
315 const std::shared_ptr<BufferProcessor>& processor,
316 ProcessingToken token);
317
318 /**
319 * @brief Removes a processor from a buffer
320 * @param processor Processor to remove
321 * @param buffer Target buffer
322 */
323 void remove_processor(
324 const std::shared_ptr<BufferProcessor>& processor,
325 const std::shared_ptr<Buffer>& buffer);
326
327 /**
328 * @brief Removes a processor from a token and channel (audio-specific)
329 * @param processor Processor to remove
330 * @param token Processing domain
331 * @param channel Channel index
332 */
333 void remove_processor_from_channel(
334 const std::shared_ptr<BufferProcessor>& processor,
335 ProcessingToken token,
336 uint32_t channel);
337
338 /**
339 * @brief Removes a processor from all channels in a token (audio-specific)
340 * @param processor Processor to remove
341 * @param token Processing domain
342 */
343 void remove_processor_from_token(
344 const std::shared_ptr<BufferProcessor>& processor,
345 ProcessingToken token);
346
347 /**
348 * @brief Sets a final processor for a token (audio-specific)
349 * @param processor Final processor to apply
350 * @param token Processing domain
351 */
352 void set_final_processor(
353 const std::shared_ptr<BufferProcessor>& processor,
354 ProcessingToken token);
355
356 // =========================================================================
357 // Quick Processing (Audio-Specific)
358 // =========================================================================
359
360 std::shared_ptr<BufferProcessor> attach_quick_process(
361 AudioProcessingFunction processor,
362 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::AUDIO_BACKEND);
363
364 std::shared_ptr<BufferProcessor> attach_quick_process(
366 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::GRAPHICS_BACKEND);
367
368 std::shared_ptr<BufferProcessor> attach_quick_process(
369 AudioProcessingFunction processor,
370 ProcessingToken token,
371 uint32_t channel);
372
373 std::shared_ptr<BufferProcessor> attach_quick_process(
374 AudioProcessingFunction processor,
375 ProcessingToken token);
376
377 std::shared_ptr<BufferProcessor> attach_quick_process(
379 ProcessingToken token);
380
381 // =========================================================================
382 // Node Connection (Audio-Specific)
383 // =========================================================================
384
386 const std::shared_ptr<Nodes::Node>& node,
387 ProcessingToken token,
388 uint32_t channel,
389 float mix = 0.5F,
390 bool clear_before = false);
391
393 const std::shared_ptr<Nodes::Node>& node,
394 const std::shared_ptr<AudioBuffer>& buffer,
395 float mix = 0.5F,
396 bool clear_before = true);
397
398 // =========================================================================
399 // Data I/O (Audio-Specific)
400 // =========================================================================
401
402 void fill_from_interleaved(
403 const double* interleaved_data,
404 uint32_t num_frames,
405 ProcessingToken token,
406 uint32_t num_channels);
407
408 void fill_interleaved(
409 double* interleaved_data,
410 uint32_t num_frames,
411 ProcessingToken token,
412 uint32_t num_channels) const;
413
414 std::vector<std::shared_ptr<AudioBuffer>> clone_buffer_for_channels(
415 const std::shared_ptr<AudioBuffer>& buffer,
416 const std::vector<uint32_t>& channels,
417 ProcessingToken token);
418
419 // =========================================================================
420 // Input Handling (Audio-Specific)
421 // =========================================================================
422
423 void process_input(double* input_data, uint32_t num_channels, uint32_t num_frames);
424
425 void register_input_listener(const std::shared_ptr<AudioBuffer>& buffer, uint32_t channel);
426
427 void unregister_input_listener(const std::shared_ptr<AudioBuffer>& buffer, uint32_t channel);
428
429 // =========================================================================
430 // Buffer Supply/Mixing (Audio-Specific)
431 // =========================================================================
432
433 bool supply_buffer_to(
434 const std::shared_ptr<AudioBuffer>& buffer,
435 ProcessingToken token,
436 uint32_t channel,
437 double mix = 1.0);
438
439 bool remove_supplied_buffer(
440 const std::shared_ptr<AudioBuffer>& buffer,
441 ProcessingToken token,
442 uint32_t channel);
443
444 void route_buffer_to_channel(
445 const std::shared_ptr<AudioBuffer>& buffer,
446 uint32_t target_channel,
447 uint32_t fade_cycles,
448 ProcessingToken token);
449
450 void update_routing_states(ProcessingToken token);
451
452 void cleanup_completed_routing(ProcessingToken token);
453
454 // =========================================================================
455 // Utility
456 // =========================================================================
457
458 void initialize_buffer_service();
459
460 /**
461 * @brief Terminates all active buffers, clearing their data
462 */
463 void terminate_active_buffers();
464
465private:
466 void process_audio_token_default(ProcessingToken token, uint32_t processing_units);
467
468 void process_graphics_token_default(ProcessingToken token, uint32_t processing_units);
469
470 /// Token/unit storage and lifecycle
471 std::unique_ptr<TokenUnitManager> m_unit_manager;
472
473 /// Buffer and unit access operations
474 std::unique_ptr<BufferAccessControl> m_access_control;
475
476 /// Processor attachment/removal operations
477 std::unique_ptr<BufferProcessingControl> m_processor_control;
478
479 /// Audio input management
480 std::unique_ptr<BufferInputControl> m_input_control;
481
482 /// Buffer supply and mixing operations
483 std::unique_ptr<BufferSupplyMixing> m_supply_mixing;
484
485 /// Global processing chain applied to all tokens
486 std::shared_ptr<BufferProcessingChain> m_global_processing_chain;
487};
488
489} // namespace MayaFlux::Buffers
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.
std::function< void(const std::shared_ptr< AudioBuffer > &)> AudioProcessingFunction
Audio processing function - receives correctly-typed AudioBuffer.
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
std::function< void(std::vector< std::shared_ptr< RootAudioBuffer > > &, uint32_t)> RootAudioProcessingFunction
std::function< void(const std::shared_ptr< VKBuffer > &)> GraphicsProcessingFunction
Graphics processing function - receives correctly-typed VKBuffer.
Contains the node-based computational processing system components.
Definition Chronie.hpp:11
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:169
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:138
std::shared_ptr< Buffers::BufferProcessor > attach_quick_process(Buffers::AudioProcessingFunction processor, unsigned int channel_id)
Attaches a processing function to a specific channel.
Definition Graph.cpp:210
Buffers::RootAudioBuffer & get_root_audio_buffer(uint32_t channel)
Gets the audio buffer for a specific channel.
Definition Graph.cpp:158
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:163