22 halp_meta(name,
"LFO (v2)")
23 halp_meta(c_name,
"LFO")
24 halp_meta(category,
"Control/Generators")
25 halp_meta(author,
"ossia score")
26 halp_meta(manual_url,
"https://ossia.io/score-docs/processes/lfo.html#lfo")
27 halp_meta(description,
"Low-frequency oscillator")
28 halp_flag(deprecated);
29 halp_meta(recommended_height, 130.)
30 halp_meta(uuid,
"1e17e479-3513-44c8-a8a7-017be9f6ac8a");
34 halp::log_hslider_f32<
"Freq.", halp::range{0.01f, 100.f, 1.f}> freq;
35 halp::knob_f32<
"Ampl.", halp::range{0., 2., 0.5}> ampl;
36 halp::knob_f32<
"Offset", halp::range{-1., 1., 0.5}> offset;
37 halp::knob_f32<
"Jitter", halp::range{0., 1., 0}> jitter;
38 halp::knob_f32<
"Phase", halp::range{-1., 1., 0.}> phase;
39 struct : halp::enum_t<Control::Widgets::Waveform,
"Waveform">
41 static constexpr auto pixmaps()
43 return std::array<const char*, 16>{
44 ":/icons/wave_sin_off.png",
45 ":/icons/wave_sin_on.png",
46 ":/icons/wave_triangle_off.png",
47 ":/icons/wave_triangle_on.png",
48 ":/icons/wave_saw_off.png",
49 ":/icons/wave_saw_on.png",
50 ":/icons/wave_square_off.png",
51 ":/icons/wave_square_on.png",
52 ":/icons/wave_sample_and_hold_off.png",
53 ":/icons/wave_sample_and_hold_on.png",
54 ":/icons/wave_noise1_off.png",
55 ":/icons/wave_noise1_on.png",
56 ":/icons/wave_noise2_off.png",
57 ":/icons/wave_noise2_on.png",
58 ":/icons/wave_noise3_off.png",
59 ":/icons/wave_noise3_on.png"};
68 struct : halp::val_port<
"Out", std::optional<float>>
79 rnd::pcg rd{random_source()};
81 using tick = halp::tick_flicks;
82 void operator()(
const halp::tick_flicks& tk)
84 const auto quantif = inputs.quant.value;
85 const auto ampl = inputs.ampl.value;
86 const auto offset = inputs.offset.value;
87 const auto jitter = inputs.jitter.value;
88 const auto custom_phase = inputs.phase.value;
89 const auto type = inputs.waveform.value;
95 if(tk.unexpected_bar_change())
98 const double bar_length = 4.0 * tk.signature.num / tk.signature.denom;
99 const double quarters_elapsed
100 = tk.end_position_in_quarters - tk.start_position_in_quarters;
101 const double quarters_per_cycle = bar_length * quantif * 2.;
103 ph_delta = (quarters_elapsed / quarters_per_cycle) * 2.0 * std::numbers::pi;
107 constexpr double sine_ratio = ossia::two_pi / ossia::flicks_per_second<double>;
108 ph_delta = tk.model_read_duration() * inputs.freq.value * sine_ratio;
111 double ph = this->phase;
113 ph += std::normal_distribution<float>(0., 0.25)(this->rd) * jitter;
117 using namespace Control::Widgets;
119 = [&](
auto new_val) { outputs.out.value = ampl * new_val + offset; };
124 add_val(std::sin(ph));
127 add_val(std::asin(std::sin(ph)) / ossia::half_pi);
130 add_val(std::atan(std::tan(ph)) / ossia::half_pi);
133 add_val((std::sin(ph) > 0.f) ? 1.f : -1.f);
135 case SampleAndHold: {
136 const auto start_s = std::sin(ph);
137 const auto end_s = std::sin(ph + ph_delta);
138 if((start_s > 0 && end_s <= 0) || (start_s <= 0 && end_s > 0))
139 add_val(std::uniform_real_distribution<float>(-1.f, 1.f)(this->rd));
143 add_val(std::uniform_real_distribution<float>(-1.f, 1.f)(this->rd));
146 add_val(std::normal_distribution<float>(0.f, 1.f)(this->rd));
150 std::clamp(std::cauchy_distribution<float>(0.f, 1.f)(this->rd), 0.f, 1.f));
154 this->phase += ph_delta;
155 if(this->phase > 1e6)
156 this->phase = std::fmod(this->phase, 2.0 * std::numbers::pi);
161 halp_meta(layout, halp::layouts::hbox)
164 halp_meta(layout, halp::layouts::vbox)
165 halp_meta(background, halp::colors::background_mid)
168 halp_meta(layout, halp::layouts::hbox)
170 halp::control<&ins::freq> f;
171 halp::control<&ins::quant> q;
173 halp::control<&ins::waveform> w;
178 halp_meta(layout, halp::layouts::vbox)
179 halp_meta(background, halp::colors::background_mid)
180 halp::control<&ins::ampl> a;
181 halp::control<&ins::offset> o;
185 halp_meta(layout, halp::layouts::vbox)
186 halp_meta(background, halp::colors::background_mid)
187 halp::control<&ins::jitter> j;
188 halp::control<&ins::phase> p;