SaleLAUNCH SALE$29$910 days leftGet Deal
Please note that oooo is in BETA, expect bugs! Please report them.

Documentation

This page mirrors the control help shown inside the app (toggle with H).

Keybindings #

Control Action
Htoggle help
Ncreate new loop
CLICK INSIDE Oselect loop (nearest center)
DRAG Omove selected loop (pan/volume)
CLICK PERIMETER Ojump cut on selected loop
DBL-CLICK OUTSIDE Oclear loop selection
CLICK+DRAG OUTSIDE Oadjust selected parameter
LEFT / RIGHTselect parameter
UP / DOWNadjust value (or LFO period)
Pglobal play/stop all loops
SPACE / Ptoggle selected loop playback
Rtoggle selected loop recording
Ztap: load preset, hold 1s: save slot
I / Ohold 1s: load / save session archive (.zip)
C / Vcopy selected loop / paste duplicate
DELETE / BACKSPACEhold 1s: delete selected loop
Xhold 1s: clear selected loop audio
F1..F12select loop 1..12
0..7cut: 0/8..7/8 (selected/all)
Ttoggle dark/light theme
Ltoggle LFO on selected parameter
Q / Aincrease / decrease LFO min (x)
W / Sincrease / decrease LFO max (y)

Tape Controls #

The tape controls provide another way to control the loops when hotkeys are not an option.

Press Play () to play a loop (when selected) or all loops (when not). Press Stop () to stop all loops, or the selected loop if it is the only one playing. When stopped, press Stop () again or key 0 to jump to the start of the loop(s).

Press Forward () or Reverse () to step the playback rate up or down, respectively. Press Play () twice to return to normal speed.

Press Record () to toggle recording on the selected loop. Note, in Continuous Mode, if you stop a recording that was started from the beginning it will size the loop to the length of the recording.

Loop Parameters #

Loop parameters are accessible by clicking a loop. Use ← / → to scroll through parameters and ↑ / ↓ to change values.

Values can also be adjusted at any time by clicking a non-loop area of the screen and dragging the mouse up and down.

Additionally, values can be set to change via an LFO by pressing L and then using hotkeys: Q/A increases/decreases LFO min (x) and W/S increases/decreases LFO max (y).

Mix #

Volume sets loop output level and Pan places the loop in the stereo field.

Window #

Loop Start and Loop Length define the active playback window within the loop allocation.

Playback #

Rate changes playback speed/pitch, Fade Time controls loop boundary crossfade and also sets post-roll duration when using Record Mode = Once, and DAW Sync links loop timing behavior to host transport sync state.

Record Path #

Record New controls incoming write level, Record Keep controls retained buffer level during overdub, Record Mode selects Continuous (default) or Once, and Reverb sets loop send amount to the reverb bus.

In Record Mode = Once, recording automatically disarms after one loop span and applies post-roll equal to the current Fade Time.

Tape #

Tape Bias and Tape Gain shape tape drive behavior; Bass Freq, Bass Boost, and Bass Q tune the low-frequency tape contour.

Filters #

Post LPF/Post LPF Q and Post HPF/Post HPF Q control post-stage low-pass and high-pass filter cutoff and resonance.

Note Envelope #

Note Attack, Note Decay, Note Sustain, and Note Release define the per-note ADSR envelope for note-triggered loop playback.

Note Trigger/MIDI #

Note Start % randomizes note start offset, MIDI CH sets MIDI channel filtering per loop, and Note Mode chooses the note playback start behavior.

Global Parameters #

Global parameters are reached by double-clicking anywhere that is not a loop to open the global parameters menu. Navigate with ← / →, change values with ↑ / ↓, or click-drag in a non-loop area to adjust values directly.

Length/Tempo #

Length Mode controls loop length quantization behavior, and Length BPM sets the tempo used for beat-based length calculations.

Record Chain #

Record Chain is great for recording a series of loops in order. When enabled, starting recording on one loop can hand off recording to the next loop when the current loop reaches its boundary, continuing through the remaining loop order.

To use it, select the loop you want to start from and toggle recording with R (or the loop record gesture). Turning Record Chain off cancels future automatic handoffs; manually stopping the currently chained loop also stops the rest of the chain.

Mix: Input, Dry, Wet #

Input sets global input trim, while Dry and Wet control global dry/wet output balance.

Reverb #

These parameters shape the global reverb path: Predelay, input level, LPF, HPF, damping, mod frequency and mod depth.

MIDI #

Using oooo with a MIDI keyboard lets you play the loops as if it were a Mellotron - each note will change the rate scaling of the playing loop based around middle C. MIDI note input is handled per loop through MIDI CH and Note Mode: channel mode decides which incoming channels are accepted, note mode decides where playback starts on note-on, and note-off (including note-on with velocity 0) releases active note heads while Note Attack, Note Decay, Note Sustain, Note Release, and Note Start % shape the loop’s note response.

Grid #

A monome grid is automatically detected in oooo. When a monome grid is detected, an icon () appears automatically in the top-right corner. Each 8x8 section of the grid (a "tile") controls one loop. Column 1 is the tile menu and columns 2-8 are the active area.

Each tile has four modes: Isomorphic (col1,row1), Slice (col1,row2), Volume/Pan (col1,row3), and Rate (col1,row4). In Slice mode, playhead and loop span are shown across columns 2-8 in recorded-normalized space.

Grid Tutorials

Use these guided tours for layout, mode rows, mode-specific gestures, and gesture recording.

Isomorphic Tile Reference (8x8)

Column 1 is the tile menu. Columns 2-8 show note names sent in Isomorphic mode (note + octave). C notes are dimly highlighted. Example below: held D4 is bright, matching D4 pads are ghost-highlighted.

ISO
C3
F3
B3
E4
A4
D5
G5
SLICE
B2
E3
A3
D4
G4
C5
F5
VOL/PAN
A2
D3
G3
C4
F4
B4
E5
RATE
G2
C3
F3
B3
E4
A4
D5
PAT REC
F2
B2
E3
A3
D4
G4
C5
PAT PLAY
E2
A2
D3
G3
C4
F4
B4
REC
D2
G2
C3
F3
B3
E4
A4
PLAY
C2
F2
B2
E3
A3
D4
G4

Anchor used by current runtime mapping: local tile row=8, col=2 is C2 (MIDI 36).

Live Coding #

Open Live Coding by clicking the terminal icon () in the top-right app bar. This opens the browser-based Lua editor at http://127.0.0.1:17321/ by default.

Run the whole file or selected lines to create loops, shape playback, and control engine globals from Lua.

Common commands include o.create, o.set(loop_id, ...), o.get(), o.record, and o.play.

Example 1: Create, Record, and Play

-- create and start a 4 second loop
loop_id, err = o.create({ seconds = 4.0, fade = 0.15 })
assert(loop_id, err)
o.record(loop_id, true)
o.play(loop_id, true)

Example 2: Update, Query, and Jump

o.set(loop_id, {
  pan = -0.25,
  db = -6.0,
  pan_slew = 0.3,
  db_slew = 0.3,
})

state = o.get(loop_id)
print('seconds', state.seconds, 'playing', state.playing)
o.jumpn(loop_id, 0.5)

Example 3: Set and Read Engine Globals

o.set({
  in_db = -3,
  wet_db = -6,
  rv_predelay = 12,
  rv_mod_depth = 2,
})

engine = o.get()
print('input', engine.in_db, 'wet', engine.wet_db)

o.* API Reference

This reference reflects the current runtime Lua bindings. Mutating commands return true on success, or nil, err on failure.

Setters / Mutators #

Functions are listed first. Any opts/props object keys are defined in the props tables directly below.

FunctionParametersReturnsNotes
o.create(opts)opts table (optional)loop_id | nil, erropts keys come from Loop Props.
o.set(loop_id, props)loop_id integer, props tabletrue | nil, errprops keys come from Loop Props.
o.set(props)props tabletrue | nil, errprops keys come from Engine Props.
o.record(loop_id, on)loop_id integer, on booleantrue | nil, errStarts/stops recording on one loop.
o.play(loop_id, on)loop_id integer, on booleantrue | nil, errStarts/stops playback on one loop.
o.jump(loop_id, seconds)loop_id integer, seconds numbertrue | nil, errSeeks to timeline seconds.
o.jumpn(loop_id, normalized)loop_id integer, normalized numbertrue | nil, errnormalized must be in [0, 1].
o.bpm(value)value numberbpm | nil, errvalue must be > 0.
o.clear(loop_id)loop_id integertrue | nil, errClears loop audio/buffer content.
o.delete(loop_id)loop_id integertrue | nil, errDeletes a loop.

For o.create(opts), length resolution order is: beats (if > 0), then seconds (if > 0), else defaults to 10.0 seconds.

Loop Props (for o.create(opts) and o.set(loop_id, props))
Key (opts/props)MeaningRange / Behavior
beatsLoop length in beats.Number; must be > 0 to apply. Converted using current o.bpm().
secondsLoop length in seconds.Number; must be > 0 to apply.
fadePost-roll / fade time.Clamped to [0, 20] seconds.
preBuffer keep amount.Clamped to [0, 1].
pre_slewSlew time for pre.Seconds; negative values are treated as 0.
recInput write gain.Clamped to [0, 1].
rec_slewSlew time for rec.Seconds; negative values are treated as 0.
dbLoop output level in dB.Upper-clamped by engine to about +12 dB.
db_slewSlew time for db.Seconds; negative values are treated as 0.
panStereo pan position.Clamped to [-1, 1].
pan_slewSlew time for pan.Seconds; negative values are treated as 0.
Engine Props (for o.set(props))
ParameterMeaningRange / Behavior
in_dbGlobal input trim (dB).Upper-clamped to +24 dB; supports very low values including -inf.
dry_dbGlobal dry level (dB).Upper-clamped to +24 dB; supports very low values including -inf.
wet_dbGlobal wet level (dB).Upper-clamped to +24 dB; supports very low values including -inf.
in_db_slewSlew time for in_db.Seconds; must be >= 0, negative values return error.
dry_db_slewSlew time for dry_db.Seconds; must be >= 0, negative values return error.
wet_db_slewSlew time for wet_db.Seconds; must be >= 0, negative values return error.
rv_predelayReverb predelay (ms).Clamped to [0, 300] ms.
rv_predelay_slewSlew time for rv_predelay.Seconds; must be >= 0, negative values return error.
rv_inReverb input amount (%).Clamped to [0, 100] %.
rv_in_slewSlew time for rv_in.Seconds; must be >= 0, negative values return error.
rv_lpfReverb input low-pass cutoff (Hz).Clamped to [1, 20000] Hz.
rv_lpf_slewSlew time for rv_lpf.Seconds; must be >= 0, negative values return error.
rv_hpfReverb input high-pass cutoff (Hz).Clamped to [1, 1000] Hz.
rv_hpf_slewSlew time for rv_hpf.Seconds; must be >= 0, negative values return error.
rv_dampReverb damping frequency (Hz).Clamped to [10, 20000] Hz.
rv_damp_slewSlew time for rv_damp.Seconds; must be >= 0, negative values return error.
rv_mod_freqReverb modulator frequency (Hz).Clamped to [0.01, 4.0] Hz.
rv_mod_freq_slewSlew time for rv_mod_freq.Seconds; must be >= 0, negative values return error.
rv_mod_depthReverb modulator depth (ms).Clamped to [0, 10] ms.
rv_mod_depth_slewSlew time for rv_mod_depth.Seconds; must be >= 0, negative values return error.

Getters / Queries #

FunctionParametersReturnsNotes
o.get(loop_id)loop_id integerloop_state | nil, errReturns one loop snapshot table.
o.get()noneengine_state | nil, errReturns global engine snapshot table.
o.list()none{loop_id, ...} | nil, errReturns sorted loop IDs.
o.bpm()nonenumber | nil, errReturns current BPM.
o.get

Form: o.get(loop_id) returns loop_state or nil, err.

FieldMeaningRange / Type
loop_idLoop identifier.Integer.
playingCurrent playback state.Boolean.
recordingCurrent recording state.Boolean.
posCurrent position (seconds).Number.
pos_normCurrent normalized position.Number in [0, 1].
secondsCurrent loop length.Number, expected > 0.
alloc_secondsAllocated loop buffer length.Number, expected > 0.
fadePost-roll / fade time.Number in [0, 20].
preBuffer keep amount.Number in [0, 1].
pre_slewSlew time for pre.Number, >= 0.
recInput write gain.Number in [0, 1].
rec_slewSlew time for rec.Number, >= 0.
dbLoop output dB target.Number, upper-clamped by engine.
db_slewSlew time for db.Number, >= 0.
panStereo pan target.Number in [-1, 1].
pan_slewSlew time for pan.Number, >= 0.
o.get

Form: o.get() returns engine_state or nil, err.

Engine FieldMeaningRange / Type
in_db / dry_db / wet_dbGlobal mix dB values.Number, upper-clamped to +24 dB.
in_db_slew / dry_db_slew / wet_db_slewLag time for global dB values.Number, >= 0.
rv_predelayReverb predelay.Number in [0, 300] ms.
rv_predelay_slewPredelay lag time.Number, >= 0.
rv_inReverb input amount.Number in [0, 100] %.
rv_in_slewReverb input amount lag.Number, >= 0.
rv_lpf / rv_hpf / rv_dampReverb filter/damping frequencies.rv_lpf: [1, 20000] Hz, rv_hpf: [1, 1000] Hz, rv_damp: [10, 20000] Hz.
rv_lpf_slew / rv_hpf_slew / rv_damp_slewLag time for reverb filter/damping params.Number, >= 0.
rv_mod_freq / rv_mod_depthReverb modulation params.rv_mod_freq: [0.01, 4.0] Hz, rv_mod_depth: [0, 10] ms.
rv_mod_freq_slew / rv_mod_depth_slewLag time for reverb modulation params.Number, >= 0.
bpmCurrent BPM.Number, > 0.

Need setup/download info? Visit Downloads or Buy.