MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
StreamSliceProcessor.hpp
Go to the documentation of this file.
1#pragma once
2
6
7namespace MayaFlux::Buffers {
8
9/**
10 * @class StreamSliceProcessor
11 * @brief BufferProcessor that drives a pool of independent StreamSlices against
12 * DynamicSoundStream instances, mixing results into the attached AudioBuffer
13 * each processing cycle.
14 *
15 * Each slot owns a CursorAccessProcessor responsible for cursor advancement,
16 * loop wrapping, speed scaling, and dynamic slot allocation on the stream.
17 * StreamSlice acts as a region descriptor only -- cursor state is internal to
18 * the per-slot processor. Multiple StreamSliceProcessor instances may reference
19 * the same DynamicSoundStream without contention; each allocates an independent
20 * dynamic slot via DynamicSoundStream::allocate_dynamic_slot().
21 *
22 * load() must be called after attachment to a buffer. Attachment populates the
23 * frame block size used to construct the per-slot CursorAccessProcessor. Calling
24 * load() before attachment is a no-op with an error log.
25 *
26 * Inactive slots contribute silence. Active slot outputs are accumulated into
27 * the buffer in index order with no further scaling applied here beyond what
28 * CursorAccessProcessor produces.
29 */
30class MAYAFLUX_API StreamSliceProcessor : public BufferProcessor {
31public:
33 ~StreamSliceProcessor() override = default;
34
35 void on_attach(const std::shared_ptr<Buffer>& buffer) override;
36 void on_detach(const std::shared_ptr<Buffer>& buffer) override;
37 void processing_function(const std::shared_ptr<Buffer>& buffer) override;
38 [[nodiscard]] bool is_compatible_with(const std::shared_ptr<Buffer>& buffer) const override;
39
40 /**
41 * @brief Assign a StreamSlice to a slot.
42 *
43 * Must be called after the processor is attached to a buffer, as the
44 * buffer's frame count is required to configure the CursorAccessProcessor.
45 * Calling load() before attachment is a no-op with an error log.
46 *
47 * Constructs a CursorAccessProcessor owned by this slot, attaches it to
48 * the slice's stream, and configures the loop region from the slice's
49 * Region. Any previously loaded slot processor is detached first.
50 * The slot is left inactive; call bind() to start playback.
51 * Grows the slot pool if index exceeds the current size.
52 *
53 * @param index The slot is left inactive; call bind() to start playback.
54 * @param slice StreamSlice describing the stream and region.
55 */
56 void load(size_t index, Kakshya::StreamSlice slice);
57
58 /**
59 * @brief Activate a slot, resetting its processor cursor to region start.
60 * @param index Slot index
61 */
62 void bind(size_t index);
63
64 /**
65 * @brief Deactivate a slot, stopping its processor without resetting the cursor.
66 * @param index Slot index.
67 */
68 void unbind(size_t index);
69
70 [[nodiscard]] Kakshya::StreamSlice& slice(size_t index) { return m_slots[index].slice; }
71 [[nodiscard]] const Kakshya::StreamSlice& slice(size_t index) const { return m_slots[index].slice; }
72
73 /**
74 * @brief Check if any slot is active.
75 * @return True if any slot is active, false if all are inactive.
76 */
77 [[nodiscard]] bool any_active() const;
78
79 /**
80 * @brief Get the current number of slots.
81 * @return The number of slots currently allocated.
82 */
83 [[nodiscard]] size_t slot_count() const { return m_slots.size(); }
84
85 /**
86 * @brief Register a callback fired when a slot's one-shot playback ends.
87 * @param cb Invoked with the slot index. Called from the processing thread.
88 */
89 void set_on_end(std::function<void(size_t)> cb) { m_on_end = std::move(cb); }
90
91private:
92 struct Slot {
94 std::shared_ptr<Kakshya::CursorAccessProcessor> proc;
95 };
96
97 std::vector<Slot> m_slots;
98 std::function<void(size_t)> m_on_end;
99 uint32_t m_frames_per_block {};
100
101 void detach_slot(size_t index);
102};
103
104} // namespace MayaFlux::Buffers
Central computational transformation interface for continuous buffer processing.
void set_on_end(std::function< void(size_t)> cb)
Register a callback fired when a slot's one-shot playback ends.
const Kakshya::StreamSlice & slice(size_t index) const
size_t slot_count() const
Get the current number of slots.
Kakshya::StreamSlice & slice(size_t index)
BufferProcessor that drives a pool of independent StreamSlices against DynamicSoundStream instances,...
std::shared_ptr< Kakshya::CursorAccessProcessor > proc
A bounded region of a DynamicSoundStream with associated playback parameters.