MCPcopy Create free account
hub / github.com/FastLED/FastLED / update

Method update

src/fl/audio/detector/vocal.cpp.hpp:26–86  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

24Vocal::~Vocal() FL_NOEXCEPT = default;
25
26void Vocal::update(shared_ptr<Context> context) {
27 mSampleRate = context->getSampleRate();
28 // Dual FFT: high-resolution formant analysis + broad spectral features.
29 // Formant FFT: 64 CQ bins in 200-3500 Hz — concentrates resolution on
30 // F1/F2/F3 formants (94% bin utilization vs 73% with full-range).
31 // Broad FFT: 16 LOG_REBIN bins in 174.6-4698.3 Hz — full spectral
32 // coverage for flatness, density, flux, and vocal presence ratio.
33 mRetainedFormantFFT = context->getFFT(64, 200.0f, 3500.0f);
34 mRetainedBroadFFT = context->getFFT(16, 174.6f, 4698.3f);
35 const fft::Bins& formantFft = *mRetainedFormantFFT;
36 const fft::Bins& broadFft = *mRetainedBroadFFT;
37 mFormantNumBins = static_cast<int>(formantFft.raw().size());
38 mBroadNumBins = static_cast<int>(broadFft.raw().size());
39
40 // Formant ratio from high-res narrow FFT
41 computeFormantRatio(formantFft);
42 // Broad spectral features (flatness, density, flux) from wide FFT
43 computeBroadSpectralFeatures(broadFft);
44
45 // Vocal presence ratio from broad FFT linear bins (needs 200-4000 Hz coverage)
46 mVocalPresenceRatio = calculateVocalPresenceRatio(broadFft);
47 mSpectralVariance = mSpectralVarianceFilter.update(broadFft.raw());
48
49 // Calculate time-domain features from raw PCM
50 span<const i16> pcm = context->getPCM();
51 const float dt = computeAudioDt(pcm.size(), context->getSampleRate());
52 // Fused pass: envelope jitter + zero-crossing CV in one PCM traversal
53 computePCMTimeDomainFeatures(pcm);
54 mEnvelopeJitter = mEnvelopeJitterSmoother.update(mEnvelopeJitter, dt);
55 mAutocorrelationIrregularity = mAcfIrregularitySmoother.update(
56 calculateAutocorrelationIrregularity(pcm), dt);
57 mZeroCrossingCV = mZcCVSmoother.update(mZeroCrossingCV, dt);
58
59 // Calculate raw confidence and apply time-aware smoothing
60 float rawConfidence = calculateRawConfidence(
61 mFormantRatio, mSpectralFlatness, mHarmonicDensity,
62 mVocalPresenceRatio, mSpectralFlux, mSpectralVariance);
63 float smoothedConfidence = mConfidenceSmoother.update(rawConfidence, dt);
64
65 // Hysteresis: use separate on/off thresholds to prevent chattering
66 bool wantActive;
67 if (mVocalActive) {
68 wantActive = (smoothedConfidence >= mOffThreshold);
69 } else {
70 wantActive = (smoothedConfidence >= mOnThreshold);
71 }
72
73 // Debounce: require state to persist for MIN_FRAMES_TO_TRANSITION frames
74 if (wantActive != mVocalActive) {
75 mFramesInState++;
76 if (mFramesInState >= MIN_FRAMES_TO_TRANSITION) {
77 mVocalActive = wantActive;
78 mFramesInState = 0;
79 }
80 } else {
81 mFramesInState = 0;
82 }
83

Callers

nothing calls this directly

Calls 6

computeAudioDtFunction · 0.85
getFFTMethod · 0.80
getPCMMethod · 0.80
getSampleRateMethod · 0.45
sizeMethod · 0.45
rawMethod · 0.45

Tested by

no test coverage detected