#include "esp_dsp.h" ...... #include ".//graph//fft_c01.h" ...... uint16_t sample_rate = 24000; uint16_t channels = 2; uint16_t bits_per_sample = 16; // or try with 24 or 32 AudioInfo info(sample_rate, channels, bits_per_sample); I2SStream i2s; MultiOutput multiOutput; VolumeMeter volumeMeter; StreamCopy copier; FilteredStream inFiltered; ....... float* dsp_complex_buffer = nullptr; uint16_t sample_counter = 0; volatile bool fftDataReady = false; float globalFullAmplitudes[fft_size] = {0}; ...... //Funkcja wywołana bezpośrednio przez MultiOutput, dając kontrolę nad I oraz Q size_t writeDataCallback(const uint8_t *data, size_t len) { if (fftDataReady) return len; // Blokada, jeśli pętla główna nie obrobiła danych int16_t *samples = (int16_t*)data; size_t total_samples = len / sizeof(int16_t); // Próbki w pamięci płyną naprzemiennie z MultiOutput: I0, Q0, I1, Q1, I2, Q2... for (size_t i = 0; i < total_samples; i += 2) { if (sample_counter < fft_size) { // Przepisanie wprost wartości I oraz Q z konwersją na typ float dsp_complex_buffer[2 * sample_counter] = (float)samples[i]; // Real (I) dsp_complex_buffer[2 * sample_counter + 1] = (float)samples[i + 1]; // Imag (Q) sample_counter++; } if (sample_counter >= fft_size) { // Bufor jest pełny (256 par I/Q) -> Wykonujemy sprzętowe Complex FFT dsps_fft2r_fc32(dsp_complex_buffer, fft_size); dsps_bit_rev_fc32(dsp_complex_buffer, fft_size); // Obliczanie amplitud dla wszystkich binów (dodatnich i ujemnych) for (int k = 0; k < fft_size; k++) { float real_part = dsp_complex_buffer[2 * k]; float imag_part = dsp_complex_buffer[2 * k + 1]; globalFullAmplitudes[k] = sqrtf(real_part * real_part + imag_part * imag_part); } fftDataReady = true; sample_counter = 0; } } return len; } // CallbackStream to uniwersalna klasa strumienia w bibliotece Arduino Audio Tools CallbackStream iqReceiver; ...... void setup(void) { ...... //Complex FFT commands // Inicjalizacja struktur sprzętowych ESP-DSP dla Complex FFT dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE); // Alokacja pamięci dla bufora zespolonego (rozmiar: fft_size * 2 wartości float) dsp_complex_buffer = (float*)heap_caps_malloc(fft_size * 2 * sizeof(float), MALLOC_CAP_DMA); // Przypisanie funkcji callback do strumienia odbiorczego iqReceiver.setWriteCallback(writeDataCallback); // ...... volumeMeter.begin(info); volumeMeter.setStream(i2s); ...... //filters settings inFiltered.begin(info); inFiltered.setFilter(0, new FilterChain({ new BiQuadDF2(b_lpf24_36, a_lpf24_36), new FIR(hilbert_24_81) })); inFiltered.setFilter(1, new FilterChain({ new BiQuadDF2(b_lpf24_36, a_lpf24_36), new FIR(coeffs_delay_81) })); inFiltered.setOutput(volumeMeter); ...... //MultiOutpud settings and start multiOutput.add(iqReceiver); multiOutput.add(inFiltered); multiOutput.begin(info); copier.begin(multiOutput, i2s); ...... }