OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
faust_node.hpp
1#pragma once
2#include <ossia/dataflow/graph_node.hpp>
3#include <ossia/dataflow/nodes/faust/faust_utils.hpp>
4
5namespace ossia::nodes
6{
7using faust_port_array
8 = ossia::small_vector<std::pair<ossia::value_port*, FAUSTFLOAT*>, 8>;
9class faust_mono_fx final : public ossia::graph_node
10{
11public:
12 std::shared_ptr<dsp> m_dsp{};
13 faust_port_array controls;
14 faust_port_array displays;
15 int generation{};
16
17 struct clone
18 {
19 explicit clone(dsp* f, const clone& orig)
20 : fx{f}
21 {
22 controls = orig.controls;
23 displays = orig.displays;
24
25 fx->init(orig.fx->getSampleRate());
26
27 faust_exec_ui_clone<clone> ex{*this};
28 fx->buildUserInterface(&ex);
29 }
30
31 clone(dsp* f, const faust_port_array& controls, const faust_port_array& disps)
32 : fx{f}
33 , controls{controls}
34 , displays{disps}
35 {
36 }
37
38 dsp* fx{};
39 faust_port_array controls;
40 faust_port_array displays;
41 };
42
43 void set_control(int i, int v) noexcept
44 { set_control(i, (float) v); }
45 void set_control(int i, bool v) noexcept
46 { set_control(i, v ? 1.f : 0.f); }
47 void set_control(int i, const std::string& v) noexcept
48 { }
49 void set_control(int i, ossia::impulse v) noexcept
50 { }
51 template<std::size_t N>
52 void set_control(int i, const std::array<float, N>& v) noexcept
53 {
54 *controls[i].second = v[0];
55 for(std::size_t c = 0, n = std::min(clones.size(), N); c < n; c++)
56 {
57 *clones[c].controls[i].second = v[c];
58 }
59 }
60 void set_control(int i, const std::vector<ossia::value>& v) noexcept
61 {
62 if(v.empty()) return;
63 *controls[i].second = ossia::convert<float>(v[0]);
64 for(std::size_t c = 0, n = std::min(clones.size(), v.size()); c < n; c++)
65 {
66 *clones[c].controls[i].second = ossia::convert<float>(v[c]);
67 }
68 }
69 void set_control(int i, const ossia::value_map_type& v) noexcept
70 {
71
72 }
73
74 void set_control(int i, float v) noexcept
75 {
76 *controls[i].second = v;
77 for(std::size_t c = 1; c < clones.size(); c++)
78 {
79 *clones[c].controls[i].second = v;
80 }
81 }
82
83 std::vector<clone> clones;
84 faust_mono_fx(std::shared_ptr<dsp> dsp)
85 : m_dsp{std::move(dsp)}
86 {
87 m_inlets.push_back(new ossia::audio_inlet);
88 m_outlets.push_back(new ossia::audio_outlet);
89
90 // Initialize the controls
91 faust_exec_ui<faust_mono_fx, false> ex{*this};
92 m_dsp->buildUserInterface(&ex);
93
94 // Preallocate for the most common case, two channels
95 clones.emplace_back(m_dsp.get(), controls, displays);
96 clones.emplace_back(m_dsp->clone(), clones[0]);
97 }
98
99 void run(const ossia::token_request& tk, ossia::exec_state_facade e) noexcept override
100 {
101 faust_node_utils{}.exec_mono_fx(*this, *m_dsp, tk, e);
102 }
103
104 [[nodiscard]] std::string label() const noexcept override { return "Faust"; }
105
106 void all_notes_off() noexcept override { }
107 void clear() noexcept override
108 {
109 ossia::graph_node::clear();
110 generation = -1;
111 }
112
113 ~faust_mono_fx()
114 {
115 // Clone 0 is the original instance
116 for(std::size_t i = 1; i < clones.size(); i++)
117 delete clones[i].fx;
118 }
119};
120
121class faust_fx final : public ossia::graph_node
122{
123 std::shared_ptr<dsp> m_dsp{};
124
125public:
126 faust_port_array controls;
127 faust_port_array displays;
128 int generation{};
129 faust_fx(std::shared_ptr<dsp> dsp)
130 : m_dsp{std::move(dsp)}
131 {
132 m_inlets.push_back(new ossia::audio_inlet);
133 m_outlets.push_back(new ossia::audio_outlet);
134 faust_exec_ui<faust_fx, false> ex{*this};
135 m_dsp->buildUserInterface(&ex);
136 }
137
138 void set_control(int i, float v) noexcept { *controls[i].second = v; }
139 void run(const ossia::token_request& tk, ossia::exec_state_facade e) noexcept override
140 {
141 faust_node_utils{}.exec(*this, *m_dsp, tk, e);
142 }
143
144 [[nodiscard]] std::string label() const noexcept override { return "Faust"; }
145
146 void all_notes_off() noexcept override { }
147 void clear() noexcept override
148 {
149 ossia::graph_node::clear();
150 generation = -1;
151 }
152};
153
154class faust_synth final : public ossia::graph_node
155{
156 std::shared_ptr<ossia::nodes::custom_dsp_poly_effect> m_dsp{};
157
158public:
159 faust_port_array controls;
160 faust_port_array displays;
161 int generation{};
162
163 void set_control(int i, float v) noexcept { *controls[i].second = v; }
164 std::array<int8_t, 128> in_flight{};
165 faust_synth(std::shared_ptr<ossia::nodes::custom_dsp_poly_effect> dsp)
166 : m_dsp{std::move(dsp)}
167 {
168 m_inlets.push_back(new ossia::audio_inlet);
169 m_inlets.push_back(new ossia::midi_inlet);
170 m_outlets.push_back(new ossia::audio_outlet);
171 faust_exec_ui<faust_synth, true> ex{*this};
172 m_dsp->buildUserInterface(&ex);
173 }
174
175 void run(const ossia::token_request& tk, ossia::exec_state_facade e) noexcept override
176 {
177 faust_node_utils{}.exec_synth(*this, *m_dsp, tk, e);
178 }
179
180 [[nodiscard]] std::string label() const noexcept override { return "Faust Synth"; }
181
182 void all_notes_off() noexcept override
183 {
184 faust_node_utils{}.all_notes_off(*this, *m_dsp);
185 }
186 void clear() noexcept override
187 {
188 ossia::graph_node::clear();
189 generation = -1;
190 }
191};
192
193}