# `Mx.Loop`
[🔗](https://github.com/mx-music/mx/blob/main/lib/mx/loop.ex#L1)

Plays one loop of a song, pass after pass.

A pass is worked out `ahead_ms` before it starts, and each of its notes is sent `ahead_ms` before it plays, stamped with the real time of its beat on the band's timeline.
Notes are stamped from the timeline rather than from the previous note, so nothing adds up to a drift.
A pass worked out later than its start is late: its notes more than a quarter of a beat late are dropped, and the rest play as soon as the engine gets them.

A new version takes over when the next pass is worked out, and a stopped loop ends with its current pass.
A loop with a number of passes ends once its last pass has played to its end, exiting with `{:shutdown, :ended}`.
A loop started with `pass` and `skip` plays that pass first, leaving out its notes before beat `skip` of it.
A loop started with `start: :join` waits for the band to send `{:join, beat, pass}`, and plays that pass from that beat.

A sample plays from the buffer the song loaded for it.
A sample named while the pass runs has no buffer yet, so the loop asks for it with `load_sample`, leaves it out, and plays it from the next pass once it is loaded.

A loop with effects starts its chain with `start_fx` before its first pass, and plays its notes into the chain.
The chain lasts from pass to pass, and is replaced at the start of a pass whose effects or tempo give it other options.
A replaced chain, or the chain of a stopped loop, is handed to `stop_fx` with the end of its last pass, so its sounds finish through it.

MIDI and OSC steps go to `out` with the real time of their beat, as the loop's notes go to the engine through `play`; a MIDI note is a note on and a note off after its length.

A pass reads the inputs as `inputs` returns them for its first beat, waiting at most until its start, and a set step hands its value to `set` with its beat and that beat's real time as soon as its pass is worked out.
Each pass then tells `worked_out` the beat it has worked out up to, so the other loops' passes wait for its set steps, and nil once it works out no more passes on its own.
A loop with `on:` plays no pass on its own: the band sends it each input it waits for, and it plays a pass at once, 10 ms ahead so its first notes are on time.

A sound a control step changes starts with an id of its own from `new_id`, and the step sets its options at its beat; other sounds have none.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `start_link`

Starts playing a loop from the version, band and functions in `opts`.

# `stop`

Stops the loop once its current pass ends.

# `switch`

Hands the loop a new version of itself, which takes over when its next pass is worked out.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
