Spaces:
Running
Running
File size: 4,265 Bytes
be60cf4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | """Hugging Face Hub-compatible wrappers (safetensors + from_pretrained/push_to_hub).
Three model types, all <=16M params, MIT-licensed:
SoftChartGenerator audio log-mel -> chart event tokens (the main model; pr12)
SoftChartBeat audio log-mel -> beat/downbeat activations (barline anchor)
SoftChartPlanner block features -> per-block plan tokens (auto-planning)
Usage:
from softchart.hf import SoftChartGenerator
gen = SoftChartGenerator.from_pretrained("JacobLinCool/softchart-generator")
"""
import torch
import torch.nn as nn
from huggingface_hub import PyTorchModelHubMixin
from .model import ChartModel, sinusoidal
_CARD = "See https://github.com/JacobLinCool/SoftChart — MIT licensed."
class SoftChartGenerator(
nn.Module,
PyTorchModelHubMixin,
repo_url="https://github.com/JacobLinCool/SoftChart",
license="mit",
tags=["taiko", "rhythm-game", "chart-generation", "music", "audio-to-symbolic"],
):
"""Encoder-decoder chart generator. Config is stored as config.json and the
full architecture (condition tokens, heads) is reconstructed on load."""
def __init__(self, d_model=256, enc_layers=4, dec_layers=4, ffn=1024,
vocab_size=1802, aux=True, global_ctx=False, func_time=False,
ptr=False, beat=False, in_ch=None, emb_factor=None,
capabilities=None, nhead=8, clean_phase=False,
enc_share=None, dec_share=None, adapter_rank=0,
unique_layernorm=False, adapter_rank_ffn=0, depth_emb=False,
unshare_last_dec=False):
super().__init__()
# nhead and the v1.6/v1.7 sharing flags (enc_share/dec_share/adapter_rank/
# unique_layernorm/adapter_rank_ffn/depth_emb/unshare_last_dec) and
# clean_phase must be persisted in config.json: from_pretrained rebuilds
# the architecture from these kwargs alone, before any weights are loaded.
# Defaults reproduce the pre-v1.6 unshared architecture for older repos.
self.net = ChartModel(
d_model=d_model, nhead=nhead, enc_layers=enc_layers, dec_layers=dec_layers,
ffn=ffn, vocab_size=vocab_size, aux=aux, global_ctx=global_ctx,
func_time=func_time, ptr=ptr, beat=beat, in_ch=in_ch, emb_factor=emb_factor,
clean_phase=clean_phase, enc_share=enc_share, dec_share=dec_share,
adapter_rank=adapter_rank, unique_layernorm=unique_layernorm,
adapter_rank_ffn=adapter_rank_ffn, depth_emb=depth_emb,
unshare_last_dec=unshare_last_dec,
)
# capabilities: which condition axes this checkpoint was trained with,
# so inference knows which prefix tokens to emit
self.capabilities = capabilities or {}
# delegate the generation interface to the inner net
def encode(self, *a, **k):
return self.net.encode(*a, **k)
def decode(self, *a, **k):
return self.net.decode(*a, **k)
def forward(self, *a, **k):
return self.net(*a, **k)
@property
def ptr(self):
return self.net.ptr
@property
def beat(self):
return self.net.beat
@property
def tok_emb(self):
return self.net.tok_emb
class SoftChartPlanner(
nn.Module,
PyTorchModelHubMixin,
repo_url="https://github.com/JacobLinCool/SoftChart",
license="mit",
tags=["taiko", "rhythm-game", "planning", "music"],
):
"""Song-level plan generator: block audio summaries -> (density, flag) tokens."""
def __init__(self, feat_dim=261, d=192, layers=4, n_dens=8, n_flag=3):
super().__init__()
self.inp = nn.Linear(feat_dim, d)
self.course = nn.Embedding(5, d)
self.register_buffer("pos", sinusoidal(128, d), persistent=False)
enc = nn.TransformerEncoderLayer(d, 6, d * 4, 0.1, activation="gelu",
batch_first=True, norm_first=True)
self.enc = nn.TransformerEncoder(enc, layers, nn.LayerNorm(d))
self.h_dens = nn.Linear(d, n_dens)
self.h_flag = nn.Linear(d, n_flag)
def forward(self, x, cid):
h = self.inp(x) + self.course(cid)[:, None] + self.pos[: x.shape[1]]
h = self.enc(h)
return self.h_dens(h), self.h_flag(h)
|