3 #include "AudioTools/CoreAudio/AudioOutput.h"
4 #include "AudioTools/CoreAudio/MusicalNotes.h"
17 static MusicalNotes AudioFFTNotes;
29 return round(frequency);
31 const char* frequencyAsNote() {
32 return AudioFFTNotes.
note(frequency);
34 const char* frequencyAsNote(
float &diff) {
35 return AudioFFTNotes.
note(frequency, diff);
72 void multiply(
float f){
94 virtual bool begin(
int len) =0;
95 virtual void end() =0;
97 virtual void setValue(
int pos,
float value) =0;
99 virtual void fft() = 0;
104 virtual bool isValid() = 0;
108 virtual void rfft() {LOGE(
"Not implemented"); }
112 virtual bool setBin(
int idx,
float real,
float img) {
return false;}
151 if (!isPowerOfTwo(cfg.length)){
152 LOGE(
"Len must be of the power of 2: %d", cfg.length);
155 if (cfg.stride>0 && cfg.stride<cfg.length){
157 stride_buffer.resize((cfg.length - cfg.stride)*bytesPerSample());
159 if (!p_driver->begin(cfg.length)){
160 LOGE(
"Not enough memory");
168 return p_driver->isValid();
180 return p_driver!=
nullptr && p_driver->isValid();
194 if (p_magnitudes!=
nullptr)
delete []p_magnitudes;
198 size_t write(
const uint8_t*data,
size_t len)
override {
200 if (p_driver->isValid()){
204 processSamples<int16_t>(data, len/2);
207 processSamples<int24_t>(data, len/3);
210 processSamples<int32_t>(data, len/4);
241 return timestamp_begin;
247 LOGE(
"Invalid bin %d", bin);
250 return static_cast<float>(bin) * cfg.
sample_rate / cfg.length;
256 ret_value.magnitude = 0;
259 for (
int j=0;j<
size();j++){
261 if (m>ret_value.magnitude){
262 ret_value.magnitude = m;
266 ret_value.frequency =
frequency(ret_value.bin);
275 for (
int j=0;j<N;j++){
276 result[j].magnitude = -1000000;
280 for (
int j=0;j<
size();j++){
284 insertSorted<N>(
result, act);
296 LOGE(
"Invalid bin %d", bin);
302 float magnitudeFast(
int bin){
304 LOGE(
"Invalid bin %d", bin);
311 if (p_magnitudes==
nullptr){
312 p_magnitudes =
new float[
size()];
314 for (
int j=0;j<
size();j++){
322 if (p_magnitudes==
nullptr){
323 p_magnitudes =
new float[
size()];
325 for (
int j=0;j<
size();j++){
326 p_magnitudes[j]= magnitudeFast(j);
332 bool setBin(
int idx,
float real,
float img) {
return p_driver->
setBin(idx, real, img);}
358 unsigned long timestamp_begin=0l;
359 unsigned long timestamp=0l;
361 float *p_magnitudes =
nullptr;
363 Print *p_out =
nullptr;
369 void processSamples(
const void *data,
size_t samples) {
370 T *dataT = (T*) data;
372 float sample_windowed;
373 for (
int j=0; j<samples; j+=cfg.
channels){
375 p_driver->
setValue(current_pos, windowedSample(sample));
376 writeStrideBuffer((uint8_t*)&sample,
sizeof(T));
377 if (++current_pos>=cfg.length){
385 if (stride_buffer.
size()>0){
389 stride_buffer.
readArray((uint8_t*)&sample,
sizeof(T));
390 p_driver->
setValue(current_pos, windowedSample(sample));
400 T windowedSample(T sample){
410 timestamp_begin =
millis();
423 for (
int j=0;j<cfg.length;j++){
424 float value = p_driver->
getValue(j);
425 if (rfft_max < value ) rfft_max = value;
430 for (
int ch=0;ch<cfg.
channels; ch++)
431 p_out->write((uint8_t*)&out16,
sizeof(out16));
435 for (
int ch=0;ch<cfg.
channels; ch++)
436 p_out->write((uint8_t*)&out24,
sizeof(out24));
440 for (
int ch=0;ch<cfg.
channels; ch++)
441 p_out->write((uint8_t*)&out32,
sizeof(out32));
444 LOGE(
"Unsupported bits")
449 int bytesPerSample() {
457 for (
int j=0;j<N;j++){
459 if (tmp.magnitude>
result[j].magnitude){
461 for (
int i=N-2;i>=j;i--){
472 void writeStrideBuffer(uint8_t* buffer,
size_t len){
473 if (stride_buffer.
size()>0){
477 int diff = len-available;
478 for(
int j=0;j<diff;j++){
479 stride_buffer.
read();
486 bool isPowerOfTwo(uint16_t x) {
487 return (x & (x - 1)) == 0;
Different Window functions that can be used by FFT.