MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Tasks.cpp
Go to the documentation of this file.
1#include "Tasks.hpp"
5
7
9
10namespace MayaFlux::Kriya {
11
12std::shared_ptr<Vruta::Routine> metro(double interval_seconds, std::function<void()> callback, Vruta::ProcessingToken token)
13{
15 auto coro = [](double interval, std::function<void()> cb) -> Vruta::GraphicsRoutine {
16 uint64_t units = Vruta::seconds_to_frames(interval);
17 auto& p = co_await GetGraphicsPromise {};
18 while (!p.should_terminate) {
19 cb();
20 co_await FrameDelay { .frames_to_wait = units };
21 }
22 };
23 return std::make_shared<Vruta::GraphicsRoutine>(coro(interval_seconds, std::move(callback)));
24 }
25 auto coro = [](double interval, std::function<void()> cb) -> Vruta::SoundRoutine {
26 uint64_t units = Vruta::seconds_to_samples(interval);
27 auto& p = co_await GetAudioPromise {};
28 while (!p.should_terminate) {
29 cb();
30 co_await SampleDelay { units };
31 }
32 };
33 return std::make_shared<Vruta::SoundRoutine>(coro(interval_seconds, std::move(callback)));
34}
35
36std::shared_ptr<Vruta::Routine> sequence(std::vector<std::pair<double, std::function<void()>>> sequence, Vruta::ProcessingToken token)
37{
39 auto coro = [](std::vector<std::pair<double, std::function<void()>>> seq) -> Vruta::GraphicsRoutine {
40 for (const auto& [time, cb] : seq) {
42 cb();
43 }
44 };
45 return std::make_shared<Vruta::GraphicsRoutine>(coro(std::move(sequence)));
46 }
47 auto coro = [](std::vector<std::pair<double, std::function<void()>>> seq) -> Vruta::SoundRoutine {
48 for (const auto& [time, cb] : seq) {
49 co_await SampleDelay { Vruta::seconds_to_samples(time) };
50 cb();
51 }
52 };
53 return std::make_shared<Vruta::SoundRoutine>(coro(std::move(sequence)));
54}
55
56Vruta::SoundRoutine line(float start_value, float end_value, float duration_seconds, uint32_t step_duration, bool restartable)
57{
58 auto& promise_ref = co_await GetAudioPromise {};
59
60 promise_ref.set_state("current_value", start_value);
61 promise_ref.set_state("end_value", end_value);
62 promise_ref.set_state("restart", false);
63
64 const unsigned int sample_rate = Vruta::s_registered_sample_rate;
65 if (step_duration < 1) {
66 step_duration = 1;
67 }
68
69 uint64_t total_samples = (uint64_t)duration_seconds * sample_rate;
70 float per_sample_step = (end_value - start_value) / (float)total_samples;
71 float sample_step = per_sample_step * (float)step_duration;
72
73 promise_ref.set_state("step", sample_step);
74
75 for (;;) {
76 auto current_value = promise_ref.get_state<float>("current_value");
77 auto last_value = promise_ref.get_state<float>("end_value");
78 auto step = promise_ref.get_state<float>("step");
79
80 if (!current_value || !last_value || !step) {
81 MF_ERROR(Journal::Component::Kriya, Journal::Context::CoroutineScheduling, "Line task state not properly initialized");
82 co_return;
83 }
84
85 *current_value = start_value;
86
87 uint64_t samples_elapsed = 0;
88
89 co_await SampleDelay { 1 };
90
91 while (samples_elapsed < total_samples) {
92 *current_value += *step;
93
94 if ((*step > 0 && *current_value >= *last_value) || (*step < 0 && *current_value <= *last_value)) {
95 *current_value = *last_value;
96 }
97
98 samples_elapsed += step_duration;
99 co_await SampleDelay { step_duration };
100 }
101
102 if (!restartable)
103 break;
104
105 auto restart_requested = promise_ref.get_state<bool>("restart");
106 if (restart_requested && *restart_requested) {
107 *restart_requested = false;
108 continue;
109 }
110
111 promise_ref.auto_resume = false;
112 co_await std::suspend_always {};
113 }
114}
115
116std::shared_ptr<Vruta::Routine> pattern(std::function<std::any(uint64_t)> pattern_func, std::function<void(std::any)> callback, double interval_seconds, Vruta::ProcessingToken token)
117{
119 auto coro = [](std::function<std::any(uint64_t)> fn, std::function<void(std::any)> cb, double interval) -> Vruta::GraphicsRoutine {
120 uint64_t units = Vruta::seconds_to_frames(interval);
121 uint64_t step = 0;
122 while (true) {
123 cb(fn(step++));
124 co_await FrameDelay { .frames_to_wait = units };
125 }
126 };
127 return std::make_shared<Vruta::GraphicsRoutine>(coro(std::move(pattern_func), std::move(callback), interval_seconds));
128 }
129
130 auto coro = [](std::function<std::any(uint64_t)> fn, std::function<void(std::any)> cb, double interval) -> Vruta::SoundRoutine {
131 uint64_t units = Vruta::seconds_to_samples(interval);
132 uint64_t step = 0;
133 while (true) {
134 cb(fn(step++));
135 co_await SampleDelay { units };
136 }
137 };
138 return std::make_shared<Vruta::SoundRoutine>(coro(std::move(pattern_func), std::move(callback), interval_seconds));
139}
140
142 std::function<void()> callback,
143 std::shared_ptr<Nodes::Generator::Logic> logic_node,
144 bool open)
145{
146 auto& promise_ref = co_await GetAudioPromise {};
147
148 if (!logic_node) {
149 logic_node = std::make_shared<Nodes::Generator::Logic>(0.5);
150 }
151
152 if (open) {
153 logic_node->while_true([callback](const Nodes::NodeContext& /*ctx*/) {
154 callback();
155 });
156 } else {
157 logic_node->while_false([callback](const Nodes::NodeContext& /*ctx*/) {
158 callback();
159 });
160 }
161
162 while (true) {
163 if (promise_ref.should_terminate) {
164 break;
165 }
166
167 logic_node->process_sample(0.0);
168
169 co_await SampleDelay { 1 };
170 }
171}
172
174 bool target_state,
175 std::function<void()> callback,
176 std::shared_ptr<Nodes::Generator::Logic> logic_node)
177{
178 auto& promise_ref = co_await GetAudioPromise {};
179
180 if (!logic_node) {
181 logic_node = std::make_shared<Nodes::Generator::Logic>(0.5);
182 }
183
184 logic_node->on_change_to(target_state,
185 [callback](const Nodes::NodeContext& /*ctx*/) {
186 callback();
187 });
188
189 while (true) {
190 if (promise_ref.should_terminate) {
191 break;
192 }
193
194 logic_node->process_sample(0.0);
195
196 co_await SampleDelay { 1 };
197 }
198}
199
201 std::function<void()> callback,
202 std::shared_ptr<Nodes::Generator::Logic> logic_node)
203{
204 auto& promise_ref = co_await GetAudioPromise {};
205
206 if (!logic_node) {
207 logic_node = std::make_shared<Nodes::Generator::Logic>(0.5);
208 }
209
210 logic_node->on_change([callback](const Nodes::NodeContext& /*ctx*/) {
211 callback();
212 });
213
214 while (true) {
215 if (promise_ref.should_terminate) {
216 break;
217 }
218
219 logic_node->process_sample(0.0);
220
221 co_await SampleDelay { 1 };
222 }
223}
224}
#define MF_ERROR(comp, ctx,...)
Base context class for node callbacks.
Definition Node.hpp:53
A C++20 coroutine-based graphics processing task with frame-accurate timing.
Definition Routine.hpp:496
A C++20 coroutine-based audio processing task with sample-accurate timing.
Definition Routine.hpp:316
@ CoroutineScheduling
Coroutine scheduling and temporal coordination (Vruta::TaskScheduler)
@ Kriya
Automatable tasks and fluent scheduling api for Nodes and Buffers.
Vruta::SoundRoutine Gate(std::function< void()> callback, std::shared_ptr< Nodes::Generator::Logic > logic_node, bool open)
Coroutine that executes callback continuously while logic node outputs true.
Definition Tasks.cpp:141
Vruta::SoundRoutine Toggle(std::function< void()> callback, std::shared_ptr< Nodes::Generator::Logic > logic_node)
Coroutine that executes callback on any logic node state change.
Definition Tasks.cpp:200
Vruta::SoundRoutine line(float start_value, float end_value, float duration_seconds, uint32_t step_duration, bool restartable)
Creates a continuous interpolation generator between two values over time.
Definition Tasks.cpp:56
std::shared_ptr< Vruta::Routine > sequence(std::vector< std::pair< double, std::function< void()> > > sequence, Vruta::ProcessingToken token)
Creates a temporal sequence that executes callbacks at specified time offsets.
Definition Tasks.cpp:36
Vruta::SoundRoutine Trigger(bool target_state, std::function< void()> callback, std::shared_ptr< Nodes::Generator::Logic > logic_node)
Coroutine that executes callback when logic node changes to specific state.
Definition Tasks.cpp:173
std::shared_ptr< Vruta::Routine > metro(double interval_seconds, std::function< void()> callback, Vruta::ProcessingToken token)
Creates a periodic event generator that executes a callback at regular intervals.
Definition Tasks.cpp:12
std::shared_ptr< Vruta::Routine > pattern(std::function< std::any(uint64_t)> pattern_func, std::function< void(std::any)> callback, double interval_seconds, Vruta::ProcessingToken token)
Creates a generative algorithm that produces values based on a pattern function.
Definition Tasks.cpp:116
uint64_t seconds_to_samples(double seconds, uint32_t sample_rate=s_registered_sample_rate)
Convert seconds to samples at a given sample rate.
@ FRAME_ACCURATE
Coroutine is frame-accurate.
uint32_t s_registered_sample_rate
Definition ChronUtils.hpp:5
uint64_t seconds_to_frames(double seconds, uint32_t frame_rate=s_registered_frame_rate)
Convert seconds to frames at a given frame rate.
graphics-domain awaiter for frame-accurate timing delays
Templated awaitable for accessing a coroutine's promise object.
Awaitable object for precise sample-accurate timing delays.