chore: publish current ableton mcp ai workspace
This commit is contained in:
250
validate_audio_resampler.py
Normal file
250
validate_audio_resampler.py
Normal file
@@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script de validacion para el Audio Resampler.
|
||||
Verifica que:
|
||||
1. Las 4 funciones standalone existan y sean importables
|
||||
2. La clase AudioResampler funcione correctamente
|
||||
3. El cache LRU opera correctamente
|
||||
4. La integracion con build_transition_layers funcione
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Agregar el path del MCP_Server
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
mcp_server_dir = os.path.join(script_dir, "AbletonMCP_AI", "MCP_Server")
|
||||
sys.path.insert(0, mcp_server_dir)
|
||||
|
||||
def test_imports():
|
||||
"""Test 1: Verificar que todas las funciones se pueden importar"""
|
||||
print("=" * 60)
|
||||
print("TEST 1: Verificacion de imports")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
from audio_resampler import (
|
||||
AudioResampler,
|
||||
create_reverse_fx,
|
||||
create_riser_fx,
|
||||
create_downlifter_fx,
|
||||
create_stutter_fx,
|
||||
)
|
||||
print("[OK] Todos los imports exitosos")
|
||||
print(f" - AudioResampler: {AudioResampler}")
|
||||
print(f" - create_reverse_fx: {create_reverse_fx}")
|
||||
print(f" - create_riser_fx: {create_riser_fx}")
|
||||
print(f" - create_downlifter_fx: {create_downlifter_fx}")
|
||||
print(f" - create_stutter_fx: {create_stutter_fx}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Fallo en imports: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_class_structure():
|
||||
"""Test 2: Verificar estructura de la clase AudioResampler"""
|
||||
print("\n" + "=" * 60)
|
||||
print("TEST 2: Estructura de AudioResampler")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
from audio_resampler import AudioResampler
|
||||
|
||||
# Verificar metodos privados de FX
|
||||
required_methods = [
|
||||
'_render_reverse_fx',
|
||||
'_render_riser',
|
||||
'_render_downlifter',
|
||||
'_render_stutter',
|
||||
'_load_audio',
|
||||
'_write_audio',
|
||||
'_output_path',
|
||||
'build_transition_layers',
|
||||
'cache_stats',
|
||||
'clear_cache',
|
||||
]
|
||||
|
||||
resampler = AudioResampler()
|
||||
missing = []
|
||||
for method in required_methods:
|
||||
if not hasattr(resampler, method):
|
||||
missing.append(method)
|
||||
else:
|
||||
print(f"[OK] Metodo encontrado: {method}")
|
||||
|
||||
if missing:
|
||||
print(f"[ERROR] Metodos faltantes: {missing}")
|
||||
return False
|
||||
|
||||
# Verificar constantes de cache
|
||||
print(f"[OK] Cache limit: {resampler._CACHE_LIMIT}")
|
||||
print(f"[OK] Cache max age: {resampler._CACHE_MAX_AGE_S}s")
|
||||
print(f"[OK] Default peak: {resampler._DEFAULT_PEAK}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Fallo en estructura: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_cache_system():
|
||||
"""Test 3: Verificar sistema de cache"""
|
||||
print("\n" + "=" * 60)
|
||||
print("TEST 3: Sistema de Cache LRU")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
from audio_resampler import AudioResampler
|
||||
|
||||
resampler = AudioResampler()
|
||||
|
||||
# Verificar cache inicial vacio
|
||||
stats = resampler.cache_stats()
|
||||
print(f"[OK] Cache stats inicial: entries={stats['entries']}, hits={stats['hits']}")
|
||||
|
||||
# Verificar que el cache funciona (incluso sin audio)
|
||||
assert stats['entries'] == 0, "Cache deberia estar vacio al inicio"
|
||||
assert stats['max_entries'] == 50, "Cache limit deberia ser 50"
|
||||
assert stats['max_age_s'] == 1800.0, "Cache max age deberia ser 1800s"
|
||||
|
||||
print("[OK] Sistema de cache operando correctamente")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Fallo en cache: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_transition_layers_structure():
|
||||
"""Test 4: Verificar estructura de build_transition_layers"""
|
||||
print("\n" + "=" * 60)
|
||||
print("TEST 4: Estructura de build_transition_layers")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
from audio_resampler import AudioResampler
|
||||
|
||||
resampler = AudioResampler()
|
||||
|
||||
# Probar con un plan vacio
|
||||
empty_plan = {"matches": {}}
|
||||
sections = [
|
||||
{"kind": "intro", "name": "Intro", "beats": 16},
|
||||
{"kind": "build", "name": "Build Up", "beats": 16},
|
||||
{"kind": "drop", "name": "Drop A", "beats": 32},
|
||||
]
|
||||
|
||||
layers = resampler.build_transition_layers(empty_plan, sections, 128.0)
|
||||
|
||||
# Verificar que retorna una lista
|
||||
assert isinstance(layers, list), "Debe retornar una lista"
|
||||
print(f"[OK] build_transition_layers retorna lista: {len(layers)} capas")
|
||||
|
||||
# Verificar estructura de capas (si hay alguna)
|
||||
for i, layer in enumerate(layers):
|
||||
required_keys = ['name', 'file_path', 'positions', 'color', 'volume', 'source', 'generated']
|
||||
missing = [k for k in required_keys if k not in layer]
|
||||
if missing:
|
||||
print(f"[WARN] Capa {i} falta keys: {missing}")
|
||||
else:
|
||||
print(f"[OK] Capa {i} '{layer['name']}' estructura correcta")
|
||||
|
||||
print("[OK] build_transition_layers estructura correcta")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Fallo en transition_layers: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_function_signatures():
|
||||
"""Test 5: Verificar firmas de funciones standalone"""
|
||||
print("\n" + "=" * 60)
|
||||
print("TEST 5: Firmas de funciones standalone")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
from audio_resampler import (
|
||||
create_reverse_fx,
|
||||
create_riser_fx,
|
||||
create_downlifter_fx,
|
||||
create_stutter_fx,
|
||||
)
|
||||
import inspect
|
||||
|
||||
functions = [
|
||||
('create_reverse_fx', create_reverse_fx),
|
||||
('create_riser_fx', create_riser_fx),
|
||||
('create_downlifter_fx', create_downlifter_fx),
|
||||
('create_stutter_fx', create_stutter_fx),
|
||||
]
|
||||
|
||||
for name, func in functions:
|
||||
sig = inspect.signature(func)
|
||||
params = list(sig.parameters.keys())
|
||||
|
||||
# Verificar parametros minimos
|
||||
assert 'source_path' in params, f"{name} debe tener source_path"
|
||||
assert 'output_path' in params, f"{name} debe tener output_path"
|
||||
|
||||
print(f"[OK] {name} firma: {sig}")
|
||||
|
||||
print("[OK] Todas las funciones tienen firmas correctas")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Fallo en firmas: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Ejecutar todos los tests"""
|
||||
print("\n" + "=" * 60)
|
||||
print("VALIDACION DE AUDIO RESAMPLER")
|
||||
print("=" * 60)
|
||||
|
||||
results = [
|
||||
("Imports", test_imports),
|
||||
("Estructura de clase", test_class_structure),
|
||||
("Sistema de cache", test_cache_system),
|
||||
("Transition layers", test_transition_layers_structure),
|
||||
("Firmas de funciones", test_function_signatures),
|
||||
]
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for name, test_func in results:
|
||||
try:
|
||||
if test_func():
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
except Exception as e:
|
||||
print(f"\n[ERROR CRITICO] {name}: {e}")
|
||||
failed += 1
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("RESUMEN DE VALIDACION")
|
||||
print("=" * 60)
|
||||
print(f"Tests pasados: {passed}/{len(results)}")
|
||||
print(f"Tests fallidos: {failed}/{len(results)}")
|
||||
|
||||
if failed == 0:
|
||||
print("\n[OK] Audio Resampler validado exitosamente!")
|
||||
return 0
|
||||
else:
|
||||
print("\n[ERROR] Algunos tests fallaron")
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user