MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Impulse.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Generator.hpp"
4
6
7/**
8 * @class Impulse
9 * @brief Impulse generator node
10 *
11 * The Impulse class generates a single spike followed by zeros, which is a fundamental
12 * signal used in digital signal processing. It produces a value of 1.0 (or specified amplitude)
13 * at specified intervals, and 0.0 elsewhere.
14 *
15 * Key features:
16 * - Configurable frequency, amplitude, and DC offset
17 * - Support for frequency modulation (changing impulse rate)
18 * - Support for amplitude modulation (changing impulse height)
19 * - Automatic registration with the node graph manager (optional)
20 * - Precise timing control for impulse generation
21 *
22 * Impulse generators are used extensively in audio and signal processing for:
23 * - Triggering events at specific intervals
24 * - Testing system responses (impulse response)
25 * - Creating click trains and metronome-like signals
26 * - Serving as the basis for more complex event-based generators
27 * - Synchronization signals for other generators
28 *
29 * The implementation uses a phase accumulation approach similar to other oscillators
30 * but only outputs a non-zero value at the beginning of each cycle.
31 */
32class MAYAFLUX_API Impulse : public Generator, public std::enable_shared_from_this<Impulse> {
33public:
34 /**
35 * @brief Basic constructor with fixed parameters
36 * @param frequency Impulse repetition rate in Hz (default: 1Hz, one impulse per second)
37 * @param amplitude Impulse amplitude (default: 1.0)
38 * @param offset DC offset added to the output (default: 0.0)
39 *
40 * Creates an impulse generator with fixed frequency and amplitude.
41 */
42 Impulse(float frequency = 1, double amplitude = 1, float offset = 0);
43
44 /**
45 * @brief Constructor with frequency modulation
46 * @param frequency_modulator Node that modulates the frequency
47 * @param frequency Base frequency in Hz (default: 1Hz)
48 * @param amplitude Impulse amplitude (default: 1.0)
49 * @param offset DC offset added to the output (default: 0.0)
50 *
51 * Creates an impulse generator with frequency modulation, where the actual frequency
52 * is the base frequency plus the output of the modulator node.
53 */
54 Impulse(const std::shared_ptr<Node>& frequency_modulator, float frequency = 1, double amplitude = 1, float offset = 0);
55
56 /**
57 * @brief Constructor with amplitude modulation
58 * @param frequency Impulse repetition rate in Hz
59 * @param amplitude_modulator Node that modulates the amplitude
60 * @param amplitude Base amplitude (default: 1.0)
61 * @param offset DC offset added to the output (default: 0.0)
62 *
63 * Creates an impulse generator with amplitude modulation, where the actual amplitude
64 * is the base amplitude multiplied by the output of the modulator node.
65 */
66 Impulse(float frequency, const std::shared_ptr<Node>& amplitude_modulator, double amplitude = 1, float offset = 0);
67
68 /**
69 * @brief Constructor with both frequency and amplitude modulation
70 * @param frequency_modulator Node that modulates the frequency
71 * @param amplitude_modulator Node that modulates the amplitude
72 * @param frequency Base frequency in Hz (default: 1Hz)
73 * @param amplitude Base amplitude (default: 1.0)
74 * @param offset DC offset added to the output (default: 0.0)
75 *
76 * Creates an impulse generator with both frequency and amplitude modulation,
77 * enabling complex timing and amplitude control.
78 */
79 Impulse(const std::shared_ptr<Node>& frequency_modulator, const std::shared_ptr<Node>& amplitude_modulator,
80 float frequency = 1, double amplitude = 1, float offset = 0);
81
82 /**
83 * @brief Virtual destructor
84 */
85 ~Impulse() override = default;
86
87 /**
88 * @brief Processes a single input sample and generates an impulse sample
89 * @param input Input sample (used for modulation when modulators are connected)
90 * @return Generated impulse sample (1.0 at the start of each cycle, 0.0 elsewhere)
91 *
92 * This method advances the generator's phase and computes the next
93 * sample of the impulse train, applying any modulation from connected nodes.
94 */
95 double process_sample(double input = 0.) override;
96
97 /**
98 * @brief Processes multiple samples at once
99 * @param num_samples Number of samples to generate
100 * @return Vector of generated impulse samples
101 *
102 * This method is more efficient than calling process_sample() repeatedly
103 * when generating multiple samples at once.
104 */
105 std::vector<double> process_batch(unsigned int num_samples) override;
106
107 /**
108 * @brief Sets the generator's frequency
109 * @param frequency New frequency in Hz
110 *
111 * Updates the generator's frequency, which controls how often impulses occur.
112 */
113 void set_frequency(float frequency) override;
114
115 /**
116 * @brief Gets the current base frequency
117 * @return Current frequency in Hz
118 */
119 inline float get_frequency() const { return m_frequency; }
120
121 /**
122 * @brief Sets all basic parameters at once
123 * @param frequency New frequency in Hz
124 * @param amplitude New amplitude
125 * @param offset New DC offset
126 *
127 * This is more efficient than setting parameters individually
128 * when multiple parameters need to be changed.
129 */
130 inline void set_params(float frequency, double amplitude, float offset)
131 {
132 m_amplitude = amplitude;
133 m_offset = offset;
134 set_frequency(frequency);
135 }
136
137 /**
138 * @brief Sets a node to modulate the generator's frequency
139 * @param modulator Node that will modulate the frequency
140 *
141 * The modulator's output is added to the base frequency,
142 * enabling dynamic control of impulse timing.
143 */
144 void set_frequency_modulator(const std::shared_ptr<Node>& modulator);
145
146 /**
147 * @brief Sets a node to modulate the generator's amplitude
148 * @param modulator Node that will modulate the amplitude
149 *
150 * The modulator's output is multiplied with the base amplitude,
151 * enabling dynamic control of impulse height.
152 */
153 void set_amplitude_modulator(const std::shared_ptr<Node>& modulator);
154
155 /**
156 * @brief Removes all modulation connections
157 *
158 * After calling this method, the generator will use only its
159 * base frequency and amplitude without any modulation.
160 */
161 void clear_modulators();
162
163 /**
164 * @brief Resets the generator's phase and parameters
165 * @param frequency New frequency in Hz (default: 1Hz)
166 * @param amplitude New amplitude (default: 1.0)
167 * @param offset New DC offset (default: 0)
168 *
169 * This method resets the generator's internal state and parameters,
170 * effectively restarting it from the beginning of its cycle.
171 */
172 void reset(float frequency = 1, float amplitude = 1.0F, float offset = 0);
173
174 /**
175 * @brief Registers a callback for every impulse
176 * @param callback Function to call when an impulse occurs
177 *
178 * This method allows external components to monitor or react to
179 * every impulse produced by the generator. The callback
180 * receives a GeneratorContext containing the generated value and
181 * generator parameters like frequency, amplitude, and phase.
182 */
183 void on_impulse(const TypedHook<GeneratorContext>& callback);
184
185 /**
186 * @brief Removes a previously registered callback
187 * @param callback The callback function to remove
188 * @return True if the callback was found and removed, false otherwise
189 *
190 * Unregisters a callback previously added with on_tick(), stopping
191 * it from receiving further notifications about generated samples.
192 */
193 bool remove_hook(const TypedHook<GeneratorContext>& callback);
194
195 /**
196 * @brief Removes all registered callbacks
197 *
198 * Clears all standard and conditional callbacks, effectively
199 * disconnecting all external components from this generator's
200 * notification system. Useful when reconfiguring the processing
201 * graph or shutting down components.
202 */
203 inline void remove_all_hooks() override
204 {
205 m_callbacks.clear();
206 m_conditional_callbacks.clear();
207 m_impulse_callbacks.clear();
208 }
209
210 void save_state() override;
211 void restore_state() override;
212
213 /**
214 * @brief Retrieves the current modulators connected to this node
215 * @return Vector of pairs containing the modulator role and the corresponding node
216 */
217 [[nodiscard]] std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>> get_modulators() const override;
218
219protected:
220 /**
221 * @brief Notifies all registered callbacks about a new sample
222 * @param value The newly generated sample
223 *
224 * This method is called internally whenever a new sample is generated,
225 * creating the appropriate context and invoking all registered callbacks
226 * that should receive notification about this sample.
227 */
228 void notify_tick(double value) override;
229
230private:
231 /**
232 * @brief Phase increment per sample
233 *
234 * This value determines how much the phase advances with each sample,
235 * controlling the generator's frequency.
236 */
237 double m_phase_inc {};
238
239 /**
240 * @brief DC offset added to the output
241 */
242 float m_offset;
243
244 /**
245 * @brief Node that modulates the frequency
246 */
247 std::shared_ptr<Node> m_frequency_modulator;
248
249 /**
250 * @brief Node that modulates the amplitude
251 */
252 std::shared_ptr<Node> m_amplitude_modulator;
253
254 /**
255 * @brief Updates the phase increment based on a new frequency
256 * @param frequency New frequency in Hz
257 *
258 * This method calculates the phase increment needed to produce
259 * impulses at the specified frequency at the current sample rate.
260 */
261 void update_phase_increment(double frequency);
262
263 /**
264 * @brief Collection of impulse-specific callback functions
265 */
266 std::vector<TypedHook<GeneratorContext>> m_impulse_callbacks;
267
269
270 double m_saved_phase {};
271 float m_saved_frequency {};
272 float m_saved_offset {};
273 double m_saved_phase_inc {};
274 double m_saved_last_output {};
275};
276}
Core::GlobalInputConfig input
Definition Config.cpp:36
double frequency
Base class for all signal and pattern generators in Maya Flux.
std::shared_ptr< Node > m_amplitude_modulator
Node that modulates the amplitude.
Definition Impulse.hpp:252
~Impulse() override=default
Virtual destructor.
void set_params(float frequency, double amplitude, float offset)
Sets all basic parameters at once.
Definition Impulse.hpp:130
std::vector< TypedHook< GeneratorContext > > m_impulse_callbacks
Collection of impulse-specific callback functions.
Definition Impulse.hpp:266
float get_frequency() const
Gets the current base frequency.
Definition Impulse.hpp:119
float m_offset
DC offset added to the output.
Definition Impulse.hpp:242
void remove_all_hooks() override
Removes all registered callbacks.
Definition Impulse.hpp:203
std::shared_ptr< Node > m_frequency_modulator
Node that modulates the frequency.
Definition Impulse.hpp:247
Impulse generator node.
Definition Impulse.hpp:32
std::function< void(ContextT &)> TypedHook
Callback function type for node processing events, parameterised on context type.
Definition NodeUtils.hpp:28