MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
AudioWriteProcessor.cpp
Go to the documentation of this file.
2
5
7
8namespace MayaFlux::Buffers {
9
10//==============================================================================
11// set_data overloads
12//==============================================================================
13
14void AudioWriteProcessor::set_data(std::vector<double> data)
15{
16 m_pending = std::move(data);
17 m_dirty.test_and_set(std::memory_order_release);
18}
19
21{
22 const bool is_glm = std::holds_alternative<std::vector<glm::vec2>>(variant)
23 || std::holds_alternative<std::vector<glm::vec3>>(variant)
24 || std::holds_alternative<std::vector<glm::vec4>>(variant)
25 || std::holds_alternative<std::vector<glm::mat4>>(variant);
26
27 if (is_glm) {
28 /** EigenAccess::to_matrix() flattens glm types into a components-as-rows MatrixXd.
29 Flatten column-major into a double sequence: [x0,y0,z0, x1,y1,z1, ...]
30 **/
31 const Eigen::MatrixXd mat = Kakshya::EigenAccess(variant).to_matrix();
32 const Eigen::Index total = mat.size();
33 m_pending.resize(static_cast<size_t>(total));
34 /** Map column-major layout directly — Eigen default is column-major. **/
35 Eigen::Map<Eigen::VectorXd>(m_pending.data(), total) = Eigen::Map<const Eigen::VectorXd>(mat.data(), total);
36 } else {
37 /** Arithmetic and complex types: to_vector() handles magnitude for complex. **/
38 const Eigen::VectorXd vec = Kakshya::EigenAccess(variant).to_vector();
39 m_pending.resize(static_cast<size_t>(vec.size()));
40 Eigen::Map<Eigen::VectorXd>(m_pending.data(), vec.size()) = vec;
41 }
42
43 m_dirty.test_and_set(std::memory_order_release);
44}
45
46void AudioWriteProcessor::set_data(std::span<const float> data)
47{
48 m_pending.resize(data.size());
49 std::ranges::transform(data, m_pending.begin(),
50 [](float s) { return static_cast<double>(s); });
51 m_dirty.test_and_set(std::memory_order_release);
52}
53
54void AudioWriteProcessor::set_data(std::span<const double> data)
55{
56 m_pending.assign(data.begin(), data.end());
57 m_dirty.test_and_set(std::memory_order_release);
58}
59
61{
62 m_pending.clear();
63 m_dirty.test_and_set(std::memory_order_release);
64}
65
67{
68 return m_dirty.test(std::memory_order_acquire);
69}
70
71//==============================================================================
72// Processor interface
73//==============================================================================
74
75void AudioWriteProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
76{
77 if (!std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
78 error<std::invalid_argument>(
81 std::source_location::current(),
82 "AudioWriteProcessor requires an AudioBuffer");
83 }
84}
85
86void AudioWriteProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
87{
88 auto audio = std::dynamic_pointer_cast<AudioBuffer>(buffer);
89 if (!audio) {
91 "AudioWriteProcessor attached to non-AudioBuffer");
92 return;
93 }
94
96 write_to_buffer(*audio);
97}
98
99bool AudioWriteProcessor::is_compatible_with(const std::shared_ptr<Buffer>& buffer) const
100{
101 return std::dynamic_pointer_cast<AudioBuffer>(buffer) != nullptr;
102}
103
104//==============================================================================
105// Private
106//==============================================================================
107
109{
110 if (m_dirty.test(std::memory_order_acquire)) {
111 m_dirty.clear(std::memory_order_release);
112 std::swap(m_active, m_pending);
113 }
114}
115
117{
118 auto& dst = buf.get_data();
119 const size_t dst_n = dst.size();
120
121 if (m_active.empty()) {
122 std::ranges::fill(dst, 0.0);
123 return;
124 }
125
126 const size_t copy_n = std::min(dst_n, m_active.size());
127 std::ranges::copy_n(m_active.begin(), static_cast<std::ptrdiff_t>(copy_n), dst.begin());
128
129 if (copy_n < dst_n) {
130 std::fill(dst.begin() + static_cast<std::ptrdiff_t>(copy_n), dst.end(), 0.0);
131 }
132}
133
134} // namespace MayaFlux::Buffers
#define MF_RT_ERROR(comp, ctx,...)
virtual std::vector< double > & get_data()
Gets mutable access to the buffer's underlying audio data.
Concrete audio implementation of the Buffer interface for double-precision audio data.
void write_to_buffer(AudioBuffer &buf) const
bool has_pending() const noexcept
Returns true if a snapshot has been set and not yet consumed.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
bool is_compatible_with(const std::shared_ptr< Buffer > &buffer) const override
Checks if this processor can handle the specified buffer type.
void set_data(std::vector< double > data)
Supply the next frame of double-precision samples.
void clear()
Clear any pending snapshot.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
Eigen::VectorXd to_vector() const
Convert DataVariant to Eigen column vector.
Eigen::MatrixXd to_matrix() const
Convert DataVariant to Eigen matrix.
Type-erased accessor for converting DataVariant to Eigen types.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
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