aax

star 8

Optional AAX support for Pulp, including developer-supplied Avid SDK setup, CMake enablement, DigiShell/AAX Validator workflows, and local AAX builds on macOS or Windows.

danielraffel By danielraffel schedule Updated 4/18/2026

name: aax description: Optional AAX support for Pulp, including developer-supplied Avid SDK setup, CMake enablement, DigiShell/AAX Validator workflows, and local AAX builds on macOS or Windows. requires: scripts: - tools/audit.py - tools/deps/audit.py

tools: []

AAX Skill

Use this when working on Pulp's optional AAX support or when guiding users who want to build and validate AAX plugins locally.

Scope

  • Supported hosts: macOS and Windows

  • Unsupported: Linux and Ubuntu

  • Current scope: AAX Native

  • Out of scope: bundling Avid assets, DSP/AudioSuite support, PACE release automation

  • Never commit the AAX SDK, DigiShell, validator binaries, or Avid example code.

  • Never unpack Avid downloads inside the Pulp repo.

  • Keep AAX developer-supplied, opt-in, and out-of-tree.

  • Run the repo audits after AAX-related changes:

python3 tools/deps/audit.py --strict

What Users Should Download

Tell users to sign in at:

https://developer.avid.com/aax/

Required downloads:

  • AAX SDK
  • DigiShell and AAX Validator

Optional later:

  • AAX Plug-In Page Table Editor

Do not recommend these for normal Pulp AAX setup unless the task explicitly needs them:

  • AAX Developer Tools beta bundles
  • Pro Tools installers
  • HD Driver
  • Avid Cloud Client Services

Suggested Install Locations

Preferred user-local locations so Pulp can auto-discover them:

~/SDKs/avid/aax-sdk/current
~/SDKs/avid/aax-validator/current
%USERPROFILE%\SDKs\avid\aax-sdk\current
%USERPROFILE%\SDKs\avid\aax-validator\current

Environment variables override auto-discovery:

export PULP_AAX_SDK_DIR=~/SDKs/avid/aax-sdk/current
export PULP_AAX_VALIDATOR_DIR=~/SDKs/avid/aax-validator/current

Core Commands

Check current AAX availability:

pulp status
pulp doctor

Build with AAX enabled:

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Debug \
  -DPULP_ENABLE_AAX=ON \
  -DPULP_AAX_SDK_DIR="$PULP_AAX_SDK_DIR"
cmake --build build --target MyPlugin_AAX -j$(sysctl -n hw.ncpu 2>/dev/null || nproc)

Validate built plugins:

pulp validate
pulp validate --all

Notes:

  • pulp validate uses the faster AAX describe-validation path when the validator is installed.
  • pulp validate --all runs the broader AAX validator suite.
  • Do not launch multiple full AAX validator runs in parallel; DigiShell can collide on local ports.

Expected UX

  • If the AAX SDK is missing, point users to the Avid sign-in page and PULP_AAX_SDK_DIR.
  • If DigiShell/AAX Validator is missing, point users to the Avid sign-in page and PULP_AAX_VALIDATOR_DIR.
  • On Linux or Ubuntu, explain that AAX is unsupported and remove AAX from FORMATS.
  • If validation reports that a bundle exists but the plugin binary is missing, build the target before validating it.

Gotchas

MIDI sysex accumulator

AAX splits multi-byte sysex (F0 … F7) across sequential AAX_CMidiPacket entries — the first packet carries the F0 status byte, continuation packets can appear with no status byte, and the final packet carries F7. Each packet's mData field is at most 4 bytes. A single-packet decoder will silently drop everything after the first 4 sysex bytes, and the host will never see the real message.

The correct shape is a per-node accumulator:

std::vector<uint8_t> sysex_buffer;
bool sysex_in_progress = false;
int32_t sysex_start_offset = 0;
// for each packet in the node's buffer:
//   if byte == 0xF0 → start accumulator, capture start_offset from mTimestamp
//   while sysex_in_progress → append every payload byte (no status-byte requirement)
//   if byte == 0xF7 → flush accumulator as one MidiEvent, reset

This matches the shape used for CLAP/VST3/AU/CoreMIDI/ALSA sysex. See core/format/src/aax_runtime.cpp::decode_midi_node for the canonical implementation. The AAX bypass MIDI-thru helper must copy sidecar payloads with MidiBuffer::add_sysex_copy(); MidiBuffer::SysexPayload is deliberately not a movable raw std::vector.

When clearing an AAX process block's MIDI buffers, clear both the short-event storage and the sysex sidecars. MidiBuffer::clear() resets short events only; call clear_sysex() on both input and output buffers before decoding the next block, or stale sidecar payloads can be re-emitted by a later block.

When adding or changing any AAX MIDI input path, exercise this against a multi-packet sysex vector (at least one packet across the 4-byte boundary and one terminator-only packet) in a unit test. Adapter fixes should ship with the regression tests that prove the fixed behavior.

Review Checklist

After any AAX-related change:

  1. Build with AAX disabled and confirm the repo still works normally.
  2. Build with PULP_ENABLE_AAX=ON against a developer-supplied SDK.
  3. Run pulp validate and pulp validate --all when the validator is installed.
  4. Recheck the user-facing guidance in docs/guides/aax.md if behavior changed.
Install via CLI
npx skills add https://github.com/danielraffel/pulp --skill aax
Repository Details
star Stars 8
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator
danielraffel
danielraffel Explore all skills →