MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Phasor.cpp
Go to the documentation of this file.
1#include "Phasor.hpp"
3
5
6Phasor::Phasor(float frequency, double amplitude, float offset)
7 : m_offset(offset)
8 , m_frequency_modulator(nullptr)
9 , m_amplitude_modulator(nullptr)
10 , m_phase_wrapped(false)
11 , m_threshold_crossed(false)
12{
13 m_amplitude = amplitude;
14 m_frequency = frequency;
15 update_phase_increment(frequency);
16}
17
18Phasor::Phasor(const std::shared_ptr<Node>& frequency_modulator, float frequency, double amplitude, float offset)
19 : m_offset(offset)
20 , m_frequency_modulator(frequency_modulator)
21 , m_amplitude_modulator(nullptr)
22 , m_phase_wrapped(false)
23 , m_threshold_crossed(false)
24{
25 m_amplitude = amplitude;
26 m_frequency = frequency;
27 update_phase_increment(frequency);
28}
29
30Phasor::Phasor(float frequency, const std::shared_ptr<Node>& amplitude_modulator, double amplitude, float offset)
31 : m_offset(offset)
32 , m_frequency_modulator(nullptr)
33 , m_amplitude_modulator(amplitude_modulator)
34 , m_phase_wrapped(false)
35 , m_threshold_crossed(false)
36{
37 m_amplitude = amplitude;
38 update_phase_increment(frequency);
39}
40
41Phasor::Phasor(const std::shared_ptr<Node>& frequency_modulator, const std::shared_ptr<Node>& amplitude_modulator,
42 float frequency, double amplitude, float offset)
43 : m_offset(offset)
44 , m_frequency_modulator(frequency_modulator)
45 , m_amplitude_modulator(amplitude_modulator)
46 , m_phase_wrapped(false)
47 , m_threshold_crossed(false)
48{
49 m_amplitude = amplitude;
50 m_frequency = frequency;
51 update_phase_increment(frequency);
52}
53
54void Phasor::set_frequency(float frequency)
55{
56 m_frequency = frequency;
57 update_phase_increment(frequency);
58}
59
60void Phasor::update_phase_increment(double frequency)
61{
62 uint64_t s_rate = 48000U;
64 s_rate = Config::get_sample_rate();
65 }
66 m_phase_inc = frequency / (double)s_rate;
67}
68
69void Phasor::set_frequency_modulator(const std::shared_ptr<Node>& modulator)
70{
71 m_frequency_modulator = modulator;
72}
73
74void Phasor::set_amplitude_modulator(const std::shared_ptr<Node>& modulator)
75{
76 m_amplitude_modulator = modulator;
77}
78
80{
81 m_frequency_modulator = nullptr;
82 m_amplitude_modulator = nullptr;
83}
84
85double Phasor::process_sample(double input)
86{
87 double output = 0.0;
88
89 double effective_freq = m_frequency;
90
93 uint32_t state = m_frequency_modulator->m_state.load();
94 if (state & Utils::NodeState::PROCESSED) {
95 effective_freq += m_frequency_modulator->get_last_output();
96 } else {
97 effective_freq = m_frequency_modulator->process_sample(0.F);
99 }
100
101 update_phase_increment(effective_freq);
102 }
103
104 output = m_phase * m_amplitude;
105
108 uint32_t state = m_amplitude_modulator->m_state.load();
109 if (state & Utils::NodeState::PROCESSED) {
110 output *= m_amplitude_modulator->get_last_output();
111 } else {
112 output *= m_amplitude_modulator->process_sample(0.F);
114 }
115 }
116
117 output += m_offset;
118
120 if (m_phase >= 1.0) {
121 m_phase -= 1.0;
122 m_phase_wrapped = true;
123 }
124
125 m_last_output = output;
126
128 && !m_networked_node) {
129 notify_tick(output);
130 }
131
135 }
139 }
140
141 return output;
142}
143
144std::vector<double> Phasor::process_batch(unsigned int num_samples)
145{
146 std::vector<double> output(num_samples, 0.0);
147
148 for (unsigned int i = 0; i < num_samples; ++i) {
149 output[i] = process_sample(0.0); // Use 0.0 as default input
150 }
151
152 return output;
153}
154
155void Phasor::reset(float frequency, float amplitude, float offset, double phase)
156{
157 m_frequency = frequency;
158 m_amplitude = amplitude;
159 m_offset = offset;
160 m_phase = phase;
161
162 while (m_phase >= 1.0)
163 m_phase -= 1.0;
164 while (m_phase < 0.0)
165 m_phase += 1.0;
166
167 update_phase_increment(frequency);
168 m_last_output = 0.0;
169}
170
171void Phasor::on_phase_wrap(const NodeHook& callback)
172{
174}
175
176void Phasor::on_threshold(const NodeHook& callback, double threshold, bool /*rising*/)
177{
178 std::pair<NodeHook, double> entry = std::make_pair(callback, threshold);
179 for (auto& pair : m_threshold_callbacks) {
180 if (pair.first.target_type() == callback.target_type() && pair.second == threshold) {
181 return;
182 }
183 }
184 m_threshold_callbacks.push_back(entry);
185}
186
188{
189 for (auto it = m_threshold_callbacks.begin(); it != m_threshold_callbacks.end(); ++it) {
190 if (it->first.target_type() == callback.target_type()) {
191 m_threshold_callbacks.erase(it);
192 return true;
193 }
194 }
195 return false;
196}
197
198bool Phasor::remove_hook(const NodeHook& callback)
199{
200 bool removed_from_tick = safe_remove_callback(m_callbacks, callback);
201 bool removed_from_phase_wrap = safe_remove_callback(m_phase_wrap_callbacks, callback);
202 bool removed_from_threshold = remove_threshold_callback(callback);
203 return removed_from_tick || removed_from_phase_wrap || removed_from_threshold;
204}
205
206void Phasor::notify_tick(double value)
207{
208 update_context(value);
209
210 auto& ctx = get_last_context();
211 for (auto& callback : m_callbacks) {
212 callback(ctx);
213 }
214
215 if (m_phase_wrapped) {
216 for (auto& callback : m_phase_wrap_callbacks) {
217 callback(ctx);
218 }
219 }
220
221 for (auto& [callback, condition] : m_conditional_callbacks) {
222 if (condition(ctx)) {
223 callback(ctx);
224 }
225 }
226
227 for (auto& [callback, threshold] : m_threshold_callbacks) {
228 if (value >= threshold && !m_threshold_crossed) {
229 callback(ctx);
230 m_threshold_crossed = true;
231 } else if (value < threshold) {
232 m_threshold_crossed = false;
233 }
234 }
235}
236
252
268
269} // namespace MayaFlux::Nodes::Generator
float m_frequency
Base frequency of the generator.
NodeContext & get_last_context() override
Gets the last created context object.
Definition Generator.cpp:49
double m_amplitude
Base amplitude of the generator.
virtual void update_context(double value) override
Updates the context object for callbacks.
Definition Generator.cpp:19
double m_phase
Current phase of the generator.
std::shared_ptr< Node > m_frequency_modulator
Node that modulates the frequency.
Definition Phasor.hpp:304
void set_amplitude_modulator(const std::shared_ptr< Node > &modulator)
Sets a node to modulate the generator's amplitude.
Definition Phasor.cpp:74
bool remove_threshold_callback(const NodeHook &callback)
Removes a previously registered phase wrap callback.
Definition Phasor.cpp:187
bool m_threshold_crossed
Flag indicating whether the threshold has been crossed in the current sample.
Definition Phasor.hpp:338
void restore_state() override
Restores the node's state from the last save Recursively cascades through all connected modulator nod...
Definition Phasor.cpp:253
bool m_phase_wrapped
Flag indicating whether the phase has wrapped in the current sample.
Definition Phasor.hpp:333
void set_frequency(float frequency) override
Sets the generator's frequency.
Definition Phasor.cpp:54
bool remove_hook(const NodeHook &callback) override
Removes a previously registered callback.
Definition Phasor.cpp:198
std::shared_ptr< Node > m_amplitude_modulator
Node that modulates the amplitude.
Definition Phasor.hpp:309
std::vector< NodeHook > m_phase_wrap_callbacks
Collection of phase wrap-specific callback functions.
Definition Phasor.hpp:323
std::vector< double > process_batch(unsigned int num_samples) override
Processes multiple samples at once.
Definition Phasor.cpp:144
void update_phase_increment(double frequency)
Updates the phase increment based on a new frequency.
Definition Phasor.cpp:60
double m_phase_inc
Phase increment per sample.
Definition Phasor.hpp:294
std::vector< std::pair< NodeHook, double > > m_threshold_callbacks
Collection of threshold-specific callback functions with their thresholds.
Definition Phasor.hpp:328
void notify_tick(double value) override
Notifies all registered callbacks about a new sample.
Definition Phasor.cpp:206
void reset(float frequency=1, float amplitude=1.0, float offset=0, double phase=0.0)
Resets the generator's phase and parameters.
Definition Phasor.cpp:155
void on_threshold(const NodeHook &callback, double threshold, bool rising=true)
Registers a callback for every time the phasor crosses a threshold.
Definition Phasor.cpp:176
void set_frequency_modulator(const std::shared_ptr< Node > &modulator)
Sets a node to modulate the generator's frequency.
Definition Phasor.cpp:69
void save_state() override
Saves the node's current state for later restoration Recursively cascades through all connected modul...
Definition Phasor.cpp:237
Phasor(float frequency=1, double amplitude=1, float offset=0)
Basic constructor with fixed parameters.
Definition Phasor.cpp:6
double process_sample(double input=0.) override
Processes a single input sample and generates a phasor sample.
Definition Phasor.cpp:85
void clear_modulators()
Removes all modulation connections.
Definition Phasor.cpp:79
void on_phase_wrap(const NodeHook &callback)
Registers a callback for every phase wrap.
Definition Phasor.cpp:171
float m_offset
DC offset added to the output.
Definition Phasor.hpp:299
std::vector< NodeHook > m_callbacks
Collection of standard callback functions.
Definition Node.hpp:403
bool m_state_saved
tracks if the node's state has been saved by a snapshot operation
Definition Node.hpp:426
bool m_networked_node
Flag indicating if the node is part of a NodeNetwork This flag is used to disable event firing when t...
Definition Node.hpp:421
double m_last_output
The most recent sample value generated by this oscillator.
Definition Node.hpp:374
bool m_fire_events_during_snapshot
Internal flag controlling whether notify_tick fires during state snapshots Default: false (events don...
Definition Node.hpp:448
std::vector< std::pair< NodeHook, NodeCondition > > m_conditional_callbacks
Collection of conditional callback functions with their predicates.
Definition Node.hpp:413
uint32_t get_sample_rate()
Gets the sample rate from the default engine.
Definition Config.cpp:46
std::function< void(NodeContext &)> NodeHook
Callback function type for node processing events.
Definition NodeUtils.hpp:25
void atomic_add_flag(std::atomic< Utils::NodeState > &state, Utils::NodeState flag)
Atomically adds a flag to a node state.
Definition NodeUtils.cpp:96
bool safe_add_callback(std::vector< NodeHook > &callbacks, const NodeHook &callback)
Safely adds a callback to a collection if it doesn't already exist.
Definition NodeUtils.cpp:33
void try_reset_processed_state(std::shared_ptr< Node > node)
Attempts to reset the processed state of a node.
void atomic_inc_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically increments the modulator count by a specified amount.
void atomic_dec_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically decrements the modulator count by a specified amount.
bool safe_remove_callback(std::vector< NodeHook > &callbacks, const NodeHook &callback)
Safely removes a callback from a collection.
Definition NodeUtils.cpp:51
@ PROCESSED
Node has been processed this cycle.
Definition Utils.hpp:34
bool is_engine_initialized()
Checks if the default audio engine is initialized.
Definition Config.cpp:9