287fe16a562ebf215dea8a34c617c3452c735d16
- Create beats.js with BeatGrid class: load(), getCalibratedBeats(), getCalibratedOnsets(), snap(), hasBeats getter - BeatGrid manages calibrationOffset and snapEnabled state - snap() uses 100ms threshold against calibrated beat positions - Handles API field variants: beats/beat_times, tempo/tempo_bpm - Refactor timeline.js: replace beatTimes/calibrationOffset/snapEnabled with this.beatGrid - Add getters/setters for calibrationOffset and snapEnabled (backward compat with app.js) - render() now shows DETECTING BEATS... loading indicator and error state - render() draws beat marks via getCalibratedBeats(), onset ticks via getCalibratedOnsets() - snapToBeat() delegates to beatGrid.snap() - app.js chains BPM label update after loadBeats() resolves
Description
LightSync LED show system
Languages
Python
61.1%
JavaScript
30.5%
CSS
5.5%
HTML
2.8%
Dockerfile
0.1%