40 fl::u32 currentTimeMs = sample.
timestamp();
62 const auto& pcmData = sample.
pcm();
63 if (pcmData.empty())
return;
74 for (
int i = 0; i < 16; ++i) {
75 if (i <
static_cast<int>(
mFFTBins.bins_raw.size())) {
83 for (
int i = 0; i < 16; ++i) {
88 float maxMagnitude = 0.0f;
90 for (
int i = 0; i < 16; ++i) {
99 const float binCenterFrequencies[16] = {
118 mCurrentData.dominantFrequency = binCenterFrequencies[maxBin];
124 const auto& pcmData = sample.
pcm();
125 if (pcmData.empty()) {
136 float maxSample = 0.0f;
137 for (fl::i16 pcmSample : pcmData) {
138 float absSample = (pcmSample < 0) ? -pcmSample : pcmSample;
139 maxSample = (maxSample > absSample) ? maxSample : absSample;
152 float agcAttackRate =
mConfig.attack / 255.0f * 0.2f + 0.01f;
153 float agcDecayRate =
mConfig.decay / 255.0f * 0.05f + 0.001f;
166 float targetLevel = 16384.0f;
167 float newMultiplier = targetLevel /
mMaxSample;
196 currentVolume > 5.0f) {
204 float beatAttackRate =
mConfig.attack / 255.0f * 0.5f + 0.1f;
205 float beatDecayRate =
mConfig.decay / 255.0f * 0.3f + 0.05f;
218 float gainMultiplier =
static_cast<float>(
mConfig.gain) / 128.0f;
224 for (
int i = 0; i < 16; ++i) {
234 for (
int i = 0; i < 16; ++i) {
242 for (
int i = 0; i < 16; ++i) {
248 value = logf(value) * 20.0f;
260 value = sqrtf(value) * 8.0f;
280 float attackFactor = 1.0f - (
mConfig.attack / 255.0f * 0.9f);
281 float decayFactor = 1.0f - (
mConfig.decay / 255.0f * 0.95f);
313 for (
int i = 0; i < 16; ++i) {
365 return static_cast<fl::u8>(vol);
371 return CRGB(index, index, index);
375 if (binIndex >= 16)
return 0;
377 float value = (
mCurrentData.frequencyBins[binIndex] < 0.0f) ? 0.0f :
379 return static_cast<fl::u8>(value);
384 if (fromBin < 0 || toBin >=
static_cast<int>(
mFFTBins.size()) || fromBin > toBin) {
389 for (
int i = fromBin; i <= toBin; ++i) {
390 if (i <
static_cast<int>(
mFFTBins.bins_raw.size())) {
395 return sum /
static_cast<float>(toBin - fromBin + 1);
399 if (samples.
empty())
return 0.0f;
401 float sumSquares = 0.0f;
402 for (
const auto& sample : samples) {
403 float f =
static_cast<float>(sample);
407 return sqrtf(sumSquares / samples.
size());
float rms(Slice< const int16_t > data)
CRGB volumeToColor(const CRGBPalette16 &palette) const
const AudioData & getData() const
void update(fl::u32 currentTimeMs)
void processFFT(const AudioSample &sample)
fl::u8 volumeToScale255() const
void detectBeat(fl::u32 currentTimeMs)
void mapFFTBinsToFrequencyChannels()
float computeRMS(const fl::vector< fl::i16 > &samples)
static constexpr float PINK_NOISE_COMPENSATION[16]
void updateVolumeAndPeak(const AudioSample &sample)
void setConfig(const AudioConfig &config)
static constexpr fl::u32 BEAT_COOLDOWN
void begin(const AudioConfig &config=AudioConfig{})
float mapFrequencyBin(int fromBin, int toBin)
const AudioData & getSmoothedData() const
fl::u8 frequencyToScale255(fl::u8 binIndex) const
void processSample(const AudioSample &sample)
const VectorPCM & pcm() const
void fft(FFTBins *out) const
fl::u32 timestamp() const
HeapVector< T, Allocator > vector
Representation of an RGB pixel (Red, Green, Blue)