Spaces:
Sleeping
Sleeping
Fixed-BPM grid + piecewise fit + dual-mode support
Browse files
app.py
CHANGED
|
@@ -15,7 +15,7 @@ import numpy as np
|
|
| 15 |
import torch
|
| 16 |
|
| 17 |
from softchart.generate import generate_song, generate_song_slot, load_hf
|
| 18 |
-
from softchart.grid import debias_to_grid,
|
| 19 |
from softchart.hf import SoftChartPlanner
|
| 20 |
from softchart.rhythm import snap_chart
|
| 21 |
from softchart.tja import write_tja_slots
|
|
@@ -246,7 +246,7 @@ def generate(audio, course, level, bpm_override, auto_plan_on, use_beat, use_pla
|
|
| 246 |
if use_beat and M["beat"] is not None:
|
| 247 |
# global robust (period, phase) fit over the whole song — much more
|
| 248 |
# precise than per-peak use (each raw peak carries ~±23 ms bin noise)
|
| 249 |
-
grid =
|
| 250 |
if grid is not None:
|
| 251 |
# rigid synthesized barlines when the fit is trustworthy; raw peaks
|
| 252 |
# (plan-block edges only, no anchoring) when it is not
|
|
@@ -255,8 +255,13 @@ def generate(audio, course, level, bpm_override, auto_plan_on, use_beat, use_pla
|
|
| 255 |
grid = None
|
| 256 |
if bpm_override and bpm_override > 0:
|
| 257 |
bpm = float(bpm_override)
|
| 258 |
-
if
|
| 259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
elif grid is not None:
|
| 261 |
bpm = grid["bpm"] # already integer-snapped when the residual allows
|
| 262 |
elif dbs is not None and len(dbs) > 4:
|
|
@@ -301,6 +306,7 @@ def generate(audio, course, level, bpm_override, auto_plan_on, use_beat, use_pla
|
|
| 301 |
img = render(mel, g, title, course)
|
| 302 |
if grid is not None:
|
| 303 |
grid_info = (f" · grid: rms {grid['rms_ms']:.1f}ms ({grid['inlier_frac']:.0%} inlier)"
|
|
|
|
| 304 |
+ (" · slot-exact" if slot_used else ""))
|
| 305 |
elif use_beat and M["beat"] is not None:
|
| 306 |
grid_info = " · grid: unreliable, barline anchoring off"
|
|
|
|
| 15 |
import torch
|
| 16 |
|
| 17 |
from softchart.generate import generate_song, generate_song_slot, load_hf
|
| 18 |
+
from softchart.grid import debias_to_grid, fit_grid_fixed_bpm, fit_grid_piecewise
|
| 19 |
from softchart.hf import SoftChartPlanner
|
| 20 |
from softchart.rhythm import snap_chart
|
| 21 |
from softchart.tja import write_tja_slots
|
|
|
|
| 246 |
if use_beat and M["beat"] is not None:
|
| 247 |
# global robust (period, phase) fit over the whole song — much more
|
| 248 |
# precise than per-peak use (each raw peak carries ~±23 ms bin noise)
|
| 249 |
+
grid = fit_grid_piecewise(M["beat"], mel, device=DEVICE)
|
| 250 |
if grid is not None:
|
| 251 |
# rigid synthesized barlines when the fit is trustworthy; raw peaks
|
| 252 |
# (plan-block edges only, no anchoring) when it is not
|
|
|
|
| 255 |
grid = None
|
| 256 |
if bpm_override and bpm_override > 0:
|
| 257 |
bpm = float(bpm_override)
|
| 258 |
+
if use_beat and M["beat"] is not None and (grid is None or abs(grid["bpm"] - bpm) > 0.5):
|
| 259 |
+
# the user KNOWS the tempo: phase-only fit with a trusted period —
|
| 260 |
+
# much easier than the free fit, often unlocks the slot-exact path
|
| 261 |
+
g2 = fit_grid_fixed_bpm(M["beat"], mel, bpm, device=DEVICE)
|
| 262 |
+
grid = g2 if (g2 is not None and g2["ok"]) else None
|
| 263 |
+
if grid is not None:
|
| 264 |
+
dbs = grid["downbeats"]
|
| 265 |
elif grid is not None:
|
| 266 |
bpm = grid["bpm"] # already integer-snapped when the residual allows
|
| 267 |
elif dbs is not None and len(dbs) > 4:
|
|
|
|
| 306 |
img = render(mel, g, title, course)
|
| 307 |
if grid is not None:
|
| 308 |
grid_info = (f" · grid: rms {grid['rms_ms']:.1f}ms ({grid['inlier_frac']:.0%} inlier)"
|
| 309 |
+
+ (f" · {grid['n_segments']} tempo segs" if grid.get("piecewise") else "")
|
| 310 |
+ (" · slot-exact" if slot_used else ""))
|
| 311 |
elif use_beat and M["beat"] is not None:
|
| 312 |
grid_info = " · grid: unreliable, barline anchoring off"
|