Spammer.hpp
1 #include <ossia/detail/jthread.hpp>
2 #include <ossia/detail/triple_buffer.hpp>
3 #include <halp/mappers.hpp>
4 #include <AvndProcesses/AddressTools.hpp>
5 
6 namespace avnd_tools
7 {
8 
10 {
11  halp_meta(name, "Spammer")
12  halp_meta(author, "ossia team")
13  halp_meta(category, "Control/Data processing")
14  halp_meta(description, "Send a message at a given frequency")
15  halp_meta(c_name, "avnd_pattern_spam")
16  halp_meta(manual_url, "https://ossia.io/score-docs/processes/spammer.html")
17  halp_meta(uuid, "0fa9415b-dcda-4ab8-b3f5-353c5d35fc8a")
18 
19  struct
20  {
21  halp::val_port<"Input", ossia::value> input;
22 
23  struct : halp::time_chooser<"Delay", halp::range{0.0001, 30., 0.2}>
24  {
25  using mapper = halp::log_mapper<std::ratio<95, 100>>;
26  } delay;
27 
28  PatternSelector pattern;
29  halp::knob_f32<"Smooth", halp::range{0., 1., 0.5}> smooth;
30  } inputs;
31 
32  struct
33  {
34 
35  } outputs;
36 
37  void update()
38  {
39  m_thread = std::jthread{};
40  inputs.pattern.reprocess();
41  m_thread = std::jthread([this, roots = this->roots, cur = ossia::value{},
42  smooth = ossia::value{}](std::stop_token tk) mutable {
43  while(!tk.stop_requested())
44  {
45  std::this_thread::sleep_for(m_delay.load(std::memory_order_relaxed));
46  float s = m_smooth.load(std::memory_order_relaxed);
47  this->m_buffer.consume(cur);
48 
49  smooth_recursively(smooth, cur, 1.f - s);
50  cur = smooth;
51 
52  if(cur.valid())
53  {
54  for(auto p : roots)
55  {
56  p->get_parameter()->push_value(cur);
57  }
58  }
59  }
60  });
61  }
62 
63  void operator()()
64  {
65  if(!m_path)
66  return;
67 
68  m_smooth.store(inputs.smooth.value, std::memory_order_relaxed);
69  m_buffer.produce(inputs.input.value);
70 
71  m_delay.store(
72  std::chrono::nanoseconds(int64_t(1e9 * inputs.delay.value)),
73  std::memory_order_release);
74  if(!m_thread.joinable() || inputs.pattern.devices_dirty)
75  {
76  update();
77  }
78  }
79 
80  struct do_smooth
81  {
82  float a{};
83  void operator()(const int& in, int& filtered)
84  {
85  filtered = in * a + filtered * (1.0f - a);
86  }
87 
88  void operator()(const float& in, float& filtered)
89  {
90  filtered = in * a + filtered * (1.0f - a);
91  }
92 
93  void operator()(const bool& in, bool& filtered)
94  {
95  filtered = in * a + filtered * (1.0f - a);
96  }
97 
98  template <std::size_t N>
99  void operator()(const std::array<float, N>& in, std::array<float, N>& filtered)
100  {
101  for(std::size_t i = 0; i < N; i++)
102  filtered[i] = in[i] * a + filtered[i] * (1.0f - a);
103  }
104 
105  void
106  operator()(const std::vector<ossia::value>& in, std::vector<ossia::value>& filtered)
107  {
108  if(in.size() != filtered.size()) [[unlikely]]
109  filtered.resize(in.size());
110 
111  for(std::size_t i = 0; i < in.size(); i++)
112  {
113  if(filtered[i].get_type() != in[i].get_type()) [[unlikely]]
114  filtered[i] = in[i];
115  else
116  ossia::apply(*this, in[i], filtered[i]);
117  }
118  }
119 
120  void operator()(const std::string& in, std::string& filtered) { filtered = in; }
121  template <typename T>
122  void operator()(const T& in, T& filtered)
123  {
124  filtered = in;
125  }
126 
127  template <typename T>
128  void operator()(const ossia::impulse& in, T& filtered)
129  {
130  (*this)(filtered, filtered);
131  }
132 
133  void operator()(const ossia::impulse& in, ossia::impulse& filtered) { }
134  template <typename T, typename U>
135  void operator()(const T& in, U& filtered)
136  {
137  }
138  };
139 
140  static void
141  smooth_recursively(ossia::value& prev, const ossia::value& next, float alpha)
142  {
143  if(prev.get_type() != next.get_type()) [[unlikely]]
144  prev = next;
145  else [[likely]]
146  {
147  if(prev.valid() && next.valid())
148  ossia::apply(do_smooth{alpha}, next, prev);
149  }
150  }
151 
152  static_assert(std::atomic<std::chrono::nanoseconds>::is_always_lock_free);
153  std::atomic<std::chrono::nanoseconds> m_delay{std::chrono::nanoseconds{100000}};
154  std::atomic<float> m_smooth{};
155  std::jthread m_thread;
156  ossia::triple_buffer<ossia::value> m_buffer{ossia::value{}};
157 
158  ossia::value m_prev;
159 };
160 }
Definition: AddressTools.hpp:21
Definition: AddressTools.hpp:28
Definition: Spammer.hpp:81
Definition: Spammer.hpp:10