Loading...
Searching...
No Matches
LFO.hpp
1#pragma once
2#include <Fx/Types.hpp>
3
4#include <ossia/detail/flicks.hpp>
5#include <ossia/detail/math.hpp>
6
7#include <halp/controls.hpp>
8#include <halp/meta.hpp>
9#include <halp/midi.hpp>
10#include <rnd/random.hpp>
11#include <tuplet/tuple.hpp>
12
13#include <random>
14
15namespace Nodes
16{
17
18namespace LFO
19{
20static inline std::random_device& random_source()
21{
22 static thread_local std::random_device d;
23 return d;
24}
25
26namespace v1
27{
28struct Node
29{
30 halp_meta(name, "LFO (old)")
31 halp_meta(c_name, "LFO")
32 halp_meta(category, "Control/Generators")
33 halp_meta(author, "ossia score")
34 halp_meta(manual_url, "https://ossia.io/score-docs/processes/lfo.html#lfo")
35 halp_meta(description, "Low-frequency oscillator")
36 halp_flag(deprecated);
37 halp_meta(recommended_height, 130.)
38 halp_meta(uuid, "0697b807-f588-49b5-926c-f97701edd0d8");
39
40 struct Inputs
41 {
42 // FIXME knob
43 halp::log_hslider_f32<"Freq.", halp::range{0.01f, 100.f, 1.f}> freq;
44 halp::knob_f32<"Ampl.", halp::range{0., 1000., 0.}> ampl;
45 halp::knob_f32<"Fine", halp::range{0., 1., 0.5}> ampl_fine;
46 halp::knob_f32<"Offset", halp::range{-1000., 1000., 0.}> offset;
47 halp::knob_f32<"Fine", halp::range{-1., 1., 0.5}> offset_fine;
48 halp::knob_f32<"Jitter", halp::range{0., 1., 0}> jitter;
49 halp::knob_f32<"Phase", halp::range{-1., 1., 0.}> phase;
50 halp::enum_t<Control::Widgets::Waveform, "Waveform"> waveform;
51 quant_selector<"Quantification"> quant;
52 } inputs;
53 struct
54 {
55 halp::val_port<"Out", std::optional<float>> out;
56 } outputs;
57
58 double phase{};
59 rnd::pcg rd;
60
61 using tick = halp::tick_flicks;
62 void operator()(const halp::tick_flicks& tk)
63 {
64 constexpr const double sine_ratio = ossia::two_pi / ossia::flicks_per_second<double>;
65 const auto elapsed = tk.model_read_duration();
66
67 const auto quantif = inputs.quant.value;
68 auto freq = inputs.freq.value;
69 auto ampl = inputs.ampl.value;
70 const auto ampl_fine = inputs.ampl_fine.value;
71 auto offset = inputs.offset.value;
72 const auto offset_fine = inputs.offset_fine.value;
73 const auto jitter = inputs.jitter.value;
74 auto custom_phase = inputs.phase.value;
75 const auto type = inputs.waveform.value;
76
77 if(quantif)
78 {
79 // Determine the frequency with the quantification
80 if(tk.unexpected_bar_change())
81 {
82 this->phase = 0;
83 }
84
85 // If quantif == 1, we quantize to the bar
86 // => f = 0.5 hz
87 // If quantif == 1/4, we quantize to the quarter
88 // => f = 2hz
89 // -> sin(elapsed * freq * 2 * pi / fps)
90 // -> sin(elapsed * 4 * 2 * pi / fps)
91 freq = 1. / (2. * quantif);
92 }
93
94 const auto ph_delta = elapsed * freq * sine_ratio;
95
96 {
97 auto ph = this->phase;
98 if(jitter > 0)
99 {
100 ph += std::normal_distribution<float>(0., 0.25)(this->rd) * jitter;
101 }
102
103 ampl += ampl_fine;
104 offset += offset_fine;
105
106 using namespace Control::Widgets;
107
108 const auto add_val
109 = [&](auto new_val) { outputs.out.value = ampl * new_val + offset; };
110
111 custom_phase = custom_phase * ossia::pi;
112 switch(type)
113 {
114 case Sin:
115 add_val(std::sin(custom_phase + ph));
116 break;
117 case Triangle:
118 add_val(std::asin(std::sin(custom_phase + ph)) / ossia::half_pi);
119 break;
120 case Saw:
121 add_val(std::atan(std::tan(custom_phase + ph)) / ossia::half_pi);
122 break;
123 case Square:
124 add_val((std::sin(custom_phase + ph) > 0.f) ? 1.f : -1.f);
125 break;
126 case SampleAndHold: {
127 const auto start_s = std::sin(custom_phase + ph);
128 const auto end_s = std::sin(custom_phase + ph + ph_delta);
129 if((start_s > 0 && end_s <= 0) || (start_s <= 0 && end_s > 0))
130 {
131 add_val(std::uniform_real_distribution<float>(-1.f, 1.f)(this->rd));
132 }
133 break;
134 }
135 case Noise1:
136 add_val(std::uniform_real_distribution<float>(-1.f, 1.f)(this->rd));
137 break;
138 case Noise2:
139 add_val(std::normal_distribution<float>(0.f, 1.f)(this->rd));
140 break;
141 case Noise3:
142 add_val(
143 std::clamp(std::cauchy_distribution<float>(0.f, 1.f)(this->rd), 0.f, 1.f));
144 break;
145 }
146 }
147
148 this->phase += ph_delta;
149 }
150};
151}
152}
153}
Definition LFO.hpp:41
Definition LFO.hpp:29
Definition Types.hpp:48