feat(Agente 1): Implement FX Creator MCP Tools (T031-T035)
- Add 5 new MCP tools to server.py: * create_riser (T031) - Pre-drop buildup effect * create_downlifter (T032) - Post-drop energy release * create_impact (T033) - Hit, crash, sub_drop, noise impacts * create_silence (T034) - Break/silence effects * create_fx_section (T035) - Complete FX sections - Add 5 handlers to __init__.py for Remote Script execution - Update skill_produccion_audio.md with FX tools documentation All tools exposed and ready for professional FX generation. Closes Agente 1 of 20 - FX Creator implementation
This commit is contained in:
137
__init__.py
137
__init__.py
@@ -1385,6 +1385,143 @@ class _AbletonMCP(ControlSurface):
|
||||
"note": "Automation envelope planned; direct parameter automation is limited in this API context",
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# FX CREATOR HANDLERS (T031-T035) - Professional FX generation
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _cmd_create_riser(self, track_index, start_bar, duration=8, intensity=0.8,
|
||||
pitch_range=None, **kw):
|
||||
"""T031: Create a riser/buildup effect."""
|
||||
try:
|
||||
from .mcp_server.engines.arrangement_engine import FXCreator
|
||||
fx_creator = FXCreator()
|
||||
if pitch_range is None:
|
||||
pitch_range = (36, 84)
|
||||
clip = fx_creator.create_riser(
|
||||
track_index=int(track_index),
|
||||
start_bar=int(start_bar),
|
||||
duration=int(duration),
|
||||
intensity=float(intensity),
|
||||
pitch_range=tuple(pitch_range)
|
||||
)
|
||||
return {
|
||||
"success": True,
|
||||
"clip_name": clip.name,
|
||||
"track_index": clip.track_index,
|
||||
"start_time": clip.start_time,
|
||||
"duration": clip.duration,
|
||||
"note_count": len(clip.notes) if clip.notes else 0,
|
||||
}
|
||||
except Exception as e:
|
||||
self.log_message("Error creating riser: " + str(e))
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def _cmd_create_downlifter(self, track_index, start_bar, duration=4, intensity=0.7,
|
||||
pitch_range=None, **kw):
|
||||
"""T032: Create a downlifter effect."""
|
||||
try:
|
||||
from .mcp_server.engines.arrangement_engine import FXCreator
|
||||
fx_creator = FXCreator()
|
||||
if pitch_range is None:
|
||||
pitch_range = (72, 36)
|
||||
clip = fx_creator.create_downlifter(
|
||||
track_index=int(track_index),
|
||||
start_bar=int(start_bar),
|
||||
duration=int(duration),
|
||||
intensity=float(intensity),
|
||||
pitch_range=tuple(pitch_range)
|
||||
)
|
||||
return {
|
||||
"success": True,
|
||||
"clip_name": clip.name,
|
||||
"track_index": clip.track_index,
|
||||
"start_time": clip.start_time,
|
||||
"duration": clip.duration,
|
||||
"note_count": len(clip.notes) if clip.notes else 0,
|
||||
}
|
||||
except Exception as e:
|
||||
self.log_message("Error creating downlifter: " + str(e))
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def _cmd_create_impact(self, track_index, position, intensity=1.0, impact_type="hit", **kw):
|
||||
"""T033: Create an impact FX."""
|
||||
try:
|
||||
from .mcp_server.engines.arrangement_engine import FXCreator
|
||||
fx_creator = FXCreator()
|
||||
clip = fx_creator.create_impact(
|
||||
track_index=int(track_index),
|
||||
position=float(position),
|
||||
intensity=float(intensity),
|
||||
impact_type=str(impact_type)
|
||||
)
|
||||
return {
|
||||
"success": True,
|
||||
"clip_name": clip.name,
|
||||
"track_index": clip.track_index,
|
||||
"start_time": clip.start_time,
|
||||
"duration": clip.duration,
|
||||
"impact_type": impact_type,
|
||||
}
|
||||
except Exception as e:
|
||||
self.log_message("Error creating impact: " + str(e))
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def _cmd_create_silence(self, track_index, start_bar, duration=1, **kw):
|
||||
"""T034: Create silence/break effect."""
|
||||
try:
|
||||
from .mcp_server.engines.arrangement_engine import FXCreator
|
||||
fx_creator = FXCreator()
|
||||
clip = fx_creator.create_silence(
|
||||
track_index=int(track_index),
|
||||
start_bar=int(start_bar),
|
||||
duration=int(duration)
|
||||
)
|
||||
return {
|
||||
"success": True,
|
||||
"clip_name": clip.name,
|
||||
"track_index": clip.track_index,
|
||||
"start_time": clip.start_time,
|
||||
"duration": clip.duration,
|
||||
}
|
||||
except Exception as e:
|
||||
self.log_message("Error creating silence: " + str(e))
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def _cmd_create_fx_section(self, section_type, start_bar, duration=8, track_indices=None, **kw):
|
||||
"""T035: Create complete FX section."""
|
||||
try:
|
||||
from .mcp_server.engines.arrangement_engine import FXCreator
|
||||
fx_creator = FXCreator()
|
||||
section_type = str(section_type).lower()
|
||||
start_bar = int(start_bar)
|
||||
duration = int(duration)
|
||||
created_clips = []
|
||||
if section_type in ["pre_drop", "build"]:
|
||||
riser = fx_creator.create_riser(track_index=0, start_bar=start_bar,
|
||||
duration=duration-1, intensity=0.8)
|
||||
impact = fx_creator.create_impact(track_index=0, position=start_bar+duration-1,
|
||||
intensity=1.0, impact_type="hit")
|
||||
created_clips = [riser.name, impact.name]
|
||||
elif section_type == "post_drop":
|
||||
downlifter = fx_creator.create_downlifter(track_index=0, start_bar=start_bar,
|
||||
duration=duration, intensity=0.7)
|
||||
created_clips = [downlifter.name]
|
||||
elif section_type == "transition":
|
||||
silence = fx_creator.create_silence(track_index=0, start_bar=start_bar, duration=1)
|
||||
impact = fx_creator.create_impact(track_index=0, position=start_bar+1,
|
||||
intensity=1.0, impact_type="crash")
|
||||
created_clips = [silence.name, impact.name]
|
||||
return {
|
||||
"success": True,
|
||||
"section_type": section_type,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
"created_clips": created_clips,
|
||||
}
|
||||
except Exception as e:
|
||||
self.log_message("Error creating FX section: " + str(e))
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# MIXING HANDLERS (T016-T020) - Real mixing workflow
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
Binary file not shown.
@@ -67,7 +67,64 @@ ableton-live-mcp_create_arrangement_audio_pattern(
|
||||
)
|
||||
```
|
||||
|
||||
### Paso 5: Verificación Visual
|
||||
### Paso 5: FX y Transiciones Profesionales (T031-T035)
|
||||
|
||||
#### Crear Riser/Buildup (T031)
|
||||
```python
|
||||
# Riser de 8 compases antes del drop
|
||||
ableton-live-mcp_create_riser(
|
||||
track_index=7,
|
||||
start_bar=24, # Empezar en compás 24
|
||||
duration=8, # 8 compases de duración
|
||||
intensity=0.8, # Intensidad 80%
|
||||
pitch_min=36, # C2
|
||||
pitch_max=84 # C6
|
||||
)
|
||||
```
|
||||
|
||||
#### Crear Downlifter (T032)
|
||||
```python
|
||||
# Downlifter post-drop
|
||||
ableton-live-mcp_create_downlifter(
|
||||
track_index=7,
|
||||
start_bar=32, # Después del drop
|
||||
duration=4,
|
||||
intensity=0.7
|
||||
)
|
||||
```
|
||||
|
||||
#### Crear Impact FX (T033)
|
||||
```python
|
||||
# Impact en el drop
|
||||
ableton-live-mcp_create_impact(
|
||||
track_index=7,
|
||||
position=32, # Compás 32
|
||||
intensity=1.0,
|
||||
impact_type="hit" # Options: "hit", "crash", "sub_drop", "noise"
|
||||
)
|
||||
```
|
||||
|
||||
#### Crear Sección FX Completa (T035)
|
||||
```python
|
||||
# Sección completa con riser + impact
|
||||
ableton-live-mcp_create_fx_section(
|
||||
section_type="pre_drop", # "pre_drop", "post_drop", "transition", "build"
|
||||
start_bar=24,
|
||||
duration=8
|
||||
)
|
||||
```
|
||||
|
||||
#### Silence/Break Effect (T034)
|
||||
```python
|
||||
# Break de 1 compás para tensión
|
||||
ableton-live-mcp_create_silence(
|
||||
track_index=0,
|
||||
start_bar=31,
|
||||
duration=1
|
||||
)
|
||||
```
|
||||
|
||||
### Paso 6: Verificación Visual
|
||||
```python
|
||||
# Confirmar clips en Arrangement View
|
||||
ableton-live-mcp_get_arrangement_status
|
||||
|
||||
Binary file not shown.
@@ -2565,6 +2565,188 @@ def automate_filter(ctx: Context, track_index: int, start_bar: float = 0.0,
|
||||
)
|
||||
|
||||
|
||||
# ==================================================================
|
||||
# FASE 2.5: FX CREATOR TOOLS (T031-T035) - Exposición de arrangement_engine
|
||||
# ==================================================================
|
||||
|
||||
@mcp.tool()
|
||||
def create_riser(ctx: Context, track_index: int, start_bar: int,
|
||||
duration: int = 8, intensity: float = 0.8,
|
||||
pitch_min: int = 36, pitch_max: int = 84) -> str:
|
||||
"""Create a riser/buildup effect (T031).
|
||||
|
||||
Generates a pre-drop riser with ascending pitch and tension.
|
||||
Perfect for build-ups before choruses or drops.
|
||||
|
||||
Args:
|
||||
track_index: Index of the target track
|
||||
start_bar: Start bar for the riser
|
||||
duration: Duration in bars (default 8)
|
||||
intensity: Intensity 0.0-1.0 (default 0.8)
|
||||
pitch_min: Minimum MIDI pitch (default 36 = C2)
|
||||
pitch_max: Maximum MIDI pitch (default 84 = C6)
|
||||
|
||||
Returns:
|
||||
JSON with riser creation status and clip info.
|
||||
"""
|
||||
return _proxy_ableton_command(
|
||||
"create_riser",
|
||||
{
|
||||
"track_index": track_index,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
"intensity": intensity,
|
||||
"pitch_range": [pitch_min, pitch_max],
|
||||
},
|
||||
timeout=30.0,
|
||||
defaults={
|
||||
"track_index": track_index,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
"intensity": intensity,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def create_downlifter(ctx: Context, track_index: int, start_bar: int,
|
||||
duration: int = 4, intensity: float = 0.7,
|
||||
pitch_start: int = 72, pitch_end: int = 36) -> str:
|
||||
"""Create a downlifter effect (T032).
|
||||
|
||||
Generates a post-drop downlifter with descending pitch.
|
||||
Perfect for energy release after drops or impacts.
|
||||
|
||||
Args:
|
||||
track_index: Index of the target track
|
||||
start_bar: Start bar for the downlifter
|
||||
duration: Duration in bars (default 4)
|
||||
intensity: Intensity 0.0-1.0 (default 0.7)
|
||||
pitch_start: Starting MIDI pitch (default 72 = C5)
|
||||
pitch_end: Ending MIDI pitch (default 36 = C2)
|
||||
|
||||
Returns:
|
||||
JSON with downlifter creation status and clip info.
|
||||
"""
|
||||
return _proxy_ableton_command(
|
||||
"create_downlifter",
|
||||
{
|
||||
"track_index": track_index,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
"intensity": intensity,
|
||||
"pitch_range": [pitch_start, pitch_end],
|
||||
},
|
||||
timeout=30.0,
|
||||
defaults={
|
||||
"track_index": track_index,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
"intensity": intensity,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def create_impact(ctx: Context, track_index: int, position: float,
|
||||
intensity: float = 1.0, impact_type: str = "hit") -> str:
|
||||
"""Create an impact FX (T033).
|
||||
|
||||
Generates impact effects (hit, crash, sub drop, noise).
|
||||
Perfect for emphasizing drops, transitions, or beats.
|
||||
|
||||
Args:
|
||||
track_index: Index of the target track
|
||||
position: Position in bars (int) or beats (float)
|
||||
intensity: Intensity 0.0-1.0 (default 1.0)
|
||||
impact_type: Type of impact - "hit", "crash", "sub_drop", "noise"
|
||||
|
||||
Returns:
|
||||
JSON with impact creation status and clip info.
|
||||
"""
|
||||
return _proxy_ableton_command(
|
||||
"create_impact",
|
||||
{
|
||||
"track_index": track_index,
|
||||
"position": position,
|
||||
"intensity": intensity,
|
||||
"impact_type": impact_type,
|
||||
},
|
||||
timeout=30.0,
|
||||
defaults={
|
||||
"track_index": track_index,
|
||||
"position": position,
|
||||
"intensity": intensity,
|
||||
"impact_type": impact_type,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def create_silence(ctx: Context, track_index: int, start_bar: int,
|
||||
duration: int = 1) -> str:
|
||||
"""Create silence/break effect (T034).
|
||||
|
||||
Generates a moment of silence for dramatic effect.
|
||||
Perfect for creating tension before drops.
|
||||
|
||||
Args:
|
||||
track_index: Index of the target track (for context)
|
||||
start_bar: Start bar for the silence
|
||||
duration: Duration in bars (default 1)
|
||||
|
||||
Returns:
|
||||
JSON with silence creation status.
|
||||
"""
|
||||
return _proxy_ableton_command(
|
||||
"create_silence",
|
||||
{
|
||||
"track_index": track_index,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
},
|
||||
timeout=30.0,
|
||||
defaults={
|
||||
"track_index": track_index,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def create_fx_section(ctx: Context, section_type: str, start_bar: int,
|
||||
duration: int = 8, track_indices: list = None) -> str:
|
||||
"""Create complete FX section (T035).
|
||||
|
||||
Generates a complete FX section with risers, impacts, and transitions.
|
||||
|
||||
Args:
|
||||
section_type: Type - "pre_drop", "post_drop", "transition", "build"
|
||||
start_bar: Start bar for the section
|
||||
duration: Duration in bars (default 8)
|
||||
track_indices: List of track indices to apply FX (optional)
|
||||
|
||||
Returns:
|
||||
JSON with FX section creation status.
|
||||
"""
|
||||
return _proxy_ableton_command(
|
||||
"create_fx_section",
|
||||
{
|
||||
"section_type": section_type,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
"track_indices": track_indices or [],
|
||||
},
|
||||
timeout=30.0,
|
||||
defaults={
|
||||
"section_type": section_type,
|
||||
"start_bar": start_bar,
|
||||
"duration": duration,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
# ==================================================================
|
||||
# FASE 3: INTELIGENCIA MUSICAL (T041-T060)
|
||||
# ==================================================================
|
||||
|
||||
Reference in New Issue
Block a user