refactor(api): complete fastapi migration and related features
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>
This commit is contained in:
@@ -115,14 +115,36 @@ def parse_args() -> argparse.Namespace:
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def _clamp_detected_bpm(bpm: float | None) -> float | None:
|
||||
if bpm is None:
|
||||
return None
|
||||
try:
|
||||
from util.bpm_limits import clamp_bpm_optional
|
||||
|
||||
return clamp_bpm_optional(bpm)
|
||||
except ImportError:
|
||||
v = float(bpm)
|
||||
if v <= 0:
|
||||
return None
|
||||
return max(60.0, min(200.0, v))
|
||||
|
||||
|
||||
def _estimate_bpm(beat_times: Deque[float]) -> float | None:
|
||||
if len(beat_times) < 3:
|
||||
return None
|
||||
try:
|
||||
from util.bpm_limits import max_beat_interval_s, min_beat_interval_s
|
||||
|
||||
ioi_min = min_beat_interval_s()
|
||||
ioi_max = max_beat_interval_s()
|
||||
except ImportError:
|
||||
ioi_min = 0.3
|
||||
ioi_max = 1.0
|
||||
intervals = np.diff(np.array(beat_times, dtype=np.float64))
|
||||
valid = intervals[(intervals > 0.2) & (intervals < 2.0)]
|
||||
valid = intervals[(intervals >= ioi_min) & (intervals <= ioi_max)]
|
||||
if valid.size == 0:
|
||||
return None
|
||||
return 60.0 / float(np.median(valid))
|
||||
return _clamp_detected_bpm(60.0 / float(np.median(valid)))
|
||||
|
||||
|
||||
def _is_plausible_ioi(
|
||||
@@ -131,7 +153,7 @@ def _is_plausible_ioi(
|
||||
now_s: float,
|
||||
*,
|
||||
min_ratio: float = 0.42,
|
||||
max_ratio: float = 2.5,
|
||||
max_ratio: float = 3.5,
|
||||
) -> bool:
|
||||
"""Reject double-time / half-time false triggers vs recent median interval."""
|
||||
if last_trigger_s <= 0 or len(beat_times) < 2:
|
||||
@@ -251,7 +273,7 @@ def _resolve_bpm(
|
||||
) -> float | None:
|
||||
estimated = _estimate_bpm(beat_times)
|
||||
if estimated is None:
|
||||
return aubio_bpm
|
||||
return _clamp_detected_bpm(aubio_bpm)
|
||||
if aubio_bpm is None or aubio_bpm <= 0:
|
||||
return estimated
|
||||
ratio = float(aubio_bpm) / estimated
|
||||
@@ -400,7 +422,7 @@ class BeatDetectRuntime:
|
||||
if self.tempo is not None:
|
||||
aubio_hit = bool(self.tempo(f32)[0])
|
||||
val = float(self.tempo.get_bpm())
|
||||
aubio_bpm = val if val > 0 else None
|
||||
aubio_bpm = _clamp_detected_bpm(val if val > 0 else None)
|
||||
|
||||
if now_s is None:
|
||||
now_s = time.time()
|
||||
|
||||
Reference in New Issue
Block a user