feat(assets): SA3 音效补齐 radio 11+1 与 dungeon 13源+15pan(token 走 hf-mirror 实测可用)
- 模型 17/17 文件经镜像全量缓存(gated+token,直连本机不通;sfx.md/setup.md/asset-pipeline.md 镜像结论同步更新) - 修复迁移遗留:stable_audio_3/models/ 源码子包被 .gitignore models/ 规则误伤丢失,从上游恢复并加白名单 - radio:arg_muffled/brake_screech 等叙事件落地(接线原有 L111/L154 零改动)+ phone_ring SYN→SA3 升级;dungeon 13 源 A/B 对齐(RMS 偏差 ≤0.3dB)全量同名替换,SYN 原版备份 tools/asset_fix_backup/sa3_ab_20260902/ - 关键玩法语义达标:echo 距离档 0.83<1.43<2.18<2.98s 严格递增;one-shot 真峰值全 ≤-3dBFS(解码回读法) - check_all_assets 8 游戏全绿(radio 254/254、dungeon 303/303);playtest radio 221/dungeon 1610 全绿
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import math
|
||||
import torch
|
||||
from torch import nn
|
||||
from torch.nn.utils import weight_norm
|
||||
|
||||
|
||||
def get_activation(activation, channels=None) -> nn.Module:
|
||||
if activation == "elu":
|
||||
return nn.ELU()
|
||||
elif activation == "none":
|
||||
return nn.Identity()
|
||||
else:
|
||||
raise ValueError(f"Unknown activation {activation}")
|
||||
|
||||
def WNConv1d(*args, **kwargs):
|
||||
return weight_norm(nn.Conv1d(*args, **kwargs))
|
||||
|
||||
class ResidualUnit(nn.Module):
|
||||
def __init__(self, in_channels, out_channels, dilation, depthwise=False, bias=True):
|
||||
super().__init__()
|
||||
|
||||
self.dilation = dilation
|
||||
|
||||
padding = (dilation * (7-1)) // 2
|
||||
|
||||
self.layers = nn.Sequential(
|
||||
get_activation("elu"),
|
||||
WNConv1d(in_channels=in_channels, out_channels=out_channels,
|
||||
kernel_size=7, dilation=dilation, padding=padding, groups=1 if not depthwise else out_channels, bias=bias),
|
||||
get_activation("elu"),
|
||||
WNConv1d(in_channels=out_channels, out_channels=out_channels,
|
||||
kernel_size=1, bias=bias)
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
res = x
|
||||
x = self.layers(x)
|
||||
return x + res
|
||||
|
||||
class FourierFeatures(nn.Module):
|
||||
def __init__(self, in_features, out_features, std=16.):
|
||||
super().__init__()
|
||||
assert out_features % 2 == 0
|
||||
self.register_buffer('weight', torch.randn([out_features // 2, in_features]) * std)
|
||||
|
||||
def forward(self, input):
|
||||
f = 2 * math.pi * input @ self.weight.T
|
||||
return torch.cat([f.cos(), f.sin()], dim=-1)
|
||||
|
||||
class ExpoFourierFeatures(nn.Module):
|
||||
def __init__(self, dim, min_freq=0.5, max_freq=10000.0):
|
||||
super().__init__()
|
||||
self.dim = dim
|
||||
self.min_freq = min_freq
|
||||
self.max_freq = max_freq
|
||||
|
||||
@torch.amp.autocast("cuda",enabled=False)
|
||||
def forward(self, t):
|
||||
"""
|
||||
t: [B] tensor.
|
||||
"""
|
||||
in_dtype = t.dtype
|
||||
t = t.float()
|
||||
|
||||
if t.dim() == 1:
|
||||
t = t.unsqueeze(-1)
|
||||
|
||||
half_dim = self.dim // 2
|
||||
|
||||
# Calculate frequencies (safely in FP32)
|
||||
ramp = torch.linspace(0, 1, half_dim, device=t.device, dtype=torch.float32)
|
||||
log_min = math.log(self.min_freq)
|
||||
log_max = math.log(self.max_freq)
|
||||
|
||||
freqs = torch.exp(ramp * (log_max - log_min) + log_min)
|
||||
|
||||
# Calculate arguments (safely in FP32)
|
||||
args = t * freqs * 2 * math.pi
|
||||
|
||||
embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
|
||||
|
||||
return embedding.to(in_dtype)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user