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