MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
StreamSliceProcessor.cpp
Go to the documentation of this file.
2
5
7
8namespace MayaFlux::Buffers {
9
10void StreamSliceProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
11{
12 auto audio = std::dynamic_pointer_cast<AudioBuffer>(buffer);
13 if (!audio) {
15 "StreamSliceProcessor requires an AudioBuffer");
16 return;
17 }
18 m_frames_per_block = static_cast<uint32_t>(audio->get_num_samples());
19}
20
21void StreamSliceProcessor::on_detach(const std::shared_ptr<Buffer>&)
22{
23 for (size_t i = 0; i < m_slots.size(); ++i)
24 detach_slot(i);
25}
26
27bool StreamSliceProcessor::is_compatible_with(const std::shared_ptr<Buffer>& buffer) const
28{
29 return std::dynamic_pointer_cast<AudioBuffer>(buffer) != nullptr;
30}
31
33{
34 auto& slot = m_slots[index];
35 if (slot.proc && slot.slice.stream)
36 slot.proc->on_detach(slot.slice.stream);
37 slot = {};
38}
39
41{
42 if (m_frames_per_block == 0) {
44 "StreamSliceProcessor::load called before attachment to a buffer -- attach first");
45 return;
46 }
47
48 if (!slice.stream)
49 return;
50
51 if (index > m_slots.size()) {
53 "StreamSliceProcessor::load index {} exceeds slot count {}; use {} for next available",
54 index, m_slots.size(), m_slots.size());
55 }
56
57 if (index >= m_slots.size())
58 m_slots.resize(index + 1);
59
60 detach_slot(index);
61
62 slice.active = false;
63 slice.index = static_cast<uint8_t>(index);
64
65 auto proc = std::make_shared<Kakshya::CursorAccessProcessor>(m_frames_per_block);
66 proc->set_loop_region(slice.start_frame(), slice.end_frame());
67 proc->set_looping(slice.looping);
68 proc->set_loop_count(slice.loop_count);
69
70 if (slice.speed != 1.0)
71 proc->set_speed(slice.speed);
72
73 proc->set_on_end([this, index] {
74 m_slots[index].slice.active = false;
75 if (m_on_end)
76 m_on_end(index);
77 });
78
79 proc->on_attach(slice.stream);
80
81 m_slots[index].slice = std::move(slice);
82 m_slots[index].proc = std::move(proc);
83}
84
86{
87 if (index >= m_slots.size() || !m_slots[index].proc)
88 return;
89
90 m_slots[index].proc->reset();
91 m_slots[index].slice.active = true;
92}
93
95{
96 if (index >= m_slots.size() || !m_slots[index].proc)
97 return;
98
99 m_slots[index].proc->stop();
100 m_slots[index].slice.active = false;
101}
102
104{
105 return std::ranges::any_of(m_slots, [](const auto& slot) {
106 return slot.slice.active;
107 });
108}
109
110void StreamSliceProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
111{
112 auto audio = std::dynamic_pointer_cast<AudioBuffer>(buffer);
113 if (!audio)
114 return;
115
116 const uint32_t ch = audio->get_channel_id();
117 auto& dst = audio->get_data();
118 std::ranges::fill(dst, 0.0);
119
120 for (auto& slot : m_slots) {
121 if (!slot.slice.active || !slot.slice.stream || !slot.proc)
122 continue;
123
124 slot.proc->process(slot.slice.stream);
125
126 const auto& pd = slot.slice.stream->get_dynamic_data(slot.proc->get_slot_index());
127 if (pd.empty())
128 continue;
129
130 const auto structure = slot.slice.stream->get_structure();
131 std::vector<double> tmp(dst.size(), 0.0);
132 Kakshya::extract_processed_data(pd, structure.organization, structure.get_channel_count(), ch, tmp);
133
134 for (size_t s = 0; s < dst.size(); ++s)
135 dst[s] += tmp[s];
136 }
137}
138
139} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
void unbind(size_t index)
Deactivate a slot, stopping its processor without resetting the cursor.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void bind(size_t index)
Activate a slot, resetting its processor cursor to region start.
bool is_compatible_with(const std::shared_ptr< Buffer > &buffer) const override
Checks if this processor can handle the specified buffer type.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
bool any_active() const
Check if any slot is active.
void load(size_t index, Kakshya::StreamSlice slice)
Assign a StreamSlice to a slot.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
Kakshya::StreamSlice & slice(size_t index)
@ Configuration
Configuration and parameter updates.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
void extract_processed_data(const std::vector< DataVariant > &pd, OrganizationStrategy organization, uint64_t num_channels, uint32_t ch, std::span< double > output)
Extract one channel's samples from a processed dynamic data block.
std::shared_ptr< DynamicSoundStream > stream
A bounded region of a DynamicSoundStream with associated playback parameters.