Visualization: Spectrum Bars
| 180 | |
| 181 | // Visualization: Spectrum Bars |
| 182 | void drawSpectrumBars(fl::audio::fft::Bins* fft, float /* peak */) { |
| 183 | clearDisplay(); |
| 184 | fl::CRGBPalette16 palette = getCurrentPalette(); |
| 185 | |
| 186 | int barWidth = WIDTH / NUM_BANDS; |
| 187 | |
| 188 | auto bands = fft->db(); |
| 189 | |
| 190 | for (size_t band = 0; band < NUM_BANDS && band < bands.size(); band++) { |
| 191 | float magnitude = bands[band]; |
| 192 | |
| 193 | // Apply noise floor |
| 194 | magnitude = magnitude / 100.0f; // Normalize from dB |
| 195 | magnitude = fl::max(0.0f, magnitude - noiseFloor.value()); |
| 196 | |
| 197 | // Smooth the FFT |
| 198 | fftSmooth[band] = fftSmooth[band] * 0.8f + magnitude * 0.2f; |
| 199 | magnitude = fftSmooth[band]; |
| 200 | |
| 201 | // Apply gain |
| 202 | magnitude *= audioGain.value() * autoGainValue; |
| 203 | magnitude = fl::clamp(magnitude, 0.0f, 1.0f); |
| 204 | |
| 205 | int barHeight = magnitude * HEIGHT; |
| 206 | int xStart = band * barWidth; |
| 207 | |
| 208 | for (int x = 0; x < fl::max(barWidth, 1); x++) { |
| 209 | for (int y = 0; y < barHeight; y++) { |
| 210 | uint8_t colorIndex = fl::map_range<float, uint8_t>( |
| 211 | float(y) / HEIGHT, 0, 1, 0, 255 |
| 212 | ); |
| 213 | fl::CRGB color = ColorFromPalette(palette, colorIndex + hue); |
| 214 | |
| 215 | int ledIndex = xyMap(xStart + x, y); |
| 216 | if (ledIndex >= 0 && ledIndex < NUM_LEDS) { |
| 217 | leds[ledIndex] = color; |
| 218 | } |
| 219 | |
| 220 | if (mirrorMode) { |
| 221 | int mirrorIndex = xyMap(WIDTH - 1 - (xStart + x), y); |
| 222 | if (mirrorIndex >= 0 && mirrorIndex < NUM_LEDS) { |
| 223 | leds[mirrorIndex] = color; |
| 224 | } |
| 225 | } |
| 226 | } |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | // Visualization: Radial Spectrum |
| 232 | void drawRadialSpectrum(fl::audio::fft::Bins* fft, float /* peak */) { |
no test coverage detected