MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ capture_operation()

void MayaFlux::Kriya::BufferPipeline::capture_operation ( BufferOperation op,
uint64_t  cycle 
)
private

Definition at line 295 of file BufferPipeline.cpp.

296{
297 bool should_process = op.m_capture.get_processing_control() == BufferCapture::ProcessingControl::ON_CAPTURE;
298 auto buffer_data = extract_buffer_data(op.m_capture.get_buffer(), should_process);
299
300 if (op.m_capture.m_data_ready_callback) {
301 op.m_capture.m_data_ready_callback(buffer_data, cycle);
302 }
303
304 auto capture_mode = op.m_capture.get_mode();
305
306 switch (capture_mode) {
308 m_operation_data[&op] = buffer_data;
309 break;
310
312 auto it = m_operation_data.find(&op);
313 if (it == m_operation_data.end()) {
314 m_operation_data[&op] = buffer_data;
315 } else {
316 try {
317 auto& existing = std::get<std::vector<double>>(it->second);
318 const auto& new_data = std::get<std::vector<double>>(buffer_data);
319 existing.insert(existing.end(), new_data.begin(), new_data.end());
320
321 } catch (const std::bad_variant_access& e) {
324 "Data type mismatch during ACCUMULATE capture: {}",
325 e.what());
326 m_operation_data[&op] = buffer_data;
327 }
328 }
329 break;
330 }
332 uint32_t circular_size = op.m_capture.get_circular_size();
333 if (circular_size == 0) {
334 circular_size = 4096;
335 }
336
337 auto it = m_operation_data.find(&op);
338 if (it == m_operation_data.end()) {
339 m_operation_data[&op] = buffer_data;
340 } else {
341 try {
342 auto& circular = std::get<std::vector<double>>(it->second);
343 const auto& new_data = std::get<std::vector<double>>(buffer_data);
344
345 circular.insert(circular.end(), new_data.begin(), new_data.end());
346
347 if (circular.size() > circular_size) {
348 circular.erase(circular.begin(),
349 circular.begin() + static_cast<int64_t>(circular.size() - circular_size));
350 }
351
352 } catch (const std::bad_variant_access& e) {
355 "Data type mismatch during CIRCULAR capture: {}",
356 e.what());
357 m_operation_data[&op] = buffer_data;
358 } catch (std::exception& e) {
361 std::source_location::current(),
362 "Error during CIRCULAR capture: {}",
363 e.what());
364 m_operation_data[&op] = buffer_data;
365 }
366 }
367 break;
368 }
370 uint32_t window_size = op.m_capture.get_window_size();
371 float overlap_ratio = op.m_capture.get_overlap_ratio();
372
373 if (window_size == 0) {
374 window_size = 512;
375 }
376
377 auto hop_size = static_cast<uint32_t>((float)window_size * (1.0F - overlap_ratio));
378 if (hop_size == 0)
379 hop_size = 1;
380
381 auto it = m_operation_data.find(&op);
382 if (it == m_operation_data.end()) {
383 m_operation_data[&op] = buffer_data;
384 } else {
385 try {
386 auto& windowed = std::get<std::vector<double>>(it->second);
387 const auto& new_data = std::get<std::vector<double>>(buffer_data);
388
389 if (windowed.size() >= window_size) {
390 if (hop_size >= windowed.size()) {
391 windowed = std::get<std::vector<double>>(buffer_data);
392 } else {
393 windowed.erase(windowed.begin(),
394 windowed.begin() + hop_size);
395
396 windowed.insert(windowed.end(), new_data.begin(), new_data.end());
397
398 if (windowed.size() > window_size) {
399 size_t excess = windowed.size() - window_size;
400 windowed.erase(windowed.begin(),
401 windowed.begin() + excess);
402 }
403 }
404 } else {
405 windowed.insert(windowed.end(), new_data.begin(), new_data.end());
406
407 if (windowed.size() > window_size) {
408 size_t excess = windowed.size() - window_size;
409 windowed.erase(windowed.begin(),
410 windowed.begin() + excess);
411 }
412 }
413
414 } catch (const std::bad_variant_access& e) {
416 "Data type mismatch during WINDOWED capture: {}", e.what());
417 m_operation_data[&op] = buffer_data;
418 }
419 }
420 break;
421 }
422
424 if (op.m_capture.m_stop_condition && op.m_capture.m_stop_condition()) {
425 m_operation_data[&op] = buffer_data;
426 }
427 break;
428 }
429
430 default:
431 m_operation_data[&op] = buffer_data;
432 break;
433 }
434
435 if (has_immediate_routing(op)) {
436 auto current_it = std::ranges::find_if(m_operations,
437 [&op](const BufferOperation& o) { return &o == &op; });
438
439 if (current_it != m_operations.end()) {
440 auto next_it = std::next(current_it);
441 if (next_it != m_operations.end() && next_it->get_type() == BufferOperation::OpType::ROUTE) {
442
443 if (next_it->m_target_buffer) {
444 write_to_buffer(next_it->m_target_buffer, buffer_data);
445 } else if (next_it->m_target_container) {
446 write_to_container(next_it->m_target_container, buffer_data);
447 }
448
449 size_t route_index = std::distance(m_operations.begin(), next_it);
450 if (route_index < m_data_states.size()) {
451 m_data_states[route_index] = DataState::CONSUMED;
452 }
453 }
454 }
455 }
456}
#define MF_ERROR(comp, ctx,...)
Cycle Behavior: The for_cycles(N) configuration controls how many times the capture operation execute...
@ TRANSIENT
Single cycle capture (default) - data expires after 1 cycle.
@ CIRCULAR
Circular buffer with overwrite.
@ ACCUMULATE
Accumulate over multiple cycles in container.
@ WINDOWED
Rolling window capture with overlap.
@ TRIGGERED
Capture only when condition met.
@ ROUTE
Route data to destination (buffer or container)
std::unordered_map< BufferOperation *, Kakshya::DataVariant > m_operation_data
static void write_to_container(const std::shared_ptr< Kakshya::DynamicSoundStream > &container, const Kakshya::DataVariant &data)
std::vector< BufferOperation > m_operations
std::vector< DataState > m_data_states
static void write_to_buffer(const std::shared_ptr< Buffers::AudioBuffer > &buffer, const Kakshya::DataVariant &data)
bool has_immediate_routing(const BufferOperation &op) const
static Kakshya::DataVariant extract_buffer_data(const std::shared_ptr< Buffers::AudioBuffer > &buffer, bool should_process=false)
@ CoroutineScheduling
Coroutine scheduling and temporal coordination (Vruta::TaskScheduler)
void error_rethrow(Component component, Context context, std::source_location location=std::source_location::current(), std::string_view additional_context="")
Catch and log an exception, then rethrow it.
@ Kriya
Automatable tasks and fluent scheduling api for Nodes and Buffers.

References MayaFlux::Kriya::BufferCapture::ACCUMULATE, MayaFlux::Kriya::BufferCapture::CIRCULAR, CONSUMED, MayaFlux::Journal::CoroutineScheduling, extract_buffer_data(), MayaFlux::Kriya::BufferCapture::get_buffer(), MayaFlux::Kriya::BufferCapture::get_circular_size(), MayaFlux::Kriya::BufferCapture::get_mode(), MayaFlux::Kriya::BufferCapture::get_overlap_ratio(), MayaFlux::Kriya::BufferCapture::get_processing_control(), MayaFlux::Kriya::BufferCapture::get_window_size(), has_immediate_routing(), MayaFlux::Journal::Kriya, MayaFlux::Kriya::BufferOperation::m_capture, MayaFlux::Kriya::BufferCapture::m_data_ready_callback, m_data_states, m_operation_data, m_operations, MayaFlux::Kriya::BufferCapture::m_stop_condition, MF_ERROR, MayaFlux::Kriya::BufferCapture::ON_CAPTURE, MayaFlux::Kriya::BufferOperation::ROUTE, MayaFlux::Kriya::BufferCapture::TRANSIENT, MayaFlux::Kriya::BufferCapture::TRIGGERED, MayaFlux::Kriya::BufferCapture::WINDOWED, write_to_buffer(), and write_to_container().

Referenced by process_operation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: