- MCP Server with audio fallback, sample management - Song generator with bus routing - Reference listener and audio resampler - Vector-based sample search - Master chain with limiter and calibration - Fix: Audio fallback now works without M4L - Fix: Full song detection in sample loader Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
245 lines
6.7 KiB
Python
245 lines
6.7 KiB
Python
"""
|
|
Demo del Sistema de Gestión de Samples para AbletonMCP-AI
|
|
|
|
Este script demuestra las capacidades del sistema completo de samples.
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
|
|
from sample_manager import get_manager
|
|
from sample_selector import get_selector
|
|
from audio_analyzer import analyze_sample, AudioAnalyzer
|
|
|
|
|
|
def demo_analyzer():
|
|
"""Demostración del analizador de audio"""
|
|
print("=" * 60)
|
|
print("DEMO: Audio Analyzer")
|
|
print("=" * 60)
|
|
|
|
AudioAnalyzer(backend='basic')
|
|
|
|
# Analizar un archivo de ejemplo
|
|
test_file = r"C:\Users\ren\embeddings\all_tracks\BBH - Primer Impacto - Kick 1.wav"
|
|
|
|
print(f"\nAnalizando: {Path(test_file).name}")
|
|
print("-" * 40)
|
|
|
|
try:
|
|
result = analyze_sample(test_file)
|
|
|
|
print(f"Tipo detectado: {result['sample_type']}")
|
|
print(f"BPM: {result.get('bpm') or 'No detectado'}")
|
|
print(f"Key: {result.get('key') or 'No detectado'}")
|
|
print(f"Duración: {result['duration']:.3f}s")
|
|
print(f"Es percusivo: {result['is_percussive']}")
|
|
print(f"Géneros sugeridos: {', '.join(result['suggested_genres'])}")
|
|
|
|
except Exception as e:
|
|
print(f"Error: {e}")
|
|
|
|
print()
|
|
|
|
|
|
def demo_manager():
|
|
"""Demostración del gestor de samples"""
|
|
print("=" * 60)
|
|
print("DEMO: Sample Manager")
|
|
print("=" * 60)
|
|
|
|
manager = get_manager(r"C:\Users\ren\embeddings\all_tracks")
|
|
|
|
# Escanear librería
|
|
print("\nEscaneando librería...")
|
|
stats = manager.scan_directory()
|
|
print(f" Samples procesados: {stats['processed']}")
|
|
print(f" Nuevos: {stats['added']}")
|
|
print(f" Total en librería: {stats['total_samples']}")
|
|
|
|
# Estadísticas
|
|
print("\nEstadísticas:")
|
|
stats = manager.get_stats()
|
|
print(f" Total: {stats['total_samples']} samples")
|
|
print(f" Tamaño: {stats['total_size'] / (1024**2):.1f} MB")
|
|
|
|
if stats['by_category']:
|
|
print("\n Por categoría:")
|
|
for cat, count in sorted(stats['by_category'].items(), key=lambda x: -x[1]):
|
|
print(f" {cat}: {count}")
|
|
|
|
if stats['by_key']:
|
|
print("\n Por key:")
|
|
for key, count in sorted(stats['by_key'].items(), key=lambda x: -x[1]):
|
|
print(f" {key}: {count}")
|
|
|
|
# Búsquedas
|
|
print("\nBúsquedas:")
|
|
print("-" * 40)
|
|
|
|
# Buscar kicks
|
|
kicks = manager.search(sample_type="kick", limit=3)
|
|
print(f"\nKicks encontrados: {len(kicks)}")
|
|
for s in kicks:
|
|
print(f" - {s.name}")
|
|
|
|
# Buscar por key
|
|
g_sharp = manager.search(key="G#m", limit=3)
|
|
print(f"\nSamples en G#m: {len(g_sharp)}")
|
|
for s in g_sharp:
|
|
print(f" - {s.name} ({s.sample_type})")
|
|
|
|
# Buscar por BPM
|
|
bpm_128 = manager.search(bpm=128, bpm_tolerance=5, limit=3)
|
|
print(f"\nSamples ~128 BPM: {len(bpm_128)}")
|
|
for s in bpm_128:
|
|
key_info = f" [{s.key}]" if s.key else ""
|
|
print(f" - {s.name}{key_info}")
|
|
|
|
print()
|
|
|
|
|
|
def demo_selector():
|
|
"""Demostración del selector inteligente"""
|
|
print("=" * 60)
|
|
print("DEMO: Sample Selector")
|
|
print("=" * 60)
|
|
|
|
selector = get_selector()
|
|
|
|
# Seleccionar para diferentes géneros
|
|
genres = ['techno', 'house', 'tech-house']
|
|
|
|
for genre in genres:
|
|
print(f"\n{genre.upper()}:")
|
|
print("-" * 40)
|
|
|
|
group = selector.select_for_genre(genre, key='Am', bpm=128)
|
|
|
|
print(f" Key: {group.key} | BPM: {group.bpm}")
|
|
|
|
# Drum kit
|
|
kit = group.drums
|
|
print("\n Drum Kit:")
|
|
if kit.kick:
|
|
print(f" Kick: {kit.kick.name}")
|
|
if kit.snare:
|
|
print(f" Snare: {kit.snare.name}")
|
|
if kit.clap:
|
|
print(f" Clap: {kit.clap.name}")
|
|
if kit.hat_closed:
|
|
print(f" Hat: {kit.hat_closed.name}")
|
|
|
|
# Mapeo MIDI
|
|
mapping = selector.get_midi_mapping_for_kit(kit)
|
|
print("\n Mapeo MIDI:")
|
|
for note, info in sorted(mapping['notes'].items())[:4]:
|
|
if info['sample']:
|
|
print(f" Note {note}: {info['sample'][:40]}...")
|
|
|
|
# Bass
|
|
if group.bass:
|
|
print(f"\n Bass ({len(group.bass)}):")
|
|
for s in group.bass[:2]:
|
|
key_info = f" [{s.key}]" if s.key else ""
|
|
print(f" - {s.name}{key_info}")
|
|
|
|
# Cambio de key
|
|
print("\n" + "-" * 40)
|
|
print("Cambios de Key Sugeridos (desde Am):")
|
|
changes = ['fifth_up', 'fifth_down', 'relative', 'parallel']
|
|
for change in changes:
|
|
new_key = selector.suggest_key_change('Am', change)
|
|
print(f" {change}: {new_key}")
|
|
|
|
print()
|
|
|
|
|
|
def demo_compatibility():
|
|
"""Demostración de búsqueda de samples compatibles"""
|
|
print("=" * 60)
|
|
print("DEMO: Compatibilidad de Samples")
|
|
print("=" * 60)
|
|
|
|
manager = get_manager()
|
|
selector = get_selector()
|
|
|
|
# Encontrar un sample con key para usar de referencia
|
|
samples_with_key = manager.search(key="G#m", limit=1)
|
|
|
|
if samples_with_key:
|
|
reference = samples_with_key[0]
|
|
print(f"\nSample de referencia: {reference.name}")
|
|
print(f" Key: {reference.key} | BPM: {reference.bpm}")
|
|
|
|
# Buscar compatibles
|
|
compatible = selector.find_compatible_samples(reference, max_results=5)
|
|
|
|
print("\nSamples compatibles:")
|
|
print("-" * 40)
|
|
|
|
for sample, score in compatible:
|
|
bar_len = int(score * 20)
|
|
bar = "█" * bar_len + "░" * (20 - bar_len)
|
|
print(f" [{bar}] {score:.1%} - {sample.name}")
|
|
|
|
print()
|
|
|
|
|
|
def demo_pack_generation():
|
|
"""Demostración de generación de packs"""
|
|
print("=" * 60)
|
|
print("DEMO: Generación de Sample Packs")
|
|
print("=" * 60)
|
|
|
|
manager = get_manager()
|
|
|
|
genres = ['techno', 'house', 'deep-house']
|
|
|
|
for genre in genres:
|
|
print(f"\n{genre.upper()} Pack:")
|
|
print("-" * 40)
|
|
|
|
pack = manager.get_pack_for_genre(genre, key='Am', bpm=128)
|
|
|
|
total = 0
|
|
for category, samples in pack.items():
|
|
if samples:
|
|
count = len(samples)
|
|
total += count
|
|
print(f" {category}: {count}")
|
|
|
|
print(f" Total: {total} samples")
|
|
|
|
print()
|
|
|
|
|
|
def main():
|
|
"""Ejecutar todas las demos"""
|
|
print("\n")
|
|
print("=" * 60)
|
|
print(" AbletonMCP-AI Sample System Demo ".center(60))
|
|
print("=" * 60)
|
|
print()
|
|
|
|
try:
|
|
demo_analyzer()
|
|
demo_manager()
|
|
demo_selector()
|
|
demo_compatibility()
|
|
demo_pack_generation()
|
|
|
|
print("=" * 60)
|
|
print("Todas las demos completadas exitosamente!")
|
|
print("=" * 60)
|
|
|
|
except Exception as e:
|
|
print(f"\nError en demo: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|