Spaces:
Running
Running
| """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) | |
| def ptr(self): | |
| return self.net.ptr | |
| def beat(self): | |
| return self.net.beat | |
| 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) | |