45 u32 timestamp = context->getTimestamp();
54 float totalEnergy = 0.0f;
55 for (fl::size i = 0; i <
fft.raw().size(); ++i) {
56 totalEnergy +=
fft.raw()[i];
58 const float dt =
computeAudioDt(context->getPCM().size(), context->getSampleRate());
60 float flux =
fl::max(0.0f, totalEnergy - envValue);
64 static constexpr float kOnsetGate = 0.05f;
147 auto bins =
fft.raw();
148 int n =
static_cast<int>(bins.size());
164 int bassCutBin =
fl::max(1,
fft.freqToBin(300.0f));
165 int trebleCutBin =
fl::max(bassCutBin + 1,
fft.freqToBin(2000.0f));
166 int clickLoBin =
fl::max(bassCutBin,
fft.freqToBin(1500.0f));
167 int clickHiBin =
fl::min(n - 1,
fft.freqToBin(4500.0f));
169 float bassSum = 0.0f;
170 for (
int i = 0; i <= bassCutBin; ++i) bassSum += bins[i];
173 for (
int i = bassCutBin + 1; i < trebleCutBin; ++i) midSum += bins[i];
175 float trebleSum = 0.0f;
176 for (
int i = trebleCutBin; i < n; ++i) trebleSum += bins[i];
179 float clickBandSum = 0.0f;
180 for (
int i = clickLoBin; i <= clickHiBin; ++i) clickBandSum += bins[i];
183 float upperMidSum = midSum;
185 float total = bassSum + midSum + trebleSum;
188 mBassToTotal = (total > 1e-6f) ? bassSum / total : 0.0f;
194 mClickRatio = (upperMidSum > 1e-6f) ? clickBandSum / upperMidSum : 0.0f;
197 mMidToTreble = (trebleSum > 1e-6f) ? midSum / trebleSum : 0.0f;
200 int firstMidBin = bassCutBin + 1;
201 mSubBassProxy = (firstMidBin < n && bins[firstMidBin] > 1e-6f)
202 ? bins[0] / bins[firstMidBin]
206 int trebleBinCount = n - trebleCutBin;
207 float trebleArithMean = (trebleBinCount > 0) ? trebleSum /
static_cast<float>(trebleBinCount) : 0.0f;
208 if (trebleArithMean > 1e-6f) {
211 for (
int i = trebleCutBin; i < n; ++i) {
212 if (bins[i] > 1e-6f) {
217 if (validCount > 0) {
218 float geoMean =
fl::expf(sumLog /
static_cast<float>(validCount));
251 0.20f * trebleScore + 0.20f * zcfScore;
266 zcfScore =
fl::min(1.0f, zcfScore);
269 0.15f * midTrebleScore + 0.20f * noSubBassScore +
277 trebleScore =
fl::min(1.0f, trebleScore);
282 highClickScore =
fl::min(1.0f, highClickScore);
285 zcfScore =
fl::min(1.0f, zcfScore);
288 0.25f * highClickScore + 0.25f * zcfScore;
299 midTrebleScore =
fl::min(1.0f, midTrebleScore);
304 0.20f * midTrebleScore + 0.25f * zcfScore;
static constexpr u32 SNARE_COOLDOWN_MS
shared_ptr< const fft::Bins > mRetainedFFT
AttackDecayFilter< float > mTotalEnvelope
function_list< void(PercussionType type)> onPercussionHit
function_list< void()> onKick
static constexpr u32 KICK_COOLDOWN_MS
void applyCrossBandRejection()
function_list< void()> onSnare
static constexpr u32 HIHAT_COOLDOWN_MS
void computeConfidences()
function_list< void()> onTom
void fireCallbacks() override
void computeFeatures(const fft::Bins &fft)
~Percussion() FL_NOEXCEPT override
void update(shared_ptr< Context > context) override
static constexpr u32 TOM_COOLDOWN_MS
function_list< void()> onHiHat
float mZeroCrossingFactor
float computeAudioDt(fl::size pcmSize, int sampleRate) FL_NOEXCEPT
Compute the time delta (in seconds) for an audio buffer.
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
float expf(float value) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type abs(T x) FL_NOEXCEPT
float logf(float value) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NOEXCEPT
Base definition for an LED controller.