| from __future__ import annotations |
|
|
| import torch |
| import torch.nn as nn |
|
|
|
|
| class Decoder4FeatureExtractor(nn.Module): |
| """MOSS audio-tokenizer codebook decode plus decoder blocks 0..4.""" |
|
|
| def __init__( |
| self, |
| audio_tokenizer: nn.Module, |
| num_quantizers: int = 32, |
| output_dtype: torch.dtype = torch.float16, |
| ) -> None: |
| super().__init__() |
| quantizer = getattr(audio_tokenizer, "quantizer") |
| self.quantizers = quantizer.quantizers |
| self.output_proj = quantizer.output_proj |
| self.decoder_prefix = nn.ModuleList(list(audio_tokenizer.decoder[:5])) |
| self.rvq_dim = int(quantizer.rvq_dim) |
| self.num_quantizers = int(num_quantizers) |
| self.output_dtype = output_dtype |
|
|
| def forward(self, codes: torch.Tensor, lengths: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: |
| _, batch, frames = codes.shape |
| emb = torch.zeros(batch, self.rvq_dim, frames, device=codes.device, dtype=self.output_dtype) |
| for index, quantizer in enumerate(self.quantizers[: self.num_quantizers]): |
| if self.output_dtype == torch.float16: |
| z_q = quantizer.embed_code(codes[index]).transpose(1, 2).to(self.output_dtype) |
| z_q = quantizer.out_proj(z_q) |
| else: |
| z_q = quantizer.decode_code(codes[index]) |
| emb = emb + z_q.to(self.output_dtype) |
| features = self.output_proj(emb) |
| feature_lengths = lengths |
| for module in self.decoder_prefix: |
| features, feature_lengths = module(features, feature_lengths) |
| return features.to(self.output_dtype), feature_lengths |
|
|