Rezuwan commited on
Commit
85f9ccb
·
verified ·
1 Parent(s): d057196

Upload install_spleeter.py

Browse files
Files changed (1) hide show
  1. install_spleeter.py +159 -0
install_spleeter.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import soundfile as sf
4
+ import onnxruntime as ort
5
+ from scipy.signal import stft, istft
6
+ import os
7
+ import uuid
8
+
9
+ # ====== Load Model ======
10
+ MODEL_PATH = "models/mdxnet.onnx"
11
+
12
+ print("Loading MDX-Net model...")
13
+ sess = ort.InferenceSession(MODEL_PATH, providers=["CPUExecutionProvider"])
14
+ input_name = sess.get_inputs()[0].name
15
+ input_shape = sess.get_inputs()[0].shape # ['batch_size', 4, 3072, 256]
16
+ output_name = sess.get_outputs()[0].name
17
+ print("Loaded model with input shape:", input_shape)
18
+
19
+
20
+ # ====== PARAMETERS (from UVR MDX pipeline) ======
21
+ N_FFT = 6144
22
+ HOP = 1536
23
+
24
+ # For reconstruction (ISTFT) — correct value
25
+ F_BIN_FULL = N_FFT // 2 + 1 # 3073
26
+
27
+ # For MDX model input (fixed)
28
+ F_BIN_MODEL = 3072
29
+
30
+ CHUNK_T = 256
31
+ N_CHANNELS = 4
32
+
33
+
34
+ def prepare_spectrogram(audio, sr):
35
+ """Return stacked model input (4×3072×T) and full 3073-bin complex STFT."""
36
+
37
+ # Convert stereo → mono
38
+ if audio.ndim == 2:
39
+ audio = np.mean(audio, axis=1)
40
+
41
+ audio = audio.astype(np.float32)
42
+
43
+ # STFT
44
+ f, t, Zxx = stft(
45
+ audio,
46
+ fs=sr,
47
+ nperseg=N_FFT,
48
+ noverlap=N_FFT - HOP
49
+ )
50
+ Zxx = Zxx.astype(np.complex64)
51
+
52
+ # Full resolution for ISTFT later (3073)
53
+ original_spec = Zxx[:F_BIN_FULL, :]
54
+
55
+ # Model input uses ONLY 3072 bins
56
+ spec = Zxx[:F_BIN_MODEL, :]
57
+
58
+ mag = np.abs(spec).astype(np.float32)
59
+ phase = np.angle(spec).astype(np.float32)
60
+
61
+ ch1 = mag
62
+ ch2 = np.sin(phase).astype(np.float32)
63
+ ch3 = np.cos(phase).astype(np.float32)
64
+ ch4 = (mag ** 2).astype(np.float32)
65
+
66
+ stacked = np.stack([ch1, ch2, ch3, ch4], axis=0).astype(np.float32)
67
+ return stacked, original_spec
68
+
69
+
70
+ def run_mdx(stacked):
71
+ _, _, T = stacked.shape
72
+ out = np.zeros((F_BIN_MODEL, T), dtype=np.float32)
73
+
74
+ for i in range(0, T, CHUNK_T):
75
+ chunk = stacked[:, :, i:i+CHUNK_T]
76
+
77
+ if chunk.shape[2] < CHUNK_T:
78
+ pad = CHUNK_T - chunk.shape[2]
79
+ chunk = np.pad(chunk, ((0,0),(0,0),(0,pad)), mode="constant")
80
+
81
+ inp = chunk[np.newaxis, :, :, :].astype(np.float32)
82
+
83
+ pred = sess.run([output_name], {input_name: inp})[0].astype(np.float32)
84
+ pred = pred[0, 0] # mask channel
85
+
86
+ out[:, i:i+CHUNK_T] = pred[:, :out[:, i:i+CHUNK_T].shape[1]]
87
+
88
+ return out
89
+
90
+
91
+ def reconstruct_audio(mask, original_spec, sr):
92
+ """Pad mask to 3073 bins, apply to full STFT, then ISTFT."""
93
+
94
+ # Pad 1 missing bin (3072 → 3073)
95
+ if mask.shape[0] == F_BIN_MODEL:
96
+ mask = np.pad(mask, ((0, 1), (0, 0)), mode="constant")
97
+
98
+ masked = mask * original_spec # complex spectrogram
99
+
100
+ # ISTFT that requires N_FFT = 6144 → 3073 bins OK
101
+ _, audio = istft(
102
+ masked,
103
+ fs=sr,
104
+ nperseg=N_FFT,
105
+ noverlap=N_FFT - HOP
106
+ )
107
+ return audio
108
+
109
+
110
+ def separate_audio(input_path):
111
+ if input_path is None:
112
+ return None, None
113
+
114
+ job = str(uuid.uuid4())
115
+ out_dir = f"output/{job}"
116
+ os.makedirs(out_dir, exist_ok=True)
117
+
118
+ audio, sr = sf.read(input_path)
119
+
120
+ # ---- Prepare spectrogram ----
121
+ stacked, original_spec = prepare_spectrogram(audio, sr)
122
+
123
+ # ---- Run MDX-Net ----
124
+ print("Running MDX-Net...")
125
+ mask = run_mdx(stacked)
126
+
127
+ mask = mask.astype(np.float32)
128
+ original_spec = original_spec.astype(np.complex64)
129
+
130
+ # ---- Reconstruct audio ----
131
+ vocals = reconstruct_audio(mask, original_spec, sr)
132
+
133
+ # Length-safe subtraction
134
+ instrumental = audio[:len(vocals)] - vocals[:len(audio)]
135
+
136
+ # ---- Save ----
137
+ v_path = os.path.join(out_dir, "vocals.wav")
138
+ i_path = os.path.join(out_dir, "instrumental.wav")
139
+
140
+ sf.write(v_path, vocals, sr)
141
+ sf.write(i_path, instrumental, sr)
142
+
143
+ return v_path, i_path
144
+
145
+
146
+ # ===== Gradio UI =====
147
+ with gr.Blocks(title="MDX-Net Vocal Remover (UVR)") as app:
148
+ gr.Markdown("# 🎵 MDX-Net Vocal Remover (UVR)")
149
+ gr.Markdown("Extract **Vocals** and **Instrumental** using the real UVR MDX-Net pipeline.")
150
+
151
+ inp = gr.Audio(type="filepath", label="Upload Audio")
152
+ btn = gr.Button("Separate", variant="primary")
153
+
154
+ out_v = gr.Audio(type="filepath", label="Vocals")
155
+ out_i = gr.Audio(type="filepath", label="Instrumental")
156
+
157
+ btn.click(separate_audio, inp, [out_v, out_i])
158
+
159
+ app.launch()