Loading...
Searching...
No Matches
DSPWrapper.hpp
1#pragma once
2#include <Process/Dataflow/PortFactory.hpp>
3#include <Process/Execution/ProcessComponent.hpp>
4#include <Process/ExecutionContext.hpp>
5#include <Process/GenericProcessFactory.hpp>
6#include <Process/Process.hpp>
7#include <Process/ProcessFactory.hpp>
8
9#include <Control/DefaultEffectItem.hpp>
10#include <Effect/EffectFactory.hpp>
11
12#include <score/tools/IdentifierGeneration.hpp>
13
14#include <ossia/dataflow/execution_state.hpp>
15#include <ossia/dataflow/node_process.hpp>
16
17#include <Faust/FaustUtils.hpp>
18
19namespace FaustDSP
20{
21template <typename DSP>
22class Fx;
23}
24
25template <typename DSP>
26struct Metadata<Category_k, FaustDSP::Fx<DSP>>
27{
28 static Q_DECL_RELAXED_CONSTEXPR const char* get() { return "Audio"; }
29};
30template <typename DSP>
31struct Metadata<Tags_k, FaustDSP::Fx<DSP>>
32{
33 static QStringList get()
34 {
35 QStringList lst{"Audio"};
36 return lst;
37 }
38};
39template <typename DSP>
41{
42 static Process::ProcessFlags get() { return Process::ProcessFlags::SupportsAll; }
43};
44template <typename DSP>
45struct Metadata<Process::Descriptor_k, FaustDSP::Fx<DSP>>
46{
47 static std::vector<Process::PortType> inletDescription()
48 {
49 std::vector<Process::PortType> port;
50 port.push_back(Process::PortType::Audio);
51 return port;
52 }
53 static std::vector<Process::PortType> outletDescription()
54 {
55 std::vector<Process::PortType> port;
56 port.push_back(Process::PortType::Audio);
57 return port;
58 }
59 static Process::Descriptor get()
60 {
61 static Process::Descriptor desc{
63 Process::ProcessCategory::AudioEffect,
65 "Faust effect",
66 "Faust",
68 inletDescription(),
69 outletDescription(),
70 QUrl("https://ossia.io/score-docs/processes/faust.html")};
71 return desc;
72 }
73};
74
75namespace FaustDSP
76{
77template <typename T>
78struct Wrap final : UI
79{
80 template <typename... Args>
81 Wrap(Args&&... args)
82 : t{args...}
83 {
84 }
85
86 T t;
87 void openTabBox(const char* label) override { t.openTabBox(label); }
88 void openHorizontalBox(const char* label) override { t.openHorizontalBox(label); }
89 void openVerticalBox(const char* label) override { t.openVerticalBox(label); }
90 void closeBox() override { t.closeBox(); }
91 void declare(FAUSTFLOAT* zone, const char* key, const char* val) override
92 {
93 t.declare(zone, key, val);
94 }
95 void
96 addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) override
97 {
98 t.addSoundfile(label, filename, sf_zone);
99 }
100 void addButton(const char* label, FAUSTFLOAT* zone) override
101 {
102 t.addButton(label, zone);
103 }
104 void addCheckButton(const char* label, FAUSTFLOAT* zone) override
105 {
106 t.addCheckButton(label, zone);
107 }
108 void addVerticalSlider(
109 const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min,
110 FAUSTFLOAT max, FAUSTFLOAT step) override
111 {
112 t.addVerticalSlider(label, zone, init, min, max, step);
113 }
114 void addHorizontalSlider(
115 const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min,
116 FAUSTFLOAT max, FAUSTFLOAT step) override
117 {
118 t.addHorizontalSlider(label, zone, init, min, max, step);
119 }
120 void addNumEntry(
121 const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min,
122 FAUSTFLOAT max, FAUSTFLOAT step) override
123 {
124 t.addNumEntry(label, zone, init, min, max, step);
125 }
126 void addHorizontalBargraph(
127 const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) override
128 {
129 t.addHorizontalBargraph(label, zone, min, max);
130 }
131 void addVerticalBargraph(
132 const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) override
133 {
134 t.addVerticalBargraph(label, zone, min, max);
135 }
136};
137
138template <typename DSP>
139class Fx final : public Process::ProcessModel
140{
141 SCORE_SERIALIZE_FRIENDS
142 PROCESS_METADATA_IMPL(Fx)
143
144public:
145 Fx(TimeVal t, const Id<Process::ProcessModel>& id, QObject* parent)
147 {
148 Wrap<Faust::UI<decltype(*this)>> ui{*this};
149 DSP d;
150
151 m_inlets.push_back(new Process::Inlet{getStrongId(m_inlets), this});
152 m_inlets.back()->type = Process::PortType::Audio;
153 m_outlets.push_back(new Process::Outlet{getStrongId(m_outlets), this});
154 m_outlets.back()->type = Process::PortType::Audio;
155 m_outlets.back()->setPropagate(true);
156
157 d.buildUserInterface(&ui);
158 }
159
160 ~Fx() override { }
161
162 template <typename Impl>
163 Fx(Impl& vis, QObject* parent)
164 : Process::ProcessModel{vis, parent}
165 {
166 vis.writeTo(*this);
167 }
168
169 QString prettyName() const noexcept override
170 {
172 }
173
174 Process::Inlets& inlets() { return m_inlets; }
175 Process::Outlets& outlets() { return m_outlets; }
176 const Process::Inlets& inlets() const { return m_inlets; }
177 const Process::Outlets& outlets() const { return m_outlets; }
178
179 bool hasExternalUI() const noexcept { return false; }
180};
181
182template <typename DSP>
183class Executor final : public Execution::ProcessComponent_T<Fx<DSP>, ossia::node_process>
184{
185
186public:
187 static constexpr bool is_unique = true;
188
189 class exec_node final : public ossia::graph_node
190 {
191 public:
192 DSP dsp;
193 ossia::small_vector<std::pair<ossia::value_port*, FAUSTFLOAT*>, 8> controls;
194 exec_node()
195 {
196 m_inlets.push_back(new ossia::audio_inlet);
197 m_outlets.push_back(new ossia::audio_outlet);
199 dsp.buildUserInterface(&ex);
200 }
201
202 void run(const ossia::token_request& tk, ossia::exec_state_facade) noexcept override
203 {
204 ossia::nodes::faust_exec(*this, dsp, tk);
205 }
206
207 std::string label() const noexcept override { return "Faust"; }
208
209 void all_notes_off() noexcept override { }
210 };
211
212 static Q_DECL_RELAXED_CONSTEXPR score::Component::Key static_key() noexcept
213 {
214 return Metadata<ConcreteKey_k, Fx<DSP>>::get().impl();
215 }
216
217 score::Component::Key key() const noexcept final override { return static_key(); }
218
219 bool key_match(score::Component::Key other) const noexcept final override
220 {
221 return static_key() == other || Execution::ProcessComponent::base_key_match(other);
222 }
223
224 Executor(Fx<DSP>& proc, const Execution::Context& ctx, QObject* parent)
225 : Execution::ProcessComponent_T<Fx<DSP>, ossia::node_process>{
226 proc, ctx, "FaustComponent", parent}
227 {
228 auto node = ossia::make_node<exec_node>(*ctx.execState);
229 this->node = node;
230 this->m_ossia_process = std::make_shared<ossia::node_process>(node);
231 node->dsp.instanceInit(ctx.execState->sampleRate);
232
233 for(std::size_t i = 1; i < proc.inlets().size(); i++)
234 {
235 auto inlet = static_cast<Process::ControlInlet*>(proc.inlets()[i]);
236 *node->controls[i - 1].second = ossia::convert<double>(inlet->value());
237 auto inl = this->node->inputs()[i];
238 QObject::connect(
239 inlet, &Process::ControlInlet::valueChanged, this,
240 [this, inl](const ossia::value& v) {
241 this->system().executionQueue.enqueue([inl, val = v]() mutable {
242 inl->data.template target<ossia::value_port>()->write_value(std::move(val), 0);
243 });
244 });
245 }
246 }
247};
248}
249
250template <typename DSP>
251struct is_custom_serialized<FaustDSP::Fx<DSP>> : std::true_type
252{
253};
254
255template <typename DSP>
256struct TSerializer<DataStream, FaustDSP::Fx<DSP>>
257{
259 static void readFrom(DataStream::Serializer& s, const model_type& eff)
260 {
261 readPorts(s, eff.inlets(), eff.outlets());
262 s.insertDelimiter();
263 }
264
265 static void writeTo(DataStream::Deserializer& s, model_type& eff)
266 {
267 writePorts(
268 s, s.components.interfaces<Process::PortFactoryList>(), eff.inlets(),
269 eff.outlets(), &eff);
270
271 s.checkDelimiter();
272 }
273};
274
275template <typename DSP>
276struct TSerializer<JSONObject, FaustDSP::Fx<DSP>>
277{
279 static void readFrom(JSONObject::Serializer& s, const model_type& eff)
280 {
281 readPorts(s.obj, eff.inlets(), eff.outlets());
282 }
283
284 static void writeTo(JSONObject::Deserializer& s, model_type& eff)
285 {
286 writePorts(
287 s.obj, s.components.interfaces<Process::PortFactoryList>(), eff.inlets(),
288 eff.outlets(), &eff);
289 }
290};
291
292namespace FaustDSP
293{
294template <typename DSP>
295using ProcessFactory = Process::ProcessFactory_T<Fx<DSP>>;
296
297template <typename DSP>
299
300template <typename DSP>
302}
Metadata to categorize objects: curves, audio, etc.
Definition VisitorInterface.hpp:53
Definition DataStreamVisitor.hpp:27
void insertDelimiter()
insertDelimiter
Definition DataStreamVisitor.hpp:156
Definition DataStreamVisitor.hpp:202
Definition Process/Execution/ProcessComponent.hpp:119
Definition DSPWrapper.hpp:190
Definition DSPWrapper.hpp:184
Definition DSPWrapper.hpp:140
Definition VisitorInterface.hpp:61
Definition JSONVisitor.hpp:52
Definition JSONVisitor.hpp:423
Definition Port.hpp:203
Definition DefaultEffectItem.hpp:26
Definition EffectFactory.hpp:67
Definition Port.hpp:177
Definition Port.hpp:273
Definition PortFactory.hpp:74
Definition GenericProcessFactory.hpp:15
The Process class.
Definition score-lib-process/Process/Process.hpp:61
Metadata to retrieve the ProcessFlags of a process.
Metadata to associate tags to objects.
The id_base_t class.
Definition Identifier.hpp:57
Components used for the execution of a score.
Definition ProcessComponent.cpp:12
Base classes and tools to implement processes and layers.
Definition JSONVisitor.hpp:1324
ProcessFlags
Various settings for processes.
Definition ProcessFlags.hpp:17
Definition ExecutionContext.hpp:76
Definition Process/Execution/ProcessComponent.hpp:89
Definition score-plugin-faust/Faust/Utils.hpp:23
Definition DSPWrapper.hpp:79
Static metadata implementation.
Definition lib/score/tools/Metadata.hpp:36
Definition score-lib-process/Process/ProcessMetadata.hpp:37
Definition PortForward.hpp:23
Definition PortForward.hpp:27
Definition VisitorInterface.hpp:13
Definition TimeValue.hpp:21