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;
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 Gets the sample rate for a token (audio-specific)
150 * @param token Processing domain
151 * @return Sample rate in Hz
152 */
153 [[nodiscard]] uint64_t get_sample_rate() const { return s_registered_sample_rate; }
154
155 /**
156 * @brief Resizes buffers for a token
157 * @param token Processing domain
158 * @param buffer_size New buffer size
159 */
160 void resize_buffers(ProcessingToken token, uint32_t buffer_size);
161
162 /**
163 * @brief Ensures minimum number of channels exist for an audio token
164 * @param token Processing domain
165 * @param channel_count Minimum number of channels
166 */
167 void ensure_channels(ProcessingToken token, uint32_t channel_count);
168
169 /**
170 * @brief Validates the number of channels and resizes buffers if necessary (audio-specific)
171 * @param token Processing domain
172 * @param num_channels Number of channels to validate
173 * @param buffer_size New buffer size to set
174 *
175 * This method ensures that the specified number of channels exists for the given token,
176 * resizing the root audio buffers accordingly.
177 */
178 void validate_num_channels(ProcessingToken token, uint32_t num_channels, uint32_t buffer_size)
179 {
180 ensure_channels(token, num_channels);
181 resize_buffers(token, buffer_size);
182 }
183
184 /**
185 * @brief Gets the processing chain for a token and channel (audio-specific)
186 * @param token Processing domain
187 * @param channel Channel index
188 * @return Shared pointer to the processing chain
189 */
190 std::shared_ptr<BufferProcessingChain> get_processing_chain(ProcessingToken token, uint32_t channel);
191
192 /**
193 * @brief Gets the global processing chain (applied to all tokens)
194 * @return Shared pointer to the global processing chain
195 */
196 std::shared_ptr<BufferProcessingChain> get_global_processing_chain();
197
198 // =========================================================================
199 // Buffer Management (Token-Generic via Dynamic Dispatch)
200 // =========================================================================
201
202 /**
203 * @brief Adds a buffer to a token and channel
204 * @param buffer Buffer to add (AudioBuffer or VKBuffer depending on token)
205 * @param token Processing domain
206 * @param channel Channel index (optional, used for audio)
207 */
208 void add_buffer(
209 const std::shared_ptr<Buffer>& buffer,
210 ProcessingToken token,
211 uint32_t channel = 0);
212
213 /**
214 * @brief Removes a buffer from a token
215 * @param buffer Buffer to remove
216 * @param token Processing domain
217 * @param channel Channel index (optional, used for audio)
218 */
219 void remove_buffer(
220 const std::shared_ptr<Buffer>& buffer,
221 ProcessingToken token,
222 uint32_t channel = 0);
223
224 /**
225 * @brief Gets buffers for a token (audio-specific due to channels)
226 * @param token Processing domain
227 * @param channel Channel index
228 * @return Const reference to vector of buffers
229 */
230 [[nodiscard]] const std::vector<std::shared_ptr<AudioBuffer>>& get_buffers(ProcessingToken token, uint32_t channel) const;
231
232 /**
233 * @brief Gets graphics buffers for a token
234 * @param token Processing domain
235 * @return Const reference to vector of VKBuffers
236 */
237 [[nodiscard]] const std::vector<std::shared_ptr<VKBuffer>>& get_graphics_buffers(ProcessingToken token) const;
238
239 /**
240 * @brief Gets graphics buffers filtered by usage
241 * @param usage VKBuffer usage type
242 * @param token Processing domain
243 * @return Vector of matching buffers
244 */
245 [[nodiscard]] std::vector<std::shared_ptr<VKBuffer>> get_buffers_by_usage(
246 VKBuffer::Usage usage,
247 ProcessingToken token) const;
248
249 /**
250 * @brief Creates a specialized audio buffer and adds it to the specified token/channel
251 * @tparam BufferType Type of buffer to create (must be compatible with token)
252 * @tparam Args Constructor argument types
253 * @param token Processing domain
254 * @param channel Channel index
255 * @param args Constructor arguments
256 * @return Shared pointer to the created buffer
257 */
258 template <typename BufferType, typename... Args>
259 std::shared_ptr<BufferType> create_audio_buffer(ProcessingToken token, uint32_t channel, Args&&... args)
260 {
261 auto& unit = m_unit_manager->ensure_and_get_audio_unit(token, channel);
262 auto buffer = std::make_shared<BufferType>(channel, unit.buffer_size, std::forward<Args>(args)...);
263
264 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
265 add_buffer(audio_buffer, token, channel);
266 }
267
268 return buffer;
269 }
270
271 /**
272 * @brief Creates a specialized vulkan buffer and adds it to the specified token/channel
273 * @tparam BufferType Type of buffer to create (must be compatible with token)
274 * @tparam Args Constructor argument types
275 * @param token Processing domain
276 * @param args Constructor arguments
277 * @return Shared pointer to the created buffer
278 */
279 template <typename BufferType, typename... Args>
280 std::shared_ptr<BufferType> create_graphics_buffer(ProcessingToken token, Args&&... args)
281 {
282 auto& unit = m_unit_manager->get_or_create_graphics_unit(token);
283 auto buffer = std::make_shared<BufferType>(std::forward<Args>(args)...);
284
285 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
286 add_buffer(vk_buffer, token);
287 }
288
289 return buffer;
290 }
291
292 // =========================================================================
293 // Processor Management (Token-Generic)
294 // =========================================================================
295
296 /**
297 * @brief Adds a processor to a buffer
298 * @param processor Processor to add
299 * @param buffer Target buffer (dispatches based on type)
300 */
301 void add_processor(
302 const std::shared_ptr<BufferProcessor>& processor,
303 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::AUDIO_BACKEND);
304
305 /**
306 * @brief Adds a processor to a token and channel (audio-specific)
307 * @param processor Processor to add
308 * @param token Processing domain
309 * @param channel Channel index
310 */
311 void add_processor(
312 const std::shared_ptr<BufferProcessor>& processor,
313 ProcessingToken token,
314 uint32_t channel);
315
316 /**
317 * @brief Adds a processor to all channels in a token (audio-specific)
318 * @param processor Processor to add
319 * @param token Processing domain
320 */
321 void add_processor(
322 const std::shared_ptr<BufferProcessor>& processor,
323 ProcessingToken token);
324
325 /**
326 * @brief Removes a processor from a buffer
327 * @param processor Processor to remove
328 * @param buffer Target buffer
329 */
330 void remove_processor(
331 const std::shared_ptr<BufferProcessor>& processor,
332 const std::shared_ptr<Buffer>& buffer);
333
334 /**
335 * @brief Removes a processor from a token and channel (audio-specific)
336 * @param processor Processor to remove
337 * @param token Processing domain
338 * @param channel Channel index
339 */
340 void remove_processor_from_channel(
341 const std::shared_ptr<BufferProcessor>& processor,
342 ProcessingToken token,
343 uint32_t channel);
344
345 /**
346 * @brief Removes a processor from all channels in a token (audio-specific)
347 * @param processor Processor to remove
348 * @param token Processing domain
349 */
350 void remove_processor_from_token(
351 const std::shared_ptr<BufferProcessor>& processor,
352 ProcessingToken token);
353
354 /**
355 * @brief Sets a final processor for a token (audio-specific)
356 * @param processor Final processor to apply
357 * @param token Processing domain
358 */
359 void set_final_processor(
360 const std::shared_ptr<BufferProcessor>& processor,
361 ProcessingToken token);
362
363 // =========================================================================
364 // Quick Processing (Audio-Specific)
365 // =========================================================================
366
367 std::shared_ptr<BufferProcessor> attach_quick_process(
368 AudioProcessingFunction processor,
369 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::AUDIO_BACKEND);
370
371 std::shared_ptr<BufferProcessor> attach_quick_process(
373 const std::shared_ptr<Buffer>& buffer, ProcessingToken token = ProcessingToken::GRAPHICS_BACKEND);
374
375 std::shared_ptr<BufferProcessor> attach_quick_process(
376 AudioProcessingFunction processor,
377 ProcessingToken token,
378 uint32_t channel);
379
380 std::shared_ptr<BufferProcessor> attach_quick_process(
381 AudioProcessingFunction processor,
382 ProcessingToken token);
383
384 std::shared_ptr<BufferProcessor> attach_quick_process(
386 ProcessingToken token);
387
388 // =========================================================================
389 // Node Connection (Audio-Specific)
390 // =========================================================================
391
393 const std::shared_ptr<Nodes::Node>& node,
394 ProcessingToken token,
395 uint32_t channel,
396 float mix = 0.5F,
397 bool clear_before = false);
398
400 const std::shared_ptr<Nodes::Node>& node,
401 const std::shared_ptr<AudioBuffer>& buffer,
402 float mix = 0.5F,
403 bool clear_before = true);
404
405 // =========================================================================
406 // Data I/O (Audio-Specific)
407 // =========================================================================
408
409 void fill_from_interleaved(
410 const double* interleaved_data,
411 uint32_t num_frames,
412 ProcessingToken token,
413 uint32_t num_channels);
414
415 void fill_interleaved(
416 double* interleaved_data,
417 uint32_t num_frames,
418 ProcessingToken token,
419 uint32_t num_channels) const;
420
421 std::vector<std::shared_ptr<AudioBuffer>> clone_buffer_for_channels(
422 const std::shared_ptr<AudioBuffer>& buffer,
423 const std::vector<uint32_t>& channels,
424 ProcessingToken token);
425
426 // =========================================================================
427 // Input Handling (Audio-Specific)
428 // =========================================================================
429
430 void process_input(double* input_data, uint32_t num_channels, uint32_t num_frames);
431
432 void register_input_listener(const std::shared_ptr<AudioBuffer>& buffer, uint32_t channel);
433
434 void unregister_input_listener(const std::shared_ptr<AudioBuffer>& buffer, uint32_t channel);
435
436 // =========================================================================
437 // Buffer Supply/Mixing (Audio-Specific)
438 // =========================================================================
439
440 bool supply_buffer_to(
441 const std::shared_ptr<AudioBuffer>& buffer,
442 ProcessingToken token,
443 uint32_t channel,
444 double mix = 1.0, bool force = false);
445
446 bool remove_supplied_buffer(
447 const std::shared_ptr<AudioBuffer>& buffer,
448 ProcessingToken token,
449 uint32_t channel);
450
451 void route_buffer_to_channel(
452 const std::shared_ptr<AudioBuffer>& buffer,
453 uint32_t target_channel,
454 uint32_t fade_cycles,
455 ProcessingToken token);
456
457 void update_routing_states(ProcessingToken token);
458
459 void cleanup_completed_routing(ProcessingToken token);
460
461 // =========================================================================
462 // Utility
463 // =========================================================================
464
465 void initialize_buffer_service();
466
467 /**
468 * @brief Terminates all active buffers, clearing their data
469 */
470 void terminate_active_buffers();
471
472private:
473 void process_audio_token_default(ProcessingToken token, uint32_t processing_units);
474
475 void process_graphics_token_default(ProcessingToken token, uint32_t processing_units);
476
477 /// Token/unit storage and lifecycle
478 std::unique_ptr<TokenUnitManager> m_unit_manager;
479
480 /// Buffer and unit access operations
481 std::unique_ptr<BufferAccessControl> m_access_control;
482
483 /// Processor attachment/removal operations
484 std::unique_ptr<BufferProcessingControl> m_processor_control;
485
486 /// Audio input management
487 std::unique_ptr<BufferInputControl> m_input_control;
488
489 /// Buffer supply and mixing operations
490 std::unique_ptr<BufferSupplyMixing> m_supply_mixing;
491
492 /// Global processing chain applied to all tokens
493 std::shared_ptr<BufferProcessingChain> m_global_processing_chain;
494};
495
496} // namespace MayaFlux::Buffers
uint32_t channel
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:13
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:184
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:153
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:225
Buffers::RootAudioBuffer & get_root_audio_buffer(uint32_t channel)
Gets the audio buffer for a specific channel.
Definition Graph.cpp:173
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:178