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

Method extractChroma

src/fl/audio/detector/key.cpp.hpp:209–245  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

207//------------------------------------------------------------------------------
208
209void KeyDetector::extractChroma(const fft::Bins& fft, float* chroma) {
210 // Initialize chroma to zero
211 for (int i = 0; i < 12; i++) {
212 chroma[i] = 0.0f;
213 }
214
215 // Map fft::FFT bins to pitch classes using linearly-rebinned magnitudes.
216 // Linear bins give evenly-spaced frequency mapping: freq = fmin + bin * binWidth.
217 fl::span<const float> linearBins = fft.linear();
218 const int numBins = static_cast<int>(linearBins.size());
219 const float fmin = fft.linearFmin();
220 const float fmax = fft.linearFmax();
221 const float linearBinWidth = (numBins > 0) ? (fmax - fmin) / static_cast<float>(numBins) : 1.0f;
222
223 // Process each linear bin
224 for (int bin = 0; bin < numBins; bin++) {
225 float magnitude = linearBins[bin];
226 if (magnitude < 1e-6f) continue;
227
228 // Calculate frequency for this linearly-spaced bin
229 float freq = fmin + (static_cast<float>(bin) + 0.5f) * linearBinWidth;
230
231 // Skip frequencies below 60 Hz (below C2)
232 if (freq < 60.0f) continue;
233
234 // Convert frequency to MIDI note number
235 // MIDI note = 69 + 12 * log2(freq / 440)
236 float midiNote = 69.0f + 12.0f * (fl::logf(freq / 440.0f) / fl::logf(2.0f));
237
238 // Get pitch class (0-11)
239 int pitchClass = static_cast<int>(midiNote + 0.5f) % 12;
240 if (pitchClass < 0) pitchClass += 12;
241
242 // Accumulate magnitude into pitch class
243 chroma[pitchClass] += magnitude;
244 }
245}
246
247void KeyDetector::normalizeChroma(float* chroma) {
248 // Find maximum value

Callers

nothing calls this directly

Calls 5

logfFunction · 0.85
linearMethod · 0.80
linearFminMethod · 0.80
linearFmaxMethod · 0.80
sizeMethod · 0.45

Tested by

no test coverage detected