3 #include "AudioTools/AudioOutput.h"
16 static MusicalNotes AudioFFTNotes;
28 return round(frequency);
30 const char* frequencyAsNote() {
31 return AudioFFTNotes.
note(frequency);
33 const char* frequencyAsNote(
float &diff) {
34 return AudioFFTNotes.
note(frequency, diff);
67 virtual bool begin(
int len) =0;
68 virtual void end() =0;
69 virtual void setValue(
int pos,
int value) =0;
70 virtual void fft() = 0;
71 virtual float magnitude(
int idx) = 0;
72 virtual float magnitudeFast(
int idx) = 0;
73 virtual bool isValid() = 0;
103 if (!isPowerOfTwo(cfg.length)){
104 LOGE(
"Len must be of the power of 2: %d", cfg.length);
107 if (cfg.stride>0 && cfg.stride<cfg.length){
109 stride_buffer.resize((cfg.length - cfg.stride)*bytesPerSample());
111 if (!p_driver->begin(cfg.length)){
112 LOGE(
"Not enough memory");
119 return p_driver->isValid();
131 return p_driver!=
nullptr && p_driver->isValid();
145 if (p_magnitudes!=
nullptr)
delete []p_magnitudes;
149 size_t write(
const uint8_t*data,
size_t len)
override {
151 if (p_driver->isValid()){
155 processSamples<int16_t>(data, len/2);
158 processSamples<int24_t>(data, len/3);
161 processSamples<int32_t>(data, len/4);
192 return timestamp_begin;
198 LOGE(
"Invalid bin %d", bin);
201 return static_cast<float>(bin) * cfg.
sample_rate / cfg.length;
207 ret_value.magnitude = 0;
210 for (
int j=0;j<
size();j++){
212 if (m>ret_value.magnitude){
213 ret_value.magnitude = m;
217 ret_value.frequency =
frequency(ret_value.bin);
226 for (
int j=0;j<N;j++){
227 result[j].magnitude = -1000000;
231 for (
int j=0;j<
size();j++){
235 insertSorted<N>(
result, act);
247 LOGE(
"Invalid bin %d", bin);
250 return p_driver->magnitude(bin);
253 float magnitudeFast(
int bin){
255 LOGE(
"Invalid bin %d", bin);
258 return p_driver->magnitudeFast(bin);
262 if (p_magnitudes==
nullptr){
263 p_magnitudes =
new float[
size()];
265 for (
int j=0;j<
size();j++){
273 if (p_magnitudes==
nullptr){
274 p_magnitudes =
new float[
size()];
276 for (
int j=0;j<
size();j++){
277 p_magnitudes[j]= magnitudeFast(j);
291 unsigned long timestamp_begin=0l;
292 unsigned long timestamp=0l;
294 float *p_magnitudes =
nullptr;
300 void processSamples(
const void *data,
size_t samples) {
301 T *dataT = (T*) data;
303 float sample_windowed;
304 for (
int j=0; j<samples; j+=cfg.
channels){
306 p_driver->setValue(current_pos, windowedSample(sample));
307 writeStrideBuffer((uint8_t*)&sample,
sizeof(T));
308 if (++current_pos>=cfg.length){
313 if (stride_buffer.
size()>0){
317 stride_buffer.
readArray((uint8_t*)&sample,
sizeof(T));
318 p_driver->setValue(current_pos, windowedSample(sample));
328 T windowedSample(T sample){
338 timestamp_begin =
millis();
347 int bytesPerSample() {
355 for (
int j=0;j<N;j++){
357 if (tmp.magnitude>
result[j].magnitude){
359 for (
int i=N-2;i>=j;i--){
370 void writeStrideBuffer(uint8_t* buffer,
size_t len){
371 if (stride_buffer.
size()>0){
375 int diff = len-available;
376 for(
int j=0;j<diff;j++){
377 stride_buffer.
read();
384 bool isPowerOfTwo(uint16_t x) {
385 return (x & (x - 1)) == 0;
Different Window functions that can be used by FFT.