Files
SoundGame/tools/stable-audio-3/stable_audio_3/models/blocks.py
T
xsl 24c526af68 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 全绿
2026-09-02 19:35:38 +08:00

85 lines
2.5 KiB
Python

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)