arduino-audio-tools
Loading...
Searching...
No Matches
FFTEffects.h
Go to the documentation of this file.
1#pragma once
2
3#include "AudioTools/FFT/AudioRealFFT.h" // using RealFFT
6
7namespace audio_tools {
8
11
22
73class FFTEffect : public AudioOutput {
74 public:
76 p_out = &out;
78 fft_cfg.ref = this;
79 }
80
82 p_out = &out;
83 p_fft = &fft;
84 fft_cfg.ref = this;
85 }
86
89 // use a window function owned by this instance: sharing the static
90 // default across multiple concurrently active effects would let one
91 // instance's begin() resize the buffers out from under another
93 return c;
94 }
95
97 copier.setLogName("ifft");
98 setAudioInfo(info);
99 fft_cfg.length = info.length;
100 fft_cfg.stride = info.stride > 0 ? info.stride : info.length;
102 return begin();
103 }
104
105 bool begin() override {
106 TRACED();
107 // copy result to output
109
110 // setup fft
113 LOGI("length: %d", fft_cfg.length);
114 LOGI("stride: %d", fft_cfg.stride);
115 LOGI("window_function: %s", (fft_cfg.window_function != nullptr)
117 : "-");
118 return p_fft->begin(fft_cfg);
119 }
120
121 size_t write(const uint8_t *data, size_t len) override {
122 TRACED();
123 return p_fft->write(data, len);
124 }
125
126 protected:
127 Print *p_out = nullptr;
129 AudioFFTBase *p_fft = nullptr;
134
135 virtual void effect(AudioFFTBase &fft) = 0;
136
137 static void effect_callback(AudioFFTBase &fft) {
138 TRACED();
139 FFTEffect *ref = (FFTEffect *)fft.config().ref;
140 // execute effect
141 ref->effect(fft);
142 // write ifft to output
143 ref->processOutput();
144 }
145
147 TRACED();
148 while (copier.copy());
149 }
150};
151
158class FFTRobotize : public FFTEffect {
159 public:
164 FFTRobotize(Print &out) : FFTEffect(out) {};
165 FFTRobotize(Print &out, AudioFFTBase &fft) : FFTEffect(out, fft) {};
166
167 protected:
170 void effect(AudioFFTBase &fft) override {
171 TRACED();
172 FFTBin bin;
173 for (int n = 0; n < fft.size(); n++) {
174 // update new bin value
175 bin.real = fft.magnitude(n);
176 bin.img = 0.0;
177
178 fft.setBin(n, bin);
179 }
180 }
181};
182
190class FFTWhisper : public FFTEffect {
191 public:
196 FFTWhisper(Print &out) : FFTEffect(out) {};
197 FFTWhisper(Print &out, AudioFFTBase &fft) : FFTEffect(out, fft) {};
198
199 protected:
201 void effect(AudioFFTBase &fft) override {
202 TRACED();
203 FFTBin bin;
204 for (int n = 0; n < fft.size(); n++) {
205 float amplitude = fft.magnitude(n);
206 float phase = rand() / (float)RAND_MAX * 2.f * PI;
207
208 // update new bin value
209 bin.real = cosf(phase) * amplitude;
210 bin.img = sinf(phase) * amplitude;
211 fft.setBin(n, bin);
212 }
213 }
214};
215
222class FFTNop : public FFTEffect {
223 public:
228 FFTNop(Print &out) : FFTEffect(out) {};
229 FFTNop(Print &out, AudioFFTBase &fft) : FFTEffect(out, fft) {};
230
231 protected:
233 void effect(AudioFFTBase &fft) override {}
234};
235
243 int shift = 1;
244};
245
252class FFTPitchShift : public FFTEffect {
253 public:
259 };
265 };
267 FFTPitchShift(Print &out, AudioFFTBase &fft) : FFTEffect(out, fft) {};
268
270 FFTPitchShiftConfig result;
271 result.shift = shift;
272 result.window_function = &buffered;
273 return result;
274 }
275
276 bool begin(FFTPitchShiftConfig psConfig) {
277 setShift(psConfig.shift);
278 // FFTEffect::begin(FFTEffectConfig) internally calls the virtual
279 // begin(), which dispatches to begin() below - calling it again here
280 // would re-initialize the fft and copier a second time
281 return FFTEffect::begin(psConfig);
282 }
283
284 bool begin() override {
285 bool rc = FFTEffect::begin();
286 // you can not shift more then you have bins
287 assert(abs(shift) < p_fft->size());
288 return rc;
289 }
290
292 void setShift(int bins) { shift = bins; }
293
294 protected:
295 int shift = 1;
296
298 void effect(AudioFFTBase &fft) override {
299 TRACED();
300 FFTBin bin;
301 int max = fft.size();
302
303 if (shift < 0) {
304 // copy bins: left shift
305 for (int n = -shift; n < max; n++) {
306 int to_bin = n + shift;
307 assert(to_bin >= 0);
308 assert(to_bin < max);
309 fft.getBin(n, bin);
310 fft.setBin(to_bin, bin);
311 }
312 // clear tail
313 bin.clear();
314 for (int n = max + shift; n < max; n++) {
315 fft.setBin(n, bin);
316 }
317 } else if (shift > 0) {
318 // copy bins: right shift
319 for (int n = max - shift - 1; n >= 0; n--) {
320 int to_bin = n + shift;
321 assert(to_bin >= 0);
322 assert(to_bin < max);
323 fft.getBin(n, bin);
324 fft.setBin(to_bin, bin);
325 }
326 // clear head
327 bin.clear();
328 for (int n = 0; n < shift; n++) {
329 fft.setBin(n, bin);
330 }
331 }
332 }
333};
334
342 int bands = 10;
343};
344
355class FFTEqualizer : public FFTEffect {
356 public:
361 FFTEqualizer(Print &out) : FFTEffect(out) {};
362 FFTEqualizer(Print &out, AudioFFTBase &fft) : FFTEffect(out, fft) {};
363
370
372 setBandCount(cfg.bands);
373 return FFTEffect::begin(cfg);
374 }
375
376 bool begin() override {
377 bool rc = FFTEffect::begin();
378 setupBands();
379 for (int b = 0; b < band_count; b++) {
380 LOGI("Band %d: Freq=%.2fHz, Gain=%.2fdB", b, getBandFrequency(b),
381 getBandDB(b));
382 }
383 return rc;
384 }
385
388 void setBandCount(int bands) {
389 band_count = bands > 0 ? bands : 1;
395 for (int b = 0; b < band_count; b++) {
396 gains_db[b] = 0.0f;
397 gains_linear[b] = 1.0f;
398 }
399 }
400
402 int getBandCount() { return band_count; }
403
406 bool setBandDB(int band, float gain_db) {
407 if (band < 0 || band >= band_count) return false;
408 gains_db[band] = gain_db;
409 gains_linear[band] = powf(10.0f, gain_db / 20.0f);
410 return true;
411 }
412
415 bool setBandGain(int band, float volume) {
416 float gain_db = volume < 0 ? volume * 90.0f : volume * 12.0f;
417 return setBandDB(band, gain_db);
418 }
419
421 bool setBandGains(float volume) {
422 bool ok = true;
423 for (int b = 0; b < band_count; b++) ok = setBandGain(b, volume) && ok;
424 return ok;
425 }
426
428 float getBandDB(int band) {
429 if (band < 0 || band >= band_count) return 0.0f;
430 return gains_db[band];
431 }
432
434 float getBandFrequency(int band) {
435 if (band < 0 || band >= band_count) return 0.0f;
436 return band_center_freq[band];
437 }
438
439 protected:
440 int band_count = 10;
446
449 void setupBands() {
450 float nyquist = audioInfo().sample_rate / 2.0f;
451 float f_min = log10f(20.0f);
452 float f_max = log10f(nyquist);
453 float step = (f_max - f_min) / band_count;
454 int prev_bin = 0;
455 for (int b = 0; b < band_count; b++) {
456 // last band always reaches the last bin, regardless of rounding
457 int edge_bin = (b == band_count - 1)
458 ? p_fft->size()
460 (int)powf(10.0f, f_min + step * (b + 1)));
461 band_bin_from[b] = prev_bin;
462 band_bin_to[b] = edge_bin;
463 band_center_freq[b] = powf(10.0f, f_min + step * (b + 0.5f));
464 prev_bin = edge_bin;
465 }
466 }
467
470 void effect(AudioFFTBase &fft) override {
471 TRACED();
472 FFTBin bin;
473 for (int b = 0; b < band_count; b++) {
474 float gain = gains_linear[b];
475 if (gain == 1.0f) continue; // 0dB: bin is already correct
476 for (int n = band_bin_from[b]; n < band_bin_to[b]; n++) {
477 fft.getBin(n, bin);
478 bin.real *= gain;
479 bin.img *= gain;
480 fft.setBin(n, bin);
481 }
482 }
483 }
484};
485
486} // namespace audio_tools
#define PI
Definition AudioEffectsSuite.h:27
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define assert(T)
Definition avr.h:10
Definition Arduino.h:56
Executes FFT using audio data privded by write() and/or an inverse FFT where the samples are made ava...
Definition AudioFFT.h:200
float magnitude(int bin)
Definition AudioFFT.h:579
AudioFFTConfig & config()
Provides the actual configuration.
Definition AudioFFT.h:648
size_t write(const uint8_t *data, size_t len) override
Provide the audio data as FFT input.
Definition AudioFFT.h:303
int frequencyToBin(int freq)
Determine the bin number from the frequency.
Definition AudioFFT.h:572
bool setBin(int idx, float real, float img)
sets the value of a bin
Definition AudioFFT.h:627
AudioFFTConfig defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration.
Definition AudioFFT.h:209
bool begin(AudioFFTConfig info)
starts the processing
Definition AudioFFT.h:216
bool getBin(int pos, FFTBin &bin)
gets the value of a bin
Definition AudioFFT.h:637
int size()
The number of bins used by the FFT which are relevant for the result.
Definition AudioFFT.h:358
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:149
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
AudioInfo cfg
Definition AudioOutput.h:88
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioOutput.h:49
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioOutput.h:62
AudioFFT using RealFFT.
Definition AudioRealFFT.h:125
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
Buffered window function, so that we do not need to re-calculate the values.
Definition FFTWindows.h:77
Abstract base class for effects that operate on audio in the frequency domain: incoming samples are t...
Definition FFTEffects.h:73
FFTEffect(Print &out, AudioFFTBase &fft)
Definition FFTEffects.h:81
BufferedWindow buffered
Definition FFTEffects.h:132
FFTEffectConfig defaultConfig()
Definition FFTEffects.h:87
void processOutput()
Definition FFTEffects.h:146
size_t write(const uint8_t *data, size_t len) override
Definition FFTEffects.h:121
AudioFFTBase * p_fft
Definition FFTEffects.h:129
StreamCopy copier
Definition FFTEffects.h:133
FFTEffect(Print &out)
Definition FFTEffects.h:75
Print * p_out
Definition FFTEffects.h:127
AudioRealFFT default_fft
Definition FFTEffects.h:128
static void effect_callback(AudioFFTBase &fft)
Definition FFTEffects.h:137
Hann hann
Definition FFTEffects.h:131
bool begin() override
Definition FFTEffects.h:105
virtual void effect(AudioFFTBase &fft)=0
bool begin(FFTEffectConfig info)
Definition FFTEffects.h:96
AudioFFTConfig fft_cfg
Definition FFTEffects.h:130
Graphic Equalizer implemented as an FFT effect: boosts or cuts logarithmically spaced frequency bands...
Definition FFTEffects.h:355
Vector< float > band_center_freq
Definition FFTEffects.h:443
int band_count
Definition FFTEffects.h:440
bool begin(FFTEqualizerConfig cfg)
Definition FFTEffects.h:371
bool setBandGains(float volume)
Sets the same gain for all bands.
Definition FFTEffects.h:421
Vector< int > band_bin_from
Definition FFTEffects.h:444
float getBandDB(int band)
Gets the currently defined gain for a band in dB.
Definition FFTEffects.h:428
Vector< float > gains_linear
Definition FFTEffects.h:442
Vector< float > gains_db
Definition FFTEffects.h:441
bool setBandGain(int band, float volume)
Definition FFTEffects.h:415
float getBandFrequency(int band)
Gets the center frequency of a band in Hz (only valid after begin())
Definition FFTEffects.h:434
FFTEqualizer(AudioOutput &out)
Definition FFTEffects.h:359
bool setBandDB(int band, float gain_db)
Definition FFTEffects.h:406
void setBandCount(int bands)
Definition FFTEffects.h:388
FFTEqualizer(AudioOutput &out, AudioFFTBase &fft)
Definition FFTEffects.h:360
Vector< int > band_bin_to
Definition FFTEffects.h:445
FFTEqualizerConfig defaultConfig()
Definition FFTEffects.h:364
void setupBands()
Definition FFTEffects.h:449
bool begin() override
Definition FFTEffects.h:376
FFTEqualizer(Print &out, AudioFFTBase &fft)
Definition FFTEffects.h:362
FFTEqualizer(AudioStream &out)
Definition FFTEffects.h:357
FFTEqualizer(Print &out)
Definition FFTEffects.h:361
void effect(AudioFFTBase &fft) override
Definition FFTEffects.h:470
int getBandCount()
Number of active bands.
Definition FFTEffects.h:402
FFTEqualizer(AudioStream &out, AudioFFTBase &fft)
Definition FFTEffects.h:358
Apply FFT and IFFT w/o any changes to the frequency domain.
Definition FFTEffects.h:222
FFTNop(AudioStream &out)
Definition FFTEffects.h:224
FFTNop(AudioOutput &out, AudioFFTBase &fft)
Definition FFTEffects.h:227
FFTNop(AudioOutput &out)
Definition FFTEffects.h:226
FFTNop(Print &out)
Definition FFTEffects.h:228
void effect(AudioFFTBase &fft) override
Do nothing.
Definition FFTEffects.h:233
FFTNop(Print &out, AudioFFTBase &fft)
Definition FFTEffects.h:229
FFTNop(AudioStream &out, AudioFFTBase &fft)
Definition FFTEffects.h:225
Apply Pitch Shift FFT Effect on frequency domain data: we just move the bins up or down.
Definition FFTEffects.h:252
void setShift(int bins)
defines how many bins should be shifted up (>0) or down (<0);
Definition FFTEffects.h:292
FFTPitchShift(AudioStream &out)
Definition FFTEffects.h:254
bool begin(FFTPitchShiftConfig psConfig)
Definition FFTEffects.h:276
FFTPitchShift(AudioOutput &out, AudioFFTBase &fft)
Definition FFTEffects.h:263
FFTPitchShift(AudioOutput &out)
Definition FFTEffects.h:260
FFTPitchShift(AudioStream &out, AudioFFTBase &fft)
Definition FFTEffects.h:257
FFTPitchShift(Print &out, AudioFFTBase &fft)
Definition FFTEffects.h:267
bool begin() override
Definition FFTEffects.h:284
FFTPitchShiftConfig defaultConfig()
Definition FFTEffects.h:269
FFTPitchShift(Print &out)
Definition FFTEffects.h:266
void effect(AudioFFTBase &fft) override
Pitch Shift.
Definition FFTEffects.h:298
int shift
Definition FFTEffects.h:295
Apply Robotize FFT Effect on frequency domain data. See https://learn.bela.io/tutorials/c-plus-plus-f...
Definition FFTEffects.h:158
FFTRobotize(Print &out, AudioFFTBase &fft)
Definition FFTEffects.h:165
FFTRobotize(AudioStream &out)
Definition FFTEffects.h:160
FFTRobotize(AudioStream &out, AudioFFTBase &fft)
Definition FFTEffects.h:161
FFTRobotize(Print &out)
Definition FFTEffects.h:164
FFTRobotize(AudioOutput &out, AudioFFTBase &fft)
Definition FFTEffects.h:163
FFTRobotize(AudioOutput &out)
Definition FFTEffects.h:162
void effect(AudioFFTBase &fft) override
Definition FFTEffects.h:170
Apply Whisper FFT Effect on frequency domain data: keep the magnitude of each bin but randomize its p...
Definition FFTEffects.h:190
FFTWhisper(AudioStream &out)
Definition FFTEffects.h:192
FFTWhisper(Print &out)
Definition FFTEffects.h:196
FFTWhisper(Print &out, AudioFFTBase &fft)
Definition FFTEffects.h:197
FFTWhisper(AudioStream &out, AudioFFTBase &fft)
Definition FFTEffects.h:193
FFTWhisper(AudioOutput &out)
Definition FFTEffects.h:194
FFTWhisper(AudioOutput &out, AudioFFTBase &fft)
Definition FFTEffects.h:195
void effect(AudioFFTBase &fft) override
Whisperize the output.
Definition FFTEffects.h:201
Hann FFT Window function.
Definition FFTWindows.h:149
void begin()
(Re)starts the processing
Definition StreamCopy.h:56
size_t copy()
Definition StreamCopy.h:100
void setLogName(const char *name)
Defines a name which will be printed in the log to identify the copier.
Definition StreamCopy.h:321
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
FFT Window Function.
Definition FFTWindows.h:28
virtual const char * name()=0
@ RXTX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
static Hann fft_effects_hann
Definition FFTEffects.h:9
static BufferedWindow fft_effects_buffered_window
Definition FFTEffects.h:10
Configuration for AudioFFT. If there are more then 1 channel the channel_used is defining which chann...
Definition AudioFFT.h:45
int stride
Definition AudioFFT.h:56
void * ref
caller
Definition AudioFFT.h:66
WindowFunction * window_function
Optional window function for both fft and ifft.
Definition AudioFFT.h:58
int length
Definition AudioFFT.h:55
void(* callback)(AudioFFTBase &fft)
Callback method which is called after we got a new result.
Definition AudioFFT.h:52
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:101
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
And individual FFT Bin.
Definition AudioFFT.h:70
float real
Definition AudioFFT.h:71
float img
Definition AudioFFT.h:72
void clear()
Definition AudioFFT.h:88
Common configuration for FFT effects.
Definition FFTEffects.h:17
int stride
Definition FFTEffects.h:19
WindowFunction * window_function
Definition FFTEffects.h:20
int length
Definition FFTEffects.h:18
Equalizer FFT Effect Configuration.
Definition FFTEffects.h:340
int bands
number of logarithmically spaced bands between 20Hz and Nyquist
Definition FFTEffects.h:342
Pitch Shift FFT Effect Configuration.
Definition FFTEffects.h:242
int shift
Definition FFTEffects.h:243