Finish native FastAPI controllers, drop vendored microdot, and add Wi-Fi driver runtime, beat SSE, simulated BPM, sequence playback improvements, bridge ESP-NOW sources, UI updates, and tests. Co-authored-by: Cursor <cursoragent@cursor.com>
46 lines
1.2 KiB
Python
46 lines
1.2 KiB
Python
"""BPM clamp helpers."""
|
|
|
|
import os
|
|
import sys
|
|
|
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
SRC_PATH = os.path.join(PROJECT_ROOT, "src")
|
|
if SRC_PATH not in sys.path:
|
|
sys.path.insert(0, SRC_PATH)
|
|
|
|
from util.audio_detector import AudioBeatDetector # noqa: E402
|
|
from util.bpm_limits import (
|
|
BPM_MAX,
|
|
BPM_MIN,
|
|
clamp_bpm,
|
|
clamp_bpm_optional,
|
|
max_beat_interval_s,
|
|
max_beat_min_ioi_ms,
|
|
min_beat_interval_s,
|
|
)
|
|
|
|
|
|
def test_clamp_bpm_bounds():
|
|
assert clamp_bpm(120) == 120.0
|
|
assert clamp_bpm(400) == float(BPM_MAX)
|
|
assert clamp_bpm(20) == float(BPM_MIN)
|
|
|
|
|
|
def test_clamp_bpm_optional():
|
|
assert clamp_bpm_optional(None) is None
|
|
assert clamp_bpm_optional(0) is None
|
|
assert clamp_bpm_optional(350) == float(BPM_MAX)
|
|
|
|
|
|
def test_beat_interval_bounds():
|
|
assert abs(min_beat_interval_s() - 60.0 / BPM_MAX) < 1e-9
|
|
assert abs(max_beat_interval_s() - 60.0 / BPM_MIN) < 1e-9
|
|
assert abs(max_beat_min_ioi_ms() - 60_000.0 / BPM_MAX) < 1e-6
|
|
|
|
|
|
def test_status_clamps_high_bpm():
|
|
det = AudioBeatDetector()
|
|
with det._lock:
|
|
det._status["bpm"] = 350.0
|
|
assert det.status()["bpm"] == float(BPM_MAX)
|