Download data/diffusion_cache_utils.py from soilkon/Grid2Drum: direct link, hf CLI and curl.
- Browser
- Download file 17.5 kB
-
https://huggingface.co/spaces/soilkon/Grid2Drum/resolve/main/data/diffusion_cache_utils.py
- Command line
-
hf download hf://spaces/soilkon/Grid2Drum/data/diffusion_cache_utils.py
-
curl -L -o diffusion_cache_utils.py https://huggingface.co/spaces/soilkon/Grid2Drum/resolve/main/data/diffusion_cache_utils.py
17.5 kB
| from __future__ import annotations | |
| import hashlib | |
| from typing import Any, Mapping, Sequence | |
| import numpy as np | |
| import torch | |
| FAMILY_STATE_FAMILY_NAMES: tuple[str, ...] = ( | |
| "kick", | |
| "snare", | |
| "tom_high", | |
| "tom_mid", | |
| "tom_floor", | |
| "hihat", | |
| "crash", | |
| "ride", | |
| ) | |
| FAMILY_STATE_NUMERIC_COMPONENT_NAMES: tuple[str, ...] = ( | |
| "state_vel", | |
| "onset_vel", | |
| "onset_count", | |
| ) | |
| FAMILY_STATE_FEATURE_ROW_NAMES: tuple[str, ...] = tuple( | |
| f"{family_name}_{component_name}" | |
| for family_name in FAMILY_STATE_FAMILY_NAMES | |
| for component_name in FAMILY_STATE_NUMERIC_COMPONENT_NAMES | |
| ) | |
| FAMILY_STATE_ID_VOCAB_SIZES: tuple[int, ...] = ( | |
| 1, | |
| 3, | |
| 2, | |
| 2, | |
| 2, | |
| 5, | |
| 2, | |
| 3, | |
| ) | |
| def hash_bytes(payload: bytes) -> str: | |
| digest = hashlib.sha256() | |
| digest.update(payload) | |
| return digest.hexdigest() | |
| def hash_tensor(tensor: torch.Tensor) -> str: | |
| arr = tensor.detach().to(device="cpu").contiguous().numpy() | |
| return hash_bytes(arr.tobytes()) | |
| def fit_pca( | |
| x_nd: np.ndarray, | |
| *, | |
| pca_k: int, | |
| ) -> tuple[np.ndarray, np.ndarray, np.ndarray, int]: | |
| x = np.asarray(x_nd, dtype=np.float32) | |
| if int(x.ndim) != 2: | |
| raise ValueError(f"x_nd must be [N,D], got shape {tuple(x.shape)}") | |
| if int(x.shape[0]) <= 0: | |
| raise ValueError("x_nd must have at least one row") | |
| mean = x.mean(axis=0, keepdims=True) | |
| xc = x - mean | |
| _u, s, vt = np.linalg.svd(xc, full_matrices=False) | |
| var = (s ** 2) / max(1, (xc.shape[0] - 1)) | |
| ratio = var / max(var.sum(), 1.0e-8) | |
| k = int(min(max(1, int(pca_k)), int(vt.shape[0]))) | |
| components = vt[:k].astype(np.float32, copy=False) | |
| explained = ratio[:k].astype(np.float32, copy=False) | |
| return mean.astype(np.float32, copy=False), components, explained, k | |
| def fit_projected_pca( | |
| x_nd: np.ndarray, | |
| *, | |
| projection_basis_dq: np.ndarray, | |
| pca_k: int, | |
| ) -> tuple[np.ndarray, np.ndarray, np.ndarray, int]: | |
| x = np.asarray(x_nd, dtype=np.float32) | |
| basis = np.asarray(projection_basis_dq, dtype=np.float32) | |
| if int(x.ndim) != 2: | |
| raise ValueError(f"x_nd must be [N,D], got shape {tuple(x.shape)}") | |
| if int(basis.ndim) != 2: | |
| raise ValueError(f"projection_basis_dq must be [D,Q], got shape {tuple(basis.shape)}") | |
| if int(x.shape[0]) <= 0: | |
| raise ValueError("x_nd must have at least one row") | |
| if int(x.shape[1]) != int(basis.shape[0]): | |
| raise ValueError( | |
| f"x_nd / projection basis dimension mismatch: {tuple(x.shape)} vs {tuple(basis.shape)}" | |
| ) | |
| mean_full = x.mean(axis=0, keepdims=True) | |
| coeff = (x - mean_full) @ basis | |
| coeff_mean = coeff.mean(axis=0, keepdims=True) | |
| coeff_centered = coeff - coeff_mean | |
| _u, s, vt = np.linalg.svd(coeff_centered, full_matrices=False) | |
| var = (s ** 2) / max(1, (coeff_centered.shape[0] - 1)) | |
| ratio = var / max(var.sum(), 1.0e-8) | |
| k = int(min(max(1, int(pca_k)), int(vt.shape[0]))) | |
| coeff_components = vt[:k].astype(np.float32, copy=False) | |
| components = (coeff_components @ basis.transpose()).astype(np.float32, copy=False) | |
| mean = (mean_full + (coeff_mean @ basis.transpose())).astype(np.float32, copy=False) | |
| explained = ratio[:k].astype(np.float32, copy=False) | |
| return mean.reshape(-1), components, explained, k | |
| def fix_component_signs(components: np.ndarray) -> np.ndarray: | |
| fixed = np.asarray(components, dtype=np.float32).copy() | |
| for idx in range(int(fixed.shape[0])): | |
| comp = fixed[int(idx)] | |
| max_idx = int(np.argmax(np.abs(comp))) | |
| if float(comp[int(max_idx)]) < 0.0: | |
| fixed[int(idx)] = -comp | |
| return fixed | |
| def token_times_from_duration(code_frames: int, duration_sec: float) -> np.ndarray: | |
| frames = int(max(0, int(code_frames))) | |
| dur = float(max(0.0, float(duration_sec))) | |
| if frames <= 0 or dur <= 0.0: | |
| return np.zeros((0,), dtype=np.float32) | |
| idx = np.arange(frames, dtype=np.float32) | |
| return ((idx + 0.5) * (dur / float(frames))).astype(np.float32, copy=False) | |
| def grid_times_from_fps(grid_frames: int, fps: float) -> np.ndarray: | |
| frames = int(max(0, int(grid_frames))) | |
| fps_eff = float(max(1.0e-6, float(fps))) | |
| if frames <= 0: | |
| return np.zeros((0,), dtype=np.float32) | |
| return ((np.arange(frames, dtype=np.float32) + np.float32(0.5)) / fps_eff).astype(np.float32, copy=False) | |
| def sample_beat_boundaries_from_source( | |
| *, | |
| shard: Mapping[str, Any], | |
| row: Mapping[str, Any], | |
| duration_sec: float, | |
| ) -> np.ndarray: | |
| duration_eff = float(max(1.0e-6, float(duration_sec))) | |
| beat_times_raw = shard.get("beat_times_sec") | |
| if beat_times_raw is None: | |
| return np.asarray([0.0, float(duration_eff)], dtype=np.float32) | |
| if torch.is_tensor(beat_times_raw): | |
| beat_times = beat_times_raw.detach().to(device="cpu", dtype=torch.float32).numpy().reshape(-1) | |
| else: | |
| beat_times = np.asarray(beat_times_raw, dtype=np.float32).reshape(-1) | |
| beat_times = beat_times[np.isfinite(beat_times)] | |
| boundaries = np.concatenate(([0.0], beat_times.astype(np.float32, copy=False)), dtype=np.float32) | |
| start_sec = float(row.get("start_sec", 0.0) or 0.0) | |
| end_sec = float(row.get("end_sec", start_sec + duration_eff) or (start_sec + duration_eff)) | |
| beat_index = int(row.get("beat_index", -1) or -1) | |
| if row.get("num_beats") is not None: | |
| num_beats = int(max(1, int(row.get("num_beats", 1) or 1))) | |
| else: | |
| beat_index_end = int(row.get("beat_index_end", beat_index) or beat_index) | |
| num_beats = int(max(1, int(beat_index_end) - int(beat_index) + 1)) if int(beat_index) >= 0 else 1 | |
| if int(beat_index) >= 0 and int(beat_index) + int(num_beats) < int(boundaries.shape[0]): | |
| sample_boundaries = np.asarray( | |
| boundaries[int(beat_index) : int(beat_index) + int(num_beats) + 1], | |
| dtype=np.float32, | |
| ) | |
| else: | |
| eps = np.float32(1.0e-4) | |
| mask = (boundaries >= np.float32(float(start_sec) - float(eps))) & ( | |
| boundaries <= np.float32(float(end_sec) + float(eps)) | |
| ) | |
| sample_boundaries = np.asarray(boundaries[mask], dtype=np.float32) | |
| sample_boundaries = np.concatenate( | |
| ( | |
| np.asarray([float(start_sec)], dtype=np.float32), | |
| sample_boundaries, | |
| np.asarray([float(end_sec)], dtype=np.float32), | |
| ), | |
| dtype=np.float32, | |
| ) | |
| sample_boundaries = np.clip( | |
| np.asarray(sample_boundaries, dtype=np.float32) - np.float32(float(start_sec)), | |
| np.float32(0.0), | |
| np.float32(float(duration_eff)), | |
| ) | |
| sample_boundaries = np.sort(sample_boundaries, axis=None).astype(np.float32, copy=False) | |
| if int(sample_boundaries.size) <= 0: | |
| return np.asarray([0.0, float(duration_eff)], dtype=np.float32) | |
| deduped: list[float] = [float(sample_boundaries[0])] | |
| for value in list(sample_boundaries[1:]): | |
| if float(value) > float(deduped[-1]) + 1.0e-5: | |
| deduped.append(float(value)) | |
| if float(deduped[0]) > 1.0e-5: | |
| deduped.insert(0, 0.0) | |
| else: | |
| deduped[0] = 0.0 | |
| if float(deduped[-1]) < float(duration_eff) - 1.0e-5: | |
| deduped.append(float(duration_eff)) | |
| else: | |
| deduped[-1] = float(duration_eff) | |
| if int(len(deduped)) < 2: | |
| deduped = [0.0, float(duration_eff)] | |
| return np.asarray(deduped, dtype=np.float32) | |
| def normalize_segment_beat_boundaries_rel( | |
| boundaries_sec_rel: Sequence[float], | |
| *, | |
| expected_num_beats: int, | |
| duration_sec: float, | |
| merge_tolerance_sec: float = 1.0e-4, | |
| ) -> np.ndarray: | |
| boundaries = np.asarray(boundaries_sec_rel, dtype=np.float64).reshape(-1) | |
| expected_count = int(max(1, int(expected_num_beats)) + 1) | |
| duration = float(max(1.0e-6, float(duration_sec))) | |
| tol = float(max(1.0e-8, float(merge_tolerance_sec))) | |
| if int(boundaries.size) <= 0: | |
| return np.asarray([0.0, duration], dtype=np.float32) | |
| boundaries = np.clip(boundaries, 0.0, duration) | |
| merged: list[float] = [0.0] | |
| for value in list(boundaries): | |
| v = float(value) | |
| if float(v) <= float(merged[-1]) + float(tol): | |
| merged[-1] = max(float(merged[-1]), float(v)) | |
| else: | |
| merged.append(float(v)) | |
| if float(merged[-1]) < float(duration) - float(tol): | |
| merged.append(float(duration)) | |
| else: | |
| merged[-1] = float(duration) | |
| if int(len(merged)) == int(expected_count): | |
| return np.asarray(merged, dtype=np.float32) | |
| raise ValueError( | |
| f"expected {expected_count} beat boundaries after normalization, got {tuple(np.asarray(merged).shape)} " | |
| f"from raw boundaries {np.asarray(boundaries_sec_rel, dtype=np.float32).tolist()}" | |
| ) | |
| def stack_family_state_grid( | |
| *, | |
| state_vel_ft: np.ndarray, | |
| onset_vel_ft: np.ndarray, | |
| onset_count_ft: np.ndarray, | |
| ) -> np.ndarray: | |
| state_vel = np.asarray(state_vel_ft, dtype=np.float32) | |
| onset_vel = np.asarray(onset_vel_ft, dtype=np.float32) | |
| onset_count = np.asarray(onset_count_ft, dtype=np.float32) | |
| if int(state_vel.ndim) != 2: | |
| raise ValueError(f"state_vel_ft must be [F,T], got {tuple(state_vel.shape)}") | |
| if tuple(onset_vel.shape) != tuple(state_vel.shape): | |
| raise ValueError(f"onset_vel_ft must match state_vel_ft, got {tuple(onset_vel.shape)} / {tuple(state_vel.shape)}") | |
| if tuple(onset_count.shape) != tuple(state_vel.shape): | |
| raise ValueError( | |
| f"onset_count_ft must match state_vel_ft, got {tuple(onset_count.shape)} / {tuple(state_vel.shape)}" | |
| ) | |
| num_families, num_frames = [int(x) for x in list(state_vel.shape)] | |
| if int(num_families) != int(len(FAMILY_STATE_FAMILY_NAMES)): | |
| raise ValueError( | |
| f"expected {len(FAMILY_STATE_FAMILY_NAMES)} families, got {tuple(state_vel.shape)}" | |
| ) | |
| grid_rows = [] | |
| for family_idx in range(int(num_families)): | |
| grid_rows.append(state_vel[int(family_idx)]) | |
| grid_rows.append(onset_vel[int(family_idx)]) | |
| grid_rows.append(onset_count[int(family_idx)]) | |
| out = np.stack(grid_rows, axis=0).astype(np.float32, copy=False) | |
| if tuple(out.shape) != (int(len(FAMILY_STATE_FEATURE_ROW_NAMES)), int(num_frames)): | |
| raise RuntimeError(f"unexpected stacked family-state grid shape {tuple(out.shape)}") | |
| return out | |
| def build_segment_beat_boundaries_rel( | |
| *, | |
| song_beat_times_sec: Sequence[float], | |
| beat_index: int, | |
| num_beats: int, | |
| start_sec: float, | |
| end_sec: float, | |
| ) -> np.ndarray: | |
| beat_index = int(beat_index) | |
| num_beats = int(num_beats) | |
| start_sec = float(start_sec) | |
| end_sec = float(end_sec) | |
| if int(num_beats) <= 0: | |
| raise ValueError(f"num_beats must be positive, got {num_beats}") | |
| if not float(end_sec) > float(start_sec): | |
| raise ValueError(f"end_sec must be greater than start_sec, got {start_sec} -> {end_sec}") | |
| song_beats = np.asarray(song_beat_times_sec, dtype=np.float64).reshape(-1) | |
| all_boundaries = np.concatenate((np.asarray([0.0], dtype=np.float64), song_beats), axis=0) | |
| lo = int(beat_index) | |
| hi = int(beat_index + num_beats) | |
| if int(lo) < 0 or int(hi) >= int(all_boundaries.shape[0]): | |
| raise ValueError( | |
| f"beat boundary slice [{lo}:{hi}] is out of range for {int(all_boundaries.shape[0])} boundaries" | |
| ) | |
| boundaries_abs = np.asarray(all_boundaries[int(lo) : int(hi) + 1], dtype=np.float64).copy() | |
| if int(boundaries_abs.shape[0]) != int(num_beats + 1): | |
| raise ValueError( | |
| f"expected {int(num_beats + 1)} boundaries, got shape {tuple(boundaries_abs.shape)}" | |
| ) | |
| boundaries_abs[0] = float(start_sec) | |
| boundaries_abs[-1] = float(end_sec) | |
| boundaries_rel = np.asarray(boundaries_abs - float(start_sec), dtype=np.float32) | |
| duration_sec = np.float32(float(end_sec) - float(start_sec)) | |
| boundaries_rel[0] = np.float32(0.0) | |
| boundaries_rel[-1] = duration_sec | |
| boundaries_rel = np.clip(boundaries_rel, 0.0, float(duration_sec)) | |
| diffs = np.diff(boundaries_rel.astype(np.float64)) | |
| if np.any(diffs <= 0.0): | |
| raise ValueError( | |
| f"segment beat boundaries must be strictly increasing, got {boundaries_rel.tolist()}" | |
| ) | |
| return boundaries_rel.astype(np.float32, copy=False) | |
| def expand_beat_boundaries_to_16th_steps(beat_boundaries_sec_rel: Sequence[float]) -> np.ndarray: | |
| beat_boundaries = np.asarray(beat_boundaries_sec_rel, dtype=np.float64).reshape(-1) | |
| if int(beat_boundaries.shape[0]) != 5: | |
| raise ValueError(f"expected 5 beat boundaries for a 4-beat segment, got {tuple(beat_boundaries.shape)}") | |
| diffs = np.diff(beat_boundaries) | |
| if np.any(diffs <= 0.0): | |
| raise ValueError(f"beat boundaries must be strictly increasing, got {beat_boundaries.tolist()}") | |
| step_boundaries: list[float] = [] | |
| for beat_idx in range(4): | |
| beat_start = float(beat_boundaries[int(beat_idx)]) | |
| beat_end = float(beat_boundaries[int(beat_idx) + 1]) | |
| local = np.linspace(beat_start, beat_end, num=5, endpoint=True, dtype=np.float64) | |
| step_boundaries.extend(local[:-1].tolist()) | |
| step_boundaries.append(float(beat_boundaries[-1])) | |
| out = np.asarray(step_boundaries, dtype=np.float32) | |
| if int(out.shape[0]) != 17: | |
| raise RuntimeError(f"expected 17 step boundaries, got {tuple(out.shape)}") | |
| return out | |
| def aggregate_grid16_from_conditioning( | |
| *, | |
| state_vel_ft: np.ndarray, | |
| onset_vel_ft: np.ndarray, | |
| onset_ids_ft: np.ndarray, | |
| family_onsets_ft: np.ndarray, | |
| onset_count_ft: np.ndarray, | |
| step_boundaries_sec_rel: Sequence[float], | |
| duration_sec: float, | |
| ) -> dict[str, np.ndarray]: | |
| state_vel = np.asarray(state_vel_ft, dtype=np.float32) | |
| onset_vel = np.asarray(onset_vel_ft, dtype=np.float32) | |
| onset_ids = np.asarray(onset_ids_ft, dtype=np.int64) | |
| family_onsets = np.asarray(family_onsets_ft, dtype=np.bool_) | |
| onset_count = np.asarray(onset_count_ft, dtype=np.uint8) | |
| step_boundaries = np.asarray(step_boundaries_sec_rel, dtype=np.float64).reshape(-1) | |
| duration_sec = float(duration_sec) | |
| if int(state_vel.ndim) != 2: | |
| raise ValueError(f"state_vel_ft must be [F,T], got {tuple(state_vel.shape)}") | |
| if tuple(onset_vel.shape) != tuple(state_vel.shape): | |
| raise ValueError(f"onset_vel_ft must match state_vel_ft, got {tuple(onset_vel.shape)} / {tuple(state_vel.shape)}") | |
| if tuple(onset_ids.shape) != tuple(state_vel.shape): | |
| raise ValueError(f"onset_ids_ft must match state_vel_ft, got {tuple(onset_ids.shape)} / {tuple(state_vel.shape)}") | |
| if tuple(family_onsets.shape) != tuple(state_vel.shape): | |
| raise ValueError( | |
| f"family_onsets_ft must match state_vel_ft, got {tuple(family_onsets.shape)} / {tuple(state_vel.shape)}" | |
| ) | |
| if tuple(onset_count.shape) != tuple(state_vel.shape): | |
| raise ValueError( | |
| f"onset_count_ft must match state_vel_ft, got {tuple(onset_count.shape)} / {tuple(state_vel.shape)}" | |
| ) | |
| if int(step_boundaries.shape[0]) != 17: | |
| raise ValueError(f"step_boundaries_sec_rel must have 17 values, got {tuple(step_boundaries.shape)}") | |
| if not float(duration_sec) > 0.0: | |
| raise ValueError(f"duration_sec must be positive, got {duration_sec}") | |
| num_families, grid_frames = [int(x) for x in list(state_vel.shape)] | |
| frame_edges = np.linspace(0.0, float(duration_sec), num=int(grid_frames) + 1, endpoint=True, dtype=np.float64) | |
| frame_centers = 0.5 * (frame_edges[:-1] + frame_edges[1:]) | |
| grid16_state_vel = np.zeros((int(num_families), 16), dtype=np.float32) | |
| grid16_onset_vel = np.zeros((int(num_families), 16), dtype=np.float32) | |
| grid16_onset_count = np.zeros((int(num_families), 16), dtype=np.uint8) | |
| grid16_onset_ids = np.full((int(num_families), 16), -1, dtype=np.int16) | |
| for step_idx in range(16): | |
| step_start = float(step_boundaries[int(step_idx)]) | |
| step_end = float(step_boundaries[int(step_idx) + 1]) | |
| overlap = (frame_edges[1:] > float(step_start)) & (frame_edges[:-1] < float(step_end)) | |
| frame_idx = np.flatnonzero(overlap) | |
| if int(frame_idx.size) <= 0: | |
| midpoint = 0.5 * (float(step_start) + float(step_end)) | |
| frame_idx = np.asarray([int(np.argmin(np.abs(frame_centers - float(midpoint))))], dtype=np.int64) | |
| grid16_state_vel[:, int(step_idx)] = np.max(state_vel[:, frame_idx], axis=1) | |
| count_sum = onset_count[:, frame_idx].astype(np.int64).sum(axis=1) | |
| grid16_onset_count[:, int(step_idx)] = np.clip(count_sum, 0, 255).astype(np.uint8, copy=False) | |
| for family_idx in range(int(num_families)): | |
| hit_frames = frame_idx[np.flatnonzero(family_onsets[int(family_idx), frame_idx])] | |
| if int(hit_frames.size) <= 0: | |
| continue | |
| hit_vels = onset_vel[int(family_idx), hit_frames] | |
| sort_key = np.lexsort((hit_frames.astype(np.int64), hit_vels.astype(np.float64))) | |
| best_frame = int(hit_frames[int(sort_key[-1])]) | |
| grid16_onset_vel[int(family_idx), int(step_idx)] = float(onset_vel[int(family_idx), int(best_frame)]) | |
| grid16_onset_ids[int(family_idx), int(step_idx)] = np.int16(onset_ids[int(family_idx), int(best_frame)]) | |
| return { | |
| "grid16_state_vel": grid16_state_vel, | |
| "grid16_onset_vel": grid16_onset_vel, | |
| "grid16_onset_count": grid16_onset_count, | |
| "grid16_onset_ids": grid16_onset_ids, | |
| "step_boundaries_sec_rel": np.asarray(step_boundaries, dtype=np.float32), | |
| } | |