david174 commited on
Commit
628f902
·
verified ·
1 Parent(s): 6c89252

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -72
app.py CHANGED
@@ -4,118 +4,126 @@ import numpy as np
4
  from pydub import AudioSegment
5
  import os
6
 
7
- # GIF de calavera técnica de alta calidad
8
- SKULL_GIF = "https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNHJueGZ3bmZ3bmZ3bmZ3bmZ3bmZ3bmZ3bmZ3bmZ3bmZ3bmZ3JmVwPXYxX2ludGVybmFsX2dpZl9ieV9pZ25vcmUmY3Q9cw/3o7TKMGpxxcaOlbJp6/giphy.gif"
9
 
10
- def ghost_engine_v21(t, r, p, active_fix, active_master):
 
11
  if t is None:
12
- return None, "SISTEMA: ESPERANDO TRANSMISIÓN...", "SIN SEÑAL", "--", "0", None
13
 
14
  try:
15
- # --- ANÁLISIS SÓNICO ---
16
  y, sr = librosa.load(t, duration=30)
17
 
18
- # Detector de KEY
19
  chroma = librosa.feature.chroma_cqt(y=y, sr=sr)
20
  nt = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
21
- key_det = nt[np.argmax(np.mean(chroma, axis=1))]
22
-
23
- # Detector de BPM (Fix para error de escalares)
24
  tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
25
- bpm_det = str(int(np.atleast_1d(tempo)[0]))
 
 
 
 
26
 
27
  # Análisis de Espectro
28
  S = np.abs(librosa.stft(y))
29
  f = librosa.fft_frequencies(sr=sr)
30
- bass_energy = np.mean(S[f < 150])
31
- mid_energy = np.mean(S[(f >= 150) & (f < 2000)])
 
32
 
33
  audio = AudioSegment.from_file(t)
34
- log_process = ""
35
-
36
- # --- MÓDULO: MIX FIX ---
37
  if active_fix:
38
  audio = audio.high_pass_filter(32)
39
- if bass_energy > mid_energy * 1.4:
40
- audio = audio.low_pass_filter(3800)
41
- log_process += "[] MIX FIX: EQ correctiva aplicada.\n"
42
- else:
43
- log_process += "[ ] MIX FIX: Bypass.\n"
44
-
45
- # --- MÓDULO: GHOST MASTER ---
46
  if active_master:
47
- # Compresión Pro y Maximización
48
- audio = audio.compressor_dynamic_range(threshold=-16.0, ratio=3.8, attack=12.0, release=150.0)
49
  audio = audio.apply_gain((p / 10) - 3)
50
- log_process += "[✓] MASTER: Maximización y Glue activos.\n"
51
- else:
52
- log_process += "[ ] MASTER: Bypass.\n"
53
 
54
- audio.export("master_ghost_v21.wav", format="wav")
55
 
56
- # --- GENERACIÓN DE INFORMES ---
57
- diag = f"--- STATUS REPORT: {key_det} ---\n\n{log_process}\n"
58
- diag += f"▶ FUNDAMENTAL: Tu nota {key_det} resuena en {librosa.note_to_hz(key_det+'1'):.1f}Hz.\n"
59
- diag += " TIP: Si el Kick suena flojo, limpia la zona de 200Hz en tus bajos.\n"
60
- diag += " VST: Usa un Clipper antes del limitador para ganar 2dB de pegada extra."
61
-
62
- intel = "--- COMPARATIVA VS REFERENCIA ---\n\n"
63
  if r is not None:
64
  yr, _ = librosa.load(r, duration=30)
65
  diff = 20 * np.log10(np.sqrt(np.mean(yr**2)) / (np.sqrt(np.mean(y**2)) + 1e-6))
66
- intel += f"• ENERGÍA: Faltan {round(diff, 1)} dB para nivel comercial.\n"
67
- intel += "• BALANCE: Tu mezcla necesita más aire en las frecuencias altas (>10kHz)."
68
  else:
69
- intel += "Sube un track pro para analizar la diferencia de pegada."
70
 
71
- return "master_ghost_v21.wav", diag, intel, key_det, bpm_det, "https://images.unsplash.com/photo-1598488035139-bdbb2231ce04?q=80&w=500"
72
 
73
  except Exception as e:
74
- return None, f"ERROR DE SISTEMA: {str(e)}", "ERROR", "!", "0", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
- # --- CSS: ESTILO CONSOLA ELITE ---
77
  css = """
78
- body, .gradio-container { background-color: #080808 !important; color: #ff9d00 !important; font-family: 'Verdana', sans-serif !important; }
79
- .gr-box { border: 1px solid #ff9d00 !important; background: #111 !important; border-radius: 8px !important; box-shadow: 0 0 10px rgba(255,157,0,0.2); }
80
- .gr-button-primary { background: linear-gradient(180deg, #ff9d00, #ff6600) !important; color: #000 !important; font-weight: bold !important; border: none !important; border-radius: 4px !important; }
81
- .gr-button-primary:hover { box-shadow: 0 0 20px #ff9d00; transform: translateY(-1px); }
82
- .gr-label { color: #00e5ff !important; font-size: 0.8em !important; text-transform: uppercase; }
83
- .gr-textbox textarea { background: #000 !important; border: 1px solid #333 !important; color: #00ff44 !important; font-family: 'Courier New', monospace; }
84
- #header-skull { text-align: center; padding: 15px; filter: drop-shadow(0 0 8px #ff9d00); }
85
  """
86
 
87
  with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as demo:
88
- with gr.Row(elem_id="header-skull"):
89
- gr.HTML(f"<img src='{SKULL_GIF}' width='85'>")
90
- gr.Markdown("<h1 style='text-align:center; margin-top:20px;'>GHOST COMMAND CENTER v21</h1>")
91
 
92
  with gr.Row():
93
- # PANEL DE ENTRADA
94
- with gr.Column(scale=1, variant="panel"):
95
  with gr.Row():
96
- out_k = gr.Label(label="DETECCIÓN KEY")
97
- out_b = gr.Label(label="BPM ESTIMADO")
98
-
99
- gr.Markdown("### 📥 SEÑALES")
100
- in_t = gr.Audio(label="TU MEZCLA", type="filepath")
101
  in_r = gr.Audio(label="REFERENCIA", type="filepath")
102
-
103
- gr.Markdown("### ⚙️ PROCESADORES")
104
  with gr.Row():
105
- fix_check = gr.Checkbox(label="MIX FIX", value=False)
106
- master_check = gr.Checkbox(label="GHOST MASTER", value=False)
107
- in_p = gr.Slider(0, 100, label="PRESIÓN DEL MASTER", value=85)
108
- btn = gr.Button("🚀 EJECUTAR SECUENCIA", variant="primary")
109
 
110
- # PANEL DE SALIDA
111
- with gr.Column(scale=2, variant="panel"):
112
- gr.Markdown("### 🔊 MONITORIZACIÓN")
113
- out_a = gr.Audio(label="SEÑAL DE SALIDA")
114
  with gr.Row():
115
- out_i = gr.Textbox(label="LOGS DE SISTEMA", lines=10)
116
- out_c = gr.Textbox(label="INTEL REPORT", lines=10)
117
- out_v = gr.Image(label="VIBE CHECK")
 
 
 
 
 
 
118
 
119
- btn.click(ghost_engine_v21, [in_t, in_r, in_p, fix_check, master_check], [out_a, out_i, out_c, out_k, out_b, out_v])
 
120
 
121
  demo.launch()
 
4
  from pydub import AudioSegment
5
  import os
6
 
7
+ # Memoria temporal para guardar el último análisis
8
+ session_data = {"key": "--", "bpm": "0", "issues": []}
9
 
10
+ def ghost_analyser_v22(t, r, p, active_fix, active_master):
11
+ global session_data
12
  if t is None:
13
+ return None, "SISTEMA: ESPERANDO AUDIO...", "SIN DATA", "--", "0", None
14
 
15
  try:
 
16
  y, sr = librosa.load(t, duration=30)
17
 
18
+ # KEY & BPM (Blindado)
19
  chroma = librosa.feature.chroma_cqt(y=y, sr=sr)
20
  nt = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
21
+ k = nt[np.argmax(np.mean(chroma, axis=1))]
 
 
22
  tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
23
+ bpm = str(int(np.atleast_1d(tempo)[0]))
24
+
25
+ session_data["key"] = k
26
+ session_data["bpm"] = bpm
27
+ session_data["issues"] = []
28
 
29
  # Análisis de Espectro
30
  S = np.abs(librosa.stft(y))
31
  f = librosa.fft_frequencies(sr=sr)
32
+ lo = np.mean(S[f < 150])
33
+ mi = np.mean(S[(f >= 150) & (f < 2000)])
34
+ hi = np.mean(S[f >= 2000])
35
 
36
  audio = AudioSegment.from_file(t)
37
+
38
+ # Lógica de Reparación Profunda
 
39
  if active_fix:
40
  audio = audio.high_pass_filter(32)
41
+ if lo > mi * 1.5:
42
+ audio = audio.low_pass_filter(4000)
43
+ session_data["issues"].append("Exceso de lodo (muddy) en 200-400Hz.")
44
+ if hi < mi * 0.4:
45
+ session_data["issues"].append("Falta de aire y brillo por encima de 10kHz.")
46
+
 
47
  if active_master:
48
+ audio = audio.compressor_dynamic_range(threshold=-16.0, ratio=4.0, attack=10.0, release=150.0)
 
49
  audio = audio.apply_gain((p / 10) - 3)
 
 
 
50
 
51
+ audio.export("ghost_mentor_v22.wav", format="wav")
52
 
53
+ diag = f"--- SESIÓN INICIADA: {k} ---\n\n"
54
+ diag += "DETECCIONES CRÍTICAS:\n"
55
+ for iss in session_data["issues"]:
56
+ diag += f" {iss}\n"
57
+ diag += "\n[!] Ahora puedes preguntarme detalles sobre estos fallos abajo."
58
+
59
+ intel = "--- ESTUDIO DE MERCADO ---\n\n"
60
  if r is not None:
61
  yr, _ = librosa.load(r, duration=30)
62
  diff = 20 * np.log10(np.sqrt(np.mean(yr**2)) / (np.sqrt(np.mean(y**2)) + 1e-6))
63
+ intel += f"• GAP DE ENERGÍA: {round(diff, 1)} dB\n"
64
+ intel += "• CONCLUSIÓN: Tu track necesita más pegada en el transiente del Snare."
65
  else:
66
+ intel += "Sin referencia para comparar."
67
 
68
+ return "ghost_mentor_v22.wav", diag, intel, k, bpm, "https://images.unsplash.com/photo-1550684848-fac1c5b4e853?q=80&w=500"
69
 
70
  except Exception as e:
71
+ return None, f"ERROR: {str(e)}", "!", "!", "0", None
72
+
73
+ def chatbot_response(pregunta):
74
+ k = session_data["key"]
75
+ if k == "--":
76
+ return "Primero analiza un track para que pueda aconsejarte sobre él."
77
+
78
+ pregunta = pregunta.lower()
79
+ if "lodo" in pregunta or "bajo" in pregunta:
80
+ return f"Para limpiar el bajo en {k}, haz un corte tipo campana de -3dB en 250Hz. Asegúrate de que el Kick tenga su pico en {librosa.note_to_hz(k+'1'):.1f}Hz."
81
+ elif "brillo" in pregunta or "agudo" in pregunta:
82
+ return "Usa un 'High Shelf' a partir de 8kHz subiendo 2dB. Si usas saturación (Decapitator), pon el Mix al 10% en modo 'A' para añadir armónicos."
83
+ elif "compresion" in pregunta or "vst" in pregunta:
84
+ return "Para DnB, usa un ratio de 4:1 en el bus de batería. Attack lento (25ms) para que el golpe del drum pase, y Release rápido (100ms) para que respire."
85
+ else:
86
+ return "Entendido. Basado en tu tema, te recomiendo revisar la fase de los sub-graves y usar un limitador con 'Lookahead' de 1ms para evitar picos inter-sample."
87
 
88
+ # --- INTERFAZ HUD INTERACTIVA ---
89
  css = """
90
+ body, .gradio-container { background-color: #0a0a0a !important; color: #00ffcc !important; font-family: 'Courier New', monospace; }
91
+ .gr-box { border: 2px solid #00ffcc !important; background: #111 !important; }
92
+ .gr-button-primary { background: #00ffcc !important; color: #000 !important; font-weight: bold; border: none; }
93
+ .gr-textbox textarea { background: #000 !important; color: #00ffcc !important; border: 1px solid #00ffcc44 !important; }
94
+ #chat-box { border-top: 2px dashed #00ffcc; padding-top: 15px; margin-top: 15px; }
 
 
95
  """
96
 
97
  with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as demo:
98
+ gr.Markdown("<h1 style='text-align:center;'>💀 GHOST MENTOR v22</h1>")
 
 
99
 
100
  with gr.Row():
101
+ with gr.Column(scale=1):
 
102
  with gr.Row():
103
+ out_k = gr.Label(label="KEY")
104
+ out_b = gr.Label(label="BPM")
105
+ in_t = gr.Audio(label="TU TRACK", type="filepath")
 
 
106
  in_r = gr.Audio(label="REFERENCIA", type="filepath")
 
 
107
  with gr.Row():
108
+ fix_check = gr.Checkbox(label="AUTO-FIX", value=False)
109
+ mst_check = gr.Checkbox(label="MASTER", value=False)
110
+ in_p = gr.Slider(0, 100, label="POWER", value=80)
111
+ btn = gr.Button("🚀 ANALIZAR Y REPARAR", variant="primary")
112
 
113
+ with gr.Column(scale=2):
114
+ out_a = gr.Audio(label="MONITOR SALIDA")
 
 
115
  with gr.Row():
116
+ out_i = gr.Textbox(label="DIAGNÓSTICO", lines=8)
117
+ out_c = gr.Textbox(label="ESTUDIO DE REF", lines=8)
118
+
119
+ # --- SECCIÓN DE CHAT ASESOR ---
120
+ with gr.Group(elem_id="chat-box"):
121
+ gr.Markdown("### 💬 PREGUNTA AL INGENIERO GHOST")
122
+ user_msg = gr.Textbox(placeholder="¿Cómo puedo mejorar los agudos de este tema?", label="Tu consulta")
123
+ chat_btn = gr.Button("CONSULTAR ASESOR", variant="secondary")
124
+ chat_out = gr.Textbox(label="RESPUESTA DEL MENTOR")
125
 
126
+ btn.click(ghost_analyser_v22, [in_t, in_r, in_p, fix_check, mst_check], [out_a, out_i, out_c, out_k, out_b])
127
+ chat_btn.click(chatbot_response, [user_msg], [chat_out])
128
 
129
  demo.launch()