FastLED 3.9.15
Loading...
Searching...
No Matches
audio_processor.cpp.hpp
Go to the documentation of this file.
2#include "fl/stl/weak_ptr.h"
3#include "fl/audio/input.h"
24#include "fl/stl/noexcept.h"
25
26namespace fl {
27namespace audio {
28
32
36
38
40 // Signal conditioning pipeline: raw sample → conditioned sample
41 Sample conditioned = sample;
42
43 // Stage 1: Signal conditioning (DC removal, spike filtering, noise gate)
44 if (mSignalConditioningEnabled && conditioned.isValid()) {
45 conditioned = mSignalConditioner.processSample(conditioned);
46 if (!conditioned.isValid()) {
47 return; // Signal was entirely filtered out
48 }
49 }
50
51 // Stage 2: Digital gain (simple multiplier)
52 if (mGain != 1.0f && conditioned.isValid()) {
53 conditioned.applyGain(mGain);
54 }
55
56 // Stage 3: Noise floor tracking (passive — updates estimate but doesn't modify signal)
57 if (mNoiseFloorTrackingEnabled && conditioned.isValid()) {
58 mNoiseFloorTracker.update(conditioned.rms());
59 }
60
61 mContext->setSample(conditioned);
62
63 // Stage 4: Silence flag — detectors use this to gate outputs when audio stops.
64 // Only populated when NFT is enabled; otherwise silence is unknowable and
65 // stays at its default (false) after setSample() above.
66 //
67 // Uses an absolute RMS threshold rather than NFT.isAboveFloor(): the
68 // adaptive floor's first-sample init matches the current level, so
69 // isAboveFloor() stays false for any steady signal. Absolute RMS is the
70 // right silence primitive — a loud constant tone has large RMS.
71 if (mNoiseFloorTrackingEnabled && conditioned.isValid()) {
72 constexpr float kSilenceRmsThreshold = 10.0f;
73 mContext->setSilent(conditioned.rms() < kSilenceRmsThreshold);
74 }
75
76 // Phase 1: Compute state for all active detector
77 for (auto& d : mActiveDetectors) {
78 d->update(mContext);
79 }
80
81 // Phase 2: Fire callbacks for all active detector
82 for (auto& d : mActiveDetectors) {
83 d->fireCallbacks();
84 }
85}
86
88 // Use externally-provided context (FFT already cached, signal already conditioned).
89 // This avoids recomputing FFT when Reactive has already done it.
90 for (auto& d : mActiveDetectors) {
91 d->update(externalContext);
92 }
93 for (auto& d : mActiveDetectors) {
94 d->fireCallbacks();
95 }
96}
97
98void Processor::onBeat(function<void()> callback) {
100 detector->onBeat.add(callback);
101}
102
103void Processor::onBeatPhase(function<void(float)> callback) {
104 auto detector = getBeatDetector();
105 detector->onBeatPhase.add(callback);
106}
107
108void Processor::onOnset(function<void(float)> callback) {
109 auto detector = getBeatDetector();
110 detector->onOnset.add(callback);
111}
112
113void Processor::onTempoChange(function<void(float, float)> callback) {
114 auto detector = getBeatDetector();
115 detector->onTempoChange.add(callback);
116}
117
118void Processor::onTempo(function<void(float)> callback) {
119 auto detector = getTempoAnalyzer();
120 detector->onTempo.add(callback);
121}
122
123void Processor::onTempoWithConfidence(function<void(float, float)> callback) {
124 auto detector = getTempoAnalyzer();
125 detector->onTempoWithConfidence.add(callback);
126}
127
128void Processor::onTempoStable(function<void()> callback) {
129 auto detector = getTempoAnalyzer();
130 detector->onTempoStable.add(callback);
131}
132
133void Processor::onTempoUnstable(function<void()> callback) {
134 auto detector = getTempoAnalyzer();
135 detector->onTempoUnstable.add(callback);
136}
137
138void Processor::onBass(function<void(float)> callback) {
139 auto detector = getFrequencyBands();
140 detector->onBassLevel.add(callback);
141}
142
143void Processor::onMid(function<void(float)> callback) {
144 auto detector = getFrequencyBands();
145 detector->onMidLevel.add(callback);
146}
147
148void Processor::onTreble(function<void(float)> callback) {
149 auto detector = getFrequencyBands();
150 detector->onTrebleLevel.add(callback);
151}
152
153void Processor::onFrequencyBands(function<void(float, float, float)> callback) {
154 auto detector = getFrequencyBands();
155 detector->onLevelsUpdate.add(callback);
156}
157
160 detector->onEqualizer.add(callback);
161}
162
163void Processor::onEnergy(function<void(float)> callback) {
164 auto detector = getEnergyAnalyzer();
165 detector->onEnergy.add(callback);
166}
167
168void Processor::onNormalizedEnergy(function<void(float)> callback) {
169 auto detector = getEnergyAnalyzer();
170 detector->onNormalizedEnergy.add(callback);
171}
172
173void Processor::onPeak(function<void(float)> callback) {
174 auto detector = getEnergyAnalyzer();
175 detector->onPeak.add(callback);
176}
177
178void Processor::onAverageEnergy(function<void(float)> callback) {
179 auto detector = getEnergyAnalyzer();
180 detector->onAverageEnergy.add(callback);
181}
182
183void Processor::onTransient(function<void()> callback) {
185 detector->onTransient.add(callback);
186}
187
188void Processor::onTransientWithStrength(function<void(float)> callback) {
189 auto detector = getTransientDetector();
190 detector->onTransientWithStrength.add(callback);
191}
192
193void Processor::onAttack(function<void(float)> callback) {
194 auto detector = getTransientDetector();
195 detector->onAttack.add(callback);
196}
197
198void Processor::onSilence(function<void(u8)> callback) {
199 auto detector = getSilenceDetector();
200 detector->onSilence.add(callback);
201}
202
203void Processor::onSilenceStart(function<void()> callback) {
205 detector->onSilenceStart.add(callback);
206}
207
208void Processor::onSilenceEnd(function<void()> callback) {
210 detector->onSilenceEnd.add(callback);
211}
212
213void Processor::onSilenceDuration(function<void(u32)> callback) {
214 auto detector = getSilenceDetector();
215 detector->onSilenceDuration.add(callback);
216}
217
218void Processor::onCrescendo(function<void()> callback) {
220 detector->onCrescendo.add(callback);
221}
222
223void Processor::onDiminuendo(function<void()> callback) {
225 detector->onDiminuendo.add(callback);
226}
227
228void Processor::onDynamicTrend(function<void(float)> callback) {
229 auto detector = getDynamicsAnalyzer();
230 detector->onDynamicTrend.add(callback);
231}
232
233void Processor::onCompressionRatio(function<void(float)> callback) {
234 auto detector = getDynamicsAnalyzer();
235 detector->onCompressionRatio.add(callback);
236}
237
238void Processor::onPitch(function<void(float)> callback) {
239 auto detector = getPitchDetector();
240 detector->onPitch.add(callback);
241}
242
243void Processor::onPitchWithConfidence(function<void(float, float)> callback) {
244 auto detector = getPitchDetector();
245 detector->onPitchWithConfidence.add(callback);
246}
247
248void Processor::onPitchChange(function<void(float)> callback) {
249 auto detector = getPitchDetector();
250 detector->onPitchChange.add(callback);
251}
252
253void Processor::onVoiced(function<void(u8)> callback) {
254 auto detector = getPitchDetector();
255 detector->onVoiced.add(callback);
256}
257
258void Processor::onNoteOn(function<void(u8, u8)> callback) {
259 auto detector = getNoteDetector();
260 detector->onNoteOn.add(callback);
261}
262
263void Processor::onNoteOff(function<void(u8)> callback) {
264 auto detector = getNoteDetector();
265 detector->onNoteOff.add(callback);
266}
267
268void Processor::onNoteChange(function<void(u8, u8)> callback) {
269 auto detector = getNoteDetector();
270 detector->onNoteChange.add(callback);
271}
272
273void Processor::onDownbeat(function<void()> callback) {
275 detector->onDownbeat.add(callback);
276}
277
278void Processor::onMeasureBeat(function<void(u8)> callback) {
279 auto detector = getDownbeatDetector();
280 detector->onMeasureBeat.add(callback);
281}
282
283void Processor::onMeterChange(function<void(u8)> callback) {
284 auto detector = getDownbeatDetector();
285 detector->onMeterChange.add(callback);
286}
287
288void Processor::onMeasurePhase(function<void(float)> callback) {
289 auto detector = getDownbeatDetector();
290 detector->onMeasurePhase.add(callback);
291}
292
293void Processor::onBackbeat(function<void(u8 beatNumber, float confidence, float strength)> callback) {
295 detector->onBackbeat.add(callback);
296}
297
298void Processor::onVocal(function<void(u8)> callback) {
299 auto detector = getVocalDetector();
300 detector->onVocal.add(callback);
301}
302
303void Processor::onVocalStart(function<void()> callback) {
304 auto detector = getVocalDetector();
305 detector->onVocalStart.add(callback);
306}
307
308void Processor::onVocalEnd(function<void()> callback) {
309 auto detector = getVocalDetector();
310 detector->onVocalEnd.add(callback);
311}
312
313void Processor::onVocalConfidence(function<void(float)> callback) {
314 auto detector = getVocalDetector();
315 // This callback fires every frame with the current confidence
316 // We need to wrap it since detector::Vocal doesn't have this callback built-in
317 detector->onVocal.add([callback, detector](u8) {
318 if (callback) {
319 callback(detector->getConfidence());
320 }
321 });
322}
323
324void Processor::onPercussion(function<void(detector::PercussionType)> callback) {
325 auto detector = getPercussionDetector();
326 detector->onPercussionHit.add(callback);
327}
328
329void Processor::onKick(function<void()> callback) {
331 detector->onKick.add(callback);
332}
333
334void Processor::onSnare(function<void()> callback) {
336 detector->onSnare.add(callback);
337}
338
339void Processor::onHiHat(function<void()> callback) {
341 detector->onHiHat.add(callback);
342}
343
344void Processor::onTom(function<void()> callback) {
346 detector->onTom.add(callback);
347}
348
349void Processor::onChord(function<void(const detector::Chord&)> callback) {
350 auto detector = getChordDetector();
351 detector->onChord.add(callback);
352}
353
354void Processor::onChordChange(function<void(const detector::Chord&)> callback) {
355 auto detector = getChordDetector();
356 detector->onChordChange.add(callback);
357}
358
359void Processor::onChordEnd(function<void()> callback) {
360 auto detector = getChordDetector();
361 detector->onChordEnd.add(callback);
362}
363
364void Processor::onKey(function<void(const detector::Key&)> callback) {
365 auto detector = getKeyDetector();
366 detector->onKey.add(callback);
367}
368
369void Processor::onKeyChange(function<void(const detector::Key&)> callback) {
370 auto detector = getKeyDetector();
371 detector->onKeyChange.add(callback);
372}
373
374void Processor::onKeyEnd(function<void()> callback) {
375 auto detector = getKeyDetector();
376 detector->onKeyEnd.add(callback);
377}
378
379void Processor::onMood(function<void(const detector::Mood&)> callback) {
380 auto detector = getMoodAnalyzer();
381 detector->onMood.add(callback);
382}
383
384void Processor::onMoodChange(function<void(const detector::Mood&)> callback) {
385 auto detector = getMoodAnalyzer();
386 detector->onMoodChange.add(callback);
387}
388
389void Processor::onValenceArousal(function<void(float, float)> callback) {
390 auto detector = getMoodAnalyzer();
391 detector->onValenceArousal.add(callback);
392}
393
394void Processor::onBuildupStart(function<void()> callback) {
396 detector->onBuildupStart.add(callback);
397}
398
399void Processor::onBuildupProgress(function<void(float)> callback) {
400 auto detector = getBuildupDetector();
401 detector->onBuildupProgress.add(callback);
402}
403
404void Processor::onBuildupPeak(function<void()> callback) {
406 detector->onBuildupPeak.add(callback);
407}
408
409void Processor::onBuildupEnd(function<void()> callback) {
411 detector->onBuildupEnd.add(callback);
412}
413
414void Processor::onBuildup(function<void(const detector::Buildup&)> callback) {
416 detector->onBuildup.add(callback);
417}
418
419void Processor::onDrop(function<void()> callback) {
420 auto detector = getDropDetector();
421 detector->onDrop.add(callback);
422}
423
424void Processor::onDropEvent(function<void(const detector::Drop&)> callback) {
425 auto detector = getDropDetector();
426 detector->onDropEvent.add(callback);
427}
428
429void Processor::onDropImpact(function<void(float)> callback) {
430 auto detector = getDropDetector();
431 detector->onDropImpact.add(callback);
432}
433
435 auto detector = getVibeDetector();
436 detector->onVibeLevels.add(callback);
437}
438
439void Processor::onVibeBassSpike(function<void()> callback) {
440 auto detector = getVibeDetector();
441 detector->onBassSpike.add(callback);
442}
443
444void Processor::onVibeMidSpike(function<void()> callback) {
445 auto detector = getVibeDetector();
446 detector->onMidSpike.add(callback);
447}
448
449void Processor::onVibeTrebSpike(function<void()> callback) {
450 auto detector = getVibeDetector();
451 detector->onTrebSpike.add(callback);
452}
453
454// ----- Polling Getter Implementations -----
455
456// Helper: clamp float to 0..1
457static float clamp01(float v) {
458 if (v < 0.0f) return 0.0f;
459 if (v > 1.0f) return 1.0f;
460 return v;
461}
462
463// Helper: clamp float to -1..1
464static float clampNeg1To1(float v) {
465 if (v < -1.0f) return -1.0f;
466 if (v > 1.0f) return 1.0f;
467 return v;
468}
469
471 return clamp01(getVocalDetector()->getConfidence());
472}
473
475 return clamp01(getBeatDetector()->getConfidence());
476}
477
479 return getBeatDetector()->getBPM();
480}
481
483 return clamp01(getEnergyAnalyzer()->getNormalizedRMS());
484}
485
487 return clamp01(getEnergyAnalyzer()->getPeak());
488}
489
491 return clamp01(getFrequencyBands()->getBassNorm());
492}
493
495 return clamp01(getFrequencyBands()->getMidNorm());
496}
497
499 return clamp01(getFrequencyBands()->getTrebleNorm());
500}
501
503 return getFrequencyBands()->getBass();
504}
505
507 return getFrequencyBands()->getMid();
508}
509
511 return getFrequencyBands()->getTreble();
512}
513
515 return getSilenceDetector()->isSilent();
516}
517
519 return getSilenceDetector()->getSilenceDuration();
520}
521
523 return clamp01(getTransientDetector()->getStrength());
524}
525
529
531 return getDynamicsAnalyzer()->isCrescendo();
532}
533
535 return getDynamicsAnalyzer()->isDiminuendo();
536}
537
539 return clamp01(getPitchDetector()->getConfidence());
540}
541
543 return getPitchDetector()->getPitch();
544}
545
547 return clamp01(getTempoAnalyzer()->getConfidence());
548}
549
551 return getTempoAnalyzer()->getBPM();
552}
553
555 return clamp01(getBuildupDetector()->getIntensity());
556}
557
559 return clamp01(getBuildupDetector()->getProgress());
560}
561
563 return clamp01(getDropDetector()->getLastDrop().impact);
564}
565
567 return getPercussionDetector()->isKick();
568}
569
571 return getPercussionDetector()->isSnare();
572}
573
575 return getPercussionDetector()->isHiHat();
576}
577
579 return getPercussionDetector()->isTom();
580}
581
583 return getNoteDetector()->getCurrentNote();
584}
585
587 return getNoteDetector()->getLastVelocity() / 255.0f;
588}
589
591 return getNoteDetector()->isNoteActive() ? (getNoteDetector()->getLastVelocity() / 255.0f) : 0.0f;
592}
593
595 return clamp01(getDownbeatDetector()->getConfidence());
596}
597
601
603 return getDownbeatDetector()->getCurrentBeat();
604}
605
607 return clamp01(getBackbeatDetector()->getConfidence());
608}
609
611 return clamp01(getBackbeatDetector()->getStrength());
612}
613
615 return clamp01(getChordDetector()->getCurrentChord().confidence);
616}
617
619 return clamp01(getKeyDetector()->getCurrentKey().confidence);
620}
621
623 return clamp01(getMoodAnalyzer()->getArousal());
624}
625
627 return clampNeg1To1(getMoodAnalyzer()->getValence());
628}
629
631 return getVibeDetector()->getBass();
632}
633
635 return getVibeDetector()->getMid();
636}
637
639 return getVibeDetector()->getTreb();
640}
641
643 return getVibeDetector()->getVol();
644}
645
647 return getVibeDetector()->getBassAtt();
648}
649
651 return getVibeDetector()->getMidAtt();
652}
653
655 return getVibeDetector()->getTrebAtt();
656}
657
659 return getVibeDetector()->getVolAtt();
660}
661
663 return getVibeDetector()->isBassSpike();
664}
665
667 return getVibeDetector()->isMidSpike();
668}
669
671 return getVibeDetector()->isTrebSpike();
672}
673
675 return clamp01(getEqualizerDetector()->getBass());
676}
677
679 return clamp01(getEqualizerDetector()->getMid());
680}
681
683 return clamp01(getEqualizerDetector()->getTreble());
684}
685
687 return clamp01(getEqualizerDetector()->getVolume());
688}
689
691 return clamp01(getEqualizerDetector()->getVolumeNormFactor());
692}
693
695 return clamp01(getEqualizerDetector()->getZcf());
696}
697
698float Processor::getEqBin(int index) {
699 return clamp01(getEqualizerDetector()->getBin(index));
700}
701
703 return getEqualizerDetector()->getAutoGain();
704}
705
707 return getEqualizerDetector()->getIsSilence();
708}
709
711 return getEqualizerDetector()->getDominantFreqHz();
712}
713
715 return clamp01(getEqualizerDetector()->getDominantMagnitude());
716}
717
719 return getEqualizerDetector()->getVolumeDb();
720}
721
722void Processor::setSampleRate(int sampleRate) {
723 mSampleRate = sampleRate;
724 mContext->setSampleRate(sampleRate);
725
726 // Propagate to all active detector that are sample-rate-aware
727 for (auto& d : mActiveDetectors) {
728 d->setSampleRate(sampleRate);
729 }
730}
731
733 return mSampleRate;
734}
735
736void Processor::setGain(float gain) {
737 mGain = gain;
738}
739
740float Processor::getGain() const {
741 return mGain;
742}
743
747
751
756
761
763 mMicProfile = profile;
764 if (mEqualizerDetector) {
765 mEqualizerDetector->setMicProfile(profile);
766 }
767}
768
770 getEqualizerDetector()->configure(config);
771}
772
774 return mContext->getSample();
775}
776
778 mSignalConditioner.reset();
779 mNoiseFloorTracker.reset();
780 mContext->clearCache();
781
782 for (auto& d : mActiveDetectors) {
783 d->reset();
784 }
785 mActiveDetectors.clear();
786
787 // Null out all typed pointers so re-registration works on next use
788 mBeatDetector.reset();
789 mFrequencyBands.reset();
790 mEnergyAnalyzer.reset();
791 mTempoAnalyzer.reset();
792 mTransientDetector.reset();
793 mSilenceDetector.reset();
794 mDynamicsAnalyzer.reset();
795 mPitchDetector.reset();
796 mNoteDetector.reset();
797 mDownbeatDetector.reset();
798 mBackbeatDetector.reset();
799 mVocalDetector.reset();
800 mPercussionDetector.reset();
801 mChordDetector.reset();
802 mKeyDetector.reset();
803 mMoodAnalyzer.reset();
804 mBuildupDetector.reset();
805 mDropDetector.reset();
806 mEqualizerDetector.reset();
807 mVibeDetector.reset();
808}
809
817
825
833
841
849
857
865
873
875 if (!mNoteDetector) {
876 // Share the detector::Pitch instance between Processor and detector::Note
877 auto pitchDetector = getPitchDetector();
880 }
881 return mNoteDetector;
882}
883
885 if (!mDownbeatDetector) {
886 // Share the detector::Beat instance between Processor and detector::Downbeat
887 auto beatDetector = getBeatDetector();
890 }
891 return mDownbeatDetector;
892}
893
895 if (!mBackbeatDetector) {
896 // Share the detector::Beat and detector::Downbeat instances with detector::Backbeat
897 auto beatDetector = getBeatDetector();
898 auto downbeatDetector = getDownbeatDetector();
899 mBackbeatDetector = make_shared<detector::Backbeat>(beatDetector, downbeatDetector);
901 }
902 return mBackbeatDetector;
903}
904
912
920
928
936
944
952
960
971
979
981 shared_ptr<IInput> input) {
982 auto processor = make_shared<Processor>();
983 processor->mAudioInput = input;
984 // weak_ptr so the lambda doesn't prevent Processor destruction
985 weak_ptr<Processor> weak = processor;
986 weak_ptr<IInput> weakInput = input;
987 processor->mAutoTask = fl::task::every_ms(1).then([weak, weakInput]() {
988 auto proc = weak.lock();
989 auto inp = weakInput.lock();
990 if (!proc || !inp) {
991 return;
992 }
994 inp->readAll(&samples);
995 for (const auto& sample : samples) {
996 proc->update(sample);
997 }
998 });
999 return processor;
1000}
1001
1002} // namespace audio
1003} // namespace fl
void onBuildupProgress(function< void(float progress)> callback) FL_NOEXCEPT
void onBuildupPeak(function< void()> callback) FL_NOEXCEPT
void onTempoUnstable(function< void()> callback) FL_NOEXCEPT
float getEqDominantFreqHz() FL_NOEXCEPT
Frequency of strongest bin (Hz)
void onBuildup(function< void(const detector::Buildup &)> callback) FL_NOEXCEPT
float getMoodArousal() FL_NOEXCEPT
shared_ptr< detector::Vocal > mVocalDetector
float getVibeVol() FL_NOEXCEPT
void onVibeBassSpike(function< void()> callback) FL_NOEXCEPT
float getMidLevel() FL_NOEXCEPT
shared_ptr< detector::Percussion > getPercussionDetector() FL_NOEXCEPT
static fl::shared_ptr< Processor > createWithAutoInput(fl::shared_ptr< IInput > input) FL_NOEXCEPT
bool isSilent() FL_NOEXCEPT
shared_ptr< detector::DropDetector > getDropDetector() FL_NOEXCEPT
float getVibeBassAtt() FL_NOEXCEPT
shared_ptr< detector::DynamicsAnalyzer > mDynamicsAnalyzer
void onSnare(function< void()> callback) FL_NOEXCEPT
shared_ptr< detector::FrequencyBands > getFrequencyBands() FL_NOEXCEPT
void onVocalEnd(function< void()> callback) FL_NOEXCEPT
int getSampleRate() const FL_NOEXCEPT
shared_ptr< detector::BuildupDetector > getBuildupDetector() FL_NOEXCEPT
shared_ptr< detector::TempoAnalyzer > mTempoAnalyzer
u32 getSilenceDuration() FL_NOEXCEPT
void onTransientWithStrength(function< void(float strength)> callback) FL_NOEXCEPT
float getNoteVelocity() FL_NOEXCEPT
float getEqTreble() FL_NOEXCEPT
void onKick(function< void()> callback) FL_NOEXCEPT
float getEqBass() FL_NOEXCEPT
void updateFromContext(shared_ptr< Context > externalContext) FL_NOEXCEPT
float getEqVolumeNormFactor() FL_NOEXCEPT
float getBassRaw() FL_NOEXCEPT
bool isVibeBassSpike() FL_NOEXCEPT
SignalConditioner mSignalConditioner
shared_ptr< detector::Downbeat > mDownbeatDetector
shared_ptr< detector::Percussion > mPercussionDetector
shared_ptr< detector::Note > getNoteDetector() FL_NOEXCEPT
void onChordEnd(function< void()> callback) FL_NOEXCEPT
shared_ptr< detector::EqualizerDetector > getEqualizerDetector() FL_NOEXCEPT
bool isVibeTrebSpike() FL_NOEXCEPT
float getEnergy() FL_NOEXCEPT
float getDownbeatConfidence() FL_NOEXCEPT
float getTrebleRaw() FL_NOEXCEPT
shared_ptr< detector::ChordDetector > mChordDetector
float getChordConfidence() FL_NOEXCEPT
void onDropImpact(function< void(float impact)> callback) FL_NOEXCEPT
shared_ptr< detector::Note > mNoteDetector
void onBass(function< void(float level)> callback) FL_NOEXCEPT
void onSilenceDuration(function< void(u32 durationMs)> callback) FL_NOEXCEPT
void onBackbeat(function< void(u8 beatNumber, float confidence, float strength)> callback) FL_NOEXCEPT
void onEqualizer(function< void(const detector::Equalizer &)> callback) FL_NOEXCEPT
void onBuildupStart(function< void()> callback) FL_NOEXCEPT
void onVocal(function< void(u8 active)> callback) FL_NOEXCEPT
void onDropEvent(function< void(const detector::Drop &)> callback) FL_NOEXCEPT
shared_ptr< detector::Vibe > getVibeDetector() FL_NOEXCEPT
shared_ptr< detector::EnergyAnalyzer > getEnergyAnalyzer() FL_NOEXCEPT
float getEqBin(int index) FL_NOEXCEPT
void onSilenceStart(function< void()> callback) FL_NOEXCEPT
void onBeat(function< void()> callback) FL_NOEXCEPT
u8 getCurrentNote() FL_NOEXCEPT
void setNoiseFloorTrackingEnabled(bool enabled) FL_NOEXCEPT
Enable/disable noise floor tracking.
shared_ptr< detector::EqualizerDetector > mEqualizerDetector
shared_ptr< detector::Beat > mBeatDetector
float getNoteConfidence() FL_NOEXCEPT
float getEqZcf() FL_NOEXCEPT
u8 getCurrentBeatNumber() FL_NOEXCEPT
float getBackbeatStrength() FL_NOEXCEPT
shared_ptr< Context > mContext
shared_ptr< detector::Backbeat > mBackbeatDetector
bool getEqIsSilence() FL_NOEXCEPT
bool isCrescendo() FL_NOEXCEPT
void onVibeTrebSpike(function< void()> callback) FL_NOEXCEPT
shared_ptr< detector::Silence > getSilenceDetector() FL_NOEXCEPT
void onTempoStable(function< void()> callback) FL_NOEXCEPT
void onDiminuendo(function< void()> callback) FL_NOEXCEPT
float getVibeMid() FL_NOEXCEPT
float getBassLevel() FL_NOEXCEPT
float getMoodValence() FL_NOEXCEPT
shared_ptr< detector::KeyDetector > mKeyDetector
float getDropImpact() FL_NOEXCEPT
bool isDiminuendo() FL_NOEXCEPT
float getTrebleLevel() FL_NOEXCEPT
void onDrop(function< void()> callback) FL_NOEXCEPT
void onCrescendo(function< void()> callback) FL_NOEXCEPT
void setMicProfile(MicProfile profile) FL_NOEXCEPT
Set microphone correction profile for frequency response compensation.
void setGain(float gain) FL_NOEXCEPT
Set a simple digital gain multiplier applied to each sample before detector.
void onEnergy(function< void(float rms)> callback) FL_NOEXCEPT
float getEqMid() FL_NOEXCEPT
float getEqVolume() FL_NOEXCEPT
shared_ptr< detector::Vibe > mVibeDetector
shared_ptr< detector::Transient > getTransientDetector() FL_NOEXCEPT
void onBuildupEnd(function< void()> callback) FL_NOEXCEPT
float getDynamicTrend() FL_NOEXCEPT
shared_ptr< detector::TempoAnalyzer > getTempoAnalyzer() FL_NOEXCEPT
float getKeyConfidence() FL_NOEXCEPT
void setSampleRate(int sampleRate) FL_NOEXCEPT
Set the sample rate for all frequency-based calculations.
shared_ptr< detector::Downbeat > getDownbeatDetector() FL_NOEXCEPT
shared_ptr< detector::BuildupDetector > mBuildupDetector
void onKey(function< void(const detector::Key &key)> callback) FL_NOEXCEPT
void onBeatPhase(function< void(float phase)> callback) FL_NOEXCEPT
shared_ptr< detector::KeyDetector > getKeyDetector() FL_NOEXCEPT
float getTransientStrength() FL_NOEXCEPT
void onChord(function< void(const detector::Chord &chord)> callback) FL_NOEXCEPT
float getTempoConfidence() FL_NOEXCEPT
float getEqVolumeDb() FL_NOEXCEPT
Volume in approximate dB.
const Sample & getSample() const FL_NOEXCEPT
void configureNoiseFloorTracker(const NoiseFloorTrackerConfig &config) FL_NOEXCEPT
Configure noise floor tracker.
void onSilenceEnd(function< void()> callback) FL_NOEXCEPT
void onKeyEnd(function< void()> callback) FL_NOEXCEPT
float getGain() const FL_NOEXCEPT
float getPitch() FL_NOEXCEPT
shared_ptr< detector::Transient > mTransientDetector
float getMidRaw() FL_NOEXCEPT
void onHiHat(function< void()> callback) FL_NOEXCEPT
void onVocalStart(function< void()> callback) FL_NOEXCEPT
float getBPM() FL_NOEXCEPT
void onDynamicTrend(function< void(float trend)> callback) FL_NOEXCEPT
float getMeasurePhase() FL_NOEXCEPT
bool isVibeMidSpike() FL_NOEXCEPT
float getVibeTreb() FL_NOEXCEPT
void onVibeLevels(function< void(const detector::VibeLevels &)> callback) FL_NOEXCEPT
void onVocalConfidence(function< void(float confidence)> callback) FL_NOEXCEPT
float getTempoBPM() FL_NOEXCEPT
shared_ptr< detector::Pitch > getPitchDetector() FL_NOEXCEPT
float getEqAutoGain() FL_NOEXCEPT
vector< shared_ptr< Detector > > mActiveDetectors
void setSignalConditioningEnabled(bool enabled) FL_NOEXCEPT
Enable/disable signal conditioning pipeline (DC removal, spike filter, noise gate)
void onTransient(function< void()> callback) FL_NOEXCEPT
shared_ptr< detector::EnergyAnalyzer > mEnergyAnalyzer
shared_ptr< detector::Beat > getBeatDetector() FL_NOEXCEPT
NoiseFloorTracker mNoiseFloorTracker
float getBuildupIntensity() FL_NOEXCEPT
shared_ptr< detector::Pitch > mPitchDetector
void update(const Sample &sample) FL_NOEXCEPT
float getVibeTrebAtt() FL_NOEXCEPT
void configureSignalConditioner(const SignalConditionerConfig &config) FL_NOEXCEPT
Configure signal conditioner.
float getEqDominantMagnitude() FL_NOEXCEPT
Magnitude of strongest bin (0.0-1.0)
void onTom(function< void()> callback) FL_NOEXCEPT
float getBuildupProgress() FL_NOEXCEPT
void onMood(function< void(const detector::Mood &mood)> callback) FL_NOEXCEPT
void onDownbeat(function< void()> callback) FL_NOEXCEPT
shared_ptr< detector::Vocal > getVocalDetector() FL_NOEXCEPT
shared_ptr< detector::MoodAnalyzer > getMoodAnalyzer() FL_NOEXCEPT
shared_ptr< detector::FrequencyBands > mFrequencyBands
float getBeatConfidence() FL_NOEXCEPT
float getVibeBass() FL_NOEXCEPT
shared_ptr< detector::Silence > mSilenceDetector
shared_ptr< detector::ChordDetector > getChordDetector() FL_NOEXCEPT
void registerDetector(shared_ptr< Detector > detector) FL_NOEXCEPT
shared_ptr< detector::DropDetector > mDropDetector
float getBackbeatConfidence() FL_NOEXCEPT
float getPitchConfidence() FL_NOEXCEPT
void onMeasureBeat(function< void(u8 beatNumber)> callback) FL_NOEXCEPT
float getVibeMidAtt() FL_NOEXCEPT
float getVibeVolAtt() FL_NOEXCEPT
~Processor() FL_NOEXCEPT
float getPeakLevel() FL_NOEXCEPT
shared_ptr< detector::MoodAnalyzer > mMoodAnalyzer
shared_ptr< detector::Backbeat > getBackbeatDetector() FL_NOEXCEPT
void onVibeMidSpike(function< void()> callback) FL_NOEXCEPT
float getVocalConfidence() FL_NOEXCEPT
void configureEqualizer(const detector::EqualizerConfig &config) FL_NOEXCEPT
Configure equalizer detector tuning parameters.
shared_ptr< detector::DynamicsAnalyzer > getDynamicsAnalyzer() FL_NOEXCEPT
bool isValid() const FL_NOEXCEPT
Definition audio.h:35
Handle & then(function< void()> on_then) FL_NOEXCEPT
Definition task.cpp.hpp:276
shared_ptr< T > lock() const FL_NOEXCEPT
Definition weak_ptr.h:140
unsigned char u8
Definition stdint.h:131
Configuration for the equalizer detector.
Definition equalizer.h:26
static float clamp01(float v)
MicProfile
Microphone frequency response correction profile.
@ None
No correction (flat response assumed)
static float clampNeg1To1(float v)
bool enabled
Enable noise floor tracking.
Configuration for signal conditioning pipeline.
Configuration for noise floor tracking.
Handle every_ms(int interval_ms)
Definition task.cpp.hpp:320
unsigned char u8
Definition stdint.h:131
CRGB sample(const CRGB *grid, const XYMap &xyMap, float x, float y, SampleMode mode)
Sample a pixel from a 2D CRGB grid at floating-point coordinates.
Definition sample.cpp.hpp:9
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
VectorN< T, INLINED_SIZE > vector_inlined
Definition vector.h:1133
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT
Snapshot of equalizer state, passed to onEqualizer callbacks.
Definition equalizer.h:49