1#![allow(unused)]
2use candle::{DType, Device, IndexOp, Module, Result, Tensor, D};
10use candle_nn::{
11 linear_b, Conv1d, Conv1dConfig, ConvTranspose1d, ConvTranspose1dConfig, LayerNorm, Linear,
12 VarBuilder,
13};
14
15#[derive(serde::Deserialize, Debug, Clone)]
16pub struct Config {
17 pub sampling_rate: usize,
18 pub encoder_dim: usize,
19 pub encoder_rates: Vec<usize>,
20 pub decoder_dim: usize,
21 pub decoder_rates: Vec<usize>,
22 pub attn_window_size: Option<usize>,
23 pub codebook_size: usize,
24 pub codebook_dim: usize,
25 pub vq_strides: Vec<usize>,
26 pub noise: bool,
27 pub depthwise: bool,
28}
29
30pub fn repeat_interleave<D: candle::shape::Dim>(
32 img: &Tensor,
33 repeats: usize,
34 dim: D,
35) -> Result<Tensor> {
36 if repeats == 1 {
37 return Ok(img.clone());
38 }
39 let dim = dim.to_index(img.shape(), "chunk")?;
40 let img = img.unsqueeze(dim + 1)?;
41 let mut dims = img.dims().to_vec();
42 dims[dim + 1] = repeats;
43 img.broadcast_as(dims)?.flatten(dim, dim + 1)
44}
45
46pub fn conv1d_weight_norm(
47 in_c: usize,
48 out_c: usize,
49 kernel_size: usize,
50 config: candle_nn::Conv1dConfig,
51 vb: VarBuilder,
52) -> Result<Conv1d> {
53 let weight_g = vb.get((out_c, 1, 1), "parametrizations.weight.original0")?;
54 let weight_v = {
55 let name = "parametrizations.weight.original1";
56 match vb.get((out_c, in_c, kernel_size), name) {
57 Ok(v) => v,
58 Err(_) => vb.get((out_c, 1, kernel_size), name)?,
59 }
60 };
61 let norm_v = weight_v.sqr()?.sum_keepdim((1, 2))?.sqrt()?;
62 let weight = weight_v.broadcast_mul(&weight_g)?.broadcast_div(&norm_v)?;
63 let bias = vb.get(out_c, "bias")?;
64 Ok(Conv1d::new(weight, Some(bias), config))
65}
66
67pub fn conv1d_weight_norm_no_bias(
68 in_c: usize,
69 out_c: usize,
70 kernel_size: usize,
71 config: candle_nn::Conv1dConfig,
72 vb: VarBuilder,
73) -> Result<Conv1d> {
74 let weight_g = vb.get((out_c, 1, 1), "parametrizations.weight.original0")?;
75 let weight_v = {
76 let name = "parametrizations.weight.original1";
77 match vb.get((out_c, in_c, kernel_size), name) {
78 Ok(v) => v,
79 Err(_) => vb.get((out_c, 1, kernel_size), name)?,
80 }
81 };
82 let norm_v = weight_v.sqr()?.sum_keepdim((1, 2))?.sqrt()?;
83 let weight = weight_v.broadcast_mul(&weight_g)?.broadcast_div(&norm_v)?;
84 Ok(Conv1d::new(weight, None, config))
85}
86
87pub fn conv_transpose1d_weight_norm(
88 in_c: usize,
89 out_c: usize,
90 kernel_size: usize,
91 bias: bool,
92 config: candle_nn::ConvTranspose1dConfig,
93 vb: VarBuilder,
94) -> Result<ConvTranspose1d> {
95 let weight_g = vb.get((in_c, 1, 1), "parametrizations.weight.original0")?;
96 let weight_v = vb.get(
97 (in_c, out_c, kernel_size),
98 "parametrizations.weight.original1",
99 )?;
100 let norm_v = weight_v.sqr()?.sum_keepdim((1, 2))?.sqrt()?;
101 let weight = weight_v.broadcast_mul(&weight_g)?.broadcast_div(&norm_v)?;
102 let bias = if bias {
103 Some(vb.get(out_c, "bias")?)
104 } else {
105 None
106 };
107 Ok(ConvTranspose1d::new(weight, bias, config))
108}
109
110#[allow(unused)]
112#[derive(Debug, Clone)]
113struct SinusoidalEmbeddings {
114 inv_freq: Tensor,
115 scale: Tensor,
116 scale_base: f32,
117 use_xpos: bool,
118}
119
120impl SinusoidalEmbeddings {
121 fn new(dim: usize, scale_base: f32, use_xpos: bool, dev: &Device) -> Result<Self> {
122 let inv_freq: Vec<_> = (0..dim)
123 .step_by(2)
124 .map(|i| 1f32 / 10_000f32.powf(i as f32 / dim as f32))
125 .collect();
126 let len = inv_freq.len();
127 let inv_freq = Tensor::from_vec(inv_freq, len, dev)?.to_dtype(DType::F32)?;
128 let scale: Vec<_> = (0..dim)
129 .step_by(2)
130 .map(|i| (i as f32 + 0.4 * dim as f32) / (1.4 * dim as f32))
131 .collect();
132 let scale = Tensor::from_vec(scale, len, dev)?.to_dtype(DType::F32)?;
133 Ok(Self {
134 inv_freq,
135 scale,
136 scale_base,
137 use_xpos,
138 })
139 }
140}
141
142#[allow(unused)]
143#[derive(Debug, Clone)]
144struct LocalMHA {
145 norm: LayerNorm,
146 to_qkv: Linear,
147 to_out: Linear,
148 num_heads: usize,
149 head_dim: usize,
150 rel_pos: Option<SinusoidalEmbeddings>,
151}
152
153impl LocalMHA {
154 fn new(
155 dim: usize,
156 window_size: usize,
157 dim_head: usize,
158 use_rotary_pos_emb: bool,
159 vb: VarBuilder,
160 ) -> Result<Self> {
161 let norm = candle_nn::layer_norm(dim, 1e-5, vb.pp("norm"))?;
162 let to_qkv = linear_b(dim, dim * 3, false, vb.pp("to_qkv"))?;
163 let to_out = linear_b(dim, dim, false, vb.pp("to_out"))?;
164 let rel_pos = if use_rotary_pos_emb {
165 let rel_pos =
166 SinusoidalEmbeddings::new(dim_head, window_size as f32 / 2.0, false, vb.device())?;
167 Some(rel_pos)
168 } else {
169 None
170 };
171 Ok(Self {
172 norm,
173 to_qkv,
174 to_out,
175 rel_pos,
176 num_heads: dim / dim_head,
177 head_dim: dim_head,
178 })
179 }
180}
181
182impl Module for LocalMHA {
183 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
184 let (b, c, t) = xs.dims3()?;
185 let residual = xs.clone();
186 let xs = xs.transpose(1, 2)?.apply(&self.norm)?;
187 let qkv = xs.apply(&self.to_qkv)?;
188 let q = qkv.narrow(D::Minus1, 0, c)?;
189 let k = qkv.narrow(D::Minus1, c, c)?;
190 let v = qkv.narrow(D::Minus1, 2 * c, c)?;
191 let q = q
192 .reshape((b, t, self.num_heads, self.head_dim))?
193 .transpose(1, 2)?
194 .contiguous()?;
195 let k = k
196 .reshape((b, t, self.num_heads, self.head_dim))?
197 .transpose(1, 2)?
198 .contiguous()?;
199 let v = v
200 .reshape((b, t, self.num_heads, self.head_dim))?
201 .transpose(1, 2)?
202 .contiguous()?;
203 let (q, k) = match self.rel_pos {
204 Some(_) => todo!(),
205 None => (q, k),
206 };
207 let out = {
208 let scale = 1f64 / f64::sqrt(self.head_dim as f64);
209 let attn_weights = (q.matmul(&k.transpose(2, 3)?)? * scale)?;
210 let attn_weights = candle_nn::ops::softmax_last_dim(&attn_weights)?;
212 attn_weights.matmul(&v)?
213 };
214 let out = out
215 .transpose(1, 2)?
216 .reshape((b, t, self.num_heads * self.head_dim))?
217 .apply(&self.to_out)?;
218 out.transpose(1, 2)? + residual
219 }
220}
221
222#[derive(Debug, Clone)]
223struct Snake1d {
224 alpha: Tensor,
225}
226
227impl Snake1d {
228 pub fn new(channels: usize, vb: VarBuilder) -> Result<Self> {
229 let alpha = vb.get((1, channels, 1), "alpha")?;
230 Ok(Self { alpha })
231 }
232}
233
234impl Module for Snake1d {
235 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
236 let xs_shape = xs.shape();
237 let xs = xs.flatten_from(2)?;
238 let sin = self.alpha.broadcast_mul(&xs)?.sin()?;
239 let sin = (&sin * &sin)?;
240 (xs + (&self.alpha + 1e-9)?.recip()?.broadcast_mul(&sin)?)?.reshape(xs_shape)
241 }
242}
243
244#[derive(Debug, Clone)]
245struct ResidualUnit {
246 snake1: Snake1d,
247 conv1: Conv1d,
248 snake2: Snake1d,
249 conv2: Conv1d,
250}
251
252impl ResidualUnit {
253 fn new(
254 dim: usize,
255 dilation: usize,
256 kernel: usize,
257 groups: usize,
258 vb: VarBuilder,
259 ) -> Result<Self> {
260 let pad = ((kernel - 1) * dilation) / 2;
261 let vb = vb.pp("block");
262 let snake1 = Snake1d::new(dim, vb.pp(0))?;
263 let cfg1 = Conv1dConfig {
264 dilation,
265 padding: pad,
266 groups,
267 ..Default::default()
268 };
269 let conv1 = conv1d_weight_norm(dim, dim, 7, cfg1, vb.pp(1))?;
270 let snake2 = Snake1d::new(dim, vb.pp(2))?;
271 let conv2 = conv1d_weight_norm(dim, dim, 1, Default::default(), vb.pp(3))?;
272 Ok(Self {
273 snake1,
274 conv1,
275 snake2,
276 conv2,
277 })
278 }
279}
280
281impl Module for ResidualUnit {
282 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
283 let ys = xs
284 .apply(&self.snake1)?
285 .apply(&self.conv1)?
286 .apply(&self.snake2)?
287 .apply(&self.conv2)?;
288 let pad = (xs.dim(D::Minus1)? - ys.dim(D::Minus1)?) / 2;
289 if pad > 0 {
290 &ys + xs.narrow(D::Minus1, pad, ys.dim(D::Minus1)?)
291 } else {
292 ys + xs
293 }
294 }
295}
296
297#[derive(Debug, Clone)]
298struct NoiseBlock {
299 linear: Conv1d,
300}
301
302impl NoiseBlock {
303 fn new(dim: usize, vb: VarBuilder) -> Result<Self> {
304 let linear = conv1d_weight_norm_no_bias(dim, dim, 1, Default::default(), vb.pp("linear"))?;
305 Ok(Self { linear })
306 }
307}
308
309impl Module for NoiseBlock {
310 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
311 let (b, _c, t) = xs.dims3()?;
312 let noise = Tensor::randn(0f32, 1f32, (b, 1, t), xs.device())?;
313 let h = xs.apply(&self.linear)?;
314 let n = noise.broadcast_mul(&h)?;
315 let xs = (xs + n)?;
316 Ok(xs)
317 }
318}
319
320#[derive(Debug, Clone)]
321struct DecoderBlock {
322 snake1: Snake1d,
323 conv_tr1: ConvTranspose1d,
324 noise: Option<NoiseBlock>,
325 res1: ResidualUnit,
326 res2: ResidualUnit,
327 res3: ResidualUnit,
328}
329
330impl DecoderBlock {
331 fn new(
332 in_dim: usize,
333 out_dim: usize,
334 stride: usize,
335 noise: bool,
336 groups: usize,
337 vb: VarBuilder,
338 ) -> Result<Self> {
339 let vb = vb.pp("block");
340 let snake1 = Snake1d::new(in_dim, vb.pp(0))?;
341 let cfg = ConvTranspose1dConfig {
342 stride,
343 padding: stride.div_ceil(2),
344 output_padding: stride % 2,
345 ..Default::default()
346 };
347 let conv_tr1 =
348 conv_transpose1d_weight_norm(in_dim, out_dim, 2 * stride, true, cfg, vb.pp(1))?;
349 let (n, noise) = if noise {
350 let noise = NoiseBlock::new(out_dim, vb.pp(2))?;
351 (1, Some(noise))
352 } else {
353 (0, None)
354 };
355 let res1 = ResidualUnit::new(out_dim, 1, 7, groups, vb.pp(2 + n))?;
356 let res2 = ResidualUnit::new(out_dim, 3, 7, groups, vb.pp(3 + n))?;
357 let res3 = ResidualUnit::new(out_dim, 9, 7, groups, vb.pp(4 + n))?;
358 Ok(Self {
359 snake1,
360 conv_tr1,
361 noise,
362 res1,
363 res2,
364 res3,
365 })
366 }
367}
368
369impl Module for DecoderBlock {
370 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
371 xs.apply(&self.snake1)?
372 .apply(&self.conv_tr1)?
373 .apply(&self.noise.as_ref())?
374 .apply(&self.res1)?
375 .apply(&self.res2)?
376 .apply(&self.res3)
377 }
378}
379
380#[derive(Debug, Clone)]
381struct EncoderBlock {
382 res1: ResidualUnit,
383 res2: ResidualUnit,
384 res3: ResidualUnit,
385 snake1: Snake1d,
386 conv1: Conv1d,
387}
388
389impl EncoderBlock {
390 fn new(
391 out_dim: usize,
392 in_dim: Option<usize>,
393 stride: usize,
394 groups: usize,
395 vb: VarBuilder,
396 ) -> Result<Self> {
397 let vb = vb.pp("block");
398 let in_dim = in_dim.unwrap_or(out_dim / 2);
399 let res1 = ResidualUnit::new(in_dim, 1, 7, groups, vb.pp(0))?;
400 let res2 = ResidualUnit::new(in_dim, 3, 7, groups, vb.pp(1))?;
401 let res3 = ResidualUnit::new(in_dim, 9, 7, groups, vb.pp(2))?;
402 let snake1 = Snake1d::new(in_dim, vb.pp(3))?;
403 let cfg1 = Conv1dConfig {
404 stride,
405 padding: stride.div_ceil(2),
406 ..Default::default()
407 };
408 let conv1 = conv1d_weight_norm(in_dim, out_dim, 2 * stride, cfg1, vb.pp(4))?;
409 Ok(Self {
410 res1,
411 res2,
412 res3,
413 snake1,
414 conv1,
415 })
416 }
417}
418
419impl candle::Module for EncoderBlock {
420 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
421 xs.apply(&self.res1)?
422 .apply(&self.res2)?
423 .apply(&self.res3)?
424 .apply(&self.snake1)?
425 .apply(&self.conv1)
426 }
427}
428
429#[derive(Debug, Clone)]
430pub struct Encoder {
431 conv1: Conv1d,
432 blocks: Vec<EncoderBlock>,
433 local_mha: Option<LocalMHA>,
434 conv2: Conv1d,
435}
436
437impl candle::Module for Encoder {
438 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
439 let mut xs = xs.apply(&self.conv1)?;
440 for block in self.blocks.iter() {
441 xs = xs.apply(block)?
442 }
443 xs.apply(&self.conv2)
444 }
445}
446
447impl Encoder {
448 fn new(
449 mut d_model: usize,
450 strides: &[usize],
451 depthwise: bool,
452 attn_window_size: Option<usize>,
453 vb: VarBuilder,
454 ) -> Result<Self> {
455 let vb = vb.pp("block");
456 let mut idx = 0;
457 let cfg1 = Conv1dConfig {
458 padding: 3,
459 ..Default::default()
460 };
461 let conv1 = conv1d_weight_norm(1, d_model, 7, cfg1, vb.pp(idx))?;
462 idx += 1;
463 let mut blocks = Vec::with_capacity(strides.len());
464 for &stride in strides.iter() {
465 d_model *= 2;
466 let groups = if depthwise { d_model / 2 } else { 1 };
467 let block = EncoderBlock::new(d_model, None, stride, groups, vb.pp(idx))?;
468 idx += 1;
469 blocks.push(block)
470 }
471 let local_mha = match attn_window_size {
472 Some(w) => {
473 let mha = LocalMHA::new(d_model, w, 64, true, vb.pp(idx))?;
474 idx += 1;
475 Some(mha)
476 }
477 None => None,
478 };
479 let groups = if depthwise { d_model } else { 1 };
480 let cfg2 = Conv1dConfig {
481 padding: 3,
482 groups,
483 ..Default::default()
484 };
485 let conv2 = conv1d_weight_norm(d_model, d_model, 7, cfg2, vb.pp(idx))?;
486 idx += 1;
487 Ok(Self {
488 conv1,
489 blocks,
490 local_mha,
491 conv2,
492 })
493 }
494}
495
496#[derive(Debug, Clone)]
497enum ConvInit {
498 Depthwise(Conv1d, Conv1d),
499 Standard(Conv1d),
500}
501
502#[derive(Debug, Clone)]
503pub struct Decoder {
504 conv1: ConvInit,
505 local_mha: Option<LocalMHA>,
506 blocks: Vec<DecoderBlock>,
507 snake1: Snake1d,
508 conv2: Conv1d,
509}
510
511impl Decoder {
512 #[allow(clippy::too_many_arguments)]
513 fn new(
514 in_c: usize,
515 mut channels: usize,
516 rates: &[usize],
517 noise: bool,
518 depthwise: bool,
519 attn_window_size: Option<usize>,
520 d_out: usize,
521 vb: VarBuilder,
522 ) -> Result<Self> {
523 let vb = vb.pp("model");
524 let mut idx = 0;
525 let pad3 = Conv1dConfig {
526 padding: 3,
527 ..Default::default()
528 };
529 let conv1 = if depthwise {
530 let cfg1 = Conv1dConfig {
531 padding: 3,
532 groups: in_c,
533 ..Default::default()
534 };
535 let conv1 = conv1d_weight_norm(in_c, in_c, 7, cfg1, vb.pp(idx))?;
536 idx += 1;
537 let conv2 = conv1d_weight_norm(in_c, channels, 1, Default::default(), vb.pp(idx))?;
538 idx += 1;
539 ConvInit::Depthwise(conv1, conv2)
540 } else {
541 let conv1 = conv1d_weight_norm(in_c, channels, 7, pad3, vb.pp(idx))?;
542 idx += 1;
543 ConvInit::Standard(conv1)
544 };
545 let mut blocks = Vec::with_capacity(rates.len());
546 let local_mha = match attn_window_size {
547 Some(w) => {
548 let mha = LocalMHA::new(channels, w, 64, true, vb.pp(idx))?;
549 idx += 1;
550 Some(mha)
551 }
552 None => None,
553 };
554 for stride in rates.iter() {
555 let groups = if depthwise { channels / 2 } else { 1 };
556 let block =
557 DecoderBlock::new(channels, channels / 2, *stride, noise, groups, vb.pp(idx))?;
558 idx += 1;
559 channels /= 2;
560 blocks.push(block)
561 }
562 let snake1 = Snake1d::new(channels, vb.pp(idx))?;
563 idx += 1;
564 let conv2 = conv1d_weight_norm(channels, d_out, 7, pad3, vb.pp(idx))?;
565 idx += 1;
566 Ok(Self {
567 conv1,
568 local_mha,
569 blocks,
570 snake1,
571 conv2,
572 })
573 }
574}
575
576impl candle::Module for Decoder {
577 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
578 let mut xs = match &self.conv1 {
579 ConvInit::Standard(c) => xs.apply(c)?,
580 ConvInit::Depthwise(c1, c2) => xs.apply(c1)?.apply(c2)?,
581 };
582 for block in self.blocks.iter() {
583 xs = xs.apply(block)?
584 }
585 xs.apply(&self.snake1)?.apply(&self.conv2)
586 }
587}
588
589fn normalize(v: &Tensor) -> Result<Tensor> {
590 v.broadcast_div(&v.sqr()?.sum_keepdim(1)?.sqrt()?)
591}
592
593#[allow(unused)]
595#[derive(Clone, Debug)]
596struct VectorQuantizer {
597 in_proj: Conv1d,
598 out_proj: Conv1d,
599 codebook: candle_nn::Embedding,
600 stride: usize,
601}
602
603impl VectorQuantizer {
604 fn new(
605 in_dim: usize,
606 cb_size: usize,
607 cb_dim: usize,
608 stride: usize,
609 vb: VarBuilder,
610 ) -> Result<Self> {
611 let in_proj = conv1d_weight_norm(in_dim, cb_dim, 1, Default::default(), vb.pp("in_proj"))?;
612 let out_proj =
613 conv1d_weight_norm(cb_dim, in_dim, 1, Default::default(), vb.pp("out_proj"))?;
614 let codebook = candle_nn::embedding(cb_size, cb_dim, vb.pp("codebook"))?;
615 Ok(Self {
616 in_proj,
617 out_proj,
618 codebook,
619 stride,
620 })
621 }
622
623 fn decode_latents(&self, latents: &Tensor) -> Result<(Tensor, Tensor)> {
624 let (b, d, t) = latents.dims3()?;
625 let encodings = latents.transpose(1, 2)?.reshape((b * t, d))?;
626 let encodings = normalize(&encodings)?;
627 let codebook = normalize(self.codebook.embeddings())?;
628 let dist = (encodings
629 .sqr()?
630 .sum_keepdim(1)?
631 .broadcast_sub(&encodings.matmul(&codebook.t()?)?)?
632 * 2.0)?
633 .broadcast_add(&codebook.sqr()?.sum_keepdim(1)?.t()?)?;
634 let indices = dist.argmin(1)?.reshape((b, ()))?;
635 let z_q = self.decode_code(&indices)?;
636 Ok((z_q, indices))
637 }
638
639 fn encode(&self, z: &Tensor) -> Result<(Tensor, Tensor)> {
640 let z = if self.stride > 1 {
641 let (b, c, t) = z.dims3()?;
642 z.reshape((b, c, 1, t))?
643 .avg_pool2d((1, self.stride))?
644 .squeeze(2)?
645 } else {
646 z.clone()
647 };
648 let z_e = z.apply(&self.in_proj)?;
649 let (z_q, indices) = self.decode_latents(&z_e)?;
650 let z_q = z_q.apply(&self.out_proj)?;
651 let z_q = if self.stride > 1 {
652 repeat_interleave(&z_q, self.stride, D::Minus1)?
653 } else {
654 z_q
655 };
656 Ok((z_q, indices))
657 }
658
659 fn embed_code(&self, embed_id: &Tensor) -> Result<Tensor> {
660 embed_id.apply(&self.codebook)
661 }
662
663 fn decode_code(&self, embed_id: &Tensor) -> Result<Tensor> {
664 self.embed_code(embed_id)?.transpose(1, 2)
665 }
666}
667
668#[derive(Clone, Debug)]
669pub struct ResidualVectorQuantizer {
670 quantizers: Vec<VectorQuantizer>,
671}
672
673impl ResidualVectorQuantizer {
674 fn new(
675 input_dim: usize,
676 cb_size: usize,
677 cb_dim: usize,
678 vq_strides: &[usize],
679 vb: VarBuilder,
680 ) -> Result<Self> {
681 let vb = &vb.pp("quantizers");
682 let quantizers = vq_strides
683 .iter()
684 .enumerate()
685 .map(|(i, stride)| VectorQuantizer::new(input_dim, cb_size, cb_dim, *stride, vb.pp(i)))
686 .collect::<Result<Vec<_>>>()?;
687 Ok(Self { quantizers })
688 }
689
690 fn encode(&self, z: &Tensor) -> Result<(Tensor, Vec<Tensor>)> {
691 let mut residual = z.clone();
692 let mut z_q = z.zeros_like()?;
693 let mut codes = Vec::with_capacity(self.quantizers.len());
694 for quantizer in self.quantizers.iter() {
695 let (z_q_i, indices_i) = quantizer.encode(&residual)?;
696 z_q = (z_q + &z_q_i)?;
697 residual = (residual - &z_q_i)?;
698 codes.push(indices_i)
699 }
700 Ok((z_q, codes))
701 }
702
703 #[allow(clippy::wrong_self_convention)]
704 fn from_codes(&self, codes: &[&Tensor]) -> Result<Tensor> {
705 let mut sum = None;
706 for (quantizer, codes) in self.quantizers.iter().zip(codes.iter()) {
707 let z_p_i = quantizer.decode_code(codes)?;
708 let z_q_i = z_p_i.apply(&quantizer.out_proj)?;
709 let z_q_i = repeat_interleave(&z_q_i, quantizer.stride, D::Minus1)?;
710 let s = match sum {
711 None => z_q_i,
712 Some(s) => (s + z_q_i)?,
713 };
714 sum = Some(s)
715 }
716 match sum {
717 Some(s) => Ok(s),
718 None => candle::bail!("empty codebooks"),
719 }
720 }
721}
722
723fn gcd(mut a: usize, mut b: usize) -> usize {
724 while b != 0 {
725 let t = b;
726 b = a % b;
727 a = t;
728 }
729 a
730}
731
732fn lcm(a: usize, b: usize) -> usize {
733 a / gcd(a, b) * b
734}
735
736#[derive(Debug, Clone)]
738pub struct Model {
739 pub encoder: Encoder,
740 pub quantizer: ResidualVectorQuantizer,
741 pub decoder: Decoder,
742 pub hop_length: usize,
743 pub config: Config,
744}
745
746impl Model {
747 pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
748 let encoder = Encoder::new(
749 cfg.encoder_dim,
750 &cfg.encoder_rates,
751 cfg.depthwise,
752 cfg.attn_window_size,
753 vb.pp("encoder"),
754 )?;
755 let latent_dim = cfg.encoder_dim * 2usize.pow(cfg.encoder_rates.len() as u32);
756 let quantizer = ResidualVectorQuantizer::new(
757 latent_dim,
758 cfg.codebook_size,
759 cfg.codebook_dim,
760 &cfg.vq_strides,
761 vb.pp("quantizer"),
762 )?;
763 let decoder = Decoder::new(
764 latent_dim,
765 cfg.decoder_dim,
766 &cfg.decoder_rates,
767 cfg.noise,
768 cfg.depthwise,
769 cfg.attn_window_size,
770 1,
771 vb.pp("decoder"),
772 )?;
773 let hop_length = cfg.encoder_rates.iter().product::<usize>();
774 Ok(Self {
775 encoder,
776 decoder,
777 quantizer,
778 config: cfg.clone(),
779 hop_length,
780 })
781 }
782
783 fn preprocess(&self, audio_data: &Tensor) -> Result<Tensor> {
784 let len = audio_data.dim(D::Minus1)?;
785 let lcm = lcm(
786 self.config.vq_strides[0],
787 self.config.attn_window_size.unwrap_or(1),
788 );
789 let pad_to = self.hop_length * lcm;
790 let right_pad = len.div_ceil(pad_to) * pad_to - len;
791 let audio_data = audio_data.pad_with_zeros(D::Minus1, 0, right_pad)?;
792 Ok(audio_data)
793 }
794
795 pub fn encode(&self, audio_data: &Tensor) -> Result<Vec<Tensor>> {
796 let audio_data = self.preprocess(audio_data)?;
797 let z = self.encoder.forward(&audio_data)?;
798 let (_, codes) = self.quantizer.encode(&z)?;
799 Ok(codes)
800 }
801
802 pub fn decode(&self, audio_codes: &[&Tensor]) -> Result<Tensor> {
803 let audio_values = self.quantizer.from_codes(audio_codes)?;
804 audio_values.apply(&self.decoder)
805 }
806
807 pub fn config(&self) -> &Config {
808 &self.config
809 }
810
811 pub fn num_codebooks(&self) -> usize {
812 self.quantizer.quantizers.len()
813 }
814}