arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
AudioEffects.h
1#pragma once
2#include "AudioTools/CoreAudio/AudioBasic/Collections.h"
3#include "AudioTools/CoreAudio/AudioStreams.h"
4#include "SoundGenerator.h"
5#include "AudioEffect.h"
6#if defined(USE_VARIANTS) && __cplusplus >= 201703L
7# include <variant>
8#endif
9
16namespace audio_tools {
17
25 public:
27 void addEffect(AudioEffect &effect){
28 TRACED();
29 effects.push_back(&effect);
30 }
31
33 void addEffect(AudioEffect *effect){
34 TRACED();
35 effects.push_back(effect);
36 LOGI("addEffect -> Number of effects: %d", (int)size());
37 }
39 void clear() {
40 TRACED();
41 effects.clear();
42 }
43
45 size_t size() {
46 return effects.size();
47 }
48
51 // find AudioEffect
52 AudioEffect* result = nullptr;
53 for (int j=0;j<size();j++){
54 // we assume that ADSRGain is the first effect!
55 if (effects[j]->id()==id){
56 result = effects[j];
57 }
58 LOGI("--> findEffect -> %d", effects[j]->id());
59 }
60 return result;
61 }
64 return effects[idx];
65 }
66
67 protected:
69
70};
71
86template <class GeneratorT>
87class AudioEffects : public SoundGenerator<effect_t> {
88 public:
90 AudioEffects() = default;
91
94 TRACEI();
95 // create a copy of the source and all effects
96 p_generator = copy.p_generator;
97 for (int j=0;j<copy.size();j++){
98 effects.addEffect(copy[j]->clone());
99 }
100 LOGI("Number of effects %d -> %d", copy.size(), this->size());
101 }
102
104 AudioEffects(GeneratorT &generator) {
106 }
107
110 AudioEffects(Stream &input, int channels=2, float volume=1.0) {
111 setInput(* (new GeneratorT(input, channels, volume)));
112 owns_generator = true;
113 }
114
116 virtual ~AudioEffects(){
117 TRACED();
118 if (owns_generator && p_generator!=nullptr){
119 delete p_generator;
120 }
121 for (int j=0;j<effects.size();j++){
122 delete effects[j];
123 }
124 }
125
127 void setInput(GeneratorT &in){
128 TRACED();
129 p_generator = &in;
130 // automatically activate this object
131 AudioInfo info;
132 info.channels = 1;
133 info.bits_per_sample = sizeof(effect_t)*8;
134 begin(info);
135 }
136
138 void addEffect(AudioEffect &effect){
139 TRACED();
140 effects.addEffect(&effect);
141 }
142
144 void addEffect(AudioEffect *effect){
145 TRACED();
146 effects.addEffect(effect);
147 LOGI("addEffect -> Number of effects: %d", size());
148 }
149
151 effect_t readSample() override {
152 effect_t sample;
153 if (p_generator!=nullptr){
154 sample = p_generator->readSample();
155 int size = effects.size();
156 for (int j=0; j<size; j++){
157 sample = effects[j]->process(sample);
158 }
159 }
160 return sample;
161 }
162
164 void clear() {
165 TRACED();
166 effects.clear();
167 }
168
170 size_t size() {
171 return effects.size();
172 }
173
175 GeneratorT &generator(){
176 return *p_generator;
177 }
178
181 return effects[idx];
182 }
183
186 return effects.findEffect(id);
187 }
188
189 protected:
190 AudioEffectCommon effects;
191 GeneratorT *p_generator=nullptr;
192 bool owns_generator = false;
193};
194
195
207template <class T>
209 public:
210 AudioEffectStreamT() = default;
211
213 setStream(io);
214 }
215
217 setOutput(out);
218 }
219
220 AudioInfo defaultConfig() {
221 AudioInfo cfg;
222 cfg.sample_rate = 44100;
223 cfg.bits_per_sample = 16;
224 cfg.channels = 2;
225 return cfg;
226 }
227
228 bool begin(AudioInfo cfg){
229 info = cfg;
230 return begin();
231 }
232
233 bool begin(){
234 TRACEI();
235 if (sizeof(T)==info.bits_per_sample/8){
236 active = true;
237 } else {
238 LOGE("bits_per_sample not consistent: %d",info.bits_per_sample);
239 active = false;
240 }
241 return active;
242 }
243
244 void end() override {
245 active = false;
246 }
247
248 void setStream(Stream &io) override {
249 p_io = &io;
250 p_print = &io;
251 }
252
253
254 void setOutput(Print &print) override {
255 p_print = &print;
256 }
257
262 size_t readBytes(uint8_t *data, size_t len) override {
263 if (!active || p_io==nullptr)return 0;
264 size_t result_size = 0;
265
266 // read data from source
267 size_t result = p_io->readBytes((uint8_t*)data, len);
268 int frames = result / sizeof(T) / info.channels;
269 T* samples = (T*) data;
270
271 for (int count=0;count<frames;count++){
272 // determine sample by combining all channels in frame
273 T result_sample = 0;
274 for (int ch=0;ch<info.channels;ch++){
275 T sample = *samples++;
276 //p_io->readBytes((uint8_t*)&sample, sizeof(T));
277 result_sample += sample / info.channels;
278 }
279
280 // apply effects
281 for (int j=0; j<size(); j++){
282 result_sample = effects[j]->process(result_sample);
283 }
284
285 // write result multiplying channels
286 T* p_buffer = ((T*)data)+(count*info.channels);
287 for (int ch=0;ch<info.channels;ch++){
288 p_buffer[ch] = result_sample;
289 result_size += sizeof(T);
290 }
291 }
292 return result_size;
293 }
294
299 size_t write(const uint8_t *data, size_t len) override {
300 if (!active)return 0;
301 // length must be multple of channels
302 assert(len % (sizeof(T)*info.channels)==0);
303 int frames = len / sizeof(T) / info.channels;
304 size_t result_size = 0;
305
306 // process all samples
307 for (int j=0;j<frames;j++){
308 // calculate sample for frame
309 T* p_buffer = ((T*)data) + (j*info.channels);
310 T sample=0;
311 for (int ch=0;ch<info.channels;ch++){
312 sample += p_buffer[ch] / info.channels;
313 result_size += sizeof(T);
314 }
315
316 // apply effects
317 for (int j=0; j<size(); j++){
318 sample = effects[j]->process(sample);
319 }
320
321 // wite result channel times to output defined in constructor
322 for (int ch=0;ch<info.channels;ch++){
323 if (p_io!=nullptr){
324 p_io->write((uint8_t*)&sample, sizeof(T));
325
326 } else if (p_print!=nullptr){
327 p_print->write((uint8_t*)&sample, sizeof(T));
328 }
329 }
330 }
331 return result_size;
332 }
333
334 int available() override {
335 if (p_io==nullptr) return 0;
336 return p_io->available();
337 }
338
339 int availableForWrite() override {
340 if (p_print!=nullptr) return p_print->availableForWrite();
341 if (p_io!=nullptr) return p_io->availableForWrite();
342 return 0;
343 }
344
346 void addEffect(AudioEffect &effect){
347 TRACED();
348 effects.addEffect(&effect);
349 }
350
352 void addEffect(AudioEffect *effect){
353 TRACED();
354 effects.addEffect(effect);
355 LOGI("addEffect -> Number of effects: %d", (int) size());
356 }
357
359 void clear() {
360 TRACED();
361 effects.clear();
362 }
363
365 size_t size() {
366 return effects.size();
367 }
368
371 return effects[idx];
372 }
373
376 return effects.findEffect(id);
377 }
378
379 protected:
380 AudioEffectCommon effects;
381 bool active = false;
382 Stream *p_io=nullptr;
383 Print *p_print=nullptr;
384};
385
386#if defined(USE_VARIANTS) && __cplusplus >= 201703L || defined(DOXYGEN)
398 AudioEffectStream() = default;
399
401 setOutput(io);
402 setInput(io);
403 }
404
406 setOutput(out);
407 }
408
409 AudioInfo defaultConfig() {
410 AudioInfo cfg;
411 cfg.sample_rate = 44100;
412 cfg.bits_per_sample = 16;
413 cfg.channels = 2;
414 return cfg;
415 }
416
417 bool begin(AudioInfo cfg){
418 info = cfg;
419 return begin();
420 }
421
422 bool begin(){
423 TRACEI();
424 switch(info.bits_per_sample){
425 case 16:
426 variant.emplace<0>();
427 break;
428 case 24:
429 variant.emplace<1>();
430 break;
431 case 32:
432 variant.emplace<2>();
433 break;
434 default:
435 LOGE("Unspported bits_per_sample: %d", cfg.bits_per_sample);
436 return false;
437 }
438 std::visit( [this](auto&& e) {return e.setOutput(*p_print);}, variant );
439 std::visit( [this](auto&& e) {return e.setInput(*p_io);}, variant );
440 return std::visit( [cfg](auto&& e) {return e.begin(info);}, variant );
441 }
442
443 void end() override {
444 std::visit( [](auto&& e) {e.end();}, variant );
445 }
446
447 void setInput(Stream &io){
448 setStream(io);
449 }
450
451 void setStream(Stream &io){
452 p_io = &io;
453 }
454
455 void setOutput(Stream &io){
456 p_io = &io;
457 }
458
459 void setOutput(Print &print){
460 p_print = &print;
461 }
462
467 size_t readBytes(uint8_t *data, size_t len) override {
468 return std::visit( [data, len](auto&& e) {return e.readBytes(data, len);}, variant );
469 }
470
475 size_t write(const uint8_t *data, size_t len) override {
476 return std::visit( [data, len](auto&& e) {return e.write(data, len);}, variant );
477 }
478
479 int available() override {
480 return std::visit( [](auto&& e) {return e.available();}, variant );
481 }
482
483 int availableForWrite() override {
484 return std::visit( [](auto&& e) {return e.availableForWrite();}, variant );
485 }
486
488 void addEffect(AudioEffect &effect){
489 addEffect(&effect);
490 }
491
493 void addEffect(AudioEffect *effect){
494 std::visit( [effect](auto&& e) {e.addEffect(effect);}, variant );
495 }
496
498 void clear() {
499 std::visit( [](auto&& e) {e.clear();}, variant );
500 }
501
503 size_t size() {
504 return std::visit( [](auto&& e) {return e.size();}, variant );
505 }
506
508 AudioEffect* operator [](int idx){
509 return std::visit( [idx](auto&& e) {return e[idx];}, variant );
510 }
511
513 AudioEffect* findEffect(int id){
514 return std::visit( [id](auto&& e) {return e.findEffect(id);}, variant );
515 }
516
517 protected:
518 std::variant<AudioEffectStreamT<int16_t>, AudioEffectStreamT<int24_t>,AudioEffectStreamT<int32_t>> variant;
519 Stream *p_io=nullptr;
520 Print *p_print=nullptr;
521
522};
523
524#else
525// Use int16_t as only supported data type
527#endif
528
529} // namespace
Definition AudioEffects.h:24
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:45
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:50
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:33
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:27
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:63
void clear()
deletes all defined effects
Definition AudioEffects.h:39
Abstract Base class for Sound Effects.
Definition AudioEffect.h:21
EffectsStream supporting variable bits_per_sample. This class is only available when __cplusplus >= 2...
Definition AudioEffects.h:397
EffectsStreamT: the template class describes an input or output stream to which one or multiple effec...
Definition AudioEffects.h:208
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:365
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:375
void setOutput(Print &print) override
Defines/Changes the output target.
Definition AudioEffects.h:254
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioEffects.h:262
size_t write(const uint8_t *data, size_t len) override
Definition AudioEffects.h:299
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:352
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:346
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:370
void clear()
deletes all defined effects
Definition AudioEffects.h:359
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioEffects.h:248
OBSOLETE AudioEffects: the template class describes the input audio to which the effects are applied:...
Definition AudioEffects.h:87
effect_t readSample() override
provides the resulting sample
Definition AudioEffects.h:151
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:170
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:185
GeneratorT & generator()
Provides access to the sound generator.
Definition AudioEffects.h:175
virtual ~AudioEffects()
Destructor.
Definition AudioEffects.h:116
AudioEffects(AudioEffects &copy)
Copy constructor.
Definition AudioEffects.h:93
AudioEffects(GeneratorT &generator)
Constructor which is assigning a generator.
Definition AudioEffects.h:104
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:144
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:138
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:180
void setInput(GeneratorT &in)
Defines the input source for the raw guitar input.
Definition AudioEffects.h:127
void clear()
deletes all defined effects
Definition AudioEffects.h:164
AudioEffects(Stream &input, int channels=2, float volume=1.0)
Definition AudioEffects.h:110
AudioEffects()=default
Default constructor.
Abstract class: Objects can be put into a pipleline.
Definition AudioStreams.h:68
Definition NoArduino.h:62
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:28
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
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59