tee342 commited on
Commit
d2e08bc
Β·
verified Β·
1 Parent(s): 94c3b1e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -17
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
- # === Visualize Waveform ===
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(output_dir, "batch_output.zip")
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(