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