FL2VA/audio_vae/dac_alias_free_resample.py
| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # Adapted from https://github.com/junjun3518/alias-free-torch under the Apache License 2.0 |
| 3 | |
| 4 | import torch.nn as nn |
| 5 | from torch.nn import functional as F |
| 6 | from .dac_alias_free_filter import LowPassFilter1d |
| 7 | from .dac_alias_free_filter import kaiser_sinc_filter1d |
| 8 | |
| 9 | |
| 10 | class UpSample1d(nn.Module): |
| 11 | def __init__(self, ratio=2, kernel_size=None): |
| 12 | super().__init__() |
| 13 | self.ratio = ratio |
| 14 | self.kernel_size = int(6 * ratio // 2) * 2 if kernel_size is None else kernel_size |
| 15 | self.stride = ratio |
| 16 | self.pad = self.kernel_size // ratio - 1 |
| 17 | self.pad_left = self.pad * self.stride + (self.kernel_size - self.stride) // 2 |
| 18 | self.pad_right = self.pad * self.stride + (self.kernel_size - self.stride + 1) // 2 |
| 19 | filter = kaiser_sinc_filter1d(cutoff=0.5 / ratio, half_width=0.6 / ratio, kernel_size=self.kernel_size) |
| 20 | self.register_buffer("filter", filter) |
| 21 | |
| 22 | # x: [B, C, T] |
| 23 | def forward(self, x): |
| 24 | _, C, _ = x.shape |
| 25 | |
| 26 | x = F.pad(x, (self.pad, self.pad), mode="replicate") |
| 27 | x = self.ratio * F.conv_transpose1d(x, self.filter.expand(C, -1, -1), stride=self.stride, groups=C) |
| 28 | x = x[..., self.pad_left : -self.pad_right] |
| 29 | |
| 30 | return x |
| 31 | |
| 32 | |
| 33 | class DownSample1d(nn.Module): |
| 34 | def __init__(self, ratio=2, kernel_size=None): |
| 35 | super().__init__() |
| 36 | self.ratio = ratio |
| 37 | self.kernel_size = int(6 * ratio // 2) * 2 if kernel_size is None else kernel_size |
| 38 | self.lowpass = LowPassFilter1d( |
| 39 | cutoff=0.5 / ratio, |
| 40 | half_width=0.6 / ratio, |
| 41 | stride=ratio, |
| 42 | kernel_size=self.kernel_size, |
| 43 | ) |
| 44 | |
| 45 | def forward(self, x): |
| 46 | xx = self.lowpass(x) |
| 47 | |
| 48 | return xx |
| 49 | |