arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
Pipeline.h
1#pragma once
2
3#include "AudioTools/CoreAudio/AudioOutput.h"
4#include "AudioTools/CoreAudio/AudioStreams.h"
5#include "AudioTools/CoreAudio/AudioIO.h"
6
7namespace audio_tools {
8
17class Pipeline : public AudioStream {
18 friend MultiOutput;
19
20 public:
21 Pipeline() = default;
23 bool add(ModifyingStream& io) {
24 if (has_output) {
25 LOGE("Output already defined");
26 is_ok = false;
27 return false;
28 }
29 if (has_input) {
30 if (p_stream == nullptr) {
31 LOGE("Input not defined");
32 is_ok = false;
33 return false;
34 }
35
36 // predecessor notifies successor
37 if (p_ai_source != nullptr) {
38 p_ai_source->addNotifyAudioChange(io);
39 }
40
41 // we set up an input chain
42 components.push_back(&io);
43 io.setStream(*p_stream);
44 p_stream = &io;
45 p_ai_source = &io;
46 } else {
47 // we assume an output chain
48 if (size() > 0) {
49 auto& last_c = last();
50 last_c.setOutput(io);
51 last_c.addNotifyAudioChange(io);
52 }
53 components.push_back(&io);
54 }
55 return true;
56 }
57
59 bool add(ModifyingOutput& out) {
60 if (has_output) {
61 LOGE("Output already defined");
62 is_ok = false;
63 return false;
64 }
65 if (has_input) {
66 LOGE("Input not supported");
67 is_ok = false;
68 return false;
69 }
71 cleanup.push_back(io);
72 return add(*io);
73 }
74
77 p_out_print = &out;
78 if (size() > 0) {
80 }
81 return setOutput((Print&)out);
82 }
83
86 p_out_stream = &out;
87 if (size() > 0) {
89 }
90 return setOutput((Print&)out);
91 }
92
94 bool setOutput(Print& out) {
95 if (has_output) {
96 LOGE("Output already defined");
97 is_ok = false;
98 return false;
99 }
100 p_print = &out;
101 if (size() > 0) {
102 last().setOutput(out);
103 }
104 // must be last element
105 has_output = true;
106 return true;
107 }
108
111 p_ai_source = ∈
112 p_ai_input = ∈
113 return setInput((Stream&)in);
114 }
115
117 bool setInput(Stream& in) {
118 if (has_output) {
119 LOGE("Defined as output");
120 is_ok = false;
121 return false;
122 }
123 if (has_input) {
124 LOGE("Input already defined");
125 is_ok = false;
126 return false;
127 }
128 // must be first
129 has_input = true;
130 p_stream = ∈
131 return true;
132 }
133
134 int availableForWrite() override {
135 if (!is_active) return 0;
136 if (size() == 0) {
137 if (p_print != nullptr) return p_print->availableForWrite();
138 return 0;
139 }
140 return components[0]->availableForWrite();
141 }
142
143 size_t write(const uint8_t* data, size_t len) override {
144 if (!is_active) return 0;
145 if (size() == 0) {
146 if (p_print != nullptr) return p_print->write(data, len);
147 return 0;
148 }
149 LOGD("write: %u", (unsigned)len);
150 return components[0]->write(data, len);
151 }
152
153 int available() override {
154 if (!is_active) return 0;
155 Stream* in = getInput();
156 if (in == nullptr) return 0;
157 return in->available();
158 }
159
160 size_t readBytes(uint8_t* data, size_t len) override {
161 if (!is_active) return 0;
162 Stream* in = getInput();
163 if (in == nullptr) return 0;
164 return in->readBytes(data, len);
165 }
166
169 bool begin(AudioInfo info) {
170 LOGI("begin");
171 bool rc = begin();
172 setAudioInfo(info);
173 audioInfoOut().logInfo("pipeline out:");
174 return rc;
175 }
176
178 bool begin() override {
179 has_output = false;
180 bool ok = true;
181
182 // avoid too much noise
183 setNotifyActive(false);
184
185 // start components
186 for (auto c : components) {
187 ok = ok && c->begin();
188 }
189 // start output
190 if (p_out_stream != nullptr) {
191 ok = ok && p_out_stream->begin();
192 } else if (p_out_print != nullptr) {
193 ok = ok && p_out_print->begin();
194 }
195 // start input
196 if (p_ai_input != nullptr) {
197 ok = ok && p_ai_input->begin();
198 }
199
200 setNotifyActive(true);
201 is_active = ok;
202 is_ok = ok;
203 return ok;
204 }
205
207 void end() override {
208 for (auto c : components) {
209 c->end();
210 }
211 components.clear();
212 for (auto& c : cleanup) {
213 delete c;
214 }
215 cleanup.clear();
216
217 has_output = false;
218 has_input = false;
219 p_out_print = nullptr;
220 p_out_stream = nullptr;
221 p_print = nullptr;
222 p_stream = nullptr;
223 p_ai_source = nullptr;
224 p_ai_input = nullptr;
225 is_ok = false;
226 is_active = true;
227 }
228
231 this->info = newInfo;
232 if (has_input && p_ai_input != nullptr) {
233 p_ai_input->setAudioInfo(info);
234 } else if (has_output) {
235 components[0]->setAudioInfo(info);
236 }
237 }
238
241 AudioInfo info = audioInfo();
242 if (size() > 0) {
243 info = last().audioInfoOut();
244 }
245 return info;
246 }
247
249 bool hasComponents() { return size() > 0; }
250
252 int size() { return components.size(); }
253
255 ModifyingStream& last() { return *components[size() - 1]; }
256
258 ModifyingStream& operator[](int idx) { return *components[idx]; }
259
262 if (size() > 0) last().addNotifyAudioChange(bi);
263 }
264
267 is_notify_active = flag;
268 for (auto c : components) {
269 c->setNotifyActive(flag);
270 }
271 }
272
274 void setActive(bool flag){
275 is_active = flag;
276 }
277
279 bool isActive(){
280 return is_active;
281 }
282
284 bool isOK(){
285 return is_ok;
286 }
287
289 operator bool() { return is_ok && is_active; }
290
291 protected:
292 Vector<ModifyingStream*> components{0};
293 Vector<ModifyingStream*> cleanup{0};
294 bool has_output = false;
295 bool has_input = false;
296 bool is_ok = true;
297 bool is_active = true;
298 // prior input for input pipline
299 Stream* p_stream = nullptr;
300 AudioInfoSource* p_ai_source = nullptr;
301 AudioStream* p_ai_input = nullptr;
302 // output for notifications, begin and end calls
303 AudioOutput* p_out_print = nullptr;
304 AudioStream* p_out_stream = nullptr;
305 Print* p_print = nullptr;
306
309 ModifyingStreamAdapter(ModifyingOutput& out) { p_out = &out; }
311 void setStream(Stream& in) override { p_out->setOutput(in); }
313 void setOutput(Print& out) override { p_out->setOutput(out); }
315 int available() override { return 0; }
316
317 size_t write(const uint8_t* data, size_t len) override {
318 return p_out->write(data, len);
319 }
320
321 bool begin() override { return p_out->begin(); }
322
323 void end() override { p_out->end(); }
324
325 void setAudioInfo(AudioInfo info) override { p_out->setAudioInfo(info); }
326
328 p_out->addNotifyAudioChange(bi);
329 }
330
331 protected:
332 ModifyingOutput* p_out = nullptr;
333 };
334
338 Stream* in = p_stream;
339 if (size() > 0) {
340 in = &last();
341 }
342 return in;
343 }
344};
345
346} // namespace audio_tools
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:162
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:139
virtual AudioInfo audioInfoOut()
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition AudioTypes.h:146
Abstract Audio Ouptut class.
Definition AudioOutput.h:22
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioOutput.h:46
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:115
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:123
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:146
Abstract class: Objects can be put into a pipleline.
Definition AudioOutput.h:97
virtual void setOutput(Print &out)=0
Defines/Changes the output target.
Abstract class: Objects can be put into a pipleline.
Definition AudioStreams.h:69
virtual void setStream(Stream &in)=0
Defines/Changes the input & output.
virtual void setOutput(Print &out)=0
Defines/Changes the output target.
Replicates the output to multiple destinations.
Definition AudioIO.h:326
We can build a input or an output chain: an input chain starts with setInput(); followed by add() an ...
Definition Pipeline.h:17
bool setOutput(AudioStream &out)
Defines the output for an output pipeline: must be last call after add()
Definition Pipeline.h:85
bool isOK()
Returns true if pipeline is correctly set up.
Definition Pipeline.h:284
ModifyingStream & operator[](int idx)
Access to the components by index.
Definition Pipeline.h:258
void addNotifyAudioChange(AudioInfoSupport &bi) override
Subscribes to notifications on last component of the chain.
Definition Pipeline.h:261
void setAudioInfo(AudioInfo newInfo) override
Defines the AudioInfo for the first node.
Definition Pipeline.h:230
Stream * getInput()
Definition Pipeline.h:337
bool hasComponents()
Returns true if we have at least 1 component.
Definition Pipeline.h:249
void end() override
Calls end on all components.
Definition Pipeline.h:207
bool setOutput(AudioOutput &out)
Defines the output for an output pipeline: must be last call after add()
Definition Pipeline.h:76
bool setOutput(Print &out)
Defines the output for an output pipeline: must be last call after add()
Definition Pipeline.h:94
bool setInput(AudioStream &in)
Defines the input for an input pipeline: must be first call before add()
Definition Pipeline.h:110
ModifyingStream & last()
Provides the last component.
Definition Pipeline.h:255
void setNotifyActive(bool flag)
Activates/deactivates notifications.
Definition Pipeline.h:266
bool setInput(Stream &in)
Defines the input for an input pipeline: must be first call before add()
Definition Pipeline.h:117
bool add(ModifyingStream &io)
adds a component
Definition Pipeline.h:23
bool isActive()
Determines if the pipeline is active.
Definition Pipeline.h:279
bool add(ModifyingOutput &out)
adds a component
Definition Pipeline.h:59
AudioInfo audioInfoOut() override
Provides the resulting AudioInfo from the last node.
Definition Pipeline.h:240
void setActive(bool flag)
Activates/deactivates the pipeline (default is active)
Definition Pipeline.h:274
bool begin() override
Optional method: Calls begin on all components.
Definition Pipeline.h:178
bool begin(AudioInfo info)
Definition Pipeline.h:169
int size()
Provides the number of components.
Definition Pipeline.h:252
Definition NoArduino.h:62
Definition NoArduino.h:142
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioConfig.h:885
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:52
Support for ModifyingOutput.
Definition Pipeline.h:308
void setOutput(Print &out) override
Defines/Changes the output target.
Definition Pipeline.h:313
void addNotifyAudioChange(AudioInfoSupport &bi) override
Adds target to be notified about audio changes.
Definition Pipeline.h:327
int available() override
Read not supported.
Definition Pipeline.h:315
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition Pipeline.h:325
void setStream(Stream &in) override
Defines/Changes the input & output.
Definition Pipeline.h:311