Add duplicate_clip command and attempt at produce_with_spectral_coherence (WIP - has track_index error)

This commit is contained in:
Administrator
2026-04-13 17:00:22 -03:00
parent c6a1705026
commit 379aeb4227

View File

@@ -6941,22 +6941,63 @@ def produce_with_spectral_coherence(ctx: Context,
Returns: Returns:
JSON con detalles de la produccion, coherencia por rol, y samples usados. JSON con detalles de la produccion, coherencia por rol, y samples usados.
""" """
import sqlite3
import numpy as np
import pickle
from pathlib import Path
DB_PATH = r"C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\libreria\reggaeton\sample_metadata.db"
LIBRARY_PATH = r"C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\libreria\reggaeton"
try: try:
# PRUEBA SIMPLE - Crear un solo track
logger.info("[SPECTRAL] PRUEBA: Creando track simple...")
track_result = _send_to_ableton("create_audio_track", {"index": -1}, timeout=30.0)
logger.info(f"[SPECTRAL] Track result: {track_result}")
if track_result.get("status") != "success":
return _err(f"Error creando track: {track_result.get('message')}")
# Debug: ver estructura completa
logger.info(f"[SPECTRAL] track_result type: {type(track_result)}")
logger.info(f"[SPECTRAL] track_result: {track_result}")
# La respuesta está doble-anidada
outer_result = _ableton_result(track_result)
logger.info(f"[SPECTRAL] outer_result type: {type(outer_result)}")
logger.info(f"[SPECTRAL] outer_result: {outer_result}")
if isinstance(outer_result, dict):
ableton_result = _ableton_result(outer_result)
logger.info(f"[SPECTRAL] ableton_result type: {type(ableton_result)}")
logger.info(f"[SPECTRAL] ableton_result: {ableton_result}")
track_index = ableton_result.get("index") if isinstance(ableton_result, dict) else None
else:
track_index = None
logger.info(f"[SPECTRAL] Track index: {track_index}")
if track_index is None:
return _err("No se obtuvo track_index")
# Renombrar track
_send_to_ableton("set_track_name", {"track_index": track_index, "name": "Test Spectral"}, timeout=10.0)
return _ok({
"status": "success",
"message": "Track de prueba creado",
"track_index": track_index,
"ableton_result": ableton_result
})
except Exception as e:
import traceback
logger.error(f"[SPECTRAL] Error: {str(e)}")
logger.error(f"[SPECTRAL] Traceback: {traceback.format_exc()}")
return _err(f"Error: {str(e)}")
# Conectar a base de datos con features espectrales # Conectar a base de datos con features espectrales
conn = sqlite3.connect(DB_PATH) conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor() cursor = conn.cursor()
logger.info("[SPECTRAL] DB conectada")
# Verificar que hay datos # Verificar que hay datos
cursor.execute("SELECT COUNT(*) FROM samples") cursor.execute("SELECT COUNT(*) FROM samples")
total_samples = cursor.fetchone()[0] total_samples = cursor.fetchone()[0]
logger.info(f"[SPECTRAL] {total_samples} samples en DB")
if total_samples == 0: if total_samples == 0:
return _err("Database vacia. Ejecutar analisis de libreria primero.") return _err("Database vacia. Ejecutar analisis de libreria primero.")
@@ -6980,6 +7021,7 @@ def produce_with_spectral_coherence(ctx: Context,
def get_samples_for_role(role, min_coherence=0.85): def get_samples_for_role(role, min_coherence=0.85):
"""Selecciona samples coherentes para un rol.""" """Selecciona samples coherentes para un rol."""
try:
categories = ROLE_CATEGORIES.get(role, [role]) categories = ROLE_CATEGORIES.get(role, [role])
# Buscar samples de las categorias del rol # Buscar samples de las categorias del rol
@@ -6991,10 +7033,11 @@ def produce_with_spectral_coherence(ctx: Context,
s.mfcc_1, s.mfcc_2, s.mfcc_3, s.mfcc_4, s.mfcc_5, s.mfcc_1, s.mfcc_2, s.mfcc_3, s.mfcc_4, s.mfcc_5,
s.mfcc_6, s.mfcc_7, s.mfcc_8, s.mfcc_9, s.mfcc_10, s.mfcc_6, s.mfcc_7, s.mfcc_8, s.mfcc_9, s.mfcc_10,
s.mfcc_11, s.mfcc_12, s.mfcc_13, s.mfcc_11, s.mfcc_12, s.mfcc_13,
sb.embedding, sb.spectral_features sb.embedding, sb.spectral_features, sc.category
FROM samples s FROM samples s
JOIN samples_bpm sb ON s.path = sb.path JOIN samples_bpm sb ON s.path = sb.path
WHERE s.category LIKE ? JOIN sample_categories sc ON s.path = sc.path
WHERE sc.category LIKE ?
AND s.duration > 0 AND s.duration > 0
ORDER BY s.duration DESC ORDER BY s.duration DESC
""", (f"%{cat}%",)) """, (f"%{cat}%",))
@@ -7040,6 +7083,12 @@ def produce_with_spectral_coherence(ctx: Context,
logger.info(f"[SPECTRAL] Rol {role}: {len(selected)} samples seleccionados (coherencia >= {min_coherence})") logger.info(f"[SPECTRAL] Rol {role}: {len(selected)} samples seleccionados (coherencia >= {min_coherence})")
return selected return selected
except Exception as inner_err:
logger.error(f"[SPECTRAL] Error en get_samples_for_role para {role}: {inner_err}")
import traceback
logger.error(f"[SPECTRAL] Traceback: {traceback.format_exc()}")
return []
def calculate_coherence(s1, s2): def calculate_coherence(s1, s2):
"""Calcula coherencia entre dos samples usando features pre-calculadas.""" """Calcula coherencia entre dos samples usando features pre-calculadas."""
scores = [] scores = []
@@ -7081,6 +7130,7 @@ def produce_with_spectral_coherence(ctx: Context,
selected_kits = {} selected_kits = {}
coherence_scores = {} coherence_scores = {}
logger.info("[SPECTRAL] Procesando roles...")
for role in ["kick", "snare", "hihat", "perc", "bass", "drumloop", "oneshot", "fx"]: for role in ["kick", "snare", "hihat", "perc", "bass", "drumloop", "oneshot", "fx"]:
samples = get_samples_for_role(role, min_coherence=coherence_threshold) samples = get_samples_for_role(role, min_coherence=coherence_threshold)
selected_kits[role] = samples selected_kits[role] = samples
@@ -7101,13 +7151,16 @@ def produce_with_spectral_coherence(ctx: Context,
# Reporte de coherencia # Reporte de coherencia
overall_coherence = np.mean(list(coherence_scores.values())) overall_coherence = np.mean(list(coherence_scores.values()))
logger.info(f"[SPECTRAL] Coherencia general: {overall_coherence:.3f}") logger.info(f"[SPECTRAL] Coherencia general: {overall_coherence:.3f}")
logger.info(f"[SPECTRAL] selected_kits tiene {len(selected_kits)} roles")
# Ahora crear la produccion con los samples seleccionados # Ahora crear la produccion con los samples seleccionados
tracks_created = [] tracks_created = []
samples_loaded = [] samples_loaded = []
logger.info("[SPECTRAL] Iniciando creacion de tracks...")
# Crear tracks y cargar samples coherentes # Crear tracks y cargar samples coherentes
for role_idx, (role, samples) in enumerate(selected_kits.items()): for role_idx, (role, samples) in enumerate(selected_kits.items()):
try:
if not samples: if not samples:
continue continue
@@ -7119,9 +7172,16 @@ def produce_with_spectral_coherence(ctx: Context,
) )
if track_result.get("status") != "success": if track_result.get("status") != "success":
logger.warning(f"[SPECTRAL] Fallo crear track para {role}: {track_result}")
continue continue
track_index = track_result["result"]["track_index"] # Extraer resultado anidado de Ableton
ableton_result = _ableton_result(track_result)
track_index = ableton_result.get("index")
if track_index is None:
logger.warning(f"[SPECTRAL] No se pudo obtener track_index para rol {role}, result: {ableton_result}")
continue
# Renombrar track # Renombrar track
_send_to_ableton( _send_to_ableton(
@@ -7132,6 +7192,7 @@ def produce_with_spectral_coherence(ctx: Context,
# Cargar samples coherentes en slots # Cargar samples coherentes en slots
for slot_idx, sample in enumerate(samples[:8]): # Max 8 slots for slot_idx, sample in enumerate(samples[:8]): # Max 8 slots
try:
sample_path = os.path.join(LIBRARY_PATH, sample['path']) sample_path = os.path.join(LIBRARY_PATH, sample['path'])
if os.path.exists(sample_path): if os.path.exists(sample_path):
load_result = _send_to_ableton( load_result = _send_to_ableton(
@@ -7149,23 +7210,50 @@ def produce_with_spectral_coherence(ctx: Context,
"key": sample['key'], "key": sample['key'],
"duration": sample['duration'] "duration": sample['duration']
}) })
except Exception as slot_err:
logger.error(f"[SPECTRAL] Error cargando slot {slot_idx} para {role}: {slot_err}")
continue
tracks_created.append({ # Contar samples para este rol
"role": role, count = len([s for s in samples_loaded if s.get('role') == role])
"track_index": track_index, track_info = {"role": role, "track_index": track_index, "samples_count": count}
"samples_count": len([s for s in samples_loaded if s['role'] == role]) tracks_created.append(track_info)
}) logger.info(f"[SPECTRAL] Track creado para {role}: index={track_index}, samples={count}")
except Exception as role_err:
logger.error(f"[SPECTRAL] Error procesando rol {role}: {role_err}")
import traceback
logger.error(f"[SPECTRAL] Traceback: {traceback.format_exc()}")
continue
conn.close() conn.close()
# Disparar clips para escuchar # Disparar clips para escuchar
for track_info in tracks_created: logger.info(f"[SPECTRAL] tracks_created: {len(tracks_created)} tracks")
if track_info['samples_count'] > 0: for i, track_info in enumerate(tracks_created):
logger.info(f"[SPECTRAL] Track {i}: {type(track_info)} - {track_info}")
try:
for idx, track_info in enumerate(tracks_created):
logger.info(f"[SPECTRAL] Procesando track {idx}: {type(track_info)}")
if not isinstance(track_info, dict):
logger.warning(f"[SPECTRAL] track_info no es dict: {type(track_info)}")
continue
logger.info(f"[SPECTRAL] Keys: {list(track_info.keys())}")
if 'track_index' not in track_info:
logger.warning(f"[SPECTRAL] track_info sin track_index: {track_info}")
continue
if track_info.get('samples_count', 0) > 0:
ti = track_info['track_index']
_send_to_ableton( _send_to_ableton(
"fire_clip", "fire_clip",
{"track_index": track_info['track_index'], "clip_index": 0}, {"track_index": ti, "clip_index": 0},
timeout=10.0 timeout=10.0
) )
except Exception as fire_err:
logger.error(f"[SPECTRAL] Error en fire_clip loop: {fire_err}")
import traceback
logger.error(f"[SPECTRAL] Traceback: {traceback.format_exc()}")
# Iniciar playback # Iniciar playback
_send_to_ableton("start_playback", {}, timeout=10.0) _send_to_ableton("start_playback", {}, timeout=10.0)
@@ -7188,7 +7276,9 @@ def produce_with_spectral_coherence(ctx: Context,
}) })
except Exception as e: except Exception as e:
import traceback
logger.error(f"[SPECTRAL] Error: {str(e)}") logger.error(f"[SPECTRAL] Error: {str(e)}")
logger.error(f"[SPECTRAL] Traceback: {traceback.format_exc()}")
return _err(f"Error en produccion espectral: {str(e)}") return _err(f"Error en produccion espectral: {str(e)}")