VeriSpoof-Base / code /verispoof /audio_tokenizer.py
AustinXiao's picture
Model card ready for release; UniMelb logo; inference package under code/
a975ec5 verified
Raw History Blame Contribute Delete
1.72 kB
"""Audio tokenizer: encoder hidden states (B, T, n_layers, D) -> (B, n_global + T / frame_stack, d_llm) LLM inputs."""
import math
import torch
import torch.nn as nn
class AudioTokenizer(nn.Module):
def __init__(self, d_llm, layer_mix, d_global=2048, d_local=2048, n_global=16, d_q=512, frame_stack=2,
n_frames=104):
super().__init__()
self.mix_logits = nn.Parameter(torch.zeros(layer_mix["n_mix"], layer_mix["n_layers"]))
self.n_global, self.d_q = n_global, d_q
self.frame_stack, self.n_frames = frame_stack, n_frames
self.n_local = math.ceil(n_frames / frame_stack)
self.g_mlp = nn.Sequential(nn.LayerNorm(d_global), nn.Linear(d_global, 1024), nn.GELU(),
nn.Linear(1024, n_global * d_q))
self.g_proj = nn.Sequential(nn.LayerNorm(d_q), nn.Linear(d_q, d_llm))
self.f_proj = nn.Sequential(nn.LayerNorm(d_local * frame_stack), nn.Linear(d_local * frame_stack, 1024),
nn.GELU(), nn.Linear(1024, d_llm))
@property
def n_tokens(self):
return self.n_global + self.n_local
def forward(self, hs):
w = torch.softmax(self.mix_logits.float(), -1).to(hs.dtype)
loc = torch.einsum("btld,ml->btmd", hs, w).flatten(2)
g = loc.mean(1)
glob = self.g_proj(self.g_mlp(g).view(g.size(0), self.n_global, self.d_q))
assert loc.size(1) == self.n_frames, (loc.shape, self.n_frames)
k = self.frame_stack
pad = self.n_local * k - loc.size(1)
x = nn.functional.pad(loc, (0, 0, 0, pad)) if pad else loc
return torch.cat([glob, self.f_proj(x.reshape(loc.size(0), self.n_local, k * loc.size(2)))], 1)