{
  "$type": "at.atmosynth.module",
  "descriptionVersion": 1,
  "moduleId": "beat-repeat",
  "versionKey": "1",
  "name": "Beat repeat",
  "description": "A slice of what just came through, held and played round and round. Repeat at nothing is the signal passing straight through and nothing else; turn it up and the door on the delay line shuts, what is already inside goes round at unity, and the last Slice beats of sound loop where the music was. Slice is counted in beats against the one tempo the whole instrument keeps — the same one the arpeggiator and the sequencer count against — so a quarter is a sixteenth note, a half is an eighth, a four is a whole bar, and moving the tempo moves the stutter with it. There is no tempo knob here, and that is the point: a second tempo would be free to disagree with the first. The knob is a continuum rather than a switch, and the middle of it is worth finding — at nothing the door is open and the loop is silent, at everything the door is shut and nothing new gets in, and half way the door is half open, so fresh sound keeps arriving while what is already round goes round again, which is a synced delay. One knob, because those are three positions of one door rather than three effects. Repeat is an input as well, with a depth for how far a signal there moves it, and that is what this is really played by: a square LFO chopping it in and out, a sample and hold opening it at random, an envelope, or the knob itself under a controller. What it catches is whatever was in the line at the instant the door shut, so a stutter lands in time by being pressed in time — nothing here is told where the bar began. Decay is how much of each pass survives into the next: at everything the loop holds for as long as you keep it, and below that it fades where it stands. Nothing stands between the line and itself but that one knob, which is what lets the hold be exact — a filter in the loop is heard again on every pass, and a lowpass with any resonance at all has a frequency it hands back louder than it was given, so a loop closed through one does not hold, it climbs. Damp is that lowpass moved to where it is heard once: it is the tone of the repeat, and it is what takes the edge off the seam, since the end of a slice and its beginning were never going to meet and that joint is heard once a pass. Moving Slice while the loop runs rewrites what is in the line rather than re-cutting it, which is a tape being pulled: shorter for a pitch up, longer for a pitch down. One thing here is a correction rather than a choice, and it is worth knowing about: a loop closed through a delay line costs a render quantum on the way round, which is 128 frames wherever it is played, and nothing in a module description can ask what the sample rate is — so the slice is cut short by that much at 48 kHz, where it comes out exact, and is a quarter of a millisecond long at 44.1. It holds sound that outlives the note that made it, so it is added shared — per voice, each note would take its own loop with it when it ended.",
  "audioInputs": [
    {
      "id": "in",
      "label": "In"
    },
    {
      "id": "repeat",
      "label": "Repeat"
    }
  ],
  "audioOutputs": [
    {
      "id": "out",
      "label": "Out"
    }
  ],
  "midiInputs": [],
  "nodes": [
    {
      "id": "in",
      "kind": "moduleInput",
      "options": {
        "input": "in"
      }
    },
    {
      "id": "repeatin",
      "kind": "moduleInput",
      "options": {
        "input": "repeat"
      }
    },
    {
      "id": "engage",
      "kind": "constantSource",
      "options": {}
    },
    {
      "id": "depth",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "passing",
      "kind": "waveShaper",
      "options": {
        "curve": [
          0,
          0,
          -1
        ]
      }
    },
    {
      "id": "holding",
      "kind": "waveShaper",
      "options": {
        "curve": [
          -1,
          -1,
          0
        ]
      }
    },
    {
      "id": "gate",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "beat",
      "kind": "constantSource",
      "options": {
        "signal": "beat"
      }
    },
    {
      "id": "slice",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "quantum",
      "kind": "constantSource",
      "options": {}
    },
    {
      "id": "lead",
      "kind": "waveShaper",
      "options": {
        "curve": [
          "-0.0026666666666666666",
          "-0.0026666666666666666"
        ]
      }
    },
    {
      "id": "line",
      "kind": "delay",
      "options": {
        "maxDelayTime": 12
      }
    },
    {
      "id": "damp",
      "kind": "biquadFilter",
      "options": {
        "type": "lowpass"
      }
    },
    {
      "id": "fbgate",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "decay",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "dry",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "wet",
      "kind": "gain",
      "options": {}
    },
    {
      "id": "out",
      "kind": "moduleOutput",
      "options": {
        "output": "out"
      }
    }
  ],
  "connections": [
    {
      "from": {
        "node": "in",
        "output": 0
      },
      "to": {
        "node": "gate",
        "input": 0
      }
    },
    {
      "from": {
        "node": "gate",
        "output": 0
      },
      "to": {
        "node": "line",
        "input": 0
      }
    },
    {
      "from": {
        "node": "line",
        "output": 0
      },
      "to": {
        "node": "damp",
        "input": 0
      }
    },
    {
      "from": {
        "node": "line",
        "output": 0
      },
      "to": {
        "node": "fbgate",
        "input": 0
      }
    },
    {
      "from": {
        "node": "fbgate",
        "output": 0
      },
      "to": {
        "node": "decay",
        "input": 0
      }
    },
    {
      "from": {
        "node": "decay",
        "output": 0
      },
      "to": {
        "node": "line",
        "input": 0
      }
    },
    {
      "from": {
        "node": "damp",
        "output": 0
      },
      "to": {
        "node": "wet",
        "input": 0
      }
    },
    {
      "from": {
        "node": "wet",
        "output": 0
      },
      "to": {
        "node": "out",
        "input": 0
      }
    },
    {
      "from": {
        "node": "in",
        "output": 0
      },
      "to": {
        "node": "dry",
        "input": 0
      }
    },
    {
      "from": {
        "node": "dry",
        "output": 0
      },
      "to": {
        "node": "out",
        "input": 0
      }
    },
    {
      "from": {
        "node": "beat",
        "output": 0
      },
      "to": {
        "node": "slice",
        "input": 0
      }
    },
    {
      "from": {
        "node": "slice",
        "output": 0
      },
      "to": {
        "node": "line",
        "param": "delayTime"
      }
    },
    {
      "from": {
        "node": "quantum",
        "output": 0
      },
      "to": {
        "node": "lead",
        "input": 0
      }
    },
    {
      "from": {
        "node": "lead",
        "output": 0
      },
      "to": {
        "node": "line",
        "param": "delayTime"
      }
    },
    {
      "from": {
        "node": "engage",
        "output": 0
      },
      "to": {
        "node": "passing",
        "input": 0
      }
    },
    {
      "from": {
        "node": "engage",
        "output": 0
      },
      "to": {
        "node": "holding",
        "input": 0
      }
    },
    {
      "from": {
        "node": "repeatin",
        "output": 0
      },
      "to": {
        "node": "depth",
        "input": 0
      }
    },
    {
      "from": {
        "node": "depth",
        "output": 0
      },
      "to": {
        "node": "passing",
        "input": 0
      }
    },
    {
      "from": {
        "node": "depth",
        "output": 0
      },
      "to": {
        "node": "holding",
        "input": 0
      }
    },
    {
      "from": {
        "node": "passing",
        "output": 0
      },
      "to": {
        "node": "gate",
        "param": "gain"
      }
    },
    {
      "from": {
        "node": "passing",
        "output": 0
      },
      "to": {
        "node": "dry",
        "param": "gain"
      }
    },
    {
      "from": {
        "node": "holding",
        "output": 0
      },
      "to": {
        "node": "wet",
        "param": "gain"
      }
    },
    {
      "from": {
        "node": "holding",
        "output": 0
      },
      "to": {
        "node": "fbgate",
        "param": "gain"
      }
    }
  ],
  "automation": [],
  "parameters": [
    {
      "id": "slice",
      "label": "Slice (beats)",
      "range": {
        "min": "0.0625",
        "max": "4"
      },
      "default": "0.25",
      "targets": [
        {
          "node": "slice",
          "param": "gain"
        }
      ]
    },
    {
      "id": "repeat",
      "label": "Repeat",
      "range": {
        "min": "0",
        "max": "1"
      },
      "default": "0",
      "targets": [
        {
          "node": "engage",
          "param": "offset"
        }
      ]
    },
    {
      "id": "repeatAmount",
      "label": "Repeat amount",
      "range": {
        "min": "-1",
        "max": "1"
      },
      "default": "1",
      "targets": [
        {
          "node": "depth",
          "param": "gain"
        }
      ]
    },
    {
      "id": "decay",
      "label": "Decay",
      "range": {
        "min": "0",
        "max": "1"
      },
      "default": "1",
      "targets": [
        {
          "node": "decay",
          "param": "gain"
        }
      ]
    },
    {
      "id": "damp",
      "label": "Damp (Hz, lower is darker)",
      "range": {
        "min": "200",
        "max": "18000"
      },
      "default": "12000",
      "targets": [
        {
          "node": "damp",
          "param": "frequency"
        }
      ]
    }
  ],
  "sampleSlots": [],
  "createdAt": "2026-09-22T00:00:00.000Z"
}