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
315 size_t write(const uint8_t *data, size_t len) override {
316 if (!active)return 0;
317 // length must be multple of channels
318 assert(len % (sizeof(T)*info.channels)==0);
319 int frames = len / sizeof(T) / info.channels;
320 size_t result_size = 0;
321
322 // process all samples
323 for (int f=0;f<frames;f++){
324 const T* p_buffer = ((const T*)data) + (f*info.channels);
325 for (int ch=0;ch<info.channels;ch++){
326 T sample = p_buffer[ch];
328 for (int j=0; j<chain.size(); j++){
329 sample = chain[j]->process(sample);
330 }
331
332 if (p_io!=nullptr){
333 p_io->write((uint8_t*)&sample, sizeof(T));
334 } else if (p_print!=nullptr){
335 p_print->write((uint8_t*)&sample, sizeof(T));
336 }
337 result_size += sizeof(T);
338 }
339 }
340 return result_size;
341 }
342
343 int available() override {
344 if (p_io==nullptr) return 0;
345 return p_io->available();
346 }
347
348 int availableForWrite() override {
349 if (p_print!=nullptr) return p_print->availableForWrite();
350 if (p_io!=nullptr) return p_io->availableForWrite();
351 return 0;
352 }
353
355 void addEffect(AudioEffect &effect){
356 addEffect(&effect);
357 }
358
360 void addEffect(AudioEffect *effect){
361 TRACED();
362 effects.addEffect(effect);
363 LOGI("addEffect -> Number of effects: %d", (int) size());
364 // if channels are already set up, extend them immediately instead of
365 // waiting for the next begin()
366 if (active){
367 for (int ch=0; ch<channel_effects.size(); ch++){
368 cloneInto(ch, effect);
369 }
370 }
371 }
372
375 void addEffect(int channel, AudioEffect &effect){
376 addEffect(channel, &effect);
377 }
378
381 void addEffect(int channel, AudioEffect *effect){
382 TRACED();
383 if (!active || channel<0 || channel>=channel_effects.size()){
384 LOGE("Invalid channel %d or begin() not yet called", channel);
385 return;
386 }
387 channel_effects[channel].addEffect(effect);
388 }
389
391 void clear() {
392 TRACED();
393 for (int i=0; i<owned_clones.size(); i++){
394 delete owned_clones[i];
395 }
396 owned_clones.clear();
397 channel_effects.clear();
398 effects.clear();
399 }
400
402 size_t size() {
403 return effects.size();
404 }
405
408 return effects[idx];
409 }
410
413 return effects.findEffect(id);
414 }
415
418 return channel_effects[channel];
419 }
420
423 return channel_effects.size();
424 }
425
426 protected:
427 AudioEffectCommon effects; // template chain populated via addEffect()
428 Vector<AudioEffectCommon> channel_effects; // one independent chain per channel, cloned from `effects`
429 Vector<AudioEffect*> owned_clones; // clones created internally; ours to delete
430 bool active = false;
431 Stream *p_io=nullptr;
432 Print *p_print=nullptr;
433
435 void cloneInto(int ch, AudioEffect *effect){
436 AudioEffect *clone = effect->clone();
437 channel_effects[ch].addEffect(clone);
438 owned_clones.push_back(clone);
439 }
440
443 for (int i=0; i<owned_clones.size(); i++){
444 delete owned_clones[i];
445 }
446 owned_clones.clear();
447 channel_effects.clear();
449 for (int ch=0; ch<info.channels; ch++){
450 for (int j=0; j<effects.size(); j++){
451 cloneInto(ch, effects[j]);
452 }
453 }
454 }
455};
456
457#if USE_VARIANTS || defined(DOXYGEN)
469 public:
470 AudioEffectStream() = default;
471
473 setOutput(io);
474 setInput(io);
475 }
476
478 setOutput(out);
479 }
480
482 AudioInfo cfg;
483 cfg.sample_rate = 44100;
484 cfg.bits_per_sample = 16;
485 cfg.channels = 2;
486 return cfg;
487 }
488
489 bool begin(AudioInfo cfg){
490 info = cfg;
491 return begin();
492 }
493
494 bool begin(){
495 TRACEI();
496 switch(info.bits_per_sample){
497 case 16:
498 variant.emplace<0>();
499 break;
500 case 24:
501 variant.emplace<1>();
502 break;
503 case 32:
504 variant.emplace<2>();
505 break;
506 default:
507 LOGE("Unspported bits_per_sample: %d", info.bits_per_sample);
508 return false;
509 }
510 if (p_print != nullptr) {
511 std::visit( [this](auto&& e) {return e.setOutput(*p_print);}, variant );
512 }
513 if (p_io != nullptr) {
514 std::visit( [this](auto&& e) {return e.setStream(*p_io);}, variant );
515 }
516 return std::visit( [this](auto&& e) {return e.begin(info);}, variant );
517 }
518
519 void end() override {
520 std::visit( [](auto&& e) {e.end();}, variant );
521 }
522
523 void setInput(Stream &io){
524 setStream(io);
525 }
526
527 void setStream(Stream &io){
528 p_io = &io;
529 }
530
531 void setOutput(Stream &io){
532 p_print = &io;
533 }
534
535 void setOutput(Print &print){
536 p_print = &print;
537 }
538
543 size_t readBytes(uint8_t *data, size_t len) override {
544 return std::visit( [data, len](auto&& e) {return e.readBytes(data, len);}, variant );
545 }
546
551 size_t write(const uint8_t *data, size_t len) override {
552 return std::visit( [data, len](auto&& e) {return e.write(data, len);}, variant );
553 }
554
555 int available() override {
556 return std::visit( [](auto&& e) {return e.available();}, variant );
557 }
558
559 int availableForWrite() override {
560 return std::visit( [](auto&& e) {return e.availableForWrite();}, variant );
561 }
562
564 void addEffect(AudioEffect &effect){
565 addEffect(&effect);
566 }
567
569 void addEffect(AudioEffect *effect){
570 std::visit( [effect](auto&& e) {e.addEffect(effect);}, variant );
571 }
572
574 void addEffect(int channel, AudioEffect &effect){
575 addEffect(channel, &effect);
576 }
577
579 void addEffect(int channel, AudioEffect *effect){
580 std::visit( [channel, effect](auto&& e) {e.addEffect(channel, effect);}, variant );
581 }
582
584 void clear() {
585 std::visit( [](auto&& e) {e.clear();}, variant );
586 }
587
589 size_t size() {
590 return std::visit( [](auto&& e) {return e.size();}, variant );
591 }
592
595 return std::visit( [idx](auto&& e) {return e[idx];}, variant );
596 }
597
600 return std::visit( [id](auto&& e) {return e.findEffect(id);}, variant );
601 }
602
605 return std::visit( [channel](auto&& e) -> AudioEffectCommon& {return e.channelEffects(channel);}, variant );
606 }
607
610 return std::visit( [](auto&& e) {return e.channelCount();}, variant );
611 }
612
613 protected:
614 std::variant<AudioEffectStreamT<int16_t>, AudioEffectStreamT<int24_t>,AudioEffectStreamT<int32_t>> variant;
615 Stream *p_io=nullptr;
616 Print *p_print=nullptr;
617
618};
619
620#else
621// Use int16_t as only supported data type
623#endif
624
625} // 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
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
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:23
virtual AudioEffect * clone()=0
EffectsStream supporting variable bits_per_sample. This class is only available when __cplusplus >= 2...
Definition AudioEffects.h:468
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:589
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:599
void addEffect(int channel, AudioEffect &effect)
Adds an effect object (by reference) directly to a single channel's own chain.
Definition AudioEffects.h:574
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioEffects.h:543
AudioEffectCommon & channelEffects(int channel)
Provides access to a single channel's own effect chain (valid after begin())
Definition AudioEffects.h:604
bool begin()
Definition AudioEffects.h:494
void end() override
Definition AudioEffects.h:519
int available() override
Definition AudioEffects.h:555
size_t write(const uint8_t *data, size_t len) override
Definition AudioEffects.h:551
void addEffect(AudioEffect *effect)
Adds an effect using a pointer.
Definition AudioEffects.h:569
AudioEffectStream(Stream &io)
Definition AudioEffects.h:472
AudioEffectStream(Print &out)
Definition AudioEffects.h:477
std::variant< AudioEffectStreamT< int16_t >, AudioEffectStreamT< int24_t >, AudioEffectStreamT< int32_t > > variant
Definition AudioEffects.h:614
AudioInfo defaultConfig()
Definition AudioEffects.h:481
int availableForWrite() override
Definition AudioEffects.h:559
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:564
AudioEffect * operator[](int idx)
gets an effect by index
Definition AudioEffects.h:594
void addEffect(int channel, AudioEffect *effect)
Adds an effect using a pointer directly to a single channel's own chain.
Definition AudioEffects.h:579
int channelCount()
Provides the number of channels that have their own effect chain (valid after begin())
Definition AudioEffects.h:609
void clear()
deletes all defined effects
Definition AudioEffects.h:584
Print * p_print
Definition AudioEffects.h:616
void setStream(Stream &io)
Defines/Changes the input & output.
Definition AudioEffects.h:527
void setOutput(Stream &io)
Definition AudioEffects.h:531
bool begin(AudioInfo cfg)
Definition AudioEffects.h:489
Stream * p_io
Definition AudioEffects.h:615
void setInput(Stream &io)
Definition AudioEffects.h:523
void setOutput(Print &print)
Defines/Changes the output target.
Definition AudioEffects.h:535
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:430
size_t size()
Provides the actual number of defined effects in the template chain.
Definition AudioEffects.h:402
AudioEffect * findEffect(int id)
Finds an effect by id in the template chain.
Definition AudioEffects.h:412
void setOutput(Print &print) override
Defines/Changes the output target.
Definition AudioEffects.h:283
void addEffect(int channel, AudioEffect &effect)
Definition AudioEffects.h:375
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:442
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:417
bool begin()
Definition AudioEffects.h:256
void end() override
Definition AudioEffects.h:273
Vector< AudioEffectCommon > channel_effects
Definition AudioEffects.h:428
Vector< AudioEffect * > owned_clones
Definition AudioEffects.h:429
int available() override
Definition AudioEffects.h:343
size_t write(const uint8_t *data, size_t len) override
Definition AudioEffects.h:315
void addEffect(AudioEffect *effect)
Adds an effect using a pointer to the template chain: cloned into every channel.
Definition AudioEffects.h:360
AudioInfo defaultConfig()
Definition AudioEffects.h:243
AudioEffectStreamT(const AudioEffectStreamT &)=delete
int availableForWrite() override
Definition AudioEffects.h:348
void addEffect(AudioEffect &effect)
Adds an effect object (by reference) to the template chain: cloned into every channel.
Definition AudioEffects.h:355
AudioEffect * operator[](int idx)
gets an effect by index from the template chain
Definition AudioEffects.h:407
AudioEffectCommon effects
Definition AudioEffects.h:427
void addEffect(int channel, AudioEffect *effect)
Definition AudioEffects.h:381
~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:422
void clear()
deletes all defined effects
Definition AudioEffects.h:391
AudioEffectStreamT(Stream &io)
Definition AudioEffects.h:227
Print * p_print
Definition AudioEffects.h:432
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:435
bool begin(AudioInfo cfg)
Definition AudioEffects.h:251
Stream * p_io
Definition AudioEffects.h:431
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:14
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