Skip to content

Commit ce9fae0

Browse files
committed
Replace dynamic buffers with std::array
1 parent a748af7 commit ce9fae0

1 file changed

Lines changed: 15 additions & 30 deletions

File tree

include/soundanalyzer.h

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "globals.h"
3737
#include <algorithm>
3838
#include <numeric>
39+
#include <array>
3940
#include <arduinoFFT.h>
4041
#include <driver/adc.h>
4142
#include <driver/i2s.h>
@@ -348,8 +349,8 @@ class SoundAnalyzer : public ISoundAnalyzer
348349
float _oldVU; // Old VU value for damping
349350
float _oldPeakVU; // Old peak VU value for damping
350351
float _oldMinVU; // Old min VU value for damping
351-
float * _vPeaks; // Normalized band energies 0..1
352-
float * _livePeaks; // Attack-limited display peaks per band
352+
std::array<float, NUM_BANDS> _vPeaks{}; // Normalized band energies 0..1
353+
std::array<float, NUM_BANDS> _livePeaks{}; // Attack-limited display peaks per band
353354
int _bandBinStart[NUM_BANDS];
354355
int _bandBinEnd[NUM_BANDS];
355356
float _energyMaxEnv = 0.01f; // adaptive envelope for autoscaling (start low for fast adaptation)
@@ -373,28 +374,25 @@ class SoundAnalyzer : public ISoundAnalyzer
373374

374375
private:
375376
static constexpr int kBandOffset = 2; // number of lowest source bands to skip in layout (skip bins 0,1,2)
376-
float *_vReal = nullptr;
377-
float *_vImaginary = nullptr;
377+
std::array<float, MAX_SAMPLES> _vReal{};
378+
std::array<float, MAX_SAMPLES> _vImaginary{};
378379
std::unique_ptr<int16_t[]> ptrSampleBuffer; // sample buffer storage
379380
PeakData _Peaks; // cached last normalized peaks (moved earlier for inline method visibility)
380381

381382
// Reset and clear the FFT buffers
382383

383384
void Reset()
384385
{
385-
if (!_vReal)
386-
return;
387-
std::fill_n(_vReal, MAX_SAMPLES, 0.0f);
388-
if (_vImaginary)
389-
std::fill_n(_vImaginary, MAX_SAMPLES, 0.0f);
390-
std::fill_n(_vPeaks, NUM_BANDS, 0.0f);
386+
_vReal.fill(0.0f);
387+
_vImaginary.fill(0.0f);
388+
_vPeaks.fill(0.0f);
391389
}
392390

393391
// Perform the FFT
394392

395393
void FFT()
396394
{
397-
ArduinoFFT<float> _FFT(_vReal, _vImaginary, MAX_SAMPLES, SAMPLING_FREQUENCY);
395+
ArduinoFFT<float> _FFT(_vReal.data(), _vImaginary.data(), MAX_SAMPLES, SAMPLING_FREQUENCY);
398396
_FFT.dcRemoval();
399397
_FFT.windowing(FFTWindow::Hann, FFTDirection::Forward);
400398
_FFT.compute(FFTDirection::Forward);
@@ -572,12 +570,8 @@ class SoundAnalyzer : public ISoundAnalyzer
572570
// Use reciprocal of AudioFPS for frame-rate independent attack limiting
573571
float dt = (_AudioFPS > 0) ? (1.0f / (float)_AudioFPS) : 0.016f;
574572
// Fallback to reasonable default if FPS is invalid
575-
if (dt <= 0.0f || dt > 0.1f) dt = 0.016f;
576-
// Allocate _livePeaks if not already done
577-
if (!_livePeaks) {
578-
_livePeaks = (float *)PreferPSRAMAlloc(NUM_BANDS * sizeof(_livePeaks[0]));
579-
for (int i = 0; i < NUM_BANDS; ++i) _livePeaks[i] = 0.0f;
580-
}
573+
if (dt <= 0.0f || dt > 0.1f)
574+
dt = 0.016f;
581575
_framesProcessed++;
582576
const float binWidth = (float)SAMPLING_FREQUENCY / (MAX_SAMPLES / 2.0f);
583577
for (int b = 0; b < NUM_BANDS; b++)
@@ -862,13 +856,7 @@ class SoundAnalyzer : public ISoundAnalyzer
862856
ptrSampleBuffer.reset((int16_t *)heap_caps_malloc(MAX_SAMPLES * sizeof(int16_t), MALLOC_CAP_8BIT));
863857
if (!ptrSampleBuffer)
864858
throw std::runtime_error("Failed to allocate sample buffer");
865-
_vReal = (float *)PreferPSRAMAlloc(MAX_SAMPLES * sizeof(_vReal[0]));
866-
_vImaginary = (float *)PreferPSRAMAlloc(MAX_SAMPLES * sizeof(_vImaginary[0]));
867-
_vPeaks = (float *)PreferPSRAMAlloc(NUM_BANDS * sizeof(_vPeaks[0]));
868-
_livePeaks = (float *)PreferPSRAMAlloc(NUM_BANDS * sizeof(_livePeaks[0]));
869-
if (!_vReal || !_vImaginary || !_vPeaks || !_livePeaks)
870-
throw std::runtime_error("Failed to allocate FFT buffers");
871-
for (int i = 0; i < NUM_BANDS; ++i) _livePeaks[i] = 0.0f;
859+
// No dynamic allocations needed for FFT/peak arrays
872860
_oldVU = _oldPeakVU = _oldMinVU = 0.0f;
873861
// No runtime parameter initialization needed - all compile-time now
874862
ComputeBandLayout();
@@ -885,10 +873,7 @@ class SoundAnalyzer : public ISoundAnalyzer
885873
i2s_stop(I2S_NUM_0);
886874
i2s_driver_uninstall(I2S_NUM_0);
887875
#endif
888-
free(_vReal);
889-
free(_vImaginary);
890-
free(_vPeaks);
891-
free(_livePeaks);
876+
// No heap frees required for std::array members
892877
}
893878

894879
// These functions allow access to the last-acquired sample buffer and its size so that
@@ -1071,8 +1056,8 @@ class SoundAnalyzer : public ISoundAnalyzer
10711056
{
10721057
_msLastRemoteAudio = millis();
10731058
_Peaks = peaks;
1074-
std::copy(&_Peaks._Level[0], &_Peaks._Level[0] + NUM_BANDS, _vPeaks);
1075-
float sum = std::accumulate(_vPeaks, _vPeaks + NUM_BANDS, 0.0f);
1059+
std::copy(&_Peaks._Level[0], &_Peaks._Level[0] + NUM_BANDS, _vPeaks.data());
1060+
float sum = std::accumulate(_vPeaks.begin(), _vPeaks.end(), 0.0f);
10761061
UpdateVU(sum / NUM_BANDS);
10771062
}
10781063

0 commit comments

Comments
 (0)