chatterbox-light 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. chatterbox_light-1.0.1/LICENSE +21 -0
  2. chatterbox_light-1.0.1/PKG-INFO +141 -0
  3. chatterbox_light-1.0.1/README.md +109 -0
  4. chatterbox_light-1.0.1/pyproject.toml +48 -0
  5. chatterbox_light-1.0.1/setup.cfg +4 -0
  6. chatterbox_light-1.0.1/src/chatterbox/__init__.py +11 -0
  7. chatterbox_light-1.0.1/src/chatterbox/models/__init__.py +0 -0
  8. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/__init__.py +2 -0
  9. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/configs.py +10 -0
  10. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/const.py +2 -0
  11. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/decoder.py +292 -0
  12. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/f0_predictor.py +42 -0
  13. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/flow.py +163 -0
  14. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/flow_matching.py +140 -0
  15. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/hifigan.py +350 -0
  16. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/matcha/conformer_block.py +249 -0
  17. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/matcha/decoder.py +412 -0
  18. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/matcha/flow_matching.py +76 -0
  19. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/matcha/transformer.py +235 -0
  20. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/s3gen.py +293 -0
  21. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/__init__.py +0 -0
  22. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/activation.py +35 -0
  23. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/attention.py +153 -0
  24. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/convolution.py +97 -0
  25. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/embedding.py +170 -0
  26. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/encoder_layer.py +135 -0
  27. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/positionwise_feed_forward.py +56 -0
  28. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/subsampling.py +209 -0
  29. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/transformer/upsample_encoder.py +219 -0
  30. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/utils/class_utils.py +57 -0
  31. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/utils/intmeanflow.py +33 -0
  32. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/utils/mask.py +75 -0
  33. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/utils/mel.py +76 -0
  34. chatterbox_light-1.0.1/src/chatterbox/models/s3gen/xvector.py +399 -0
  35. chatterbox_light-1.0.1/src/chatterbox/models/s3tokenizer/__init__.py +30 -0
  36. chatterbox_light-1.0.1/src/chatterbox/models/s3tokenizer/s3tokenizer.py +140 -0
  37. chatterbox_light-1.0.1/src/chatterbox/models/t3/__init__.py +1 -0
  38. chatterbox_light-1.0.1/src/chatterbox/models/t3/inference/t3_hf_backend.py +86 -0
  39. chatterbox_light-1.0.1/src/chatterbox/models/t3/llama_configs.py +106 -0
  40. chatterbox_light-1.0.1/src/chatterbox/models/t3/modules/cond_enc.py +80 -0
  41. chatterbox_light-1.0.1/src/chatterbox/models/t3/modules/learned_pos_emb.py +22 -0
  42. chatterbox_light-1.0.1/src/chatterbox/models/t3/modules/perceiver.py +169 -0
  43. chatterbox_light-1.0.1/src/chatterbox/models/t3/modules/t3_config.py +39 -0
  44. chatterbox_light-1.0.1/src/chatterbox/models/t3/t3.py +468 -0
  45. chatterbox_light-1.0.1/src/chatterbox/models/tokenizers/__init__.py +1 -0
  46. chatterbox_light-1.0.1/src/chatterbox/models/tokenizers/tokenizer.py +286 -0
  47. chatterbox_light-1.0.1/src/chatterbox/models/utils.py +4 -0
  48. chatterbox_light-1.0.1/src/chatterbox/models/voice_encoder/__init__.py +1 -0
  49. chatterbox_light-1.0.1/src/chatterbox/models/voice_encoder/config.py +18 -0
  50. chatterbox_light-1.0.1/src/chatterbox/models/voice_encoder/melspec.py +84 -0
  51. chatterbox_light-1.0.1/src/chatterbox/models/voice_encoder/voice_encoder.py +222 -0
  52. chatterbox_light-1.0.1/src/chatterbox/mtl_tts.py +331 -0
  53. chatterbox_light-1.0.1/src/chatterbox/tts.py +252 -0
  54. chatterbox_light-1.0.1/src/chatterbox/tts_turbo.py +283 -0
  55. chatterbox_light-1.0.1/src/chatterbox/vc.py +111 -0
  56. chatterbox_light-1.0.1/src/chatterbox_light.egg-info/PKG-INFO +141 -0
  57. chatterbox_light-1.0.1/src/chatterbox_light.egg-info/SOURCES.txt +58 -0
  58. chatterbox_light-1.0.1/src/chatterbox_light.egg-info/dependency_links.txt +1 -0
  59. chatterbox_light-1.0.1/src/chatterbox_light.egg-info/requires.txt +18 -0
  60. chatterbox_light-1.0.1/src/chatterbox_light.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Resemble AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: chatterbox-light
3
+ Version: 1.0.1
4
+ Summary: Lightweight fork of Resemble AI's Chatterbox text-to-speech and voice conversion, with fewer dependencies and no watermarking
5
+ Author: Resemble AI
6
+ Maintainer: Blair Chintella
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/BBC-Esq/chatterbox-light
9
+ Project-URL: Repository, https://github.com/BBC-Esq/chatterbox-light
10
+ Project-URL: Upstream, https://github.com/resemble-ai/chatterbox
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: numpy
15
+ Requires-Dist: torch
16
+ Requires-Dist: torchaudio
17
+ Requires-Dist: transformers>=4.46.0
18
+ Requires-Dist: diffusers
19
+ Requires-Dist: safetensors
20
+ Requires-Dist: s3tokenizer
21
+ Requires-Dist: einops
22
+ Requires-Dist: scipy
23
+ Requires-Dist: pyloudnorm
24
+ Requires-Dist: soundfile
25
+ Requires-Dist: tokenizers
26
+ Requires-Dist: tqdm
27
+ Requires-Dist: huggingface-hub
28
+ Provides-Extra: multilingual
29
+ Requires-Dist: pykakasi; extra == "multilingual"
30
+ Requires-Dist: spacy-pkuseg; extra == "multilingual"
31
+ Dynamic: license-file
32
+
33
+ ## This is a light version of chatterbox that removes:
34
+ * ```librosa``` and all its required dependencies and instead uses ```torchaudio``` and ```scipy```
35
+ * ```perth``` because who the heck needs watermarking anyways
36
+ * ```omegaconf``` and instead use standard python
37
+ * others I forget, but everything works
38
+
39
+ However, I did add ```soundfile``` because I like it.
40
+
41
+ # Installation
42
+ >Go through these steps in order.
43
+ ```
44
+ python -m venv .
45
+ ```
46
+
47
+ ```
48
+ .\Scripts\activate
49
+ ```
50
+
51
+ ```
52
+ python.exe -m pip install --upgrade pip
53
+ ```
54
+
55
+ ```
56
+ pip install uv
57
+ ```
58
+
59
+ Next, make sure appropriate versions of torch, torchaudio, and CUDA are installed.
60
+
61
+ ```
62
+ uv pip install chatterbox-light
63
+ ```
64
+
65
+ To install the latest code from GitHub instead:
66
+ ```
67
+ uv pip install -r requirements.txt
68
+ ```
69
+
70
+ ```
71
+ pip install git+https://github.com/BBC-Esq/chatterbox-light.git --no-deps
72
+ ```
73
+
74
+ This package installs the `chatterbox` module, just like Resemble AI's `chatterbox-tts`, so don't install both in one environment. Installs of this fork made from GitHub before version 1.0.1 are also named `chatterbox-tts`; run `pip uninstall chatterbox-tts` before installing this.
75
+
76
+ Optional: if you'll use the multilingual model with Japanese or Chinese text, also install these (or install `"chatterbox-light[multilingual]"`). Without them, Japanese kanji are dropped and Chinese text isn't split into words. The first time Chinese text is used, spacy-pkuseg downloads a ~35 MB model to `~/.pkuseg`.
77
+ ```
78
+ uv pip install pykakasi spacy-pkuseg
79
+ ```
80
+
81
+ # Usage
82
+ Each model's `generate()` returns a `(1, samples)` tensor at `model.sr` (24 kHz). Models download from Hugging Face the first time they're used. Save the audio with `soundfile`:
83
+ ```python
84
+ import soundfile as sf
85
+ sf.write("output.wav", wav.squeeze(0).numpy(), model.sr)
86
+ ```
87
+
88
+ ### Chatterbox (English)
89
+ ```python
90
+ from chatterbox.tts import ChatterboxTTS
91
+
92
+ model = ChatterboxTTS.from_pretrained(device="cuda") # or "cpu" / "mps"
93
+ wav = model.generate("Hello there, this is Chatterbox.")
94
+
95
+ # clone a voice from a reference clip
96
+ wav = model.generate("Hello there, this is Chatterbox.", audio_prompt_path="reference.wav")
97
+
98
+ # more expressive: raise exaggeration (default 0.5) and lower cfg_weight (default 0.5) for slower pacing
99
+ wav = model.generate("Hello there, this is Chatterbox.", exaggeration=0.7, cfg_weight=0.3)
100
+ ```
101
+
102
+ ### Chatterbox Turbo (English)
103
+ Faster, and understands paralinguistic tags such as `[laugh]`, `[chuckle]` and `[cough]`. A reference clip must be longer than 5 seconds. `cfg_weight`, `exaggeration` and `min_p` are ignored.
104
+ ```python
105
+ from chatterbox.tts_turbo import ChatterboxTurboTTS
106
+
107
+ model = ChatterboxTurboTTS.from_pretrained(device="cuda")
108
+ wav = model.generate("Hi there [chuckle], have you got a minute to chat?", audio_prompt_path="reference.wav")
109
+ ```
110
+
111
+ ### Chatterbox Nano (English)
112
+ A smaller version of Turbo for CPU and tight memory budgets, loaded through the same class with `nano=True`:
113
+ ```python
114
+ from chatterbox.tts_turbo import ChatterboxTurboTTS
115
+
116
+ model = ChatterboxTurboTTS.from_pretrained(device="cpu", nano=True)
117
+ wav = model.generate("Hi there [chuckle], have you got a minute to chat?")
118
+ ```
119
+
120
+ ### Chatterbox Multilingual (23 languages)
121
+ The v2 checkpoint loads by default. Pass `t3_model="v3"` for the newer v3 checkpoint, which upstream recommends (fewer hallucinations, better speaker similarity). For Japanese or Chinese text, install the optional packages above.
122
+ ```python
123
+ from chatterbox.mtl_tts import ChatterboxMultilingualTTS, SUPPORTED_LANGUAGES
124
+
125
+ print(SUPPORTED_LANGUAGES) # language codes such as "fr", "de", "ja", "zh"
126
+ model = ChatterboxMultilingualTTS.from_pretrained(device="cuda", t3_model="v3")
127
+ wav = model.generate("Bonjour, comment ça va ?", language_id="fr")
128
+ wav = model.generate("Hola, ¿cómo estás?", language_id="es", audio_prompt_path="reference.wav")
129
+ ```
130
+
131
+ ### Voice conversion
132
+ ```python
133
+ from chatterbox.vc import ChatterboxVC
134
+
135
+ model = ChatterboxVC.from_pretrained(device="cuda")
136
+ wav = model.generate("input.wav", target_voice_path="target_voice.wav")
137
+ ```
138
+
139
+ See the `example_*.py` scripts for complete runs.
140
+
141
+ Enjoy!
@@ -0,0 +1,109 @@
1
+ ## This is a light version of chatterbox that removes:
2
+ * ```librosa``` and all its required dependencies and instead uses ```torchaudio``` and ```scipy```
3
+ * ```perth``` because who the heck needs watermarking anyways
4
+ * ```omegaconf``` and instead use standard python
5
+ * others I forget, but everything works
6
+
7
+ However, I did add ```soundfile``` because I like it.
8
+
9
+ # Installation
10
+ >Go through these steps in order.
11
+ ```
12
+ python -m venv .
13
+ ```
14
+
15
+ ```
16
+ .\Scripts\activate
17
+ ```
18
+
19
+ ```
20
+ python.exe -m pip install --upgrade pip
21
+ ```
22
+
23
+ ```
24
+ pip install uv
25
+ ```
26
+
27
+ Next, make sure appropriate versions of torch, torchaudio, and CUDA are installed.
28
+
29
+ ```
30
+ uv pip install chatterbox-light
31
+ ```
32
+
33
+ To install the latest code from GitHub instead:
34
+ ```
35
+ uv pip install -r requirements.txt
36
+ ```
37
+
38
+ ```
39
+ pip install git+https://github.com/BBC-Esq/chatterbox-light.git --no-deps
40
+ ```
41
+
42
+ This package installs the `chatterbox` module, just like Resemble AI's `chatterbox-tts`, so don't install both in one environment. Installs of this fork made from GitHub before version 1.0.1 are also named `chatterbox-tts`; run `pip uninstall chatterbox-tts` before installing this.
43
+
44
+ Optional: if you'll use the multilingual model with Japanese or Chinese text, also install these (or install `"chatterbox-light[multilingual]"`). Without them, Japanese kanji are dropped and Chinese text isn't split into words. The first time Chinese text is used, spacy-pkuseg downloads a ~35 MB model to `~/.pkuseg`.
45
+ ```
46
+ uv pip install pykakasi spacy-pkuseg
47
+ ```
48
+
49
+ # Usage
50
+ Each model's `generate()` returns a `(1, samples)` tensor at `model.sr` (24 kHz). Models download from Hugging Face the first time they're used. Save the audio with `soundfile`:
51
+ ```python
52
+ import soundfile as sf
53
+ sf.write("output.wav", wav.squeeze(0).numpy(), model.sr)
54
+ ```
55
+
56
+ ### Chatterbox (English)
57
+ ```python
58
+ from chatterbox.tts import ChatterboxTTS
59
+
60
+ model = ChatterboxTTS.from_pretrained(device="cuda") # or "cpu" / "mps"
61
+ wav = model.generate("Hello there, this is Chatterbox.")
62
+
63
+ # clone a voice from a reference clip
64
+ wav = model.generate("Hello there, this is Chatterbox.", audio_prompt_path="reference.wav")
65
+
66
+ # more expressive: raise exaggeration (default 0.5) and lower cfg_weight (default 0.5) for slower pacing
67
+ wav = model.generate("Hello there, this is Chatterbox.", exaggeration=0.7, cfg_weight=0.3)
68
+ ```
69
+
70
+ ### Chatterbox Turbo (English)
71
+ Faster, and understands paralinguistic tags such as `[laugh]`, `[chuckle]` and `[cough]`. A reference clip must be longer than 5 seconds. `cfg_weight`, `exaggeration` and `min_p` are ignored.
72
+ ```python
73
+ from chatterbox.tts_turbo import ChatterboxTurboTTS
74
+
75
+ model = ChatterboxTurboTTS.from_pretrained(device="cuda")
76
+ wav = model.generate("Hi there [chuckle], have you got a minute to chat?", audio_prompt_path="reference.wav")
77
+ ```
78
+
79
+ ### Chatterbox Nano (English)
80
+ A smaller version of Turbo for CPU and tight memory budgets, loaded through the same class with `nano=True`:
81
+ ```python
82
+ from chatterbox.tts_turbo import ChatterboxTurboTTS
83
+
84
+ model = ChatterboxTurboTTS.from_pretrained(device="cpu", nano=True)
85
+ wav = model.generate("Hi there [chuckle], have you got a minute to chat?")
86
+ ```
87
+
88
+ ### Chatterbox Multilingual (23 languages)
89
+ The v2 checkpoint loads by default. Pass `t3_model="v3"` for the newer v3 checkpoint, which upstream recommends (fewer hallucinations, better speaker similarity). For Japanese or Chinese text, install the optional packages above.
90
+ ```python
91
+ from chatterbox.mtl_tts import ChatterboxMultilingualTTS, SUPPORTED_LANGUAGES
92
+
93
+ print(SUPPORTED_LANGUAGES) # language codes such as "fr", "de", "ja", "zh"
94
+ model = ChatterboxMultilingualTTS.from_pretrained(device="cuda", t3_model="v3")
95
+ wav = model.generate("Bonjour, comment ça va ?", language_id="fr")
96
+ wav = model.generate("Hola, ¿cómo estás?", language_id="es", audio_prompt_path="reference.wav")
97
+ ```
98
+
99
+ ### Voice conversion
100
+ ```python
101
+ from chatterbox.vc import ChatterboxVC
102
+
103
+ model = ChatterboxVC.from_pretrained(device="cuda")
104
+ wav = model.generate("input.wav", target_voice_path="target_voice.wav")
105
+ ```
106
+
107
+ See the `example_*.py` scripts for complete runs.
108
+
109
+ Enjoy!
@@ -0,0 +1,48 @@
1
+ [project]
2
+ name = "chatterbox-light"
3
+ version = "1.0.1"
4
+ description = "Lightweight fork of Resemble AI's Chatterbox text-to-speech and voice conversion, with fewer dependencies and no watermarking"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [
10
+ {name = "Resemble AI"},
11
+ ]
12
+ maintainers = [
13
+ {name = "Blair Chintella"},
14
+ ]
15
+ dependencies = [
16
+ "numpy",
17
+ "torch",
18
+ "torchaudio",
19
+ "transformers>=4.46.0",
20
+ "diffusers",
21
+ "safetensors",
22
+ "s3tokenizer",
23
+ "einops",
24
+ "scipy",
25
+ "pyloudnorm",
26
+ "soundfile",
27
+ "tokenizers",
28
+ "tqdm",
29
+ "huggingface-hub",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ multilingual = [
34
+ "pykakasi",
35
+ "spacy-pkuseg",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/BBC-Esq/chatterbox-light"
40
+ Repository = "https://github.com/BBC-Esq/chatterbox-light"
41
+ Upstream = "https://github.com/resemble-ai/chatterbox"
42
+
43
+ [build-system]
44
+ requires = ["setuptools>=77.0.0"]
45
+ build-backend = "setuptools.build_meta"
46
+
47
+ [tool.setuptools.packages.find]
48
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,11 @@
1
+ try:
2
+ from importlib.metadata import version
3
+ except ImportError:
4
+ from importlib_metadata import version # For Python <3.8
5
+
6
+ __version__ = version("chatterbox-light")
7
+
8
+
9
+ from .tts import ChatterboxTTS
10
+ from .vc import ChatterboxVC
11
+ from .mtl_tts import ChatterboxMultilingualTTS, SUPPORTED_LANGUAGES
@@ -0,0 +1,2 @@
1
+ from .s3gen import S3Token2Wav as S3Gen
2
+ from .const import S3GEN_SR
@@ -0,0 +1,10 @@
1
+ from ..utils import AttrDict
2
+
3
+ CFM_PARAMS = AttrDict({
4
+ "sigma_min": 1e-06,
5
+ "solver": "euler",
6
+ "t_scheduler": "cosine",
7
+ "training_cfg_rate": 0.2,
8
+ "inference_cfg_rate": 0.7,
9
+ "reg_loss_type": "l1"
10
+ })
@@ -0,0 +1,2 @@
1
+ S3GEN_SR = 24000
2
+ S3GEN_SIL = 4299
@@ -0,0 +1,292 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ from einops import pack, rearrange, repeat
5
+
6
+ from .utils.mask import add_optional_chunk_mask
7
+ from .matcha.decoder import SinusoidalPosEmb, Block1D, ResnetBlock1D, Downsample1D, \
8
+ TimestepEmbedding, Upsample1D
9
+ from .matcha.transformer import BasicTransformerBlock
10
+ from .utils.intmeanflow import get_intmeanflow_time_mixer
11
+
12
+
13
+ def mask_to_bias(mask: torch.Tensor, dtype: torch.dtype) -> torch.Tensor:
14
+ assert mask.dtype == torch.bool
15
+ assert dtype in [torch.float32, torch.bfloat16, torch.float16]
16
+ mask = mask.to(dtype)
17
+ mask = (1.0 - mask) * -1.0e+10
18
+ return mask
19
+
20
+
21
+
22
+ class Transpose(torch.nn.Module):
23
+ def __init__(self, dim0: int, dim1: int):
24
+ super().__init__()
25
+ self.dim0 = dim0
26
+ self.dim1 = dim1
27
+
28
+ def forward(self, x: torch.Tensor):
29
+ x = torch.transpose(x, self.dim0, self.dim1)
30
+ return x
31
+
32
+
33
+ class CausalBlock1D(Block1D):
34
+ def __init__(self, dim: int, dim_out: int):
35
+ super(CausalBlock1D, self).__init__(dim, dim_out)
36
+ self.block = torch.nn.Sequential(
37
+ CausalConv1d(dim, dim_out, 3),
38
+ Transpose(1, 2),
39
+ nn.LayerNorm(dim_out),
40
+ Transpose(1, 2),
41
+ nn.Mish(),
42
+ )
43
+
44
+ def forward(self, x: torch.Tensor, mask: torch.Tensor):
45
+ output = self.block(x * mask)
46
+ return output * mask
47
+
48
+
49
+ class CausalResnetBlock1D(ResnetBlock1D):
50
+ def __init__(self, dim: int, dim_out: int, time_emb_dim: int, groups: int = 8):
51
+ super(CausalResnetBlock1D, self).__init__(dim, dim_out, time_emb_dim, groups)
52
+ self.block1 = CausalBlock1D(dim, dim_out)
53
+ self.block2 = CausalBlock1D(dim_out, dim_out)
54
+
55
+
56
+ class CausalConv1d(torch.nn.Conv1d):
57
+ def __init__(
58
+ self,
59
+ in_channels: int,
60
+ out_channels: int,
61
+ kernel_size: int,
62
+ stride: int = 1,
63
+ dilation: int = 1,
64
+ groups: int = 1,
65
+ bias: bool = True,
66
+ padding_mode: str = 'zeros',
67
+ device=None,
68
+ dtype=None
69
+ ) -> None:
70
+ super(CausalConv1d, self).__init__(in_channels, out_channels,
71
+ kernel_size, stride,
72
+ padding=0, dilation=dilation,
73
+ groups=groups, bias=bias,
74
+ padding_mode=padding_mode,
75
+ device=device, dtype=dtype)
76
+ assert stride == 1
77
+ self.causal_padding = (kernel_size - 1, 0)
78
+
79
+ def forward(self, x: torch.Tensor):
80
+ x = F.pad(x, self.causal_padding)
81
+ x = super(CausalConv1d, self).forward(x)
82
+ return x
83
+ class ConditionalDecoder(nn.Module):
84
+ def __init__(
85
+ self,
86
+ in_channels=320,
87
+ out_channels=80,
88
+ causal=True,
89
+ channels=[256],
90
+ dropout=0.0,
91
+ attention_head_dim=64,
92
+ n_blocks=4,
93
+ num_mid_blocks=12,
94
+ num_heads=8,
95
+ act_fn="gelu",
96
+ meanflow=False,
97
+ ):
98
+ super().__init__()
99
+ channels = tuple(channels)
100
+ self.meanflow = meanflow
101
+ self.in_channels = in_channels
102
+ self.out_channels = out_channels
103
+ self.causal = causal
104
+ self.time_embeddings = SinusoidalPosEmb(in_channels)
105
+ time_embed_dim = channels[0] * 4
106
+ self.time_mlp = TimestepEmbedding(
107
+ in_channels=in_channels,
108
+ time_embed_dim=time_embed_dim,
109
+ act_fn="silu",
110
+ )
111
+
112
+ self.down_blocks = nn.ModuleList([])
113
+ self.mid_blocks = nn.ModuleList([])
114
+ self.up_blocks = nn.ModuleList([])
115
+
116
+ self.static_chunk_size = 0
117
+
118
+ output_channel = in_channels
119
+ for i in range(len(channels)):
120
+ input_channel = output_channel
121
+ output_channel = channels[i]
122
+ is_last = i == len(channels) - 1
123
+ resnet = CausalResnetBlock1D(dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim) if self.causal else \
124
+ ResnetBlock1D(dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim)
125
+ transformer_blocks = nn.ModuleList(
126
+ [
127
+ BasicTransformerBlock(
128
+ dim=output_channel,
129
+ num_attention_heads=num_heads,
130
+ attention_head_dim=attention_head_dim,
131
+ dropout=dropout,
132
+ activation_fn=act_fn,
133
+ )
134
+ for _ in range(n_blocks)
135
+ ]
136
+ )
137
+ downsample = (
138
+ Downsample1D(output_channel) if not is_last else
139
+ CausalConv1d(output_channel, output_channel, 3) if self.causal else nn.Conv1d(output_channel, output_channel, 3, padding=1)
140
+ )
141
+ self.down_blocks.append(nn.ModuleList([resnet, transformer_blocks, downsample]))
142
+
143
+ for _ in range(num_mid_blocks):
144
+ input_channel = channels[-1]
145
+ out_channels = channels[-1]
146
+ resnet = CausalResnetBlock1D(dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim) if self.causal else \
147
+ ResnetBlock1D(dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim)
148
+
149
+ transformer_blocks = nn.ModuleList(
150
+ [
151
+ BasicTransformerBlock(
152
+ dim=output_channel,
153
+ num_attention_heads=num_heads,
154
+ attention_head_dim=attention_head_dim,
155
+ dropout=dropout,
156
+ activation_fn=act_fn,
157
+ )
158
+ for _ in range(n_blocks)
159
+ ]
160
+ )
161
+
162
+ self.mid_blocks.append(nn.ModuleList([resnet, transformer_blocks]))
163
+
164
+ channels = channels[::-1] + (channels[0],)
165
+ for i in range(len(channels) - 1):
166
+ input_channel = channels[i] * 2
167
+ output_channel = channels[i + 1]
168
+ is_last = i == len(channels) - 2
169
+ resnet = CausalResnetBlock1D(
170
+ dim=input_channel,
171
+ dim_out=output_channel,
172
+ time_emb_dim=time_embed_dim,
173
+ ) if self.causal else ResnetBlock1D(
174
+ dim=input_channel,
175
+ dim_out=output_channel,
176
+ time_emb_dim=time_embed_dim,
177
+ )
178
+ transformer_blocks = nn.ModuleList(
179
+ [
180
+ BasicTransformerBlock(
181
+ dim=output_channel,
182
+ num_attention_heads=num_heads,
183
+ attention_head_dim=attention_head_dim,
184
+ dropout=dropout,
185
+ activation_fn=act_fn,
186
+ )
187
+ for _ in range(n_blocks)
188
+ ]
189
+ )
190
+ upsample = (
191
+ Upsample1D(output_channel, use_conv_transpose=True)
192
+ if not is_last
193
+ else CausalConv1d(output_channel, output_channel, 3) if self.causal else nn.Conv1d(output_channel, output_channel, 3, padding=1)
194
+ )
195
+ self.up_blocks.append(nn.ModuleList([resnet, transformer_blocks, upsample]))
196
+ self.final_block = CausalBlock1D(channels[-1], channels[-1]) if self.causal else Block1D(channels[-1], channels[-1])
197
+ self.final_proj = nn.Conv1d(channels[-1], self.out_channels, 1)
198
+ self.initialize_weights()
199
+ self.time_embed_mixer = None
200
+ if self.meanflow:
201
+ self.time_embed_mixer = get_intmeanflow_time_mixer(time_embed_dim)
202
+
203
+
204
+ @property
205
+ def dtype(self):
206
+ return self.final_proj.weight.dtype
207
+
208
+ def initialize_weights(self):
209
+ for m in self.modules():
210
+ if isinstance(m, nn.Conv1d):
211
+ nn.init.kaiming_normal_(m.weight, nonlinearity="relu")
212
+ if m.bias is not None:
213
+ nn.init.constant_(m.bias, 0)
214
+ elif isinstance(m, nn.GroupNorm):
215
+ nn.init.constant_(m.weight, 1)
216
+ nn.init.constant_(m.bias, 0)
217
+ elif isinstance(m, nn.Linear):
218
+ nn.init.kaiming_normal_(m.weight, nonlinearity="relu")
219
+ if m.bias is not None:
220
+ nn.init.constant_(m.bias, 0)
221
+
222
+ def forward(self, x, mask, mu, t, spks=None, cond=None, r=None):
223
+ t = self.time_embeddings(t).to(t.dtype)
224
+ t = self.time_mlp(t)
225
+
226
+ if self.meanflow:
227
+ r = self.time_embeddings(r).to(t.dtype)
228
+ r = self.time_mlp(r)
229
+ concat_embed = torch.cat([t, r], dim=1)
230
+ t = self.time_embed_mixer(concat_embed)
231
+
232
+ x = pack([x, mu], "b * t")[0]
233
+
234
+ if spks is not None:
235
+ spks = repeat(spks, "b c -> b c t", t=x.shape[-1])
236
+ x = pack([x, spks], "b * t")[0]
237
+ if cond is not None:
238
+ x = pack([x, cond], "b * t")[0]
239
+
240
+ hiddens = []
241
+ masks = [mask]
242
+ for resnet, transformer_blocks, downsample in self.down_blocks:
243
+ mask_down = masks[-1]
244
+ x = resnet(x, mask_down, t)
245
+ x = rearrange(x, "b c t -> b t c").contiguous()
246
+ attn_mask = add_optional_chunk_mask(x, mask_down.bool(), False, False, 0, self.static_chunk_size, -1)
247
+ attn_mask = mask_to_bias(attn_mask == 1, x.dtype)
248
+ for transformer_block in transformer_blocks:
249
+ x = transformer_block(
250
+ hidden_states=x,
251
+ attention_mask=attn_mask,
252
+ timestep=t,
253
+ )
254
+ x = rearrange(x, "b t c -> b c t").contiguous()
255
+ hiddens.append(x)
256
+ x = downsample(x * mask_down)
257
+ masks.append(mask_down[:, :, ::2])
258
+ masks = masks[:-1]
259
+ mask_mid = masks[-1]
260
+
261
+ for resnet, transformer_blocks in self.mid_blocks:
262
+ x = resnet(x, mask_mid, t)
263
+ x = rearrange(x, "b c t -> b t c").contiguous()
264
+ attn_mask = add_optional_chunk_mask(x, mask_mid.bool(), False, False, 0, self.static_chunk_size, -1)
265
+ attn_mask = mask_to_bias(attn_mask == 1, x.dtype)
266
+ for transformer_block in transformer_blocks:
267
+ x = transformer_block(
268
+ hidden_states=x,
269
+ attention_mask=attn_mask,
270
+ timestep=t,
271
+ )
272
+ x = rearrange(x, "b t c -> b c t").contiguous()
273
+
274
+ for resnet, transformer_blocks, upsample in self.up_blocks:
275
+ mask_up = masks.pop()
276
+ skip = hiddens.pop()
277
+ x = pack([x[:, :, :skip.shape[-1]], skip], "b * t")[0]
278
+ x = resnet(x, mask_up, t)
279
+ x = rearrange(x, "b c t -> b t c").contiguous()
280
+ attn_mask = add_optional_chunk_mask(x, mask_up.bool(), False, False, 0, self.static_chunk_size, -1)
281
+ attn_mask = mask_to_bias(attn_mask == 1, x.dtype)
282
+ for transformer_block in transformer_blocks:
283
+ x = transformer_block(
284
+ hidden_states=x,
285
+ attention_mask=attn_mask,
286
+ timestep=t,
287
+ )
288
+ x = rearrange(x, "b t c -> b c t").contiguous()
289
+ x = upsample(x * mask_up)
290
+ x = self.final_block(x, mask_up)
291
+ output = self.final_proj(x * mask_up)
292
+ return output * mask