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