arduino-audio-tools
Loading...
Searching...
No Matches
AudioEffects.h
Go to the documentation of this file.
1#pragma once
2#include "AudioToolsConfig.h"
5#include "SoundGenerator.h"
6#include "AudioEffect.h"
7// USE_VARIANTS defaults to on whenever the compiler is capable of it (needed
8// for AudioEffectStream's runtime bits_per_sample switching); define
9// `#define USE_VARIANTS 0` before including AudioTools.h to force the plain
10// AudioEffectStreamT<effect_t> typedef instead, e.g. on a size-constrained target.
11#ifndef USE_VARIANTS
12# define USE_VARIANTS (__cplusplus >= 201703L)
13#endif
14#if USE_VARIANTS
15# include <variant>
16#endif
17
24namespace audio_tools {
25
33 public:
35 void addEffect(AudioEffect &effect){
36 TRACED();
37 effects.push_back(&effect);
38 }
39
41 void addEffect(AudioEffect *effect){
42 TRACED();
43 effects.push_back(effect);
44 LOGI("addEffect -> Number of effects: %d", (int)size());
45 }
47 void clear() {
48 TRACED();
49 effects.clear();
50 }
51
53 size_t size() {
54 return effects.size();
55 }
56
59 // find AudioEffect
60 AudioEffect* result = nullptr;
61 for (int j=0;j<size();j++){
62 // we assume that ADSRGain is the first effect!
63 if (effects[j]->id()==id){
64 result = effects[j];
65 }
66 LOGI("--> findEffect -> %d", effects[j]->id());
67 }
68 return result;
69 }
72 return effects[idx];
73 }
74
75 protected:
77
78};
79
94template <class GeneratorT>
95class AudioEffects : public SoundGenerator<effect_t> {
96 public:
98 AudioEffects() = default;
99
102 TRACEI();
103 // create a copy of the source and all effects
105 for (int j=0;j<copy.size();j++){
106 effects.addEffect(copy[j]->clone());
107 }
108 LOGI("Number of effects %d -> %d", copy.size(), this->size());
109 }
110
112 AudioEffects(GeneratorT &generator) {
114 }
115
118 AudioEffects(Stream &input, int channels=2, float volume=1.0) {
119 setInput(* (new GeneratorT(input, channels, volume)));
120 owns_generator = true;
121 }
122
124 virtual ~AudioEffects(){
125 TRACED();
126 if (owns_generator && p_generator!=nullptr){
127 delete p_generator;
128 }
129 for (int j=0;j<effects.size();j++){
130 delete effects[j];
131 }
132 }
133
135 void setInput(GeneratorT &in){
136 TRACED();
137 p_generator = &in;
138 // automatically activate this object
140 info.channels = 1;
141 info.bits_per_sample = sizeof(effect_t)*8;
142 begin(info);
143 }
144
146 void addEffect(AudioEffect &effect){
147 TRACED();
148 effects.addEffect(&effect);
149 }
150
152 void addEffect(AudioEffect *effect){
153 TRACED();
154 effects.addEffect(effect);
155 LOGI("addEffect -> Number of effects: %d", size());
156 }
157
159 effect_t readSample() override {
160 effect_t sample;
161 if (p_generator!=nullptr){
162 sample = p_generator->readSample();
163 int size = effects.size();
164 for (int j=0; j<size; j++){
165 sample = effects[j]->process(sample);
166 }
167 }
168 return sample;
169 }
170
172 void clear() {
173 TRACED();
174 effects.clear();
175 }
176
178 size_t size() {
179 return effects.size();
180 }
181
183 GeneratorT &generator(){
184 return *p_generator;
185 }
186
189 return effects[idx];
190 }
191
194 return effects.findEffect(id);
195 }
196
197 protected:
199 GeneratorT *p_generator=nullptr;
200 bool owns_generator = false;
201};
202
203
222template <class T>
224 public:
226
228 setStream(io);
229 }
230
232 setOutput(out);
233 }
234
235 // copying would shallow-copy channel_effects/owned_clones and double-free on destruction
238
240 clear();
241 }
242
244 AudioInfo cfg;
245 cfg.sample_rate = 44100;
246 cfg.bits_per_sample = 16;
247 cfg.channels = 2;
248 return cfg;
249 }
250
251 bool begin(AudioInfo cfg){
252 info = cfg;
253 return begin();
254 }
255
256 bool begin(){
257 TRACEI();
258 // 24-bit samples are commonly stored padded to 4 bytes (int24_4bytes_t,
259 // the default int24_t) for alignment/performance, so sizeof(T) won't
260 // equal bits_per_sample/8==3 in that case; accept sizeof(int24_t) too.
261 bool bits_ok = sizeof(T)==info.bits_per_sample/8
262 || (info.bits_per_sample==24 && sizeof(T)==sizeof(int24_t));
263 if (bits_ok){
264 active = true;
266 } else {
267 LOGE("bits_per_sample not consistent: %d",info.bits_per_sample);
268 active = false;
269 }
270 return active;
271 }
272
273 void end() override {
274 active = false;
275 }
276
277 void setStream(Stream &io) override {
278 p_io = &io;
279 p_print = &io;
280 }
281
282
283 void setOutput(Print &print) override {
284 p_print = &print;
285 }
286
291 size_t readBytes(uint8_t *data, size_t len) override {
292 if (!active || p_io==nullptr)return 0;
293
294 // read data from source
295 size_t result = p_io->readBytes((uint8_t*)data, len);
296 int frames = result / sizeof(T) / info.channels;
297 T* samples = (T*) data;
298
299 for (int f=0;f<frames;f++){
300 for (int ch=0;ch<info.channels;ch++){
301 T &sample = samples[f*info.channels+ch];
303 for (int j=0; j<chain.size(); j++){
304 sample = chain[j]->process(sample);
305 }
306 }
307 }
308 return result;
309 }
310
318 size_t write(const uint8_t *data, size_t len) override {
319 if (!active)return 0;
320 // length must be multple of channels
321 assert(len % (sizeof(T)*info.channels)==0);
322 int frames = len / sizeof(T) / info.channels;
323 int total_samples = frames * info.channels;
324
325 buffer_out.resize(total_samples);
326 T* out = buffer_out.data();
327
328 // process all samples
329 for (int f=0;f<frames;f++){
330 const T* p_buffer = ((const T*)data) + (f*info.channels);
331 T* p_out = out + (f*info.channels);
332 for (int ch=0;ch<info.channels;ch++){
333 T sample = p_buffer[ch];
335 for (int j=0; j<chain.size(); j++){
336 sample = chain[j]->process(sample);
337 }
338 p_out[ch] = sample;
339 }
340 }
341
342 size_t written_samples = 0;
343 if (p_io!=nullptr){
344 written_samples = writeDataT<T, Stream>(p_io, out, total_samples);
345 } else if (p_print!=nullptr){
346 written_samples = writeDataT<T, Print>(p_print, out, total_samples);
347 }
348 return written_samples * sizeof(T);
349 }
350
351 int available() override {
352 if (p_io==nullptr) return 0;
353 return p_io->available();
354 }
355
356 int availableForWrite() override {
357 if (p_print!=nullptr) return p_print->availableForWrite();
358 if (p_io!=nullptr) return p_io->availableForWrite();
359 return 0;
360 }
361
363 void addEffect(AudioEffect &effect){
364 addEffect(&effect);
365 }
366
368 void addEffect(AudioEffect *effect){
369 TRACED();
370 effects.addEffect(effect);
371 LOGI("addEffect -> Number of effects: %d", (int) size());
372 // if channels are already set up, extend them immediately instead of
373 // waiting for the next begin()
374 if (active){
375 for (int ch=0; ch<channel_effects.size(); ch++){
376 cloneInto(ch, effect);
377 }
378 }
379 }
380
383 void addEffect(int channel, AudioEffect &effect){
384 addEffect(channel, &effect);
385 }
386
389 void addEffect(int channel, AudioEffect *effect){
390 TRACED();
391 if (!active || channel<0 || channel>=channel_effects.size()){
392 LOGE("Invalid channel %d or begin() not yet called", channel);
393 return;
394 }
395 channel_effects[channel].addEffect(effect);
396 }
397
399 void clear() {
400 TRACED();
401 for (int i=0; i<owned_clones.size(); i++){
402 delete owned_clones[i];
403 }
404 owned_clones.clear();
405 channel_effects.clear();
406 effects.clear();
407 }
408
410 size_t size() {
411 return effects.size();
412 }
413
416 return effects[idx];
417 }
418
421 return effects.findEffect(id);
422 }
423
426 return channel_effects[channel];
427 }
428
431 return channel_effects.size();
432 }
433
434 protected:
435 AudioEffectCommon effects; // template chain populated via addEffect()
436 Vector<AudioEffectCommon> channel_effects; // one independent chain per channel, cloned from `effects`
437 Vector<AudioEffect*> owned_clones; // clones created internally; ours to delete
438 Vector<T> buffer_out; // reused scratch buffer for write(): avoids per-sample writes
439 bool active = false;
440 Stream *p_io=nullptr;
441 Print *p_print=nullptr;
442
444 void cloneInto(int ch, AudioEffect *effect){
445 AudioEffect *clone = effect->clone();
446 channel_effects[ch].addEffect(clone);
447 owned_clones.push_back(clone);
448 }
449
452 for (int i=0; i<owned_clones.size(); i++){
453 delete owned_clones[i];
454 }
455 owned_clones.clear();
456 channel_effects.clear();
458 for (int ch=0; ch<info.channels; ch++){
459 for (int j=0; j<effects.size(); j++){
460 cloneInto(ch, effects[j]);
461 }
462 }
463 }
464};
465
466#if USE_VARIANTS || defined(DOXYGEN)
478 public:
479 AudioEffectStream() = default;
480
482 setOutput(io);
483 setInput(io);
484 }
485
487 setOutput(out);
488 }
489
491 AudioInfo cfg;
492 cfg.sample_rate = 44100;
493 cfg.bits_per_sample = 16;
494 cfg.channels = 2;
495 return cfg;
496 }
497
498 bool begin(AudioInfo cfg){
499 info = cfg;
500 return begin();
501 }
502
503 bool begin(){
504 TRACEI();
505 switch(info.bits_per_sample){
506 case 16:
507 variant.emplace<0>();
508 break;
509 case 24:
510 variant.emplace<1>();
511 break;
512 case 32:
513 variant.emplace<2>();
514 break;
515 default:
516 LOGE("Unspported bits_per_sample: %d", info.bits_per_sample);
517 return false;
518 }
519 if (p_print != nullptr) {
520 std::visit( [this](auto&& e) {return e.setOutput(*p_print);}, variant );
521 }
522 if (p_io != nullptr) {
523 std::visit( [this](auto&& e) {return e.setStream(*p_io);}, variant );
524 }
525 return std::visit( [this](auto&& e) {return e.begin(info);}, variant );
526 }
527
528 void end() override {
529 std::visit( [](auto&& e) {e.end();}, variant );
530 }
531
532 void setInput(Stream &io){
533 setStream(io);
534 }
535
536 void setStream(Stream &io){
537 p_io = &io;
538 }
539
540 void setOutput(Stream &io){
541 p_print = &io;
542 }
543
544 void setOutput(Print &print){
545 p_print = &print;
546 }
547
552 size_t readBytes(uint8_t *data, size_t len) override {
553 return std::visit( [data, len](auto&& e) {return e.readBytes(data, len);}, variant );
554 }
555
560 size_t write(const uint8_t *data, size_t len) override {
561 return std::visit( [data, len](auto&& e) {return e.write(data, len);}, variant );
562 }
563
564 int available() override {
565 return std::visit( [](auto&& e) {return e.available();}, variant );
566 }
567
568 int availableForWrite() override {
569 return std::visit( [](auto&& e) {return e.availableForWrite();}, variant );
570 }
571
573 void addEffect(AudioEffect &effect){
574 addEffect(&effect);
575 }
576
578 void addEffect(AudioEffect *effect){
579 std::visit( [effect](auto&& e) {e.addEffect(effect);}, variant );
580 }
581
583 void addEffect(int channel, AudioEffect &effect){
584 addEffect(channel, &effect);
585 }
586
588 void addEffect(int channel, AudioEffect *effect){
589 std::visit( [channel, effect](auto&& e) {e.addEffect(channel, effect);}, variant );
590 }
591
593 void clear() {
594 std::visit( [](auto&& e) {e.clear();}, variant );
595 }
596
598 size_t size() {
599 return std::visit( [](auto&& e) {return e.size();}, variant );
600 }
601
604 return std::visit( [idx](auto&& e) {return e[idx];}, variant );
605 }
606
609 return std::visit( [id](auto&& e) {return e.findEffect(id);}, variant );
610 }
611
614 return std::visit( [channel](auto&& e) -> AudioEffectCommon& {return e.channelEffects(channel);}, variant );
615 }
616
619 return std::visit( [](auto&& e) {return e.channelCount();}, variant );
620 }
621
622 protected:
623 std::variant<AudioEffectStreamT<int16_t>, AudioEffectStreamT<int24_t>,AudioEffectStreamT<int32_t>> variant;
624 Stream *p_io=nullptr;
625 Print *p_print=nullptr;
626
627};
628
629#else
630// Use int16_t as only supported data type
632#endif
633
634} // namespace
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define assert(T)
Definition avr.h:10
Definition Arduino.h:56
virtual int availableForWrite()
Definition Arduino.h:128
Definition Arduino.h:136
virtual size_t readBytes(uint8_t *data, size_t len)
Definition Arduino.h:140
virtual int available()
Definition Arduino.h:139
Definition AudioEffects.h:32
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:53
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:58
Vector< AudioEffect * > effects
Definition AudioEffects.h:76
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:41
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:35
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:71
void clear()
deletes all defined effects
Definition AudioEffects.h:47
Abstract Base class for Sound Effects.
Definition AudioEffect.h:24
virtual AudioEffect * clone()=0
EffectsStream supporting variable bits_per_sample. This class is only available when __cplusplus >= 2...
Definition AudioEffects.h:477
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:598
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:608
void addEffect(int channel, AudioEffect &effect)
Adds an effect object (by reference) directly to a single channel's own chain.
Definition AudioEffects.h:583
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioEffects.h:552
AudioEffectCommon & channelEffects(int channel)
Provides access to a single channel's own effect chain (valid after begin())
Definition AudioEffects.h:613
bool begin()
Definition AudioEffects.h:503
void end() override
Definition AudioEffects.h:528
int available() override
Definition AudioEffects.h:564
size_t write(const uint8_t *data, size_t len) override
Definition AudioEffects.h:560
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:578
AudioEffectStream(Stream &io)
Definition AudioEffects.h:481
AudioEffectStream(Print &out)
Definition AudioEffects.h:486
std::variant< AudioEffectStreamT< int16_t >, AudioEffectStreamT< int24_t >, AudioEffectStreamT< int32_t > > variant
Definition AudioEffects.h:623
AudioInfo defaultConfig()
Definition AudioEffects.h:490
int availableForWrite() override
Definition AudioEffects.h:568
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:573
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:603
void addEffect(int channel, AudioEffect *effect)
Adds an effect using a pointer directly to a single channel's own chain.
Definition AudioEffects.h:588
int channelCount()
Provides the number of channels that have their own effect chain (valid after begin())
Definition AudioEffects.h:618
void clear()
deletes all defined effects
Definition AudioEffects.h:593
Print * p_print
Definition AudioEffects.h:625
void setStream(Stream &io)
Defines/Changes the input & output.
Definition AudioEffects.h:536
void setOutput(Stream &io)
Definition AudioEffects.h:540
bool begin(AudioInfo cfg)
Definition AudioEffects.h:498
Stream * p_io
Definition AudioEffects.h:624
void setInput(Stream &io)
Definition AudioEffects.h:532
void setOutput(Print &print)
Defines/Changes the output target.
Definition AudioEffects.h:544
EffectsStreamT: the template class describes an input or output stream to which one or multiple effec...
Definition AudioEffects.h:223
bool active
Definition AudioEffects.h:439
size_t size()
Provides the actual number of defined effects in the template chain.
Definition AudioEffects.h:410
AudioEffect * findEffect(int id)
Finds an effect by id in the template chain.
Definition AudioEffects.h:420
void setOutput(Print &print) override
Defines/Changes the output target.
Definition AudioEffects.h:283
void addEffect(int channel, AudioEffect &effect)
Definition AudioEffects.h:383
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioEffects.h:291
void setupChannels()
(re)builds channel_effects from the template effects chain
Definition AudioEffects.h:451
AudioEffectStreamT(Print &out)
Definition AudioEffects.h:231
AudioEffectCommon & channelEffects(int channel)
Provides access to a single channel's own effect chain (valid after begin())
Definition AudioEffects.h:425
Vector< T > buffer_out
Definition AudioEffects.h:438
bool begin()
Definition AudioEffects.h:256
void end() override
Definition AudioEffects.h:273
Vector< AudioEffectCommon > channel_effects
Definition AudioEffects.h:436
Vector< AudioEffect * > owned_clones
Definition AudioEffects.h:437
int available() override
Definition AudioEffects.h:351
size_t write(const uint8_t *data, size_t len) override
Definition AudioEffects.h:318
void addEffect(AudioEffect *effect)
Adds an effect using a pointer to the template chain: cloned into every channel.
Definition AudioEffects.h:368
AudioInfo defaultConfig()
Definition AudioEffects.h:243
AudioEffectStreamT(const AudioEffectStreamT &)=delete
int availableForWrite() override
Definition AudioEffects.h:356
void addEffect(AudioEffect &effect)
Adds an effect object (by reference) to the template chain: cloned into every channel.
Definition AudioEffects.h:363
AudioEffect * operator[](int idx)
gets an effect by index from the template chain
Definition AudioEffects.h:415
AudioEffectCommon effects
Definition AudioEffects.h:435
void addEffect(int channel, AudioEffect *effect)
Definition AudioEffects.h:389
~AudioEffectStreamT()
Definition AudioEffects.h:239
AudioEffectStreamT & operator=(const AudioEffectStreamT &)=delete
int channelCount()
Provides the number of channels that have their own effect chain (valid after begin())
Definition AudioEffects.h:430
void clear()
deletes all defined effects
Definition AudioEffects.h:399
AudioEffectStreamT(Stream &io)
Definition AudioEffects.h:227
Print * p_print
Definition AudioEffects.h:441
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioEffects.h:277
void cloneInto(int ch, AudioEffect *effect)
clones a single effect into a single channel's chain, tracking ownership
Definition AudioEffects.h:444
bool begin(AudioInfo cfg)
Definition AudioEffects.h:251
Stream * p_io
Definition AudioEffects.h:440
OBSOLETE AudioEffects: the template class describes the input audio to which the effects are applied:...
Definition AudioEffects.h:95
effect_t readSample() override
provides the resulting sample
Definition AudioEffects.h:159
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:178
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:193
GeneratorT & generator()
Provides access to the sound generator.
Definition AudioEffects.h:183
GeneratorT * p_generator
Definition AudioEffects.h:199
virtual ~AudioEffects()
Destructor.
Definition AudioEffects.h:124
AudioEffects(AudioEffects &copy)
Copy constructor.
Definition AudioEffects.h:101
AudioEffects(GeneratorT &generator)
Constructor which is assigning a generator.
Definition AudioEffects.h:112
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:152
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:146
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:188
AudioEffectCommon effects
Definition AudioEffects.h:198
void setInput(GeneratorT &in)
Defines the input source for the raw guitar input.
Definition AudioEffects.h:135
void clear()
deletes all defined effects
Definition AudioEffects.h:172
AudioEffects(Stream &input, int channels=2, float volume=1.0)
Definition AudioEffects.h:118
AudioEffects()=default
Default constructor.
bool owns_generator
Definition AudioEffects.h:200
AudioInfo info
Definition BaseStream.h:171
Abstract class: Objects can be put into a pipleline.
Definition AudioStreams.h:68
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:28
AudioInfo info
Definition SoundGenerator.h:116
virtual bool begin()
Starts the processing.
Definition SoundGenerator.h:41
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 LMSEchoCancellationStream.h:6
int16_t effect_t
Definition AudioEffect.h:15
int24_4bytes_t int24_t
Definition int24_t.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57