Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,47 +3,89 @@ import librosa
|
|
| 3 |
import numpy as np
|
| 4 |
from pydub import AudioSegment
|
| 5 |
|
| 6 |
-
def
|
| 7 |
if tu_track is None:
|
| 8 |
-
return None, "Sube
|
| 9 |
|
| 10 |
try:
|
| 11 |
-
# 1. CARGA Y
|
| 12 |
-
y, sr = librosa.load(tu_track, duration=
|
| 13 |
-
|
|
|
|
| 14 |
chroma = librosa.feature.chroma_cqt(y=y, sr=sr)
|
| 15 |
notas = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
| 16 |
key_det = notas[np.argmax(np.mean(chroma, axis=1))]
|
| 17 |
|
| 18 |
-
# 2.
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
if track_ref is not None:
|
| 23 |
-
y_r, _ = librosa.load(track_ref, duration=
|
| 24 |
-
|
| 25 |
-
# Comparar Brillo (Spectral Centroid)
|
| 26 |
-
sc_tu = np.mean(librosa.feature.spectral_centroid(y=y, sr=sr))
|
| 27 |
-
sc_ref = np.mean(librosa.feature.spectral_centroid(y=y_r, sr=sr))
|
| 28 |
|
| 29 |
-
# Comparar
|
| 30 |
-
|
| 31 |
-
|
| 32 |
|
| 33 |
-
#
|
| 34 |
-
if
|
| 35 |
-
|
| 36 |
-
elif sc_tu > sc_ref * 1.2:
|
| 37 |
-
critica_mix = "❌ MEZCLA: Demasiados agudos. Tu mezcla va a fatigar el oído. Baja los platos."
|
| 38 |
else:
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
critica_comp = "❌ COMPOSICIÓN: El drop se siente vacío. Añade capas (layers) de sintes o percusión extra (shakers/rides)."
|
| 44 |
else:
|
| 45 |
-
|
|
|
|
|
|
|
| 46 |
|
| 47 |
-
#
|
| 48 |
audio = AudioSegment.from_file(tu_track)
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import numpy as np
|
| 4 |
from pydub import AudioSegment
|
| 5 |
|
| 6 |
+
def neuro_producer_v10(tu_track, track_ref, intensidad):
|
| 7 |
if tu_track is None:
|
| 8 |
+
return None, "Sube audio para iniciar el escaneo neuronal.", "...", "https://images.unsplash.com/photo-1614613535308-eb5fbd3d2c17?q=80&w=500", "..."
|
| 9 |
|
| 10 |
try:
|
| 11 |
+
# 1. CARGA Y EXTRACCIÓN DE ADN MUSICAL
|
| 12 |
+
y, sr = librosa.load(tu_track, duration=45) # Más duración para analizar estructura
|
| 13 |
+
|
| 14 |
+
# Key y Estilo
|
| 15 |
chroma = librosa.feature.chroma_cqt(y=y, sr=sr)
|
| 16 |
notas = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
| 17 |
key_det = notas[np.argmax(np.mean(chroma, axis=1))]
|
| 18 |
|
| 19 |
+
# 2. ESCANEO DE ERRORES FRECUENTES
|
| 20 |
+
# Detección de 'Mud' (Barro en graves-medios)
|
| 21 |
+
S = np.abs(librosa.stft(y))
|
| 22 |
+
mud_zone = np.mean(S[librosa.fft_frequencies(sr=sr) < 500])
|
| 23 |
+
clear_zone = np.mean(S[librosa.fft_frequencies(sr=sr) > 2000])
|
| 24 |
+
mud_ratio = mud_zone / (clear_zone + 1e-6)
|
| 25 |
+
|
| 26 |
+
# 3. COMPARATIVA AVANZADA
|
| 27 |
+
diagnostico = "🧠 DIAGNÓSTICO NEURONAL:\n"
|
| 28 |
if track_ref is not None:
|
| 29 |
+
y_r, _ = librosa.load(track_ref, duration=45)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
+
# Comparar Transientes (Pegada del Kick/Snare)
|
| 32 |
+
onset_tu = len(librosa.onset.onset_detect(y=y, sr=sr))
|
| 33 |
+
onset_ref = len(librosa.onset.onset_detect(y=y_r, sr=sr))
|
| 34 |
|
| 35 |
+
# Informe de Composición y Mezcla
|
| 36 |
+
if onset_tu < onset_ref * 0.8:
|
| 37 |
+
diagnostico += "❌ RITMO: Tu composición es estática. Falta percusión secundaria (ghost snares o hi-hats rítmicos).\n"
|
|
|
|
|
|
|
| 38 |
else:
|
| 39 |
+
diagnostico += "✅ RITMO: Movimiento rítmico excelente.\n"
|
| 40 |
+
|
| 41 |
+
if mud_ratio > 15: # Umbral de 'barro'
|
| 42 |
+
diagnostico += "❌ MEZCLA: Tienes 'barro' (mud) en 300Hz. Limpia con un EQ tu bajo y quita medios a lo que no sea necesario.\n"
|
|
|
|
| 43 |
else:
|
| 44 |
+
diagnostico += "✅ MEZCLA: Espacio de medios-graves limpio.\n"
|
| 45 |
+
else:
|
| 46 |
+
diagnostico += "ℹ️ Sube una referencia para un escaneo de estructura y pegada.\n"
|
| 47 |
|
| 48 |
+
# 4. MASTERING INTELIGENTE
|
| 49 |
audio = AudioSegment.from_file(tu_track)
|
| 50 |
+
# Limpieza automática: Aplicamos un suave Roll-off si hay mucho barro
|
| 51 |
+
if mud_ratio > 15:
|
| 52 |
+
audio = audio.low_pass_filter(5000) # Simulación de suavizado
|
| 53 |
+
|
| 54 |
+
audio = audio.apply_gain((intensidad / 10) - 5)
|
| 55 |
+
audio.export("master_v10.wav", format="wav")
|
| 56 |
+
|
| 57 |
+
# Informe Final
|
| 58 |
+
informe = diagnostico + "\n🎹 RECOMENDACIÓN DE ARREGLO:\n"
|
| 59 |
+
informe += "Tu track está en " + key_det + ". Si el drop no tiene fuerza, añade un 'Noise Layer' blanco durante el impacto.\n\n"
|
| 60 |
+
informe += "🛠️ CADENA DE VSTs RECOMENDADA:\n"
|
| 61 |
+
informe += "1. Soothe2 (Para resonancias en 2kHz-5kHz)\n"
|
| 62 |
+
informe += "2. Gulfoss (Para equilibrio tonal inteligente)\n"
|
| 63 |
+
informe += "3. Invisible Limiter (Para un master transparente)\n"
|
| 64 |
+
|
| 65 |
+
prompt = "Neural Music Interface, " + key_det + " harmonic colors, data visualization, cyberpunk producer, 8k."
|
| 66 |
+
|
| 67 |
+
return "master_v10.wav", informe, key_det, "https://images.unsplash.com/photo-1508700115892-45ecd05ae2ad?q=80&w=500", prompt
|
| 68 |
+
|
| 69 |
+
except Exception as e:
|
| 70 |
+
return None, "Error de procesado: " + str(e), "!", None, "..."
|
| 71 |
+
|
| 72 |
+
# Interfaz UI
|
| 73 |
+
with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="orange")) as demo:
|
| 74 |
+
gr.Markdown("# 🧠 DNB NEURO-PRODUCER v10.0")
|
| 75 |
+
with gr.Row():
|
| 76 |
+
with gr.Column(scale=1):
|
| 77 |
+
in_t = gr.Audio(label="TU PROYECTO (WAV/MP3)", type="filepath")
|
| 78 |
+
in_r = gr.Audio(label="REFERENCIA 'GOLD STANDARD'", type="filepath")
|
| 79 |
+
in_s = gr.Slider(0, 100, label="PRESIÓN DE MASTERIZACIÓN", value=85)
|
| 80 |
+
btn = gr.Button("🧠 INICIAR ANÁLISIS NEURONAL", variant="primary")
|
| 81 |
+
with gr.Column(scale=2):
|
| 82 |
+
out_a = gr.Audio(label="RESULTADO MASTERIZADO")
|
| 83 |
+
out_i = gr.Textbox(label="DIAGNÓSTICO TÉCNICO Y ARTÍSTICO", lines=12)
|
| 84 |
+
with gr.Row():
|
| 85 |
+
out_k = gr.Label(label="KEY")
|
| 86 |
+
out_p = gr.Textbox(label="PROMPT GENERATIVO")
|
| 87 |
+
out_m = gr.Image(label="VIBE")
|
| 88 |
+
|
| 89 |
+
btn.click(neuro_producer_v10, [in_t, in_r, in_s], [out_a, out_i, out_k, out_m, out_p])
|
| 90 |
+
|
| 91 |
+
demo.launch()
|