Gravity Feed data model
What DAWs and plugins send and receive: coordinates, beats, tracks, targets, alternatives, motions and actions.
This page describes exactly what a DAW or plugin sends to Gravity Feed and what it gets back, field by field, together with the coordinate system and timebase every adapter must use. It applies to schema version 1.0.
Coordinates and time
| Item | Convention |
|---|---|
| Frame | X forward, Y left, Z up |
| Azimuth | Degrees, 0 is straight ahead, positive is to the left, range -180 to 180 |
| Elevation | Degrees, 0 is ear level, positive is up, range -90 to 90 |
| Distance | Normalized 0 to 1, where 1 is the far edge of the plugin's range |
| Time | Quarter-note beats from the start of the project |
Gravity Profiles convert from these neutral values to each plugin's own units. If a plugin measures azimuth clockwise, its profile flips the sign; your adapter never has to.
What you send
| Field | Required | Description |
|---|---|---|
schema_version | Yes | "1.0" |
request_id | Yes | Your idempotency key, 1 to 64 characters from A-Z a-z 0-9 _ . : - |
session.id | Yes | A stable, pseudonymous id for the project. Do not send the file name if it identifies a client |
session.revision | Yes | A non-negative integer that changes when the session changes |
session.tempo_map | Yes | Up to 64 points { beat, bpm }, first at beat 0, BPM 20 to 400 |
session.meter_map | No | { beat, numerator, denominator } points |
session.selection | Yes | { start_beat, length_beats }, up to 128 beats |
session.sections | No | Up to 32 { label, start_beat, end_beat } |
context | No | genre, key and mood, each { value, source } |
intent | No | Up to 500 characters of direction, such as "open the chorus upward" |
styles | No | Any of restrained, expressive, cinematic; all three by default |
targets | No | Up to 32 plugin instances the plan may write to |
tracks | Yes | Up to 32 tracks |
privacy | Yes | Exactly { "mode": "metadata_only", "audio_uploaded": false } |
Tracks
| Field | Description |
|---|---|
id | Your stable track id |
name | Optional display name, up to 60 characters |
role | { value, source }, for example { "value": "pad", "source": "host" } |
target_id | The target this track's positions can be written to |
anchor | true keeps the track still, typically the lead vocal |
locked_parameters | Any of azimuth, elevation, distance, position, effects |
position | Current { azimuth_deg, elevation_deg, distance? } |
features | Optional numbers or short strings your host already computed, such as loudness or note density |
Every labeled value carries a source: user (typed by a person), host (read from the DAW), model (guessed by software) or unknown. The planner sees the source of every label, so a role typed by a person is not confused with a guess.
Targets
| Field | Description |
|---|---|
id | Your id for this plugin instance |
profile_id | A Gravity Profile from GET /v1/profiles |
live_write | true if your adapter can send values while playing |
automation_commit | true if your adapter can write automation |
source_index | Required for index-based profiles such as ICST AmbiEncoder |
What you get back
| Field | Description |
|---|---|
plan_id | Unique id of this plan |
status | Always proposal; nothing is applied until your adapter writes it |
kind | inference |
preconditions | session_id, session_revision and input_hash the plan was built for |
expires_at | 600 seconds after creation |
timebase, coordinate_system | The conventions above, restated |
versions | Model, compiler and profile versions used |
alternatives | One per requested style |
audio_checks | not_evaluated for mono compatibility and phase, because no audio is sent |
confidence | Always null. Gravity Feed does not invent a quality score |
Each alternative
| Field | Description |
|---|---|
style | restrained, expressive or cinematic |
summary | One line describing the idea |
scene | Every track with current position, new position, changed and reason |
motions | Movements with shape, start_beat, end_beat, intensity, easing, curve points and a reason |
effect_suggestions | Effect ideas with kind, intent and executable: false |
actions | Writable automation for bound targets |
unsupported_actions | What could not be applied and why |
validation | dropped items with reasons, and respected_locks |
Style bounds
| Style | Tracks that may move | Maximum intensity | Maximum elevation |
|---|---|---|---|
| Restrained | 1 | 0.4 | 35 degrees |
| Expressive | 3 | 0.75 | 60 degrees |
| Cinematic | 6 | 1.0 | 85 degrees |
Motion shapes and effect kinds
Motion shapes: rise, sink, sweep, circle, spiral_up, fly_over, come_close, move_away, wander. Each is computed by fixed formulas, then clamped to the style bounds and the plugin's range.
Effect kinds: reverb, delay, filter, width, dynamics, synth. They are ideas for a person or an adapter to apply.
Actions
{
"action_id": "pad.azimuth",
"track_id": "pad",
"target_id": "enc-1",
"profile_id": "iem_stereoencoder_candidate_v1",
"parameter": "azimuth",
"unit": "degrees",
"range": [-180, 180],
"mode": "automation_commit",
"kind": "curve",
"interpolation": "linear_between_points",
"points": [{ "beat": 64, "value": 30 }, { "beat": 72, "value": 22.5 }],
"osc": { "address": "/StereoEncoder/azimuth", "args": ["value:float"], "source_index": null },
"conversion_verified": false
}
Values are in the plugin's own units. conversion_verified: false means nobody has confirmed in a real session that the plugin moves in the expected direction; run the fixture test in Gravity Profiles before trusting it.
Privacy
Gravity Feed never accepts audio. A request without audio_uploaded: false is rejected. Spatial9 keeps a hash of the request, the track count, timings, the transport and the returned plan, not the request body itself.