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 
15 namespace 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 
33  struct
34  {
35  halp::val_port<"Input", ossia::value> input;
36  PatternSelector pattern;
37 
38  halp::time_chooser<"Interval"> time;
39  struct
40  {
41  halp__enum("Mode", Upwards, Upwards, Downwards, UpDown, RandomWalk, Random);
42  } mode;
43  } inputs;
44 
45  struct
46  {
47 
48  } outputs;
49 
50  std::size_t current_parameter = 0;
51  double last_message_sent_pos = std::numeric_limits<double>::lowest();
52  enum
53  {
54  up,
55  down
56  } direction{up};
57  rnd::pcg pcg_state;
58 
59  void prepare()
60  {
61  std::random_device dev;
62  pcg_state.seed(dev);
63  }
64 
65  void next()
66  {
67  if(this->roots.size() <= 1)
68  {
69  current_parameter = 0;
70  return;
71  }
72  using mode = decltype(inputs.mode)::enum_type;
73  switch(inputs.mode)
74  {
75  case mode::Upwards:
76  current_parameter++;
77  current_parameter = current_parameter % this->roots.size();
78  break;
79  case mode::Downwards:
80  if(current_parameter == 0)
81  current_parameter = this->roots.size() - 1;
82  else
83  current_parameter--;
84  break;
85  case mode::UpDown: {
86  case_updown:
87  if(direction == up)
88  {
89  if(current_parameter + 1 == this->roots.size())
90  {
91  direction = down;
92  current_parameter--;
93  }
94  else
95  {
96  current_parameter++;
97  }
98  }
99  else
100  {
101  if(current_parameter == 0)
102  {
103  direction = up;
104  current_parameter++;
105  }
106  else
107  {
108  current_parameter--;
109  }
110  }
111  break;
112  }
113  case mode::RandomWalk: {
114  if(std::bernoulli_distribution{}(pcg_state))
115  direction = up;
116  else
117  direction = down;
118  goto case_updown;
119  break;
120  }
121  case mode::Random: {
122  auto dist = std::uniform_int_distribution<int>(0, std::ssize(this->roots) - 1);
123  current_parameter = dist(pcg_state);
124  break;
125  }
126  }
127  }
128 
129  using tick = halp::tick_musical;
130  void operator()(const halp::tick_musical& tk)
131  {
132  auto elapsed_ns = (tk.position_in_nanoseconds - last_message_sent_pos);
133  if(!m_path || this->roots.empty())
134  return;
135 
136  if(elapsed_ns < inputs.time.value * 1e9)
137  return;
138  last_message_sent_pos = tk.position_in_nanoseconds;
139 
140  if(current_parameter >= 0 && current_parameter < this->roots.size())
141  {
142  if(auto p = roots[current_parameter]->get_parameter())
143  {
144  p->push_value(inputs.input.value);
145  }
146 
147  next();
148  }
149  }
150 };
151 }
Definition: AddressTools.hpp:20
Definition: AddressTools.hpp:27
Definition: Sweeper.hpp:25