arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
FFTEffects.h
1#pragma once
2
3#include "AudioTools/AudioLibs/AudioRealFFT.h" // using RealFFT
4#include "AudioTools/CoreAudio/AudioOutput.h"
5#include "AudioTools/CoreAudio/StreamCopy.h"
6
7namespace audio_tools {
8
9static Hann fft_effects_hann;
10static BufferedWindow fft_effects_buffered_window{&fft_effects_hann};
11
17struct FFTEffectConfig : public AudioInfo {
18 int length = 1024;
19 int stride = 512;
20 WindowFunction *window_function = &fft_effects_buffered_window;
21};
22
23/***
24 * @brief Abstract class for common Logic for FFT based effects. The effect is
25 * applied after the fft to the frequency domain before executing the ifft.
26 * Please note that this is quite processing time intensitive: so you might keep
27 * the sample rate quite low if the processor is not fast enough!
28 * @ingroup transform
29 * @author phil schatzmann
30 */
31
32class FFTEffect : public AudioOutput {
33 public:
34 FFTEffect(Print &out) {
35 p_out = &out;
36 fft_cfg.ref = this;
37 }
38
39 FFTEffectConfig defaultConfig() {
41 return c;
42 }
43
44 bool begin(FFTEffectConfig info) {
45 copier.setLogName("ifft");
46 setAudioInfo(info);
47 fft_cfg.length = info.length;
48 fft_cfg.stride = info.stride > 0 ? info.stride : info.length;
49 fft_cfg.window_function = info.window_function;
50 return begin();
51 }
52
53 bool begin() override {
54 TRACED();
55 // copy result to output
56 copier.begin(*p_out, fft);
57
58 // setup fft
59 fft_cfg.copyFrom(audioInfo());
60 fft_cfg.callback = effect_callback;
61 LOGI("length: %d", fft_cfg.length);
62 LOGI("stride: %d", fft_cfg.stride);
63 LOGI("window_function: %s", (fft_cfg.window_function != nullptr)
64 ? fft_cfg.window_function->name()
65 : "-");
66 return fft.begin(fft_cfg);
67 }
68
69 size_t write(const uint8_t *data, size_t len) override {
70 TRACED();
71 return fft.write(data, len);
72 }
73
74 protected:
75 Print *p_out = nullptr;
76 AudioRealFFT fft;
77 AudioFFTConfig fft_cfg{fft.defaultConfig(RXTX_MODE)};
78 Hann hann;
79 BufferedWindow buffered{&hann};
80 StreamCopy copier;
81
82 virtual void effect(AudioFFTBase &fft) = 0;
83
84 static void effect_callback(AudioFFTBase &fft) {
85 TRACED();
86 FFTEffect *ref = (FFTEffect *)fft.config().ref;
87 // execute effect
88 ref->effect(fft);
89 // write ifft to output
90 ref->processOutput();
91 }
92
93 void processOutput() {
94 TRACED();
95 while (copier.copy());
96 }
97};
98
105class FFTRobotize : public FFTEffect {
106 friend FFTEffect;
107
108 public:
111 FFTRobotize(Print &out) : FFTEffect(out) {};
112
113 protected:
115 void effect(AudioFFTBase &fft) {
116 TRACED();
117 AudioFFTResult best = fft.result();
118
119 FFTBin bin;
120 for (int n = 0; n < fft.size(); n++) {
121 float amplitude = fft.magnitude(n);
122
123 // update new bin value
124 bin.real = amplitude / best.magnitude;
125 bin.img = 0.0;
126 Serial.println(bin.real);
127
128 fft.setBin(n, bin);
129 }
130 }
131};
132
139class FFTWhisper : public FFTEffect {
140 friend FFTEffect;
141
142 public:
145 FFTWhisper(Print &out) : FFTEffect(out) {};
146
147 protected:
149 void effect(AudioFFTBase &fft) {
150 TRACED();
151 FFTBin bin;
152 for (int n = 0; n < fft.size(); n++) {
153 float amplitude = fft.magnitude(n);
154 float phase = rand() / (float)RAND_MAX * 2.f * PI;
155
156 // update new bin value
157 bin.real = cosf(phase) * amplitude;
158 bin.img = sinf(phase) * amplitude;
159 fft.setBin(n, bin);
160 }
161 }
162};
163
170class FFTNop : public FFTEffect {
171 friend FFTEffect;
172
173 public:
174 FFTNop(AudioStream &out) : FFTEffect(out) { addNotifyAudioChange(out); };
175 FFTNop(AudioOutput &out) : FFTEffect(out) { addNotifyAudioChange(out); };
176 FFTNop(Print &out) : FFTEffect(out) {};
177
178 protected:
180 void effect(AudioFFTBase &fft) {}
181};
182
190 int shift = 1;
191};
192
199class FFTPitchShift : public FFTEffect {
200 friend FFTEffect;
201
202 public:
203 FFTPitchShift(AudioStream &out) : FFTEffect(out) {
205 };
206 FFTPitchShift(AudioOutput &out) : FFTEffect(out) {
208 };
209 FFTPitchShift(Print &out) : FFTEffect(out) {};
210
211 FFTPitchShiftConfig defaultConfig() {
212 FFTPitchShiftConfig result;
213 result.shift = shift;
214 return result;
215 }
216
217 bool begin(FFTPitchShiftConfig psConfig) {
218 setShift(psConfig.shift);
219 FFTEffect::begin(psConfig);
220 return begin();
221 }
222
223 bool begin() override {
224 bool rc = FFTEffect::begin();
225 // you can not shift more then you have bins
226 assert(abs(shift) < fft.size());
227 return rc;
228 }
229
231 void setShift(int bins) { shift = bins; }
232
233 protected:
234 int shift = 1;
235
237 void effect(AudioFFTBase &fft) {
238 TRACED();
239 FFTBin bin;
240 int max = fft.size();
241
242 if (shift < 0) {
243 // copy bins: left shift
244 for (int n = -shift; n < max; n++) {
245 int to_bin = n + shift;
246 assert(to_bin >= 0);
247 assert(to_bin < max);
248 fft.getBin(n, bin);
249 fft.setBin(to_bin, bin);
250 }
251 // clear tail
252 bin.clear();
253 for (int n = max + shift; n < max; n++) {
254 fft.setBin(n, bin);
255 }
256 } else if (shift > 0) {
257 // copy bins: right shift
258 for (int n = max - shift - 1; n >= 0; n--) {
259 int to_bin = n + shift;
260 assert(to_bin >= 0);
261 assert(to_bin < max);
262 fft.getBin(n, bin);
263 fft.setBin(to_bin, bin);
264 }
265 // clear head
266 bin.clear();
267 for (int n = 0; n < shift; n++) {
268 fft.setBin(n, bin);
269 }
270 }
271 }
272};
273
274} // namespace audio_tools
Executes FFT using audio data privded by write() and/or an inverse FFT where the samples are made ava...
Definition AudioFFT.h:191
float magnitude(int bin)
Definition AudioFFT.h:411
AudioFFTConfig & config()
Provides the actual configuration.
Definition AudioFFT.h:482
size_t write(const uint8_t *data, size_t len) override
Provide the audio data as FFT input.
Definition AudioFFT.h:290
bool setBin(int idx, float real, float img)
sets the value of a bin
Definition AudioFFT.h:459
AudioFFTConfig defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration.
Definition AudioFFT.h:200
bool begin(AudioFFTConfig info)
starts the processing
Definition AudioFFT.h:207
bool getBin(int pos, FFTBin &bin)
gets the value of a bin
Definition AudioFFT.h:471
AudioFFTResult result()
Determines the result values in the max magnitude bin.
Definition AudioFFT.h:357
int size()
The number of bins used by the FFT which are relevant for the result.
Definition AudioFFT.h:344
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:156
Abstract Audio Ouptut class.
Definition AudioOutput.h:22
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioOutput.h:46
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioOutput.h:59
AudioFFT using RealFFT.
Definition AudioRealFFT.h:95
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:115
Buffered window function, so that we do not need to re-calculate the values.
Definition FFTWindows.h:72
Definition FFTEffects.h:32
Apply FFT and IFFT w/o any changes to the frequency domain.
Definition FFTEffects.h:170
void effect(AudioFFTBase &fft)
Do nothing.
Definition FFTEffects.h:180
Apply Pitch Shift FFT Effect on frequency domain data: we just move the bins up or down.
Definition FFTEffects.h:199
void setShift(int bins)
defines how many bins should be shifted up (>0) or down (<0);
Definition FFTEffects.h:231
void effect(AudioFFTBase &fft)
Pitch Shift.
Definition FFTEffects.h:237
Apply Robotize FFT Effect on frequency domain data. See https://learn.bela.io/tutorials/c-plus-plus-f...
Definition FFTEffects.h:105
void effect(AudioFFTBase &fft)
Robotise the output.
Definition FFTEffects.h:115
Apply Robotize FFT Effect on frequency domain data. See https://learn.bela.io/tutorials/c-plus-plus-f...
Definition FFTEffects.h:139
void effect(AudioFFTBase &fft)
Robotise the output.
Definition FFTEffects.h:149
Hann FFT Window function.
Definition FFTWindows.h:141
Definition NoArduino.h:62
void begin()
(Re)starts the processing
Definition StreamCopy.h:50
size_t copy()
copies the data from the source to the destination and returns the processed number of bytes
Definition StreamCopy.h:95
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
FFT Window Function.
Definition FFTWindows.h:24
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioConfig.h:885
Configuration for AudioFFT. If there are more then 1 channel the channel_used is defining which chann...
Definition AudioFFT.h:40
void * ref
caller
Definition AudioFFT.h:61
WindowFunction * window_function
Optional window function for both fft and ifft.
Definition AudioFFT.h:53
void(* callback)(AudioFFTBase &fft)
Callback method which is called after we got a new result.
Definition AudioFFT.h:47
Result of the FFT.
Definition AudioFFT.h:23
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:52
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:107
And individual FFT Bin.
Definition AudioFFT.h:65
Common configuration for FFT effects.
Definition FFTEffects.h:17
Pitch Shift FFT Effect Configuration.
Definition FFTEffects.h:189