# app.atloop.project

> Published by [atloop.app](https://lexicon.garden/identity/did:plc:uifrtk7vej36miqtnbm3m5hv)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:uifrtk7vej36miqtnbm3m5hv/app.atloop.project)
- [Documentation](https://lexicon.garden/lexicon/did:plc:uifrtk7vej36miqtnbm3m5hv/app.atloop.project/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:uifrtk7vej36miqtnbm3m5hv/app.atloop.project/examples)

## Definitions

### `app.atloop.project#beltRate`

**Type**: `object`

Speed each belt holds, in hundredths of normal. Negative runs the belt backwards.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `line` | `integer` | Yes |  |
| `rhythm` | `integer` | Yes |  |

### `app.atloop.project#line`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `color` | `integer` | No |  |
| `gain` | `integer` | No |  |
| `id` | `string` | Yes |  |
| `instrument` | `string` | No |  |
| `points` | `array` | Yes |  |
| `role` | `string` | Yes |  |
| `width` | `integer` | No |  |

### `app.atloop.project`

**Type**: `record`

An ATLoop loop: the editable shape and line data for one belt project.

**Key**: `tid`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `beltRate` | `ref` → `#beltRate` | No |  |
| `bpm` | `integer` | Yes |  |
| `catalogue` | `string` (uri) | No | A fixed address shared by every published loop. Nothing lists a collection in atproto, but links are indexed network-wide, so a common link is what makes loops discoverable. |
| `createdAt` | `string` (datetime) | Yes |  |
| `engineVersion` | `string` | Yes | Audio engine the loop was authored against. Open-ended: unknown values must not be rejected. |
| `formatVersion` | `integer` | Yes |  |
| `generator` | `string` | No | Random generator that produced the loop, if any. |
| `lines` | `array` | No |  |
| `loopSteps` | `integer` | Yes |  |
| `percussion` | `array` | No |  |
| `previewAudio` | `blob` | No |  |
| `previewImage` | `blob` | No |  |
| `scale` | `ref` → `#scale` | Yes |  |
| `soundPack` | `string` | Yes |  |
| `title` | `string` | Yes |  |
| `updatedAt` | `string` (datetime) | No |  |

### `app.atloop.project#percussion`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `color` | `integer` | No |  |
| `id` | `string` | Yes |  |
| `shape` | `string` | Yes |  |
| `size` | `integer` | No |  |
| `tick` | `integer` | Yes |  |
| `voice` | `string` | No |  |

### `app.atloop.project#point`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `pitch` | `integer` | Yes | MIDI note number times 100, so it is device independent. |
| `tick` | `integer` | Yes | Normalised position in the loop; one loop is 65536 ticks. May exceed 65535 for a line that crosses the loop seam. |

### `app.atloop.project#scale`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `mode` | `string` | Yes |  |
| `root` | `integer` | Yes | Pitch class of the tonic, 0 = C. |

## Raw Schema

```json
{
  "$type": "com.atproto.lexicon.schema",
  "defs": {
    "beltRate": {
      "description": "Speed each belt holds, in hundredths of normal. Negative runs the belt backwards.",
      "properties": {
        "line": {
          "maximum": 400,
          "minimum": -400,
          "type": "integer"
        },
        "rhythm": {
          "maximum": 400,
          "minimum": -400,
          "type": "integer"
        }
      },
      "required": [
        "line",
        "rhythm"
      ],
      "type": "object"
    },
    "line": {
      "properties": {
        "color": {
          "maximum": 16777215,
          "minimum": 0,
          "type": "integer"
        },
        "gain": {
          "maximum": 1000,
          "minimum": 0,
          "type": "integer"
        },
        "id": {
          "maxLength": 64,
          "type": "string"
        },
        "instrument": {
          "knownValues": [
            "sine",
            "triangle",
            "piano",
            "square",
            "saw",
            "glass",
            "bass",
            "sub",
            "bsaw",
            "bpluck",
            "growl",
            "pulse"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "points": {
          "items": {
            "ref": "#point",
            "type": "ref"
          },
          "maxLength": 512,
          "minLength": 1,
          "type": "array"
        },
        "role": {
          "knownValues": [
            "melody",
            "bass"
          ],
          "type": "string"
        },
        "width": {
          "maximum": 1000,
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "id",
        "role",
        "points"
      ],
      "type": "object"
    },
    "main": {
      "description": "An ATLoop loop: the editable shape and line data for one belt project.",
      "key": "tid",
      "record": {
        "properties": {
          "beltRate": {
            "ref": "#beltRate",
            "type": "ref"
          },
          "bpm": {
            "maximum": 240,
            "minimum": 40,
            "type": "integer"
          },
          "catalogue": {
            "description": "A fixed address shared by every published loop. Nothing lists a collection in atproto, but links are indexed network-wide, so a common link is what makes loops discoverable.",
            "format": "uri",
            "type": "string"
          },
          "createdAt": {
            "format": "datetime",
            "type": "string"
          },
          "engineVersion": {
            "description": "Audio engine the loop was authored against. Open-ended: unknown values must not be rejected.",
            "knownValues": [
              "core-audio-v1"
            ],
            "maxLength": 64,
            "type": "string"
          },
          "formatVersion": {
            "maximum": 1000,
            "minimum": 1,
            "type": "integer"
          },
          "generator": {
            "description": "Random generator that produced the loop, if any.",
            "knownValues": [
              "groove-v1"
            ],
            "maxLength": 64,
            "type": "string"
          },
          "lines": {
            "items": {
              "ref": "#line",
              "type": "ref"
            },
            "maxLength": 256,
            "type": "array"
          },
          "loopSteps": {
            "maximum": 128,
            "minimum": 4,
            "type": "integer"
          },
          "percussion": {
            "items": {
              "ref": "#percussion",
              "type": "ref"
            },
            "maxLength": 1024,
            "type": "array"
          },
          "previewAudio": {
            "accept": [
              "audio/mp4",
              "audio/mpeg",
              "audio/ogg"
            ],
            "maxSize": 5000000,
            "type": "blob"
          },
          "previewImage": {
            "accept": [
              "image/webp",
              "image/png",
              "image/jpeg"
            ],
            "maxSize": 1000000,
            "type": "blob"
          },
          "scale": {
            "ref": "#scale",
            "type": "ref"
          },
          "soundPack": {
            "knownValues": [
              "core-v1"
            ],
            "maxLength": 64,
            "type": "string"
          },
          "title": {
            "maxGraphemes": 64,
            "maxLength": 640,
            "type": "string"
          },
          "updatedAt": {
            "format": "datetime",
            "type": "string"
          }
        },
        "required": [
          "formatVersion",
          "title",
          "createdAt",
          "bpm",
          "loopSteps",
          "engineVersion",
          "soundPack",
          "scale"
        ],
        "type": "object"
      },
      "type": "record"
    },
    "percussion": {
      "properties": {
        "color": {
          "maximum": 16777215,
          "minimum": 0,
          "type": "integer"
        },
        "id": {
          "maxLength": 64,
          "type": "string"
        },
        "shape": {
          "knownValues": [
            "circle",
            "square",
            "triangle",
            "star"
          ],
          "type": "string"
        },
        "size": {
          "maximum": 1000,
          "minimum": 0,
          "type": "integer"
        },
        "tick": {
          "maximum": 65535,
          "minimum": 0,
          "type": "integer"
        },
        "voice": {
          "knownValues": [
            "kick",
            "tom",
            "conga",
            "boom",
            "snare",
            "clap",
            "rim",
            "block",
            "closed-hat",
            "open-hat",
            "shaker",
            "cowbell",
            "crash",
            "ride",
            "zap",
            "sweep"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "id",
        "tick",
        "shape"
      ],
      "type": "object"
    },
    "point": {
      "properties": {
        "pitch": {
          "description": "MIDI note number times 100, so it is device independent.",
          "maximum": 12700,
          "minimum": 0,
          "type": "integer"
        },
        "tick": {
          "description": "Normalised position in the loop; one loop is 65536 ticks. May exceed 65535 for a line that crosses the loop seam.",
          "maximum": 131071,
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "tick",
        "pitch"
      ],
      "type": "object"
    },
    "scale": {
      "properties": {
        "mode": {
          "knownValues": [
            "major-pentatonic",
            "minor-pentatonic",
            "major",
            "minor"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "root": {
          "description": "Pitch class of the tonic, 0 = C.",
          "maximum": 11,
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "root",
        "mode"
      ],
      "type": "object"
    }
  },
  "id": "app.atloop.project",
  "lexicon": 1
}
```
