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