Loading...
Searching...
No Matches
Sweeper.hpp
1#pragma once
2#include <ossia/dataflow/exec_state_facade.hpp>
3#include <ossia/dataflow/execution_state.hpp>
4#include <ossia/network/common/path.hpp>
5
6#include <QCoreApplication>
7#include <QTimer>
8
9#include <AvndProcesses/AddressTools.hpp>
10#include <halp/audio.hpp>
11#include <halp/controls.hpp>
12#include <halp/meta.hpp>
13#include <rnd/random.hpp>
14
15namespace avnd_tools
16{
17
18// Given:
19// address: /foo.*/value
20// -> /foo.1/value, /foo.2/value, etc.
21// input: [1, 34, 6, 4]
22// -> writes 1 on foo.1/value, 34 on foo.2/value, etc
23
25{
26 halp_meta(name, "Sweeper")
27 halp_meta(author, "ossia team")
28 halp_meta(category, "Control/Data processing")
29 halp_meta(description, "Sweep a message to all nodes matching a pattern")
30 halp_meta(c_name, "avnd_pattern_sweep")
31 halp_meta(uuid, "55f4fe13-f71b-4c20-ac32-74668e82664c")
32 halp_meta(manual_url, "https://ossia.io/score-docs/processes/sweeper.html")
33
34 struct
35 {
36 halp::val_port<"Input", ossia::value> input;
37 PatternSelector pattern;
38
39 halp::time_chooser<"Interval"> time;
40 struct
41 {
42 halp__enum("Mode", Upwards, Upwards, Downwards, UpDown, RandomWalk, Random);
43 } mode;
44 } inputs;
45
46 struct
47 {
48
49 } outputs;
50
51 std::size_t current_parameter = 0;
52 double last_message_sent_pos = std::numeric_limits<double>::lowest();
53 enum
54 {
55 up,
56 down
57 } direction{up};
58 rnd::pcg pcg_state;
59
60 void prepare()
61 {
62 std::random_device dev;
63 pcg_state.seed(dev);
64 }
65
66 void next()
67 {
68 if(this->roots.size() <= 1)
69 {
70 current_parameter = 0;
71 return;
72 }
73 using mode = decltype(inputs.mode)::enum_type;
74 switch(inputs.mode)
75 {
76 case mode::Upwards:
77 current_parameter++;
78 current_parameter = current_parameter % this->roots.size();
79 break;
80 case mode::Downwards:
81 if(current_parameter == 0)
82 current_parameter = this->roots.size() - 1;
83 else
84 current_parameter--;
85 break;
86 case mode::UpDown: {
87 case_updown:
88 if(direction == up)
89 {
90 if(current_parameter + 1 == this->roots.size())
91 {
92 direction = down;
93 current_parameter--;
94 }
95 else
96 {
97 current_parameter++;
98 }
99 }
100 else
101 {
102 if(current_parameter == 0)
103 {
104 direction = up;
105 current_parameter++;
106 }
107 else
108 {
109 current_parameter--;
110 }
111 }
112 break;
113 }
114 case mode::RandomWalk: {
115 if(std::bernoulli_distribution{}(pcg_state))
116 direction = up;
117 else
118 direction = down;
119 goto case_updown;
120 break;
121 }
122 case mode::Random: {
123 auto dist = std::uniform_int_distribution<int>(0, std::ssize(this->roots) - 1);
124 current_parameter = dist(pcg_state);
125 break;
126 }
127 }
128 }
129
130 using tick = halp::tick_musical;
131 void operator()(const halp::tick_musical& tk)
132 {
133 auto elapsed_ns = (tk.position_in_nanoseconds - last_message_sent_pos);
134 if(!m_path || this->roots.empty())
135 return;
136
137 if(elapsed_ns < inputs.time.value * 1e9)
138 return;
139 last_message_sent_pos = tk.position_in_nanoseconds;
140
141 if(current_parameter >= 0 && current_parameter < this->roots.size())
142 {
143 if(auto p = roots[current_parameter]->get_parameter())
144 {
145 p->push_value(inputs.input.value);
146 }
147
148 next();
149 }
150 }
151};
152}
Definition AddressTools.hpp:21
Definition AddressTools.hpp:28
Definition Sweeper.hpp:25