arduino-audio-tools
Loading...
Searching...
No Matches
Equalizer3Bands.h
Go to the documentation of this file.
1#pragma once
2#include <math.h>
3
6#include "AudioToolsConfig.h"
7
14namespace audio_tools {
15
38 channels = 2;
39 bits_per_sample = 16;
40 sample_rate = 44100;
41 }
42
45 int freq_low = 880;
46
49 int freq_high = 5000;
50
52 float gain_low = 1.0;
53
55 float gain_medium = 1.0;
56
58 float gain_high = 1.0;
59};
60
86 public:
90
94
102
107 setStream(stream);
108 addNotifyAudioChange(stream);
109 }
110
112 if (state != nullptr) delete[] state;
113 }
114
117 void setStream(Stream& io) override {
118 p_print = &io;
119 p_stream = &io;
120 };
121
124 void setOutput(Print& out) override { p_print = &out; }
125
129
133
138 p_cfg = &config;
139 return begin();
140 }
141
142 bool begin() {
144
146 if (state != nullptr) delete[] state;
147 state = new EQSTATE[p_cfg->channels];
149 }
150
151 // Setup state
152 for (int j = 0; j < max_state_count; j++) {
153 memset(&state[j], 0, sizeof(EQSTATE));
154
155 // Calculate filter cutoff frequencies
156 state[j].lf =
157 2 *
158 sin((float)PI * ((float)p_cfg->freq_low / (float)p_cfg->sample_rate));
159 state[j].hf = 2 * sin((float)PI * ((float)p_cfg->freq_high /
160 (float)p_cfg->sample_rate));
161 }
162 is_active = true;
163 return true;
164 }
165
166 void end() { is_active = false; }
167
176
181 size_t write(const uint8_t* data, size_t len) override {
182 filterSamples(data, len);
183 return p_print->write(data, len);
184 }
185
188 int availableForWrite() override { return p_print->availableForWrite(); }
189
194 size_t readBytes(uint8_t* data, size_t len) override {
195 size_t result = 0;
196 if (p_stream != nullptr) {
197 result = p_stream->readBytes(data, len);
198 filterSamples(data, len);
199 }
200 return result;
201 }
202
205 int available() override {
206 return p_stream != nullptr ? p_stream->available() : 0;
207 }
208
209 protected:
210 bool is_active = false;
213 const float vsa =
214 (1.0 / 4294967295.0);
215 Print* p_print = nullptr;
216 Stream* p_stream = nullptr;
218
220 struct EQSTATE {
221 // Filter #1 (Low band) - 4-pole low-pass filter
222 float lf;
223 float f1p0;
224 float f1p1;
225 float f1p2;
226 float f1p3;
227
228 // Filter #2 (High band) - 4-pole high-pass filter
229 float hf;
230 float f2p0;
231 float f2p1;
232 float f2p2;
233 float f2p3;
234
235 // Sample history buffer for filter calculations
236 float sdm1;
237 float sdm2;
238 float sdm3;
239
240 }* state = nullptr;
241
245 void filterSamples(const uint8_t* data, size_t len) {
246 // no filter if not active
247 if (!is_active) return;
248
249 // process samples
250 switch (p_cfg->bits_per_sample) {
251 case 16: {
252 int16_t* p_dataT = (int16_t*)data;
253 size_t sample_count = len / sizeof(int16_t);
254 for (size_t j = 0; j < sample_count; j += p_cfg->channels) {
255 for (int ch = 0; ch < p_cfg->channels; ch++) {
257 sample(state[ch],
259 16);
260 }
261 }
262 } break;
263 case 24: {
264 int24_t* p_dataT = (int24_t*)data;
265 size_t sample_count = len / sizeof(int24_t);
266 for (size_t j = 0; j < sample_count; j += p_cfg->channels) {
267 for (int ch = 0; ch < p_cfg->channels; ch++) {
269 sample(state[ch],
271 24);
272 }
273 }
274 } break;
275 case 32: {
276 int32_t* p_dataT = (int32_t*)data;
277 size_t sample_count = len / sizeof(int32_t);
278 for (size_t j = 0; j < sample_count; j += p_cfg->channels) {
279 for (int ch = 0; ch < p_cfg->channels; ch++) {
281 sample(state[ch],
283 32);
284 }
285 }
286 } break;
287
288 default:
289 LOGE("Only 16 bits supported: %d", p_cfg->bits_per_sample);
290 break;
291 }
292 }
293
298 float sample(EQSTATE& es, float sample) {
299 // Locals
300 float l, m, h; // Low / Mid / High - Sample Values
301 // Filter #1 (lowpass)
302 es.f1p0 += (es.lf * (sample - es.f1p0)) + vsa;
303 es.f1p1 += (es.lf * (es.f1p0 - es.f1p1));
304 es.f1p2 += (es.lf * (es.f1p1 - es.f1p2));
305 es.f1p3 += (es.lf * (es.f1p2 - es.f1p3));
306
307 l = es.f1p3;
308
309 // Filter #2 (highpass)
310 es.f2p0 += (es.hf * (sample - es.f2p0)) + vsa;
311 es.f2p1 += (es.hf * (es.f2p0 - es.f2p1));
312 es.f2p2 += (es.hf * (es.f2p1 - es.f2p2));
313 es.f2p3 += (es.hf * (es.f2p2 - es.f2p3));
314
315 h = es.sdm3 - es.f2p3;
316 // Calculate midrange (signal - (low + high))
317 m = es.sdm3 - (h + l);
318 // Scale, Combine and store
319 l *= p_cfg->gain_low;
320 m *= p_cfg->gain_medium;
321 h *= p_cfg->gain_high;
322
323 // Shuffle history buffer
324 es.sdm3 = es.sdm2;
325 es.sdm2 = es.sdm1;
326 es.sdm1 = sample;
327
328 // Return result
329 return (l + m + h);
330 }
331};
332
342 public:
346
350
358
363 setStream(stream);
364 stream.addNotifyAudioChange(*this);
365 }
366
368 if (state != nullptr) delete[] state;
369 }
370
372 void setStream(Stream& io) override {
373 p_print = &io;
374 p_stream = &io;
375 };
376
378 void setOutput(Print& out) override { p_print = &out; }
379
381
383
388 p_cfg = &config;
389 return begin();
390 }
391
394 bool begin() {
396 // Ensure per-channel arrays are allocated
398
399 // Ensure that EQSTATE is allocated
401 if (state != nullptr) delete[] state;
402 state = new EQSTATE[p_cfg->channels];
404 }
405
406 // Setup state for each channel with its own parameters
407 for (int j = 0; j < p_cfg->channels; j++) {
408 memset(&state[j], 0, sizeof(EQSTATE));
409
410 // Calculate filter cutoff frequencies per channel
411 state[j].lf =
412 2 * sin((float)PI * ((float)freq_low[j] / (float)p_cfg->sample_rate));
413 state[j].hf = 2 * sin((float)PI *
414 ((float)freq_high[j] / (float)p_cfg->sample_rate));
415 }
416 is_active = true;
417 return true;
418 }
419
420 void end() override { is_active = false; }
421
428
435 if (channel >= 0 && channel < p_cfg->channels && !freq_low.empty()) {
436 freq_low[channel] = freq_low_val;
437 freq_high[channel] = freq_high_val;
438
439 // Recalculate filter coefficients for this channel
440 if (state != nullptr) {
441 state[channel].lf =
442 2 *
443 sin((float)PI * ((float)freq_low_val / (float)p_cfg->sample_rate));
444 state[channel].hf =
445 2 *
446 sin((float)PI * ((float)freq_high_val / (float)p_cfg->sample_rate));
447 }
448 }
449 }
450
456 void setChannelGains(int channel, float gain_low_val, float gain_medium_val,
457 float gain_high_val) {
459 if (channel >= 0 && channel < p_cfg->channels && !gain_low.empty()) {
460 gain_low[channel] = gain_low_val;
461 gain_medium[channel] = gain_medium_val;
462 gain_high[channel] = gain_high_val;
463 }
464 }
465
471 bool getChannelFrequencies(int channel, int& freq_low_val,
472 int& freq_high_val) {
473 if (channel >= 0 && channel < p_cfg->channels && !freq_low.empty()) {
474 freq_low_val = freq_low[channel];
475 freq_high_val = freq_high[channel];
476 return true;
477 }
478 return false;
479 }
480
487 bool getChannelGains(int channel, float& gain_low_val, float& gain_medium_val,
488 float& gain_high_val) {
489 if (channel >= 0 && channel < p_cfg->channels && !gain_low.empty()) {
490 gain_low_val = gain_low[channel];
491 gain_medium_val = gain_medium[channel];
492 gain_high_val = gain_high[channel];
493 return true;
494 }
495 return false;
496 }
497
502 size_t write(const uint8_t* data, size_t len) override {
503 filterSamples(data, len);
504 return p_print->write(data, len);
505 }
506
509 int availableForWrite() override { return p_print->availableForWrite(); }
510
515 size_t readBytes(uint8_t* data, size_t len) override {
516 size_t result = 0;
517 if (p_stream != nullptr) {
518 result = p_stream->readBytes(data, len);
519 filterSamples(data, len);
520 }
521 return result;
522 }
523
526 int available() override {
527 return p_stream != nullptr ? p_stream->available() : 0;
528 }
529
530 protected:
531 bool is_active = false;
534 const float vsa =
535 (1.0 / 4294967295.0);
536 Print* p_print = nullptr;
537 Stream* p_stream = nullptr;
539
540 // Per-channel frequency and gain settings using Vector containers
546
547 struct EQSTATE {
548 // Filter #1 (Low band)
549 float lf; // Frequency
550 float f1p0; // Poles ...
551 float f1p1;
552 float f1p2;
553 float f1p3;
554
555 // Filter #2 (High band)
556 float hf; // Frequency
557 float f2p0; // Poles ...
558 float f2p1;
559 float f2p2;
560 float f2p3;
561
562 // Sample history buffer
563 float sdm1; // Sample data minus 1
564 float sdm2; // 2
565 float sdm3; // 3
566
567 }* state = nullptr;
568
575
578 void allocateChannelArrays(int num_channels) {
579 // Resize all vectors to accommodate the number of channels
580 freq_low.resize(num_channels);
581 freq_high.resize(num_channels);
582 gain_low.resize(num_channels);
583 gain_medium.resize(num_channels);
584 gain_high.resize(num_channels);
585
586 // Initialize with config default values
587 for (int i = 0; i < num_channels; i++) {
588 freq_low[i] = p_cfg->freq_low;
590 gain_low[i] = p_cfg->gain_low;
593 }
594 }
595
599 void filterSamples(const uint8_t* data, size_t len) {
600 if (!is_active) return;
601 switch (p_cfg->bits_per_sample) {
602 case 16: {
603 int16_t* p_dataT = (int16_t*)data;
604 size_t sample_count = len / sizeof(int16_t);
605 for (size_t j = 0; j < sample_count; j += p_cfg->channels) {
606 for (int ch = 0; ch < p_cfg->channels; ch++) {
609 }
610 }
611 } break;
612 case 24: {
613 int24_t* p_dataT = (int24_t*)data;
614 size_t sample_count = len / sizeof(int24_t);
615 for (size_t j = 0; j < sample_count; j += p_cfg->channels) {
616 for (int ch = 0; ch < p_cfg->channels; ch++) {
619 }
620 }
621 } break;
622 case 32: {
623 int32_t* p_dataT = (int32_t*)data;
624 size_t sample_count = len / sizeof(int32_t);
625 for (size_t j = 0; j < sample_count; j += p_cfg->channels) {
626 for (int ch = 0; ch < p_cfg->channels; ch++) {
629 }
630 }
631 } break;
632
633 default:
634 LOGE("Only 16 bits supported: %d", p_cfg->bits_per_sample);
635 break;
636 }
637 }
638
644 float sample(int channel, float sample_val) {
645 EQSTATE& es = state[channel];
646
647 // Locals
648 float l, m, h; // Low / Mid / High - Sample Values
649
650 // Filter #1 (lowpass)
651 es.f1p0 += (es.lf * (sample_val - es.f1p0)) + vsa;
652 es.f1p1 += (es.lf * (es.f1p0 - es.f1p1));
653 es.f1p2 += (es.lf * (es.f1p1 - es.f1p2));
654 es.f1p3 += (es.lf * (es.f1p2 - es.f1p3));
655
656 l = es.f1p3;
657
658 // Filter #2 (highpass)
659 es.f2p0 += (es.hf * (sample_val - es.f2p0)) + vsa;
660 es.f2p1 += (es.hf * (es.f2p0 - es.f2p1));
661 es.f2p2 += (es.hf * (es.f2p1 - es.f2p2));
662 es.f2p3 += (es.hf * (es.f2p2 - es.f2p3));
663
664 h = es.sdm3 - es.f2p3;
665
666 // Calculate midrange (signal - (low + high))
667 m = es.sdm3 - (h + l);
668
669 // Scale with per-channel gains
670 l *= gain_low[channel];
671 m *= gain_medium[channel];
672 h *= gain_high[channel];
673
674 // Shuffle history buffer
675 es.sdm3 = es.sdm2;
676 es.sdm2 = es.sdm1;
677 es.sdm1 = sample_val;
678
679 // Return result
680 return (l + m + h);
681 }
682};
683
684} // namespace audio_tools
#define PI
Definition AudioEffectsSuite.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:153
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:123
AudioInfo info
Definition BaseStream.h:174
3 Band Equalizer with identical settings for all channels
Definition Equalizer3Bands.h:85
int max_state_count
Maximum number of allocated channel states.
Definition Equalizer3Bands.h:217
void setOutput(Print &out) override
Definition Equalizer3Bands.h:124
Equalizer3Bands(AudioStream &stream)
Definition Equalizer3Bands.h:106
void filterSamples(const uint8_t *data, size_t len)
Definition Equalizer3Bands.h:245
bool is_active
Indicates if the equalizer is active.
Definition Equalizer3Bands.h:210
size_t readBytes(uint8_t *data, size_t len) override
Definition Equalizer3Bands.h:194
const float vsa
Very small amount for denormal fix.
Definition Equalizer3Bands.h:213
float sample(EQSTATE &es, float sample)
Definition Equalizer3Bands.h:298
bool begin()
Definition Equalizer3Bands.h:142
bool begin(ConfigEqualizer3Bands &config)
Definition Equalizer3Bands.h:137
int available() override
Definition Equalizer3Bands.h:205
size_t write(const uint8_t *data, size_t len) override
Definition Equalizer3Bands.h:181
ConfigEqualizer3Bands * p_cfg
Pointer to active configuration.
Definition Equalizer3Bands.h:212
ConfigEqualizer3Bands defaultConfig()
Definition Equalizer3Bands.h:132
Stream * p_stream
Input/output stream for read operations.
Definition Equalizer3Bands.h:216
int availableForWrite() override
Definition Equalizer3Bands.h:188
Equalizer3Bands(Print &out)
Definition Equalizer3Bands.h:89
struct audio_tools::Equalizer3Bands::EQSTATE * state
virtual void setAudioInfo(AudioInfo info) override
Definition Equalizer3Bands.h:170
Equalizer3Bands(Stream &in)
Definition Equalizer3Bands.h:93
void end()
Definition Equalizer3Bands.h:166
~Equalizer3Bands()
Definition Equalizer3Bands.h:111
Print * p_print
Output stream for write operations.
Definition Equalizer3Bands.h:215
void setStream(Stream &io) override
Definition Equalizer3Bands.h:117
ConfigEqualizer3Bands cfg
Default configuration instance.
Definition Equalizer3Bands.h:211
Equalizer3Bands(AudioOutput &out)
Definition Equalizer3Bands.h:98
ConfigEqualizer3Bands & config()
Definition Equalizer3Bands.h:128
3 Band Equalizer with per-channel frequency and gain control Allows independent frequency and gain se...
Definition Equalizer3Bands.h:341
int max_state_count
Maximum number of allocated channel states.
Definition Equalizer3Bands.h:538
void setOutput(Print &out) override
Defines/Changes the output target.
Definition Equalizer3Bands.h:378
bool getChannelGains(int channel, float &gain_low_val, float &gain_medium_val, float &gain_high_val)
Definition Equalizer3Bands.h:487
bool getChannelFrequencies(int channel, int &freq_low_val, int &freq_high_val)
Definition Equalizer3Bands.h:471
~Equalizer3BandsPerChannel()
Definition Equalizer3Bands.h:367
float sample(int channel, float sample_val)
Definition Equalizer3Bands.h:644
Equalizer3BandsPerChannel(Print &out)
Definition Equalizer3Bands.h:345
Equalizer3BandsPerChannel(AudioOutput &out)
Definition Equalizer3Bands.h:354
void allocateChannelArrays(int num_channels)
Definition Equalizer3Bands.h:578
void filterSamples(const uint8_t *data, size_t len)
Definition Equalizer3Bands.h:599
bool is_active
Definition Equalizer3Bands.h:531
size_t readBytes(uint8_t *data, size_t len) override
Definition Equalizer3Bands.h:515
const float vsa
Very small amount for denormal fix.
Definition Equalizer3Bands.h:534
Vector< int > freq_high
High frequency cutoffs per channel (Hz)
Definition Equalizer3Bands.h:542
bool begin()
Definition Equalizer3Bands.h:394
void end() override
Definition Equalizer3Bands.h:420
bool begin(ConfigEqualizer3Bands &config)
Definition Equalizer3Bands.h:387
int available() override
Definition Equalizer3Bands.h:526
struct audio_tools::Equalizer3BandsPerChannel::EQSTATE * state
size_t write(const uint8_t *data, size_t len) override
Definition Equalizer3Bands.h:502
ConfigEqualizer3Bands * p_cfg
Pointer to active configuration.
Definition Equalizer3Bands.h:533
ConfigEqualizer3Bands defaultConfig()
Definition Equalizer3Bands.h:382
Stream * p_stream
Input/output stream for read operations.
Definition Equalizer3Bands.h:537
int availableForWrite() override
Definition Equalizer3Bands.h:509
Vector< float > gain_high
High frequency gains per channel.
Definition Equalizer3Bands.h:545
Vector< float > gain_medium
Medium frequency gains per channel.
Definition Equalizer3Bands.h:544
Vector< float > gain_low
Low frequency gains per channel.
Definition Equalizer3Bands.h:543
void setChannelFrequencies(int channel, int freq_low_val, int freq_high_val)
Definition Equalizer3Bands.h:433
virtual void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition Equalizer3Bands.h:422
Equalizer3BandsPerChannel(AudioStream &stream)
Definition Equalizer3Bands.h:362
void ensureChannelArraysAllocated()
Ensures that per-channel arrays are allocated and properly sized.
Definition Equalizer3Bands.h:570
Print * p_print
Output stream for write operations.
Definition Equalizer3Bands.h:536
Vector< int > freq_low
Low frequency cutoffs per channel (Hz)
Definition Equalizer3Bands.h:541
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition Equalizer3Bands.h:372
ConfigEqualizer3Bands cfg
Default configuration instance.
Definition Equalizer3Bands.h:532
void setChannelGains(int channel, float gain_low_val, float gain_medium_val, float gain_high_val)
Definition Equalizer3Bands.h:456
Equalizer3BandsPerChannel(Stream &in)
Definition Equalizer3Bands.h:349
ConfigEqualizer3Bands & config()
Definition Equalizer3Bands.h:380
Abstract class: Objects can be put into a pipleline.
Definition AudioStreams.h:68
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:376
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:381
Definition NoArduino.h:62
virtual int availableForWrite()
Definition NoArduino.h:134
virtual size_t write(const uint8_t *data, size_t len)
Definition NoArduino.h:126
Definition NoArduino.h:142
virtual size_t readBytes(uint8_t *data, size_t len)
Definition NoArduino.h:147
virtual int available()
Definition NoArduino.h:146
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool empty()
Definition Vector.h:180
bool resize(int newSize, T value)
Definition Vector.h:266
int size()
Definition Vector.h:178
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition Int24_4bytes_t.h:16
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
audio_tools::int24_4bytes_t int24_t
Definition AudioToolsConfig.h:351
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61
Configuration for 3 Band Equalizer.
Definition Equalizer3Bands.h:36
int freq_high
Definition Equalizer3Bands.h:49
int freq_low
Definition Equalizer3Bands.h:45
float gain_low
Gain multiplier for low frequencies (0.0-2.0, where 1.0 = unity gain)
Definition Equalizer3Bands.h:52
float gain_medium
Gain multiplier for medium frequencies (0.0-2.0, where 1.0 = unity gain)
Definition Equalizer3Bands.h:55
ConfigEqualizer3Bands()
Definition Equalizer3Bands.h:37
float gain_high
Gain multiplier for high frequencies (0.0-2.0, where 1.0 = unity gain)
Definition Equalizer3Bands.h:58
Filter state for each channel.
Definition Equalizer3Bands.h:220
float f2p1
Filter pole 1.
Definition Equalizer3Bands.h:231
float hf
High frequency cutoff coefficient.
Definition Equalizer3Bands.h:229
float f1p2
Filter pole 2.
Definition Equalizer3Bands.h:225
float sdm1
Sample data minus 1 (previous sample)
Definition Equalizer3Bands.h:236
float f2p3
Filter pole 3.
Definition Equalizer3Bands.h:233
float f2p0
Filter pole 0.
Definition Equalizer3Bands.h:230
float lf
Low frequency cutoff coefficient.
Definition Equalizer3Bands.h:222
float sdm3
Sample data minus 3.
Definition Equalizer3Bands.h:238
float f1p1
Filter pole 1.
Definition Equalizer3Bands.h:224
float f1p0
Filter pole 0.
Definition Equalizer3Bands.h:223
float f1p3
Filter pole 3.
Definition Equalizer3Bands.h:226
float f2p2
Filter pole 2.
Definition Equalizer3Bands.h:232
float sdm2
Sample data minus 2.
Definition Equalizer3Bands.h:237
Definition Equalizer3Bands.h:547
float f2p1
Definition Equalizer3Bands.h:558
float hf
Definition Equalizer3Bands.h:556
float f1p2
Definition Equalizer3Bands.h:552
float sdm1
Definition Equalizer3Bands.h:563
float f2p3
Definition Equalizer3Bands.h:560
float f2p0
Definition Equalizer3Bands.h:557
float lf
Definition Equalizer3Bands.h:549
float sdm3
Definition Equalizer3Bands.h:565
float f1p1
Definition Equalizer3Bands.h:551
float f1p0
Definition Equalizer3Bands.h:550
float f1p3
Definition Equalizer3Bands.h:553
float f2p2
Definition Equalizer3Bands.h:559
float sdm2
Definition Equalizer3Bands.h:564