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,103 @@
"""
Human Feel Engine for AbletonMCP-AI
T040-T050: Humanización y dinámicas
"""
import random
from typing import List, Dict, Any
class HumanFeelEngine:
"""
T040-T050: Engine de humanización y dinámica.
Aplica variaciones de timing, velocity y groove a patrones MIDI.
"""
def __init__(self, seed: int = 42):
self.rng = random.Random(seed)
self._groove_templates = {
'straight': {'swing': 0.0, 'humanize': 0.0},
'shuffle': {'swing': 0.33, 'humanize': 0.02},
'triplet': {'swing': 0.66, 'humanize': 0.03},
'latin': {'swing': 0.25, 'humanize': 0.04},
}
def apply_timing_variation(self, notes: List[Dict], amount_ms: float = 5.0) -> List[Dict]:
"""T040: Micro-offsets de timing (-5ms a +5ms)."""
result = []
for note in notes:
offset = self.rng.uniform(-amount_ms, amount_ms) / 1000.0
new_note = dict(note)
new_note['start'] = note.get('start', 0) + offset
result.append(new_note)
return result
def apply_velocity_humanize(self, notes: List[Dict], variance: float = 0.05) -> List[Dict]:
"""T041: Humanización de velocity (±5% variación)."""
result = []
for note in notes:
vel = note.get('velocity', 100)
variation = self.rng.uniform(-variance, variance)
new_vel = int(vel * (1 + variation))
new_vel = max(1, min(127, new_vel))
new_note = dict(note)
new_note['velocity'] = new_vel
result.append(new_note)
return result
def apply_note_skip_probability(self, notes: List[Dict], prob: float = 0.02) -> List[Dict]:
"""T042: Probabilidad de skip nota (2% ghost notes)."""
result = []
for note in notes:
if self.rng.random() > prob:
result.append(note)
return result
def apply_groove(self, notes: List[Dict], style: str = 'shuffle', amount: float = 0.5) -> List[Dict]:
"""T044-T046: Aplica groove template."""
template = self._groove_templates.get(style, self._groove_templates['straight'])
swing = template['swing'] * amount
result = []
for note in notes:
start = note.get('start', 0)
beat_pos = start % 1.0
if 0.4 < beat_pos < 0.6:
delay = swing * 0.1
new_note = dict(note)
new_note['start'] = start + delay
result.append(new_note)
else:
result.append(note)
return result
def apply_section_dynamics(self, notes: List[Dict], section: str) -> List[Dict]:
"""T047-T050: Dinámica por sección (intro 70%, drop 100%, etc)."""
section_scales = {
'intro': 0.70,
'build': 0.85,
'drop': 1.00,
'break': 0.75,
'outro': 0.60,
}
scale = section_scales.get(section.lower(), 1.0)
result = []
for note in notes:
vel = note.get('velocity', 100)
new_vel = int(vel * scale)
new_vel = max(1, min(127, new_vel))
new_note = dict(note)
new_note['velocity'] = new_vel
result.append(new_note)
return result
def process_notes(self, notes: List[Dict], section: str = 'drop',
humanize: bool = True, groove_style: str = 'shuffle') -> List[Dict]:
"""Procesamiento completo con todos los efectos."""
result = list(notes)
if humanize:
result = self.apply_timing_variation(result)
result = self.apply_velocity_humanize(result)
result = self.apply_note_skip_probability(result)
result = self.apply_groove(result, groove_style)
result = self.apply_section_dynamics(result, section)
return result