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