drbaph commited on
Commit
7ce841b
·
verified ·
1 Parent(s): 8f1a8d3

Upload 14 files

Browse files
dac_44khz/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
dac_44khz/README.md ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ pipeline_tag: feature-extraction
4
+ ---
5
+
6
+ # Model Card for Model ID
7
+
8
+ <!-- Provide a quick summary of what the model is/does. -->
9
+
10
+
11
+
12
+ ## Model Details
13
+
14
+ ### Model Description
15
+
16
+ <!-- Provide a longer summary of what this model is. -->
17
+
18
+ This is the model card of a 🤗 transformers model that has been pushed on the Hub. This model card has been automatically generated.
19
+
20
+ - **Developed by:** [More Information Needed]
21
+ - **Funded by [optional]:** [More Information Needed]
22
+ - **Shared by [optional]:** [More Information Needed]
23
+ - **Model type:** [More Information Needed]
24
+ - **Language(s) (NLP):** [More Information Needed]
25
+ - **License:** [More Information Needed]
26
+ - **Finetuned from model [optional]:** [More Information Needed]
27
+
28
+ ### Model Sources [optional]
29
+
30
+ <!-- Provide the basic links for the model. -->
31
+
32
+ - **Repository:** [More Information Needed]
33
+ - **Paper [optional]:** [More Information Needed]
34
+ - **Demo [optional]:** [More Information Needed]
35
+
36
+ ## Uses
37
+
38
+ <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
39
+
40
+ ### Direct Use
41
+
42
+ <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
43
+
44
+ [More Information Needed]
45
+
46
+ ### Downstream Use [optional]
47
+
48
+ <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
49
+
50
+ [More Information Needed]
51
+
52
+ ### Out-of-Scope Use
53
+
54
+ <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
55
+
56
+ [More Information Needed]
57
+
58
+ ## Bias, Risks, and Limitations
59
+
60
+ <!-- This section is meant to convey both technical and sociotechnical limitations. -->
61
+
62
+ [More Information Needed]
63
+
64
+ ### Recommendations
65
+
66
+ <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
67
+
68
+ Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
69
+
70
+ ## How to Get Started with the Model
71
+
72
+ Use the code below to get started with the model.
73
+
74
+ [More Information Needed]
75
+
76
+ ## Training Details
77
+
78
+ ### Training Data
79
+
80
+ <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
81
+
82
+ [More Information Needed]
83
+
84
+ ### Training Procedure
85
+
86
+ <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
87
+
88
+ #### Preprocessing [optional]
89
+
90
+ [More Information Needed]
91
+
92
+
93
+ #### Training Hyperparameters
94
+
95
+ - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
96
+
97
+ #### Speeds, Sizes, Times [optional]
98
+
99
+ <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
100
+
101
+ [More Information Needed]
102
+
103
+ ## Evaluation
104
+
105
+ <!-- This section describes the evaluation protocols and provides the results. -->
106
+
107
+ ### Testing Data, Factors & Metrics
108
+
109
+ #### Testing Data
110
+
111
+ <!-- This should link to a Dataset Card if possible. -->
112
+
113
+ [More Information Needed]
114
+
115
+ #### Factors
116
+
117
+ <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
118
+
119
+ [More Information Needed]
120
+
121
+ #### Metrics
122
+
123
+ <!-- These are the evaluation metrics being used, ideally with a description of why. -->
124
+
125
+ [More Information Needed]
126
+
127
+ ### Results
128
+
129
+ [More Information Needed]
130
+
131
+ #### Summary
132
+
133
+
134
+
135
+ ## Model Examination [optional]
136
+
137
+ <!-- Relevant interpretability work for the model goes here -->
138
+
139
+ [More Information Needed]
140
+
141
+ ## Environmental Impact
142
+
143
+ <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
144
+
145
+ Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
146
+
147
+ - **Hardware Type:** [More Information Needed]
148
+ - **Hours used:** [More Information Needed]
149
+ - **Cloud Provider:** [More Information Needed]
150
+ - **Compute Region:** [More Information Needed]
151
+ - **Carbon Emitted:** [More Information Needed]
152
+
153
+ ## Technical Specifications [optional]
154
+
155
+ ### Model Architecture and Objective
156
+
157
+ [More Information Needed]
158
+
159
+ ### Compute Infrastructure
160
+
161
+ [More Information Needed]
162
+
163
+ #### Hardware
164
+
165
+ [More Information Needed]
166
+
167
+ #### Software
168
+
169
+ [More Information Needed]
170
+
171
+ ## Citation [optional]
172
+
173
+ <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
174
+
175
+ **BibTeX:**
176
+
177
+ [More Information Needed]
178
+
179
+ **APA:**
180
+
181
+ [More Information Needed]
182
+
183
+ ## Glossary [optional]
184
+
185
+ <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
186
+
187
+ [More Information Needed]
188
+
189
+ ## More Information [optional]
190
+
191
+ [More Information Needed]
192
+
193
+ ## Model Card Authors [optional]
194
+
195
+ [More Information Needed]
196
+
197
+ ## Model Card Contact
198
+
199
+ [More Information Needed]
dac_44khz/config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DacModel"
4
+ ],
5
+ "codebook_dim": 8,
6
+ "codebook_loss_weight": 1.0,
7
+ "codebook_size": 1024,
8
+ "commitment_loss_weight": 0.25,
9
+ "decoder_hidden_size": 1536,
10
+ "downsampling_ratios": [
11
+ 2,
12
+ 4,
13
+ 8,
14
+ 8
15
+ ],
16
+ "encoder_hidden_size": 64,
17
+ "hidden_size": 1024,
18
+ "hop_length": 512,
19
+ "model_type": "dac",
20
+ "n_codebooks": 9,
21
+ "quantizer_dropout": 0.0,
22
+ "sampling_rate": 44100,
23
+ "torch_dtype": "float32",
24
+ "transformers_version": "4.42.0.dev0",
25
+ "upsampling_ratios": [
26
+ 8,
27
+ 8,
28
+ 4,
29
+ 2
30
+ ]
31
+ }
dac_44khz/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6128ebff483a41422b0164d079a3773b0d8d82e64c4293d775994cbf8baf913a
3
+ size 306507276
dac_44khz/preprocessor_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "feature_extractor_type": "DacFeatureExtractor",
3
+ "feature_size": 1,
4
+ "hop_length": 512,
5
+ "padding_side": "right",
6
+ "padding_value": 0.0,
7
+ "return_attention_mask": true,
8
+ "sampling_rate": 44100
9
+ }
speaker_encoder/config.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "EcapaTdnnSpeakerEncoder"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_ecapa_tdnn.EcapaTdnnSpeakerEncoderConfig",
7
+ "AutoModel": "modeling_ecapa_tdnn.EcapaTdnnSpeakerEncoder",
8
+ "AutoModelForFeatureExtraction": "modeling_ecapa_tdnn.EcapaTdnnSpeakerEncoder",
9
+ "AutoFeatureExtractor": "feature_extraction_ecapa_tdnn.EcapaTdnnFeatureExtractor",
10
+ "AutoTokenizer": "tokenizer_ecapa_tdnn.EcapaTdnnDummyTokenizer"
11
+ },
12
+ "model_type": "ecapa_tdnn_speaker_encoder",
13
+ "mel_dim": 128,
14
+ "enc_dim": 2048,
15
+ "enc_channels": [
16
+ 512,
17
+ 512,
18
+ 512,
19
+ 512,
20
+ 1536
21
+ ],
22
+ "enc_kernel_sizes": [
23
+ 5,
24
+ 3,
25
+ 3,
26
+ 3,
27
+ 1
28
+ ],
29
+ "enc_dilations": [
30
+ 1,
31
+ 2,
32
+ 3,
33
+ 4,
34
+ 1
35
+ ],
36
+ "enc_attention_channels": 128,
37
+ "enc_res2net_scale": 8,
38
+ "enc_se_channels": 128,
39
+ "sample_rate": 24000,
40
+ "pipeline_tag": "feature-extraction",
41
+ "torch_dtype": "float32",
42
+ "feature_extractor_type": "EcapaTdnnFeatureExtractor"
43
+ }
speaker_encoder/configuration_ecapa_tdnn.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ECAPA-TDNN Speaker Encoder configuration.
2
+
3
+ Standalone configuration for the ECAPA-TDNN speaker encoder extracted from
4
+ Qwen3-TTS. Compatible with the HuggingFace transformers AutoModel API.
5
+ """
6
+
7
+ from transformers import PretrainedConfig
8
+
9
+
10
+ class EcapaTdnnSpeakerEncoderConfig(PretrainedConfig):
11
+ r"""
12
+ Configuration class for the ECAPA-TDNN speaker encoder.
13
+
14
+ This model produces fixed-dimensional speaker embeddings (x-vectors) from
15
+ log-mel spectrograms. The architecture follows the ECAPA-TDNN paper:
16
+ "Emphasized Channel Attention, Propagation and Aggregation in TDNN Based
17
+ Speaker Verification" (https://arxiv.org/abs/2005.07143).
18
+
19
+ Args:
20
+ mel_dim (`int`, *optional*, defaults to 128):
21
+ Number of mel-frequency bins in the input spectrogram.
22
+ enc_dim (`int`, *optional*, defaults to 1024):
23
+ Dimension of the output speaker embedding.
24
+ enc_channels (`list[int]`, *optional*, defaults to `[512, 512, 512, 512, 1536]`):
25
+ Output channels for each encoder layer. The first is the initial
26
+ TDNN layer, the middle ones are SE-Res2Net blocks, and the last is
27
+ the multi-layer feature aggregation layer.
28
+ enc_kernel_sizes (`list[int]`, *optional*, defaults to `[5, 3, 3, 3, 1]`):
29
+ Kernel sizes for each encoder layer.
30
+ enc_dilations (`list[int]`, *optional*, defaults to `[1, 2, 3, 4, 1]`):
31
+ Dilation rates for each encoder layer.
32
+ enc_attention_channels (`int`, *optional*, defaults to 128):
33
+ Number of attention channels in the attentive statistics pooling layer.
34
+ enc_res2net_scale (`int`, *optional*, defaults to 8):
35
+ Scale factor for the Res2Net blocks.
36
+ enc_se_channels (`int`, *optional*, defaults to 128):
37
+ Number of channels in the squeeze-excitation bottleneck.
38
+ sample_rate (`int`, *optional*, defaults to 24000):
39
+ Expected audio sample rate in Hz.
40
+ """
41
+
42
+ model_type = "ecapa_tdnn_speaker_encoder"
43
+
44
+ def __init__(
45
+ self,
46
+ mel_dim=128,
47
+ enc_dim=1024,
48
+ enc_channels=None,
49
+ enc_kernel_sizes=None,
50
+ enc_dilations=None,
51
+ enc_attention_channels=128,
52
+ enc_res2net_scale=8,
53
+ enc_se_channels=128,
54
+ sample_rate=24000,
55
+ **kwargs,
56
+ ):
57
+ super().__init__(**kwargs)
58
+ self.mel_dim = mel_dim
59
+ self.enc_dim = enc_dim
60
+ self.enc_channels = enc_channels if enc_channels is not None else [512, 512, 512, 512, 1536]
61
+ self.enc_kernel_sizes = enc_kernel_sizes if enc_kernel_sizes is not None else [5, 3, 3, 3, 1]
62
+ self.enc_dilations = enc_dilations if enc_dilations is not None else [1, 2, 3, 4, 1]
63
+ self.enc_attention_channels = enc_attention_channels
64
+ self.enc_res2net_scale = enc_res2net_scale
65
+ self.enc_se_channels = enc_se_channels
66
+ self.sample_rate = sample_rate
speaker_encoder/feature_extraction_ecapa_tdnn.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Feature extractor for the ECAPA-TDNN speaker encoder.
2
+
3
+ Converts raw audio waveforms into log-mel spectrograms suitable for the
4
+ ECAPA-TDNN speaker encoder model.
5
+ """
6
+
7
+ import numpy as np
8
+ import torch
9
+ from transformers.feature_extraction_utils import BatchFeature, FeatureExtractionMixin
10
+
11
+
12
+ class EcapaTdnnFeatureExtractor(FeatureExtractionMixin):
13
+ r"""
14
+ Feature extractor for ECAPA-TDNN speaker encoder models.
15
+
16
+ Converts raw audio waveforms to 128-bin log-mel spectrograms matching the
17
+ Qwen3-TTS preprocessing pipeline.
18
+
19
+ Args:
20
+ sample_rate (`int`, defaults to 24000):
21
+ Target sample rate in Hz. Audio will be resampled if needed.
22
+ n_fft (`int`, defaults to 1024):
23
+ FFT window size.
24
+ hop_length (`int`, defaults to 256):
25
+ Hop length between STFT frames.
26
+ n_mels (`int`, defaults to 128):
27
+ Number of mel-frequency bins.
28
+ fmin (`float`, defaults to 0):
29
+ Minimum frequency for mel filterbank.
30
+ fmax (`float`, defaults to 12000):
31
+ Maximum frequency for mel filterbank.
32
+ """
33
+
34
+ model_input_names = ["input_values"]
35
+
36
+ def __init__(
37
+ self,
38
+ sample_rate=24000,
39
+ n_fft=1024,
40
+ hop_length=256,
41
+ n_mels=128,
42
+ fmin=0,
43
+ fmax=12000,
44
+ **kwargs,
45
+ ):
46
+ super().__init__(**kwargs)
47
+ self.sample_rate = sample_rate
48
+ self.sampling_rate = sample_rate # alias for HF pipeline compatibility
49
+ self.n_fft = n_fft
50
+ self.hop_length = hop_length
51
+ self.n_mels = n_mels
52
+ self.fmin = fmin
53
+ self.fmax = fmax
54
+
55
+ def __call__(self, raw_speech, sampling_rate=None, return_tensors="pt", **kwargs):
56
+ """
57
+ Process raw audio waveform(s) into log-mel spectrogram features.
58
+
59
+ Args:
60
+ raw_speech (`np.ndarray`, `list[np.ndarray]`, or file path `str`):
61
+ Raw audio waveform(s) as float32 numpy array(s), or a file path.
62
+ sampling_rate (`int`, *optional*):
63
+ Sample rate of the input audio. Resampled to ``self.sample_rate``
64
+ if different.
65
+ return_tensors (`str`, defaults to ``"pt"``):
66
+ Return type — ``"pt"`` for PyTorch tensors.
67
+
68
+ Returns:
69
+ ``BatchFeature`` with ``input_values`` key containing the log-mel
70
+ spectrogram tensor of shape ``(batch, time, n_mels)``.
71
+ """
72
+ # Handle single input
73
+ if isinstance(raw_speech, str):
74
+ import librosa
75
+ raw_speech, sampling_rate = librosa.load(raw_speech, sr=None, mono=True)
76
+
77
+ if isinstance(raw_speech, np.ndarray) and raw_speech.ndim == 1:
78
+ raw_speech = [raw_speech]
79
+
80
+ features = []
81
+ for audio in raw_speech:
82
+ if isinstance(audio, str):
83
+ import librosa
84
+ audio, sampling_rate = librosa.load(audio, sr=None, mono=True)
85
+
86
+ mel = self._compute_mel(audio, sampling_rate or self.sample_rate)
87
+ features.append(mel)
88
+
89
+ # Pad to same length
90
+ max_len = max(f.shape[1] for f in features)
91
+ padded = []
92
+ for f in features:
93
+ if f.shape[1] < max_len:
94
+ f = torch.nn.functional.pad(f, (0, 0, 0, max_len - f.shape[1]))
95
+ padded.append(f)
96
+
97
+ input_values = torch.cat(padded, dim=0)
98
+ return BatchFeature({"input_values": input_values})
99
+
100
+ def _compute_mel(self, audio, sr):
101
+ """Compute 128-bin log-mel spectrogram matching Qwen3-TTS requirements."""
102
+ import librosa
103
+ from librosa.filters import mel as librosa_mel_fn
104
+
105
+ if isinstance(audio, torch.Tensor):
106
+ audio = audio.numpy()
107
+
108
+ if sr != self.sample_rate:
109
+ audio = librosa.resample(
110
+ audio.astype(np.float32), orig_sr=sr, target_sr=self.sample_rate
111
+ )
112
+
113
+ y = torch.from_numpy(audio).unsqueeze(0).float()
114
+ mel_basis = torch.from_numpy(
115
+ librosa_mel_fn(
116
+ sr=self.sample_rate,
117
+ n_fft=self.n_fft,
118
+ n_mels=self.n_mels,
119
+ fmin=self.fmin,
120
+ fmax=self.fmax,
121
+ )
122
+ ).float()
123
+
124
+ padding = (self.n_fft - self.hop_length) // 2
125
+ y = torch.nn.functional.pad(
126
+ y.unsqueeze(1), (padding, padding), mode="reflect"
127
+ ).squeeze(1)
128
+ hann = torch.hann_window(self.n_fft)
129
+ spec = torch.stft(
130
+ y,
131
+ self.n_fft,
132
+ hop_length=self.hop_length,
133
+ win_length=self.n_fft,
134
+ window=hann,
135
+ center=False,
136
+ return_complex=True,
137
+ )
138
+ spec = torch.abs(spec)
139
+ mel = torch.matmul(mel_basis, spec)
140
+ mel = torch.log(torch.clamp(mel, min=1e-5))
141
+ return mel.transpose(1, 2) # (1, time, n_mels)
speaker_encoder/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:df60a638e7f4a29331c0af2bd2984ee5b992fee9d5923c776f7e4bdc3dedea48
3
+ size 24010000
speaker_encoder/modeling_ecapa_tdnn.py ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ECAPA-TDNN Speaker Encoder model.
2
+
3
+ Standalone implementation of the ECAPA-TDNN speaker encoder extracted from
4
+ Qwen3-TTS. Produces fixed-dimensional x-vector speaker embeddings from
5
+ log-mel spectrogram input.
6
+
7
+ Architecture: ECAPA-TDNN (Emphasized Channel Attention, Propagation and
8
+ Aggregation in TDNN Based Speaker Verification)
9
+ Paper: https://arxiv.org/abs/2005.07143
10
+
11
+ This file is self-contained and depends only on torch and transformers.
12
+ """
13
+
14
+ import torch
15
+ from torch import nn
16
+ from torch.nn import functional as F
17
+ from transformers import PreTrainedModel
18
+ from transformers.modeling_outputs import BaseModelOutputWithNoAttention
19
+
20
+ from .configuration_ecapa_tdnn import EcapaTdnnSpeakerEncoderConfig
21
+
22
+
23
+ class TimeDelayNetBlock(nn.Module):
24
+ """1-D convolution + ReLU (TDNN layer)."""
25
+
26
+ def __init__(self, in_channels, out_channels, kernel_size, dilation):
27
+ super().__init__()
28
+ self.conv = nn.Conv1d(
29
+ in_channels=in_channels,
30
+ out_channels=out_channels,
31
+ kernel_size=kernel_size,
32
+ dilation=dilation,
33
+ padding="same",
34
+ padding_mode="reflect",
35
+ )
36
+ self.activation = nn.ReLU()
37
+
38
+ def forward(self, hidden_states: torch.Tensor):
39
+ return self.activation(self.conv(hidden_states))
40
+
41
+
42
+ class Res2NetBlock(nn.Module):
43
+ """Multi-scale Res2Net block using TDNN sub-blocks."""
44
+
45
+ def __init__(self, in_channels, out_channels, scale=8, kernel_size=3, dilation=1):
46
+ super().__init__()
47
+ in_channel = in_channels // scale
48
+ hidden_channel = out_channels // scale
49
+ self.blocks = nn.ModuleList(
50
+ [
51
+ TimeDelayNetBlock(in_channel, hidden_channel, kernel_size=kernel_size, dilation=dilation)
52
+ for _ in range(scale - 1)
53
+ ]
54
+ )
55
+ self.scale = scale
56
+
57
+ def forward(self, hidden_states):
58
+ outputs = []
59
+ for i, hidden_part in enumerate(torch.chunk(hidden_states, self.scale, dim=1)):
60
+ if i == 0:
61
+ output_part = hidden_part
62
+ elif i == 1:
63
+ output_part = self.blocks[i - 1](hidden_part)
64
+ else:
65
+ output_part = self.blocks[i - 1](hidden_part + output_part)
66
+ outputs.append(output_part)
67
+ return torch.cat(outputs, dim=1)
68
+
69
+
70
+ class SqueezeExcitationBlock(nn.Module):
71
+ """Channel-wise squeeze-and-excitation attention."""
72
+
73
+ def __init__(self, in_channels, se_channels, out_channels):
74
+ super().__init__()
75
+ self.conv1 = nn.Conv1d(
76
+ in_channels=in_channels,
77
+ out_channels=se_channels,
78
+ kernel_size=1,
79
+ padding="same",
80
+ padding_mode="reflect",
81
+ )
82
+ self.relu = nn.ReLU(inplace=True)
83
+ self.conv2 = nn.Conv1d(
84
+ in_channels=se_channels,
85
+ out_channels=out_channels,
86
+ kernel_size=1,
87
+ padding="same",
88
+ padding_mode="reflect",
89
+ )
90
+ self.sigmoid = nn.Sigmoid()
91
+
92
+ def forward(self, hidden_states):
93
+ hidden_states_mean = hidden_states.mean(dim=2, keepdim=True)
94
+ hidden_states_mean = self.relu(self.conv1(hidden_states_mean))
95
+ hidden_states_mean = self.sigmoid(self.conv2(hidden_states_mean))
96
+ return hidden_states * hidden_states_mean
97
+
98
+
99
+ class SqueezeExcitationRes2NetBlock(nn.Module):
100
+ """ECAPA-TDNN building block: TDNN → Res2Net → TDNN → SE, with residual."""
101
+
102
+ def __init__(self, in_channels, out_channels, res2net_scale=8, se_channels=128, kernel_size=1, dilation=1):
103
+ super().__init__()
104
+ self.out_channels = out_channels
105
+ self.tdnn1 = TimeDelayNetBlock(in_channels, out_channels, kernel_size=1, dilation=1)
106
+ self.res2net_block = Res2NetBlock(out_channels, out_channels, res2net_scale, kernel_size, dilation)
107
+ self.tdnn2 = TimeDelayNetBlock(out_channels, out_channels, kernel_size=1, dilation=1)
108
+ self.se_block = SqueezeExcitationBlock(out_channels, se_channels, out_channels)
109
+
110
+ def forward(self, hidden_state):
111
+ residual = hidden_state
112
+ hidden_state = self.tdnn1(hidden_state)
113
+ hidden_state = self.res2net_block(hidden_state)
114
+ hidden_state = self.tdnn2(hidden_state)
115
+ hidden_state = self.se_block(hidden_state)
116
+ return hidden_state + residual
117
+
118
+
119
+ class AttentiveStatisticsPooling(nn.Module):
120
+ """Attentive statistics pooling — produces concatenated weighted mean and std."""
121
+
122
+ def __init__(self, channels, attention_channels=128):
123
+ super().__init__()
124
+ self.eps = 1e-12
125
+ self.tdnn = TimeDelayNetBlock(channels * 3, attention_channels, 1, 1)
126
+ self.tanh = nn.Tanh()
127
+ self.conv = nn.Conv1d(
128
+ in_channels=attention_channels,
129
+ out_channels=channels,
130
+ kernel_size=1,
131
+ padding="same",
132
+ padding_mode="reflect",
133
+ )
134
+
135
+ @staticmethod
136
+ def _length_to_mask(length, max_len=None, dtype=None, device=None):
137
+ if max_len is None:
138
+ max_len = length.max().long().item()
139
+ mask = torch.arange(max_len, device=length.device, dtype=length.dtype).expand(
140
+ len(length), max_len
141
+ ) < length.unsqueeze(1)
142
+ return torch.as_tensor(mask, dtype=dtype, device=device)
143
+
144
+ def _compute_statistics(self, x, m, dim=2):
145
+ mean = (m * x).sum(dim)
146
+ std = torch.sqrt((m * (x - mean.unsqueeze(dim)).pow(2)).sum(dim).clamp(self.eps))
147
+ return mean, std
148
+
149
+ def forward(self, hidden_states):
150
+ seq_length = hidden_states.shape[-1]
151
+ lengths = torch.ones(hidden_states.shape[0], device=hidden_states.device)
152
+
153
+ mask = self._length_to_mask(
154
+ lengths * seq_length, max_len=seq_length, dtype=hidden_states.dtype, device=hidden_states.device
155
+ )
156
+ mask = mask.unsqueeze(1)
157
+
158
+ total = mask.sum(dim=2, keepdim=True)
159
+ mean, std = self._compute_statistics(hidden_states, mask / total)
160
+ mean = mean.unsqueeze(2).repeat(1, 1, seq_length)
161
+ std = std.unsqueeze(2).repeat(1, 1, seq_length)
162
+ attention = torch.cat([hidden_states, mean, std], dim=1)
163
+
164
+ attention = self.conv(self.tanh(self.tdnn(attention)))
165
+ attention = attention.masked_fill(mask == 0, float("-inf"))
166
+ attention = F.softmax(attention, dim=2)
167
+
168
+ mean, std = self._compute_statistics(hidden_states, attention)
169
+ pooled_stats = torch.cat((mean, std), dim=1)
170
+ pooled_stats = pooled_stats.unsqueeze(2)
171
+ return pooled_stats
172
+
173
+
174
+ class EcapaTdnnSpeakerEncoderPreTrainedModel(PreTrainedModel):
175
+ config_class = EcapaTdnnSpeakerEncoderConfig
176
+ base_model_prefix = "encoder"
177
+
178
+ def _init_weights(self, module):
179
+ std = 0.02
180
+ if isinstance(module, (nn.Linear, nn.Conv1d)):
181
+ module.weight.data.normal_(mean=0.0, std=std)
182
+ if module.bias is not None:
183
+ module.bias.data.zero_()
184
+
185
+
186
+ class EcapaTdnnSpeakerEncoder(EcapaTdnnSpeakerEncoderPreTrainedModel):
187
+ """ECAPA-TDNN speaker encoder.
188
+
189
+ Takes a log-mel spectrogram of shape ``(batch, time, mel_dim)`` and returns
190
+ a fixed-dimensional speaker embedding of shape ``(batch, enc_dim)``.
191
+
192
+ This is a standalone extraction of the speaker encoder from Qwen3-TTS,
193
+ compatible with the HuggingFace ``AutoModel`` API.
194
+ """
195
+
196
+ def __init__(self, config: EcapaTdnnSpeakerEncoderConfig):
197
+ super().__init__(config)
198
+
199
+ if len(config.enc_channels) != len(config.enc_kernel_sizes) or len(config.enc_channels) != len(
200
+ config.enc_dilations
201
+ ):
202
+ raise ValueError("enc_channels, enc_kernel_sizes and enc_dilations must have the same length")
203
+
204
+ self.channels = config.enc_channels
205
+ self.blocks = nn.ModuleList()
206
+
207
+ # Initial TDNN layer
208
+ self.blocks.append(
209
+ TimeDelayNetBlock(
210
+ config.mel_dim,
211
+ config.enc_channels[0],
212
+ config.enc_kernel_sizes[0],
213
+ config.enc_dilations[0],
214
+ )
215
+ )
216
+
217
+ # SE-Res2Net layers
218
+ for i in range(1, len(config.enc_channels) - 1):
219
+ self.blocks.append(
220
+ SqueezeExcitationRes2NetBlock(
221
+ config.enc_channels[i - 1],
222
+ config.enc_channels[i],
223
+ res2net_scale=config.enc_res2net_scale,
224
+ se_channels=config.enc_se_channels,
225
+ kernel_size=config.enc_kernel_sizes[i],
226
+ dilation=config.enc_dilations[i],
227
+ )
228
+ )
229
+
230
+ # Multi-layer feature aggregation
231
+ self.mfa = TimeDelayNetBlock(
232
+ config.enc_channels[-1],
233
+ config.enc_channels[-1],
234
+ config.enc_kernel_sizes[-1],
235
+ config.enc_dilations[-1],
236
+ )
237
+
238
+ # Attentive Statistical Pooling
239
+ self.asp = AttentiveStatisticsPooling(
240
+ config.enc_channels[-1],
241
+ attention_channels=config.enc_attention_channels,
242
+ )
243
+
244
+ # Final linear transformation
245
+ self.fc = nn.Conv1d(
246
+ in_channels=config.enc_channels[-1] * 2,
247
+ out_channels=config.enc_dim,
248
+ kernel_size=1,
249
+ padding="same",
250
+ padding_mode="reflect",
251
+ )
252
+
253
+ self.post_init()
254
+
255
+ def forward(self, input_values=None, **kwargs):
256
+ """
257
+ Args:
258
+ input_values: Log-mel spectrogram tensor of shape ``(batch, time, mel_dim)``.
259
+
260
+ Returns:
261
+ ``BaseModelOutputWithNoAttention`` with ``last_hidden_state`` of shape
262
+ ``(batch, enc_dim)``.
263
+ """
264
+ hidden_states = input_values
265
+ # Transpose to (batch, channels, time) for Conv1d
266
+ hidden_states = hidden_states.transpose(1, 2)
267
+
268
+ hidden_states_list = []
269
+ for layer in self.blocks:
270
+ hidden_states = layer(hidden_states)
271
+ hidden_states_list.append(hidden_states)
272
+
273
+ # Multi-layer feature aggregation
274
+ hidden_states = torch.cat(hidden_states_list[1:], dim=1)
275
+ hidden_states = self.mfa(hidden_states)
276
+
277
+ # Attentive Statistical Pooling
278
+ hidden_states = self.asp(hidden_states)
279
+
280
+ # Final linear transformation
281
+ hidden_states = self.fc(hidden_states)
282
+ hidden_states = hidden_states.squeeze(-1)
283
+
284
+ return BaseModelOutputWithNoAttention(last_hidden_state=hidden_states)
speaker_encoder/preprocessor_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "feature_extractor_type": "EcapaTdnnFeatureExtractor",
3
+ "auto_map": {
4
+ "AutoFeatureExtractor": "feature_extraction_ecapa_tdnn.EcapaTdnnFeatureExtractor"
5
+ },
6
+ "sample_rate": 24000,
7
+ "n_fft": 1024,
8
+ "hop_length": 256,
9
+ "n_mels": 128,
10
+ "fmin": 0,
11
+ "fmax": 12000
12
+ }
speaker_encoder/tokenizer_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "tokenizer_class": "EcapaTdnnDummyTokenizer",
3
+ "auto_map": {
4
+ "AutoTokenizer": [
5
+ "tokenizer_ecapa_tdnn.EcapaTdnnDummyTokenizer",
6
+ null
7
+ ]
8
+ }
9
+ }
speaker_encoder/tokenizer_ecapa_tdnn.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Dummy tokenizer for pipeline("feature-extraction") compatibility.
2
+
3
+ The HuggingFace ``FeatureExtractionPipeline`` unconditionally requires a
4
+ tokenizer, even for audio models that have no vocabulary. This thin wrapper
5
+ satisfies that interface by delegating ``__call__`` to the real
6
+ ``EcapaTdnnFeatureExtractor``, which computes log-mel spectrograms from raw
7
+ audio.
8
+
9
+ >>> pipe = pipeline("feature-extraction", model=model_id, trust_remote_code=True)
10
+ >>> pipe("audio.wav") # works!
11
+ """
12
+
13
+ import os
14
+
15
+ import numpy as np
16
+ from transformers import PreTrainedTokenizer
17
+ from transformers.feature_extraction_utils import BatchFeature
18
+
19
+
20
+ class EcapaTdnnDummyTokenizer(PreTrainedTokenizer):
21
+ """Tokenizer shim that wraps :class:`EcapaTdnnFeatureExtractor`.
22
+
23
+ This class exists *only* to make ``pipeline("feature-extraction")`` work
24
+ with ECAPA-TDNN speaker encoder models. It contains no real vocabulary —
25
+ all audio preprocessing is handled by the feature extractor.
26
+ """
27
+
28
+ vocab_files_names: dict[str, str] = {}
29
+ model_input_names = ["input_values"]
30
+
31
+ def __init__(self, **kwargs):
32
+ # Filter out tokenizer-specific kwargs that don't apply to us
33
+ kwargs.pop("added_tokens_decoder", None)
34
+ super().__init__(**kwargs)
35
+
36
+ # -- abstract method stubs (unused but required) -----------------------
37
+
38
+ @property
39
+ def vocab_size(self) -> int:
40
+ return 0
41
+
42
+ def get_vocab(self) -> dict[str, int]:
43
+ return {}
44
+
45
+ def _tokenize(self, text, **kwargs):
46
+ return []
47
+
48
+ def _convert_token_to_id(self, token):
49
+ return 0
50
+
51
+ def _convert_id_to_token(self, index):
52
+ return ""
53
+
54
+ def save_vocabulary(self, save_directory, filename_prefix=None):
55
+ return ()
56
+
57
+ # -- the only method that actually matters ------------------------------
58
+
59
+ def __call__(self, raw_speech, return_tensors="pt", **kwargs):
60
+ """Preprocess audio via the feature extractor.
61
+
62
+ Accepts the same inputs as :class:`EcapaTdnnFeatureExtractor`:
63
+ file paths, numpy arrays, or lists thereof.
64
+ """
65
+ try:
66
+ from .feature_extraction_ecapa_tdnn import EcapaTdnnFeatureExtractor
67
+ except ImportError:
68
+ from feature_extraction_ecapa_tdnn import EcapaTdnnFeatureExtractor
69
+
70
+ # Load the feature extractor config from the same directory
71
+ model_dir = os.path.dirname(os.path.abspath(__file__))
72
+ try:
73
+ fe = EcapaTdnnFeatureExtractor.from_pretrained(model_dir)
74
+ except Exception:
75
+ fe = EcapaTdnnFeatureExtractor()
76
+
77
+ return fe(raw_speech, return_tensors=return_tensors, **kwargs)
zonos2-fp8-mixed.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:326e1d68c66cde0af14c27570edfdbf2d339be50ce3d6fafb8778ceaf3f9381a
3
+ size 10504655360