Spaces:
Running on Zero
Running on Zero
| """Model-agnostic inference orchestration: notes+params -> new velocities.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| from ..data.features import build_note_features | |
| _NOTE_DT = np.dtype([("onset_sec", float), ("pitch", int), ("velocity", int)]) | |
| def _note_array(notes): | |
| return np.array([(n["onset_sec"], n["pitch"], n["velocity"]) for n in notes], dtype=_NOTE_DT) | |
| def predict_velocities(request, predict_all): | |
| notes = request["notes"] | |
| if not notes: | |
| return {} | |
| na = _note_array(notes) | |
| # build_note_features sorts by onset_sec (stable); reproduce that order to map back. | |
| order = np.argsort(na["onset_sec"], kind="stable") | |
| meta = {"id": "infer", "drummer": "infer", "split": "infer", | |
| "bpm": float(request["bpm"]), "time_signature": str(request["time_signature"]), | |
| "style": str(request["style"]), "beat_type": str(request["beat_type"])} | |
| df = build_note_features(na, meta) # rows correspond to na[order] | |
| preds_sorted = np.asarray(predict_all(df), dtype=float) | |
| preds = np.empty(len(notes), dtype=float) | |
| preds[order] = preds_sorted # back to input positions | |
| blend = float(request.get("blend", 1.0)) | |
| out = {} | |
| for pos, n in enumerate(notes): | |
| if not n.get("selected"): | |
| continue | |
| v = blend * preds[pos] + (1.0 - blend) * float(n["velocity"]) | |
| out[n["index"]] = int(np.clip(round(v), 1, 127)) | |
| return out | |