Implement FASE 3, 4, 6 - 15 new MCP tools, 76/110 tasks complete

FASE 3 - Human Feel & Dynamics (10/11 tasks):
- apply_clip_fades() - T041: Fade automation per section
- write_volume_automation() - T042: Curves (linear, exp, s_curve, punch)
- apply_sidechain_pump() - T045: Sidechain by intensity/style
- inject_pattern_fills() - T048: Snare rolls, fills by density
- humanize_set() - T050: Timing + velocity + groove automation

FASE 4 - Key Compatibility & Tonal (9/12 tasks):
- audio_key_compatibility.py: Full KEY_COMPATIBILITY_MATRIX
- analyze_key_compatibility() - T053: Harmonic compatibility scoring
- suggest_key_change() - T054: Circle of fifths modulation
- validate_sample_key() - T055: Sample key validation
- analyze_spectral_fit() - T057/T062: Spectral role matching

FASE 6 - Mastering & QA (8/13 tasks):
- calibrate_gain_staging() - T079: Auto gain by bus targets
- run_mix_quality_check() - T085: LUFS, peaks, L/R balance
- export_stem_mixdown() - T087: 24-bit/44.1kHz stem export

New files:
- audio_key_compatibility.py (T052)
- bus_routing_fix.py (T101-T104)
- validation_system_fix.py (T105-T106)

Total: 76/110 tasks (69%), 71 MCP tools exposed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renato97
2026-03-29 00:59:24 -03:00
parent ed6f75c49f
commit 4332ff65da
24 changed files with 6586 additions and 38 deletions

View File

@@ -0,0 +1,192 @@
"""
full_integration.py - Integración completa de todas las fases
Este módulo conecta todos los nuevos engines con el flujo principal.
"""
import logging
from typing import Dict, Any, List, Optional
from pathlib import Path
# Imports de todos los nuevos módulos
from human_feel import HumanFeelEngine
from audio_soundscape import SoundscapeEngine, FXEngine, TonalAnalyzer
from audio_arrangement import DJArrangementEngine, TransitionEngine
from audio_mastering import MasterChain, LoudnessAnalyzer, QASuite, MasteringPreset
from self_ai import AutoPrompter, CritiqueEngine, AutoFixEngine
logger = logging.getLogger("FullIntegration")
class AbletonMCPFullPipeline:
"""
Pipeline completo que integra todas las fases:
1. Auto-prompter (Fase 7)
2. Palette selection (Fase 2)
3. Arrangement generation (Fase 5)
4. Human feel (Fase 3)
5. Soundscape/FX (Fase 4)
6. Mastering (Fase 6)
7. QA validation (Fase 6)
8. Critique & Auto-fix (Fase 7)
"""
def __init__(self, seed: int = 42):
self.seed = seed
self.human_engine = HumanFeelEngine(seed=seed)
self.soundscape_engine = SoundscapeEngine()
self.fx_engine = FXEngine()
self.tonal_analyzer = TonalAnalyzer()
self.arrangement_engine = DJArrangementEngine(seed=seed)
self.transition_engine = TransitionEngine()
self.master_chain = MasterChain()
self.loudness_analyzer = LoudnessAnalyzer()
self.qa_suite = QASuite()
self.auto_prompter = AutoPrompter()
self.critique_engine = CritiqueEngine()
self.auto_fix_engine = AutoFixEngine()
def generate_from_vibe(self, vibe_text: str, apply_full_pipeline: bool = True) -> Dict[str, Any]:
"""
Generación completa desde descripción de vibe.
Args:
vibe_text: Descripción (ej: "dark warehouse techno")
apply_full_pipeline: Si aplicar todas las fases
Returns:
Dict con configuración completa del track
"""
logger.info(f"Starting generation from vibe: '{vibe_text}'")
# Fase 7: Auto-prompter
params = self.auto_prompter.generate_from_vibe(vibe_text)
logger.info(f"Detected: genre={params['genre']}, bpm={params['bpm']}, key={params['key']}")
# Preparar configuración
config = {
'vibe_params': params,
'genre': params['genre'],
'bpm': params['bpm'],
'key': params['key'],
'style': params['style'],
'structure_type': params['structure'],
'seed': self.seed,
}
if apply_full_pipeline:
config = self._apply_full_pipeline(config)
return config
def _apply_full_pipeline(self, config: Dict[str, Any]) -> Dict[str, Any]:
"""Aplica todas las fases del pipeline."""
# Fase 5: Generar estructura
structure = self.arrangement_engine.generate_structure(config.get('structure_type', 'standard'))
config['structure'] = [
{'name': s.name, 'kind': s.kind, 'bars': s.bars, 'energy': s.energy}
for s in structure
]
config['dj_friendly'] = self.arrangement_engine.is_dj_friendly(structure)
# Fase 5: Transiciones
transitions = self.transition_engine.generate_all_transitions(structure)
config['transitions'] = transitions
# Fase 4: Soundscape gaps
timeline = [{'start': 0, 'end': s.bars * 4, 'kind': s.kind} for s in structure]
gaps = self.soundscape_engine.detect_ambience_gaps(timeline)
atmos_events = self.soundscape_engine.fill_with_atmos(gaps, config['genre'], config['key'])
config['atmos_events'] = atmos_events
# Fase 4: FX automáticos
fx_events = []
for section in structure:
if section.kind == 'drop':
riser = self.fx_engine.auto_riser_before_drop(section.bars * 4, 8)
snare_roll = self.fx_engine.auto_snare_roll(section.bars * 4, 4)
fx_events.extend([riser, snare_roll])
config['fx_events'] = fx_events
# Fase 6: Master chain
preset = MasteringPreset.get_preset('club' if 'techno' in config['genre'] else 'streaming')
self.master_chain.set_limiter_ceiling(preset['ceiling'])
config['master_chain'] = self.master_chain.get_ableton_device_chain()
# Fase 3: Configurar human feel
config['human_feel'] = {
'enabled': True,
'timing_variation_ms': 5.0,
'velocity_variance': 0.05,
'note_skip_prob': 0.02,
'groove_style': 'shuffle',
'section_dynamics': True,
}
return config
def critique_and_fix(self, song_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Fase 7: Critique loop y auto-fix.
Args:
song_data: Datos de la canción generada
Returns:
Resultado con scores y fixes aplicados
"""
# Critique
critique = self.critique_engine.critique_song(song_data)
# Auto-fix si hay weaknesses
if critique['weaknesses']:
fixes = self.auto_fix_engine.auto_fix(critique, song_data)
return {
'critique': critique,
'fixes': fixes,
'final_score': fixes['after_score']
}
return {
'critique': critique,
'fixes': None,
'final_score': critique['overall_score']
}
def validate_master(self, audio_data: Any) -> Dict[str, Any]:
"""
Fase 6: Validación completa del master.
Args:
audio_data: Datos de audio a validar
Returns:
Reporte QA
"""
return self.qa_suite.run_full_qa(audio_data, {})
# Instancia global
_full_pipeline: Optional[AbletonMCPFullPipeline] = None
def get_full_pipeline(seed: int = 42) -> AbletonMCPFullPipeline:
"""Obtiene instancia del pipeline completo."""
global _full_pipeline
if _full_pipeline is None:
_full_pipeline = AbletonMCPFullPipeline(seed=seed)
return _full_pipeline
def generate_complete_track(vibe_text: str, seed: int = 42) -> Dict[str, Any]:
"""
Función de conveniencia para generar un track completo.
Args:
vibe_text: Descripción del vibe deseado
seed: Seed para reproducibilidad
Returns:
Configuración completa lista para AbletonMCP
"""
pipeline = get_full_pipeline(seed)
return pipeline.generate_from_vibe(vibe_text, apply_full_pipeline=True)