GOVO commited on
Commit
e303baa
·
verified ·
1 Parent(s): 16d63b2

Upload folder using huggingface_hub

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
 
HTDemucs_6S_Split_F32.mlpackage/Data/com.apple.CoreML/model.mlmodel ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e9db3ae8f1d1724cc6ea13888029aeae567125141f744f2150e8bfdceae86ccb
3
+ size 560679
HTDemucs_6S_Split_F32.mlpackage/Data/com.apple.CoreML/weights/weight.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:78e9b2b5bef1dd618afbee5dbc20a4996a6fcf5b3d5aebd2ec66b4e389255281
3
+ size 152947392
HTDemucs_6S_Split_F32.mlpackage/Manifest.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fileFormatVersion": "1.0.0",
3
+ "itemInfoEntries": {
4
+ "A5ED0403-384D-4AB3-B8E0-154E6EC780BB": {
5
+ "author": "com.apple.CoreML",
6
+ "description": "CoreML Model Weights",
7
+ "name": "weights",
8
+ "path": "com.apple.CoreML/weights"
9
+ },
10
+ "ADB7E7D2-7FF6-416F-B6F9-D25FFD816320": {
11
+ "author": "com.apple.CoreML",
12
+ "description": "CoreML Model Specification",
13
+ "name": "model.mlmodel",
14
+ "path": "com.apple.CoreML/model.mlmodel"
15
+ }
16
+ },
17
+ "rootModelIdentifier": "ADB7E7D2-7FF6-416F-B6F9-D25FFD816320"
18
+ }
HTDemucs_SourceSeparation_F32.mlpackage/Data/com.apple.CoreML/model.mlmodel ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:790ed91e443ff3e446f1bac328a389b377f3656f0b09ac526817caa467aceeac
3
+ size 609766
HTDemucs_SourceSeparation_F32.mlpackage/Data/com.apple.CoreML/weights/weight.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:508b3a0e3f9fd69db1e252ee120d5fc5cff742cad4a3bea9ccab42248f80efb3
3
+ size 104599040
HTDemucs_SourceSeparation_F32.mlpackage/Manifest.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fileFormatVersion": "1.0.0",
3
+ "itemInfoEntries": {
4
+ "2D126888-F20C-42D9-B54C-A25C7994664D": {
5
+ "author": "com.apple.CoreML",
6
+ "description": "CoreML Model Specification",
7
+ "name": "model.mlmodel",
8
+ "path": "com.apple.CoreML/model.mlmodel"
9
+ },
10
+ "D2E7EAD1-5A9F-4503-8620-2485EE5A5AB0": {
11
+ "author": "com.apple.CoreML",
12
+ "description": "CoreML Model Weights",
13
+ "name": "weights",
14
+ "path": "com.apple.CoreML/weights"
15
+ }
16
+ },
17
+ "rootModelIdentifier": "2D126888-F20C-42D9-B54C-A25C7994664D"
18
+ }
convert_htdemucs_6s_split_coreml.py ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Convert Meta's htdemucs_6s model to a CoreML package that matches the
4
+ StemsPlayer iOS DSP pipeline.
5
+
6
+ This export intentionally keeps STFT/iSTFT outside the CoreML graph. The iOS
7
+ app computes the complex spectrogram with Accelerate, calls this model, then
8
+ reconstructs audio with iSTFT. This avoids CoreMLTools' complex64 conversion
9
+ failure when trying to convert the waveform-only HTDemucs graph.
10
+
11
+ Inputs:
12
+ spectral_magnitude: [1, 4, 2048, 336] # stereo complex spectrogram as
13
+ # L.real, L.imag, R.real, R.imag
14
+ audio_waveform: [1, 2, 343980]
15
+
16
+ Outputs:
17
+ freq_output: [1, 24, 2048, 336] # 6 stems * 2 channels * real/imag
18
+ time_output: [1, 12, 343980] # 6 stems * 2 channels
19
+
20
+ Source order:
21
+ drums, bass, other, vocals, guitar, piano
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import argparse
27
+ from pathlib import Path
28
+
29
+ import coremltools as ct
30
+ import torch
31
+ from demucs.pretrained import get_model
32
+ from einops import rearrange
33
+
34
+
35
+ SEGMENT_SAMPLES = 343_980
36
+ NUM_BINS = 2_048
37
+ NUM_FRAMES = 336
38
+
39
+
40
+ class HTDemucs6SSplitExport(torch.nn.Module):
41
+ def __init__(self, model: torch.nn.Module):
42
+ super().__init__()
43
+ self.model = model
44
+
45
+ def forward(
46
+ self,
47
+ spectral_magnitude: torch.Tensor,
48
+ audio_waveform: torch.Tensor,
49
+ ) -> tuple[torch.Tensor, torch.Tensor]:
50
+ model = self.model
51
+ x = spectral_magnitude
52
+ xt = audio_waveform
53
+
54
+ batch = x.shape[0]
55
+ spec_channels = x.shape[1]
56
+ freq_bins = x.shape[2]
57
+ frames = x.shape[3]
58
+
59
+ mean = x.mean(dim=(1, 2, 3), keepdim=True)
60
+ std = x.std(dim=(1, 2, 3), keepdim=True)
61
+ x = (x - mean) / (1e-5 + std)
62
+
63
+ time_mean = xt.mean(dim=(1, 2), keepdim=True)
64
+ time_std = xt.std(dim=(1, 2), keepdim=True)
65
+ xt = (xt - time_mean) / (1e-5 + time_std)
66
+
67
+ saved = []
68
+ saved_t = []
69
+ lengths = []
70
+ lengths_t = []
71
+
72
+ for idx, encode in enumerate(model.encoder):
73
+ lengths.append(x.shape[-1])
74
+ inject = None
75
+
76
+ if idx < len(model.tencoder):
77
+ lengths_t.append(xt.shape[-1])
78
+ tenc = model.tencoder[idx]
79
+ xt = tenc(xt)
80
+
81
+ if not tenc.empty:
82
+ saved_t.append(xt)
83
+ else:
84
+ inject = xt
85
+
86
+ x = encode(x, inject)
87
+
88
+ if idx == 0 and model.freq_emb is not None:
89
+ freqs = torch.arange(x.shape[-2], device=x.device)
90
+ emb = model.freq_emb(freqs).t()[None, :, :, None].expand_as(x)
91
+ x = x + model.freq_emb_scale * emb
92
+
93
+ saved.append(x)
94
+
95
+ if model.crosstransformer:
96
+ if model.bottom_channels:
97
+ _, _, freq, _ = x.shape
98
+ x = rearrange(x, "b c f t -> b c (f t)")
99
+ x = model.channel_upsampler(x)
100
+ x = rearrange(x, "b c (f t) -> b c f t", f=freq)
101
+ xt = model.channel_upsampler_t(xt)
102
+
103
+ x, xt = model.crosstransformer(x, xt)
104
+
105
+ if model.bottom_channels:
106
+ _, _, freq, _ = x.shape
107
+ x = rearrange(x, "b c f t -> b c (f t)")
108
+ x = model.channel_downsampler(x)
109
+ x = rearrange(x, "b c (f t) -> b c f t", f=freq)
110
+ xt = model.channel_downsampler_t(xt)
111
+
112
+ for idx, decode in enumerate(model.decoder):
113
+ skip = saved.pop(-1)
114
+ x, pre = decode(x, skip, lengths.pop(-1))
115
+
116
+ offset = model.depth - len(model.tdecoder)
117
+ if idx >= offset:
118
+ tdec = model.tdecoder[idx - offset]
119
+ length_t = lengths_t.pop(-1)
120
+
121
+ if tdec.empty:
122
+ pre = pre[:, :, 0]
123
+ xt, _ = tdec(pre, None, length_t)
124
+ else:
125
+ skip = saved_t.pop(-1)
126
+ xt, _ = tdec(xt, skip, length_t)
127
+
128
+ stem_count = len(model.sources)
129
+
130
+ freq_out = x.view(batch, stem_count, -1, freq_bins, frames)
131
+ freq_out = freq_out * std[:, None] + mean[:, None]
132
+ freq_out = freq_out.reshape(batch, stem_count * spec_channels, freq_bins, frames)
133
+
134
+ time_out = xt.view(batch, stem_count, -1, audio_waveform.shape[-1])
135
+ time_out = time_out * time_std[:, None] + time_mean[:, None]
136
+ time_out = time_out.reshape(batch, stem_count * 2, audio_waveform.shape[-1])
137
+
138
+ return freq_out, time_out
139
+
140
+
141
+ def convert(output: Path) -> None:
142
+ bag = get_model("htdemucs_6s")
143
+ model = bag.models[0] if hasattr(bag, "models") else bag
144
+ model.eval()
145
+
146
+ print(f"sources: {model.sources}")
147
+ print(f"samplerate: {model.samplerate}")
148
+ print(f"segment_samples: {int(model.segment * model.samplerate)}")
149
+
150
+ wrapper = HTDemucs6SSplitExport(model).eval()
151
+ spectral = torch.randn(1, 4, NUM_BINS, NUM_FRAMES)
152
+ waveform = torch.randn(1, 2, SEGMENT_SAMPLES)
153
+
154
+ with torch.no_grad():
155
+ freq_out, time_out = wrapper(spectral, waveform)
156
+ print(f"freq_output: {tuple(freq_out.shape)}")
157
+ print(f"time_output: {tuple(time_out.shape)}")
158
+
159
+ traced = torch.jit.trace(
160
+ wrapper,
161
+ (spectral, waveform),
162
+ strict=False,
163
+ check_trace=False,
164
+ )
165
+
166
+ mlmodel = ct.convert(
167
+ traced,
168
+ inputs=[
169
+ ct.TensorType(name="spectral_magnitude", shape=spectral.shape),
170
+ ct.TensorType(name="audio_waveform", shape=waveform.shape),
171
+ ],
172
+ outputs=[
173
+ ct.TensorType(name="freq_output"),
174
+ ct.TensorType(name="time_output"),
175
+ ],
176
+ minimum_deployment_target=ct.target.iOS16,
177
+ convert_to="mlprogram",
178
+ compute_precision=ct.precision.FLOAT32,
179
+ )
180
+
181
+ mlmodel.author = "Meta Research (Demucs)"
182
+ mlmodel.license = "MIT License"
183
+ mlmodel.short_description = (
184
+ "HTDemucs 6-stem split CoreML export. STFT/iSTFT are computed by the app; "
185
+ "the model runs the HTDemucs neural network body."
186
+ )
187
+ mlmodel.input_description["spectral_magnitude"] = (
188
+ "Stereo complex STFT [1,4,2048,336]: L.real, L.imag, R.real, R.imag."
189
+ )
190
+ mlmodel.input_description["audio_waveform"] = (
191
+ "Stereo waveform [1,2,343980] at 44100 Hz."
192
+ )
193
+ mlmodel.output_description["freq_output"] = (
194
+ "Frequency branch [1,24,2048,336]. Source order: drums, bass, other, vocals, guitar, piano."
195
+ )
196
+ mlmodel.output_description["time_output"] = (
197
+ "Time branch [1,12,343980]. Source order: drums, bass, other, vocals, guitar, piano."
198
+ )
199
+
200
+ mlmodel.save(str(output))
201
+ print(f"Saved {output}")
202
+
203
+
204
+ def main() -> None:
205
+ parser = argparse.ArgumentParser()
206
+ parser.add_argument(
207
+ "--output",
208
+ type=Path,
209
+ default=Path("HTDemucs_6S_Split_F32.mlpackage"),
210
+ help="Output .mlpackage path.",
211
+ )
212
+ args = parser.parse_args()
213
+ convert(args.output)
214
+
215
+
216
+ if __name__ == "__main__":
217
+ main()