Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -21,6 +21,7 @@ from faster_whisper import WhisperModel
|
|
21 |
from TTS.api import TTS
|
22 |
import base64
|
23 |
import pickle
|
|
|
24 |
|
25 |
# Suppress warnings
|
26 |
warnings.filterwarnings("ignore")
|
@@ -157,6 +158,29 @@ def auto_eq(audio, genre="Pop"):
|
|
157 |
|
158 |
return array_to_audiosegment(samples.astype(np.int16), sr, channels=audio.channels)
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
# === Vocal Isolation Helpers ===
|
161 |
def load_track_local(path, sample_rate, channels=2):
|
162 |
sig, rate = torchaudio.load(path)
|
@@ -255,7 +279,7 @@ def process_audio(audio_file, selected_effects, isolate_vocals, preset_name, exp
|
|
255 |
status = f"β Error: {str(e)}"
|
256 |
return None, None, status, "", status
|
257 |
|
258 |
-
# ===
|
259 |
def show_waveform(audio_file):
|
260 |
try:
|
261 |
audio = AudioSegment.from_file(audio_file)
|
@@ -323,7 +347,7 @@ def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, ex
|
|
323 |
results.append(processed_path)
|
324 |
session_logs.append(log)
|
325 |
|
326 |
-
zip_path = os.path.join(
|
327 |
with zipfile.ZipFile(zip_path, 'w') as zipf:
|
328 |
for i, res in enumerate(results):
|
329 |
filename = f"processed_{i}.{export_format.lower()}"
|
@@ -347,6 +371,7 @@ def auto_tune_vocal(audio_path, target_key="C"):
|
|
347 |
def visualize_spectrum(audio_path):
|
348 |
y, sr = torchaudio.load(audio_path)
|
349 |
y_np = y.numpy().flatten()
|
|
|
350 |
stft = librosa.stft(y_np)
|
351 |
db = librosa.amplitude_to_db(abs(stft))
|
352 |
|
@@ -388,6 +413,21 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
388 |
output_audio, waveform_img, session_log_out, genre_out, status_box
|
389 |
])
|
390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
# --- Remix Mode ---
|
392 |
with gr.Tab("π Remix Mode"):
|
393 |
gr.Interface(
|
@@ -405,21 +445,6 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
405 |
clear_btn=None
|
406 |
)
|
407 |
|
408 |
-
# --- AI Mastering Chain Tab ===
|
409 |
-
with gr.Tab("π§ AI Mastering Chain"):
|
410 |
-
gr.Interface(
|
411 |
-
fn=ai_mastering_chain,
|
412 |
-
inputs=[
|
413 |
-
gr.Audio(label="Upload Track", type="filepath"),
|
414 |
-
gr.Dropdown(choices=["Pop", "EDM", "Rock", "Hip-Hop", "Acoustic", "Metal", "Trap", "LoFi"], label="Genre", value="Pop"),
|
415 |
-
gr.Slider(minimum=-24, maximum=-6, value=-14, label="Target LUFS")
|
416 |
-
],
|
417 |
-
outputs=gr.Audio(label="Mastered Output", type="filepath"),
|
418 |
-
title="Genre-Based Mastering",
|
419 |
-
description="Apply genre-specific EQ + loudness matching + limiter",
|
420 |
-
allow_flagging="never"
|
421 |
-
)
|
422 |
-
|
423 |
# --- Harmonic Saturation / Exciter ===
|
424 |
with gr.Tab("𧬠Harmonic Saturation"):
|
425 |
gr.Interface(
|
|
|
21 |
from TTS.api import TTS
|
22 |
import base64
|
23 |
import pickle
|
24 |
+
import json
|
25 |
|
26 |
# Suppress warnings
|
27 |
warnings.filterwarnings("ignore")
|
|
|
158 |
|
159 |
return array_to_audiosegment(samples.astype(np.int16), sr, channels=audio.channels)
|
160 |
|
161 |
+
# === AI Mastering Chain β Genre EQ + Loudness Match + Limiting ===
|
162 |
+
def ai_mastering_chain(audio_path, genre="Pop", target_lufs=-14.0):
|
163 |
+
audio = AudioSegment.from_file(audio_path)
|
164 |
+
|
165 |
+
# Apply Genre EQ
|
166 |
+
eq_audio = auto_eq(audio, genre=genre)
|
167 |
+
|
168 |
+
# Convert to numpy for loudness
|
169 |
+
samples, sr = audiosegment_to_array(eq_audio)
|
170 |
+
|
171 |
+
# Apply loudness normalization
|
172 |
+
meter = pyln.Meter(sr)
|
173 |
+
loudness = meter.integrated_loudness(samples.astype(np.float64) / 32768.0)
|
174 |
+
gain_db = target_lufs - loudness
|
175 |
+
final_audio = eq_audio + gain_db
|
176 |
+
|
177 |
+
# Final limiting
|
178 |
+
final_audio = apply_limiter(final_audio)
|
179 |
+
|
180 |
+
out_path = os.path.join(tempfile.gettempdir(), "mastered_output.wav")
|
181 |
+
final_audio.export(out_path, format="wav")
|
182 |
+
return out_path
|
183 |
+
|
184 |
# === Vocal Isolation Helpers ===
|
185 |
def load_track_local(path, sample_rate, channels=2):
|
186 |
sig, rate = torchaudio.load(path)
|
|
|
279 |
status = f"β Error: {str(e)}"
|
280 |
return None, None, status, "", status
|
281 |
|
282 |
+
# === Waveform + Spectrogram Generator ===
|
283 |
def show_waveform(audio_file):
|
284 |
try:
|
285 |
audio = AudioSegment.from_file(audio_file)
|
|
|
347 |
results.append(processed_path)
|
348 |
session_logs.append(log)
|
349 |
|
350 |
+
zip_path = os.path.join(tempfile.gettempdir(), "batch_output.zip")
|
351 |
with zipfile.ZipFile(zip_path, 'w') as zipf:
|
352 |
for i, res in enumerate(results):
|
353 |
filename = f"processed_{i}.{export_format.lower()}"
|
|
|
371 |
def visualize_spectrum(audio_path):
|
372 |
y, sr = torchaudio.load(audio_path)
|
373 |
y_np = y.numpy().flatten()
|
374 |
+
|
375 |
stft = librosa.stft(y_np)
|
376 |
db = librosa.amplitude_to_db(abs(stft))
|
377 |
|
|
|
413 |
output_audio, waveform_img, session_log_out, genre_out, status_box
|
414 |
])
|
415 |
|
416 |
+
# --- AI Mastering Chain Tab β Now Fully Defined ===
|
417 |
+
with gr.Tab("π§ AI Mastering Chain"):
|
418 |
+
gr.Interface(
|
419 |
+
fn=ai_mastering_chain,
|
420 |
+
inputs=[
|
421 |
+
gr.Audio(label="Upload Track", type="filepath"),
|
422 |
+
gr.Dropdown(choices=["Pop", "EDM", "Rock", "Hip-Hop", "Acoustic", "Metal", "Trap", "LoFi"], label="Genre", value="Pop"),
|
423 |
+
gr.Slider(minimum=-24, maximum=-6, value=-14, label="Target LUFS")
|
424 |
+
],
|
425 |
+
outputs=gr.Audio(label="Mastered Output", type="filepath"),
|
426 |
+
title="Genre-Based Mastering",
|
427 |
+
description="Apply genre-specific EQ + loudness matching + limiter",
|
428 |
+
allow_flagging="never"
|
429 |
+
)
|
430 |
+
|
431 |
# --- Remix Mode ---
|
432 |
with gr.Tab("π Remix Mode"):
|
433 |
gr.Interface(
|
|
|
445 |
clear_btn=None
|
446 |
)
|
447 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
# --- Harmonic Saturation / Exciter ===
|
449 |
with gr.Tab("𧬠Harmonic Saturation"):
|
450 |
gr.Interface(
|