Computed Values in Aliases¶
Overview¶
Computed values allow you to perform calculations and transformations on alias parameters before they're used in MIDI commands. This powerful feature lets you create more intuitive aliases that hide complex MIDI details and let musicians think in natural units like BPM, percentages, decibels, or time values.
Table of Contents¶
- Basic Syntax
- Why Use Computed Values?
- Available Functions
- Real-World Examples
- Best Practices
- Security and Limitations
- Troubleshooting
Basic Syntax¶
Computed values are defined using curly braces with an assignment expression:
@alias alias_name {param1} {param2} "Description"
{computed_var = expression}
- command using {computed_var}
@end
Simple Example¶
@alias double_value {ch} {value:0-63} "Double a value"
{doubled = ${value} * 2}
- cc {ch}.7.{doubled}
@end
# Usage
- double_value 1 50 # Sends CC 1.7.100
Key Points¶
- Variable Reference: Use
${param}to reference alias parameters in expressions - Multiple Computed Values: You can define multiple computed variables
- Order Matters: Computed values are evaluated in the order they appear
- Dependency: Later computed values can reference earlier ones
Why Use Computed Values?¶
1. Hide MIDI Complexity¶
MIDI uses 0-127 values, but musicians think in different units:
# Without computed values (confusing)
@alias set_tempo {ch} {midi_val:0-127} "Set tempo"
- cc {ch}.14.{midi_val}
@end
- set_tempo 1 39 # What BPM is this?
# With computed values (intuitive)
@alias set_tempo {ch} {bpm:40-300} "Set tempo in BPM"
{midi_val = int((${bpm} - 40) * 127 / 260)}
- cc {ch}.14.{midi_val}
@end
- set_tempo 1 120 # Clear: 120 BPM
2. Automate Complex Calculations¶
# 14-bit MIDI value splitting
@alias pitch_bend_14bit {ch} {value:0-16383} "High-res pitch"
{msb_val = msb(${value})}
{lsb_val = lsb(${value})}
- cc {ch}.64.{msb_val}
- cc {ch}.96.{lsb_val}
@end
3. Ensure Correctness¶
Computed values prevent manual calculation errors:
# Complementary mix (A + B = 100%)
@alias mix_ab {ch} {a_percent:0-100} "A/B mix"
{b_percent = 100 - ${a_percent}}
{a_midi = int(${a_percent} * 127 / 100)}
{b_midi = int(${b_percent} * 127 / 100)}
- cc {ch}.84.{a_midi}
- cc {ch}.85.{b_midi}
@end
4. Create Parameter Relationships¶
# Linked cutoff and resonance
@alias filter_sweep {ch} {cutoff:0-127} "Filter with auto-resonance"
{resonance = clamp(int(${cutoff} / 2), 0, 80)}
- cc {ch}.74.{cutoff} # Cutoff
- cc {ch}.71.{resonance} # Resonance (half of cutoff, max 80)
@end
Available Functions¶
Arithmetic Operators¶
+- Addition-- Subtraction*- Multiplication/- Division (floating point)//- Integer division (floor division)%- Modulo (remainder)**- Exponentiation
Built-in Functions¶
int(value)¶
Convert to integer (truncate decimals).
float(value)¶
Convert to floating point number.
round(value[, decimals])¶
Round to nearest integer or specified decimal places.
{rounded = round(${value} * 1.5)} # Round to integer
{precise = round(${value} * 1.5, 2)} # Round to 2 decimal places
abs(value)¶
Get absolute value (remove negative sign).
min(a, b, ...)¶
Return the smallest value.
max(a, b, ...)¶
Return the largest value.
MIDI Helper Functions¶
clamp(value, min, max)¶
Constrain value to range [min, max].
Use Case: Prevent values from exceeding MIDI limits after calculations.
scale_range(value, from_min, from_max, to_min, to_max)¶
Map value from one range to another (linear interpolation).
# Map 0-100% to MIDI 0-127
{midi_val = int(scale_range(${percent}, 0, 100, 0, 127))}
# Map dB (-60 to +6) to MIDI (0-127)
{midi_val = int(scale_range(${db}, -60, 6, 0, 127))}
Use Case: Convert between different parameter scales.
msb(value)¶
Extract most significant byte (high 7 bits) from 14-bit value.
Use Case: Split 14-bit values for high-resolution MIDI control.
lsb(value)¶
Extract least significant byte (low 7 bits) from 14-bit value.
Use Case: Split 14-bit values for high-resolution MIDI control.
Real-World Examples¶
Example 1: BPM to MIDI Conversion¶
Problem: Device accepts tempo via MIDI CC, but musicians think in BPM.
Solution:
@alias set_tempo {ch} {bpm:40-300} "Set tempo (40-300 BPM)"
{midi_val = int((${bpm} - 40) * 127 / 260)}
- cc {ch}.14.{midi_val}
@end
# Usage
- set_tempo 1 120 # 120 BPM → MIDI 39
- set_tempo 1 180 # 180 BPM → MIDI 68
Math Explanation:
- Range: 40-300 BPM → 260 BPM span
- MIDI: 0-127 → 127 value span
- Formula: (BPM - 40) * 127 / 260
Example 2: Percentage to MIDI¶
Problem: Mixing percentages are more intuitive than 0-127 values.
Solution:
@alias set_mix {ch} {percent:0-100} "Set mix level (0-100%)"
{midi_val = int(${percent} * 127 / 100)}
- cc {ch}.7.{midi_val}
@end
# Usage
- set_mix 1 75 # 75% → MIDI 95
- set_mix 1 50 # 50% → MIDI 63
Example 3: Velocity Curve¶
Problem: Apply dynamic scaling to velocity for expression.
Solution:
@alias vel_curve {ch} {note} {vel} {curve:50-150} "Velocity with curve"
{scaled = int(${vel} * ${curve} / 100)}
{safe_vel = clamp(${scaled}, 0, 127)}
- note_on {ch}.{note}.{safe_vel} 1b
@end
# Usage
- vel_curve 1 60 90 150 # 90 * 150% = 135 → clamp to 127
- vel_curve 1 64 80 75 # 80 * 75% = 60
Example 4: 14-bit MIDI Control¶
Problem: High-resolution parameter needs 14-bit precision.
Solution:
@alias pitch_14bit {ch} {value:0-16383} "14-bit pitch control"
{msb_val = msb(${value})}
{lsb_val = lsb(${value})}
- cc {ch}.64.{msb_val} # Coarse
- cc {ch}.96.{lsb_val} # Fine
@end
# Usage
- pitch_14bit 1 8192 # Center: MSB=64, LSB=0
- pitch_14bit 1 12288 # 75% up: MSB=96, LSB=0
Example 5: Multi-Step Computation¶
Problem: Create custom response curve for expression pedal.
Solution:
@alias expr_curve {ch} {raw:0-127} "Logarithmic expression"
{normalized = ${raw} / 127.0}
{curved = ${normalized} * ${normalized}} # Square
{result = clamp(int(${curved} * 127), 0, 127)}
- cc {ch}.11.{result}
@end
# Usage
- expr_curve 1 64 # 50% input → 25% output
- expr_curve 1 127 # 100% input → 100% output
Best Practices¶
1. Use Descriptive Variable Names¶
2. Always Clamp Calculated Values¶
MIDI values must be 0-127. Prevent overflow:
3. Use int() for MIDI Values¶
MIDI doesn't support decimal values:
{midi_val = int(${percent} * 1.27)} # Good: integer
{midi_val = ${percent} * 1.27} # Bad: might be decimal
4. Document Your Formulas¶
Add comments explaining complex calculations:
@alias cortex_tempo {ch} {bpm:40-300} "Set tempo"
# Quad Cortex maps BPM 40-300 to MIDI 0-127 linearly
{midi_val = int((${bpm} - 40) * 127 / 260)}
- cc {ch}.14.{midi_val}
@end
5. Order Dependencies Correctly¶
If one computed value depends on another, define it after:
# Good
{step1 = ${value} * 2}
{step2 = ${step1} + 10} # Uses step1
# Bad
{step2 = ${step1} + 10} # Error: step1 not defined yet
{step1 = ${value} * 2}
6. Use Range Constraints on Parameters¶
# Good: Range prevents invalid BPM
@alias set_tempo {ch} {bpm:40-300} "Set tempo"
{midi_val = int((${bpm} - 40) * 127 / 260)}
- cc {ch}.14.{midi_val}
@end
# Bad: User could pass 500 BPM
@alias set_tempo {ch} {bpm} "Set tempo"
{midi_val = int((${bpm} - 40) * 127 / 260)}
- cc {ch}.14.{midi_val}
@end
Security and Limitations¶
Security Features¶
Computed values are evaluated in a sandboxed environment with these safety features:
- Whitelisted Operations: Only safe arithmetic operators and functions allowed
- Operation Limit: Maximum 10,000 operations per expression
- Timeout: 1-second execution limit (prevents infinite loops)
- No Imports: Cannot import modules or access file system
- No Attributes: Cannot access object attributes or methods
- Read-Only Parameters: Input parameters cannot be modified
Limitations¶
- No Loops: Cannot use
for,while, or recursion - No Conditionals: Cannot use
if/else(use alias conditionals instead) - No String Operations: Only numeric calculations
- No Variable Assignment: Cannot reassign computed values
- No Side Effects: Cannot modify external state
Performance¶
- Fast: Simple expressions evaluate in <1ms
- Cached: Computations are not cached between alias calls
- Linear: Performance scales linearly with expression complexity
Troubleshooting¶
Common Errors¶
Error: "Division by zero"¶
# Bad
{result = ${value} / 0}
# Good
{result = ${value} / max(${divisor}, 1)} # Prevent zero division
Error: "Undefined variable"¶
Error: "Exceeds operation limit"¶
# Bad
{result = ${val} ** ${val} ** ${val}} # Exponential explosion
# Good
{result = ${val} ** 3} # Simple exponentiation
Error: "Invalid expression syntax"¶
Debugging Tips¶
- Test Incrementally: Add computed values one at a time
- Use Simple Values: Test with known inputs (e.g., 0, 64, 127)
- Check Math: Verify calculations manually
- Add Clamp: Use
clamp()to catch out-of-range values - Check Types: Ensure
int()conversion where needed
Advanced Techniques¶
Technique 1: Chained Transformations¶
@alias complex_transform {ch} {raw:0-127} "Multi-step transform"
{normalized = ${raw} / 127.0}
{curved = ${normalized} ** 2} # Square
{scaled = ${curved} * 100}
{result = clamp(int(${scaled}), 0, 127)}
- cc {ch}.7.{result}
@end
Technique 2: Parameter Validation¶
@alias safe_cc {ch} {cc_num:0-127} {value} "CC with clamping"
{safe_val = clamp(int(${value}), 0, 127)}
- cc {ch}.{cc_num}.{safe_val}
@end
Technique 3: Unit Conversion¶
# Decibels to MIDI gain
@alias gain_db {ch} {db:-60-6} "Set gain in dB"
{midi_val = int(scale_range(${db}, -60, 6, 0, 127))}
- cc {ch}.7.{midi_val}
@end
Technique 4: Custom Curves¶
# Exponential curve (for faders)
@alias exp_fader {ch} {position:0-127} "Exponential fader"
{norm = ${position} / 127.0}
{exp_val = (${norm} ** 3) * 127} # Cubic curve
{result = clamp(int(${exp_val}), 0, 127)}
- cc {ch}.7.{result}
@end
See Also¶
- Alias System Guide
- Expression Syntax Reference
- Device Library Creation
- Examples: computed_values.mmd
Last Updated: November 2025 Version: 1.0 Status: Complete - Feature fully implemented and tested