MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DynamicSoundStream.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace MayaFlux::IO {
6class SoundFileReader;
7}
8
9namespace MayaFlux::Kakshya {
10
11/**
12 * @class DynamicSoundStream
13 * @brief Dynamic capacity streaming audio container with automatic resizing and circular buffering.
14 *
15 * DynamicSoundStream extends SoundStreamContainer to provide dynamic capacity management
16 * for real-time audio streaming scenarios where the buffer size cannot be predetermined.
17 * It combines the full functionality of SoundStreamContainer with:
18 *
19 * **Key Features:**
20 * - **Dynamic Resizing**: Automatically expands capacity when writing beyond current bounds
21 * - **Circular Buffering**: Optional fixed-size circular buffer mode for continuous streaming
22 * - **Buffer-Sized Operations**: Optimized read/write operations using buffer-sized chunks
23 * - **Capacity Management**: Manual control over buffer allocation and expansion strategies
24 * - **Real-time Safe**: Lock-free operations where possible for audio thread compatibility
25 *
26 * **Use Cases:**
27 * - Real-time audio recording with unknown duration
28 * - Streaming buffers that grow dynamically during playback
29 * - Circular delay lines and feedback systems
30 * - Live audio processing with variable latency requirements
31 * - Audio looping and granular synthesis applications
32 *
33 * **Memory Management:**
34 * The container supports two primary modes:
35 * 1. **Linear Mode**: Automatically expands as data is written, suitable for recording
36 * 2. **Circular Mode**: Fixed-size buffer that wraps around, ideal for delay effects
37 *
38 * **Thread Safety:**
39 * Inherits full thread safety from SoundStreamContainer including shared/exclusive locks
40 * for concurrent read/write access and atomic state management for processing coordination.
41 *
42 * **Integration:**
43 * Fully compatible with the MayaFlux processing ecosystem including DataProcessor implementations,
44 * region-based operations, buffer manager integration, and sample-accurate timing.
45 *
46 * @note When auto-resize is enabled, write operations may trigger memory allocation.
47 * For real-time audio threads, consider pre-allocating capacity or using circular mode.
48 *
49 * @warning Circular mode discards old data when capacity is exceeded. Ensure appropriate
50 * capacity sizing for your use case to prevent data loss.
51 */
52class MAYAFLUX_API DynamicSoundStream : public SoundStreamContainer {
53public:
54 /**
55 * @brief Construct a DynamicSoundStream with specified audio parameters.
56 * @param sample_rate Sample rate in Hz for temporal calculations and timing
57 * @param num_channels Number of audio channels (typically 1=mono, 2=stereo)
58 */
59 DynamicSoundStream(uint32_t sample_rate = 48000, uint32_t num_channels = 2);
60
61 /**
62 * @brief Write audio frame data to the container with automatic capacity management.
63 * @param data Span of interleaved audio samples to write
64 * @param start_frame Frame index where writing begins (default: append at end)
65 % @param channel Channel index for planar data (default: 0)
66 * @return Number of frames actually written
67 */
68 uint64_t write_frames(std::span<const double> data, uint64_t start_frame = 0, uint32_t channel = 0);
69 uint64_t write_frames(std::vector<std::span<const double>> data, uint64_t start_frame = 0);
70
71 /**
72 * @brief Read audio frames using sequential reading with automatic position management.
73 * @param output Span to fill with interleaved audio data
74 * @param count Maximum number of frames to read
75 * @return Number of frames actually read (may be less than requested)
76 */
77 inline uint64_t read_frames(std::span<double> output, uint64_t count)
78 {
79 return read_sequential(output, count);
80 }
81
82 /**
83 * @brief Enable or disable automatic capacity expansion during write operations.
84 * @param enable True to enable auto-resize, false to disable
85 */
86 inline void set_auto_resize(bool enable) { m_auto_resize = enable; }
87
88 /**
89 * @brief Check if automatic capacity expansion is currently enabled.
90 * @return True if auto-resize is enabled, false otherwise
91 */
92 inline bool get_auto_resize() const { return m_auto_resize; }
93
94 /**
95 * @brief Pre-allocate capacity for the specified number of frames.
96 * Essential for real-time scenarios where allocation delays are unacceptable.
97 * @param required_frames Minimum number of frames the container should hold
98 */
99 void ensure_capacity(uint64_t required_frames);
100
101 /**
102 * @brief Enable circular buffer mode with fixed capacity.
103 * Writes wrap around at capacity boundary, potentially overwriting older data.
104 * @param capacity Fixed number of frames the circular buffer can hold
105 */
106 void enable_circular_buffer(uint64_t capacity);
107
108 /**
109 * @brief Disable circular buffer mode and return to linear operation.
110 * Preserves all current data and restores auto-resize behavior.
111 */
112 void disable_circular_buffer();
113
114 /**
115 * @brief Check if the container is currently operating in circular buffer mode.
116 * @return True if circular mode is active, false if in linear mode
117 */
118 bool is_circular() const { return m_is_circular; }
119
120 /**
121 * @brief Get the fixed capacity of the circular buffer if enabled.
122 * @return Capacity in frames if circular mode is active, 0 otherwise
123 */
124 std::span<const double> get_channel_frames(uint32_t channel, uint64_t start_frame, uint64_t num_frames) const;
125
126 void get_channel_frames(std::span<double> output, uint32_t channel, uint64_t start_frame) const;
127
128 uint64_t get_circular_capacity() const { return m_circular_capacity; }
129
130 /**
131 * @brief Allocate an independent processed data slot.
132 *
133 * Returns a unique index into m_dynamic_data. Intended for processors
134 * that share this stream but require independent output buffers, such
135 * as multiple CursorAccessProcessor instances reading at different
136 * cursors. The slot is empty on allocation.
137 *
138 * @return Slot index, stable until release_dynamic_slot is called.
139 */
140 uint32_t allocate_dynamic_slot();
141
142 /**
143 * @brief Release a previously allocated dynamic slot, clearing its data.
144 * @param index Slot index returned by allocate_dynamic_slot.
145 */
146 void release_dynamic_slot(uint32_t index);
147
148 /**
149 * @brief Access a dynamic processed data slot by index.
150 * @param index Slot index returned by allocate_dynamic_slot.
151 */
152 [[nodiscard]] std::vector<DataVariant>& get_dynamic_data(uint32_t index);
153 [[nodiscard]] const std::vector<DataVariant>& get_dynamic_data(uint32_t index) const;
154
155private:
156 bool m_auto_resize; ///< Enable automatic capacity expansion
157 bool m_is_circular {}; ///< True when operating in circular buffer mode
158 uint64_t m_circular_capacity {}; ///< Fixed capacity for circular mode
159 std::vector<std::vector<DataVariant>> m_dynamic_data;
160 std::vector<bool> m_dynamic_slots;
161
162 void expand_to(uint64_t target_frames);
163
164 std::vector<DataVariant> create_expanded_data(uint64_t new_frame_count);
165
166 void set_all_data(const DataVariant& new_data);
167 void set_all_data(const std::vector<DataVariant>& new_data);
168
169 uint64_t validate(std::vector<std::span<const double>>& data, uint64_t start_frame = 0);
170
171 uint64_t validate_single_channel(std::span<const double> data, uint64_t start_frame = 0, uint32_t channel = 0);
172
173 friend class MayaFlux::IO::SoundFileReader; ///< Allow SoundFileReader to access private members for loading data
174};
175
176} // namespace MayaFlux::Kakshya
Eigen::Index count
uint32_t channel
FFmpeg-based audio file reader for MayaFlux.
bool m_auto_resize
Enable automatic capacity expansion.
bool get_auto_resize() const
Check if automatic capacity expansion is currently enabled.
void set_auto_resize(bool enable)
Enable or disable automatic capacity expansion during write operations.
bool is_circular() const
Check if the container is currently operating in circular buffer mode.
uint64_t read_frames(std::span< double > output, uint64_t count)
Read audio frames using sequential reading with automatic position management.
std::vector< std::vector< DataVariant > > m_dynamic_data
Dynamic capacity streaming audio container with automatic resizing and circular buffering.
Concrete base implementation for streaming audio containers.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:76