1 #include <ossia/detail/jthread.hpp>
2 #include <ossia/detail/triple_buffer.hpp>
3 #include <halp/mappers.hpp>
4 #include <AvndProcesses/AddressTools.hpp>
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")
21 halp::val_port<
"Input", ossia::value> input;
23 struct : halp::time_chooser<
"Delay", halp::range{0.0001, 30., 0.2}>
25 using mapper = halp::log_mapper<std::ratio<95, 100>>;
29 halp::knob_f32<
"Smooth", halp::range{0., 1., 0.5}> smooth;
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())
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);
49 smooth_recursively(smooth, cur, 1.f - s);
56 p->get_parameter()->push_value(cur);
68 m_smooth.store(inputs.smooth.value, std::memory_order_relaxed);
69 m_buffer.produce(inputs.input.value);
72 std::chrono::nanoseconds(int64_t(1e9 * inputs.delay.value)),
73 std::memory_order_release);
74 if(!m_thread.joinable() || inputs.pattern.devices_dirty)
83 void operator()(
const int& in,
int& filtered)
85 filtered = in * a + filtered * (1.0f - a);
88 void operator()(
const float& in,
float& filtered)
90 filtered = in * a + filtered * (1.0f - a);
93 void operator()(
const bool& in,
bool& filtered)
95 filtered = in * a + filtered * (1.0f - a);
98 template <std::
size_t N>
99 void operator()(
const std::array<float, N>& in, std::array<float, N>& filtered)
101 for(std::size_t i = 0; i < N; i++)
102 filtered[i] = in[i] * a + filtered[i] * (1.0f - a);
106 operator()(
const std::vector<ossia::value>& in, std::vector<ossia::value>& filtered)
108 if(in.size() != filtered.size()) [[unlikely]]
109 filtered.resize(in.size());
111 for(std::size_t i = 0; i < in.size(); i++)
113 if(filtered[i].get_type() != in[i].get_type()) [[unlikely]]
116 ossia::apply(*
this, in[i], filtered[i]);
120 void operator()(
const std::string& in, std::string& filtered) { filtered = in; }
121 template <
typename T>
122 void operator()(
const T& in, T& filtered)
127 template <
typename T>
128 void operator()(
const ossia::impulse& in, T& filtered)
130 (*this)(filtered, filtered);
133 void operator()(
const ossia::impulse& in, ossia::impulse& filtered) { }
134 template <
typename T,
typename U>
135 void operator()(
const T& in, U& filtered)
141 smooth_recursively(ossia::value& prev,
const ossia::value& next,
float alpha)
143 if(prev.get_type() != next.get_type()) [[unlikely]]
147 if(prev.valid() && next.valid())
148 ossia::apply(
do_smooth{alpha}, next, prev);
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{}};