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(uuid,
"0fa9415b-dcda-4ab8-b3f5-353c5d35fc8a")
20 halp::val_port<
"Input", ossia::value> input;
22 struct : halp::time_chooser<
"Delay", halp::range{0.0001, 30., 0.2}>
24 using mapper = halp::log_mapper<std::ratio<95, 100>>;
28 halp::knob_f32<
"Smooth", halp::range{0., 1., 0.5}> smooth;
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())
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);
48 smooth_recursively(smooth, cur, 1.f - s);
55 p->get_parameter()->push_value(cur);
67 m_smooth.store(inputs.smooth.value, std::memory_order_relaxed);
68 m_buffer.produce(inputs.input.value);
71 std::chrono::nanoseconds(int64_t(1e9 * inputs.delay.value)),
72 std::memory_order_release);
73 if(!m_thread.joinable() || inputs.pattern.devices_dirty)
82 void operator()(
const int& in,
int& filtered)
84 filtered = in * a + filtered * (1.0f - a);
87 void operator()(
const float& in,
float& filtered)
89 filtered = in * a + filtered * (1.0f - a);
92 void operator()(
const bool& in,
bool& filtered)
94 filtered = in * a + filtered * (1.0f - a);
97 template <std::
size_t N>
98 void operator()(
const std::array<float, N>& in, std::array<float, N>& filtered)
100 for(std::size_t i = 0; i < N; i++)
101 filtered[i] = in[i] * a + filtered[i] * (1.0f - a);
105 operator()(
const std::vector<ossia::value>& in, std::vector<ossia::value>& filtered)
107 if(in.size() != filtered.size()) [[unlikely]]
108 filtered.resize(in.size());
110 for(std::size_t i = 0; i < in.size(); i++)
112 if(filtered[i].get_type() != in[i].get_type()) [[unlikely]]
115 ossia::apply(*
this, in[i], filtered[i]);
119 void operator()(
const std::string& in, std::string& filtered) { filtered = in; }
120 template <
typename T>
121 void operator()(
const T& in, T& filtered)
126 template <
typename T>
127 void operator()(
const ossia::impulse& in, T& filtered)
129 (*this)(filtered, filtered);
132 void operator()(
const ossia::impulse& in, ossia::impulse& filtered) { }
133 template <
typename T,
typename U>
134 void operator()(
const T& in, U& filtered)
140 smooth_recursively(ossia::value& prev,
const ossia::value& next,
float alpha)
142 if(prev.get_type() != next.get_type()) [[unlikely]]
146 if(prev.valid() && next.valid())
147 ossia::apply(
do_smooth{alpha}, next, prev);
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{}};