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  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