Encode audio waveform to latent representation. Input: (batch, 1, samples) or (batch, samples) Output: (batch, frames, vae_dim)
(&self, audio: &Tensor)
| 302 | /// Input: (batch, 1, samples) or (batch, samples) |
| 303 | /// Output: (batch, frames, vae_dim) |
| 304 | pub fn encode(&self, audio: &Tensor) -> Result<Tensor> { |
| 305 | // Ensure input is (batch, channels=1, samples) |
| 306 | let x = if audio.rank() == 2 { |
| 307 | audio.unsqueeze(1)? |
| 308 | } else { |
| 309 | audio.clone() |
| 310 | }; |
| 311 | |
| 312 | let mut h = x; |
| 313 | |
| 314 | // Interleave: downsample → stage blocks |
| 315 | for (i, (conv, stage)) in self |
| 316 | .downsample_convs |
| 317 | .iter() |
| 318 | .zip(self.stages.iter()) |
| 319 | .enumerate() |
| 320 | { |
| 321 | // Causal left-pad then conv |
| 322 | h = Self::causal_pad(&h, self.downsample_paddings[i])?; |
| 323 | |
| 324 | // For strided convolutions, add extra padding for alignment |
| 325 | if self.downsample_strides[i] > 1 { |
| 326 | let kernel = conv.weight.dim(2)?; |
| 327 | let stride = self.downsample_strides[i]; |
| 328 | let length = h.dim(2)?; |
| 329 | let n_frames = (length - kernel) / stride + 1; |
| 330 | let ideal_length = n_frames * stride + kernel; |
| 331 | if ideal_length < length { |
| 332 | // This shouldn't happen with proper causal padding |
| 333 | } else if ideal_length > length { |
| 334 | let extra = ideal_length - length; |
| 335 | h = Tensor::cat( |
| 336 | &[ |
| 337 | &h, |
| 338 | &Tensor::zeros( |
| 339 | (h.dim(0)?, h.dim(1)?, extra), |
| 340 | h.dtype(), |
| 341 | h.device(), |
| 342 | )?, |
| 343 | ], |
| 344 | 2, |
| 345 | )?; |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | h = self.backend.conv1d(&h, &conv.weight, conv.bias.as_ref(), conv.padding, conv.stride, conv.dilation, conv.groups)?; |
| 350 | h = stage.forward(&h)?; |
| 351 | } |
| 352 | |
| 353 | // Head conv: causal left-pad 6 |
| 354 | h = Self::causal_pad(&h, 6)?; |
| 355 | h = self.backend.conv1d(&h, &self.head_conv.weight, self.head_conv.bias.as_ref(), self.head_conv.padding, self.head_conv.stride, self.head_conv.dilation, self.head_conv.groups)?; |
| 356 | |
| 357 | // Return as (batch, frames, vae_dim) |
| 358 | h.transpose(1, 2) |
| 359 | } |
| 360 | |
| 361 | /// Streaming encode: uses cache for correct context between frames. |