A Polyphonic and Polyrhythmic MIDI Arpeggiator
TeAr is an advanced polyrhythmic and polyphonic MIDI arpeggiator plugin. It features a variable number of independent arpeggiator engines (add or remove them at any time), each with its own pattern, subdivision, and MIDI output channel. This allows for the creation of complex, evolving musical phrases and textures.
At its core, TeAr is scale-aware. You can select a root note and one of many scale types, and the arpeggiators will intelligently conform to that musical context. A "Follow MIDI In" mode allows the scale's root to be changed dynamically by the notes you play.
Video demo: https://www.youtube.com/watch?v=__oc9Wncv1Y
Video tutorial: https://www.youtube.com/watch?v=pWOuQep7nIs
- Variable Number of Arpeggiator Engines: Add or remove engines on the fly with the
+/-buttons. Create complex polyrhythms and layered melodic lines. - Per-Arp Controls: Each engine has its own On/Off switch, pattern editor, subdivision, and MIDI output channel.
- Powerful Pattern Language: A rich text-based language for defining arpeggio sequences with modifiers for velocity, octave, pitch, gate and step duration, plus chords, euclidean and binary rhythms, repeats and variations.
- Comprehensive Scale Library: A wide selection of musical scales and modes to define the harmonic landscape.
- Visual Feedback: A real-time scale display highlights the active scale, its root, and the notes currently being played by each arpeggiator, color-coded for clarity.
Clicking the ? button next to an arpeggiator's On/Off switch opens the Pattern Generator popup. This tool allows you to quickly create new rhythmic patterns.
- Randomize: Generates a random pattern string using a mix of notes, rests, and modifiers.
- Euclidean Rhythm: Generates a Euclidean rhythm pattern based on the following parameters:
- Hits: The number of active notes (pulses) in the sequence.
- Steps: The total length of the sequence.
- Rot: Rotates the pattern by a specified number of steps.
The pattern string consists of characters that define the arpeggio's behavior at each step. The sections below, down to the end of "Block Commands", describe the core language (syntax 2); Syntax 3 extends it.
Degrees and velocity levels are written as a single character in uppercase hexadecimal: 0-9 then A-F, covering 0 to 15. Uppercase only, because b is the flat command and a lowercase b would be ambiguous. Octave (0-7) and probability (0-9) keep their decimal ranges, which already cover everything they need.
| Command | Description |
|---|---|
1 to F |
Plays a specific degree of the chord/scale (1=fundamental, 2=second, ..., 7=seventh, up to 15 for chords and scales with more than nine notes). |
0 |
Plays the current degree without naming one. Mostly used to close a step that only carries modifiers, as in vF0. |
_ |
Sustains the previously played note. |
. |
A rest; no note is played. |
+ |
Plays the next degree in the chord (e.g., from 1 to 2). |
- |
Plays the previous degree in the chord (e.g., from 2 to 1). |
? |
Plays a random, valid note from the current chord. |
= |
Repeats the last played degree. |
These are prefixed to a note command to alter its pitch for that step only.
| Command | Description | Example |
|---|---|---|
# |
Pitches the next note up by one semitone. | #0 |
b |
Pitches the next note down by one semitone. | b0 |
Velocity is specified with a hexadecimal level from 1 to F, spread evenly over the MIDI range: 1 is 8, 8 is 68 and F is 127.
| Command | Description | Example |
|---|---|---|
vN |
Local: Sets velocity for the next note only. | vF0 (plays the current degree at max velocity) |
v+ |
Local: One level louder, for the next note only. | v+0 |
v- |
Local: One level quieter, for the next note only. | v-0 |
v? |
Local: Random velocity for the next note only. | v?0 |
VN |
Global: Sets velocity for all subsequent notes until the next V command. |
V80 (sets global velocity to 68) |
V+ |
Global: One level louder, from here on. | V+0 |
V- |
Global: One level quieter, from here on. | V-0 |
V? |
Global: Random velocity for all subsequent notes. | V?0 |
The relative commands step from whatever velocity is in effect at that point, and saturate rather than wrap: V+ at F stays at F, and V- floors at 1 so a run of them can never silence the pattern.
Changed in 0.4.0: velocity levels used to run
1-8in decimal over a coarser scale. Patterns saved by earlier versions are converted automatically when a session or preset is loaded, so they keep the velocities they had. A pattern typed or pasted in by hand is read with the new meaning, so an oldv8now means roughly half velocity rather than maximum — usevF.Also new in 0.4.0:
v+,v-,V+andV-now work. They were documented in earlier versions but had no effect, so a pattern of yours that uses them will start changing velocity where it previously did not.
| Command | Description | Example |
|---|---|---|
oN |
Local: Sets octave for the next note only (N is 0-7). | o30 (plays root in octave 3) |
o+ |
Local: Increases octave by one for the next note only. | o+0 |
o- |
Local: Decreases octave by one for the next note only. | o-0 |
ON |
Global: Sets octave for all subsequent notes (N is 0-7). | O5 |
O+ |
Global: Increases the global octave by one. | O+ |
O- |
Global: Decreases the global octave by one. | O- |
pN prefixes a step or a group of steps and plays them only N×10% of the time (N is a digit from 1–9). On a failed roll the step becomes a rest unless a fallback is specified after a :.
pN X
pN X:Y
X is any note command (digit, ?, +, -, =, ., _). On success X plays; on failure the step becomes a rest. With the optional :Y fallback, Y plays on failure instead.
| Example | Behaviour |
|---|---|
p5 1 |
Plays degree 1 with 50% probability; otherwise rest. |
p3 1:2 |
Plays degree 1 with 30% probability; plays degree 2 on failure. |
p7 1:. |
Plays degree 1 with 70% probability; silent rest on failure. |
p5 1:_ |
Plays degree 1 with 50% probability; sustains previous note on failure. |
p5 1:? |
Plays degree 1 with 50% probability; plays a random chord note on failure. |
pN (success steps):(fallback steps)
pN gates an entire parenthesised group. On success, the steps inside (…) play; on failure the steps inside the fallback (…) play. Either branch can contain any note commands or modifiers. A space between pN and ( is allowed.
| Example | Behaviour |
|---|---|
p5 (1 2 3):(4 5) |
Plays degrees 1–3 on success (50%); degrees 4–5 on failure. |
p5 (12):(34) |
Plays degrees 1,2 on success; degrees 3,4 on failure. |
p8 (O+ 1 2 3) |
Plays degrees 1–3 one octave up with 80% probability; rest on failure. |
The fallback :(…) is optional; omitting it makes the entire group silent on failure.
Block commands wrap a group of steps to change their evaluation context.
Any global modifier (O+, O-, V+, V-, etc.) used inside parentheses applies only within the block. When the closing ) is reached the global octave and velocity are restored to the values they had at the opening (.
1 2 (O+ 1 2 3) 1 2
In this example O+ raises the octave for steps 3–5 only; steps 1, 2, 6, 7 play at the original octave.
Parentheses can be nested.
In Scale chord-method mode (single-note mode in the GUI), notes are normally played relative to the degree of the pressed MIDI note within the selected scale. Steps placed between double-quotes are instead played relative to the Scale Root parameter - that is, as if the root note of the scale were pressed regardless of what key is actually held.
1 2 "1 2 3" 4
Here steps 3–5 are always anchored to the scale root while steps 1, 2, 4 follow the pressed note's degree as usual.
Note: In versions up to 0.2,
"was used to "repeat last degree" command. The dedicated command for that is now=.
Version 0.5.0 reads patterns in syntax 3, the language now shared with other FX-Mechanics projects (it lives in FxmeTools). It is a superset of everything above: a valid older pattern keeps its meaning, and these are added.
| Write | Meaning |
|---|---|
x |
A hit without pitch. TeAr has no sound of its own to trigger, so a hit takes a step and plays no note. |
{135} |
A chord: degrees 1, 3 and 5 together, as one step. Inside the braces: degrees (1-F, +, -, =, ?) with their own local prefixes ({1 o+5}); no rest, hold, hit or group. A prefix before the braces applies to every note (v9{135}). After a chord, +, - and = move from its first note, and _ holds the whole chord. |
m4 m8 m16 m32 m64 (m1, m2 too) |
Sets the step duration, as a note value, until the end of the enclosing ( … ). Add t for a triplet: m8t. An m at the start of the pattern replaces the arpeggiator's step duration selector for the whole pattern. Digits after m are read together: m16 is a sixteenth. |
(m32 1 2 3 4) 5 6 |
Four 32nds, then two steps at the outer duration. |
g5, G5, gx |
A gate: the note sounds that many tenths of its step (gx: the whole step, the default). g is local, G global. With _, it applies to the whole held length. |
A generator makes a group of n steps at the duration in effect. The token that follows says what its hits play; every other step is a rest.
| Write | Meaning |
|---|---|
e5/16 x |
An euclidean rhythm: 5 hits spread as evenly as possible over 16 steps. |
e3/8+2 (1 3 5) |
3 hits over 8 steps, rotated by 2. A group after the generator is played in turn, one step per hit: 1, then 3, then 5, then 1 again. |
e3/8 1, e3/8 {135} |
A degree or a chord, played on every hit. |
n8:32-251 1 |
A binary rhythm: a number drawn between 32 and 251, read as 8 bits, the highest bit first. (n, not b, which is the flat.) Without :lo-hi, any number of 0 to 2ⁿ-1. |
e3-5/16 x, e3/8+0-6 x |
Any of k, n, r can be a range a-b, drawn again at each pass. A range on the step count makes the pattern's length vary from pass to pass. |
A global prefix before a generator applies once to all its hits (V8 e5/16 x), a local prefix to every hit (o+e3/8 1), and a probability is rolled for each hit. Limits: 1 to 1024 steps for an euclidean rhythm, 1 to 32 bits for a binary one.
| Write | Meaning |
|---|---|
(1 2 3)*3 |
A repeat: the group played 3 times in a row (2 to 64). It needs a group: write (1)*4, not 1*4. |
1 [3|5|7] |
A variation by pass: 3 the first time through the pattern, 5 the second, 7 the third, then 3 again. A part can be empty ([1|] plays 1 every other pass) and can hold several steps. For the pattern to keep its length all parts should last the same; a difference is a warning, not an error. |
; … |
A comment, to the end of the line. |
- Every pass starts from the pattern's defaults. The global octave and velocity, the gate and the step duration are those of the pattern's start, no
" … "block is left open, and the last degree is 1. So1 O+ 2 3plays 2 and 3 an octave up on every pass, instead of climbing an octave per pass as in syntax 2. - A probability's two branches must last the same.
p5 (1 2):(3 4)is fine,p5 (1 2):(3)is an error. A failedp5 (…)without a fallback now plays the group in silence, so the length stays the same. - Values follow their prefix directly.
o 1is an error in syntax 3. - Unknown characters are errors. Syntax 2 skipped them silently.
o?draws an octave from 0 to 7, ando8,o9are clamped to 7.- A hold at the very start of a pattern (
_ 1 _ . _ 2) holds the last sound of the previous pass, so it loops. - Quotes must be balanced. The
"blocks do not nest: the next"closes the block.
When a pattern has a typing error, the error is shown under the pattern with its position, and the last valid pattern keeps playing. Typical messages: unknown character 'w', prefix 'o' without a value, missing ')', a probability's branches must last the same, a repeat must be 2-64.
The language is shared with hosts that have more to offer than a MIDI arpeggiator. In TeAr, these are accepted by the compiler but have no effect or no use:
~(glide) is meant for hosts that drive a value rather than a note. TeAr ignores it.- A value between single quotes (
v'0.5',p'0.3') is accepted when it is a plain number. Real expressions ('64*energy') need a host that provides them, and TeAr gives the errorexpressions need a host. letlines (aliases for such expressions) are skipped.
A pattern saved before syntax 3 (by a preset or a project) is read in syntax 2 and plays exactly as it did; "syntax 2" is shown under it. It becomes syntax 3 as soon as you edit it. New arpeggiators start in syntax 3.
The full reference, with a one-page summary to print, is in doc/TeAr-language-reference.tex.
| Scale/Mode Name | Intervals (from root) |
|---|---|
| Major Scale Modes | |
| Major (Ionian) | 0, 2, 4, 5, 7, 9, 11 |
| Dorian | 0, 2, 3, 5, 7, 9, 10 |
| Phrygian | 0, 1, 3, 5, 7, 8, 10 |
| Lydian | 0, 2, 4, 6, 7, 9, 11 |
| Mixolydian | 0, 2, 4, 5, 7, 9, 10 |
| Aeolian | 0, 2, 3, 5, 7, 8, 10 |
| Locrian | 0, 1, 3, 5, 6, 8, 10 |
| Melodic Minor Modes | |
| Melodic Minor | 0, 2, 3, 5, 7, 9, 11 |
| Dorian b9 | 0, 1, 3, 5, 7, 9, 10 |
| Lydian #5 | 0, 2, 4, 6, 8, 9, 11 |
| Lydian b7 (Bartok) | 0, 2, 4, 6, 7, 9, 10 |
| Mixolydian b13 | 0, 2, 4, 5, 7, 8, 10 |
| Locrian Natural 9 | 0, 2, 3, 5, 6, 8, 10 |
| Altered | 0, 1, 3, 4, 6, 8, 10 |
| Harmonic Minor Modes | |
| Harmonic Minor | 0, 2, 3, 5, 7, 8, 11 |
| Locrian Natural 6 | 0, 1, 3, 5, 6, 9, 10 |
| Ionian #5 | 0, 2, 4, 5, 8, 9, 11 |
| Dorian #4 | 0, 2, 3, 6, 7, 9, 10 |
| Phrygian Dominant | 0, 1, 4, 5, 7, 8, 10 |
| Lydian #2 | 0, 3, 4, 6, 7, 9, 11 |
| Altered bb7 (Ultralocrian) | 0, 1, 3, 4, 6, 8, 9 |
| Other 7-note scales | |
| Harmonic Major | 0, 2, 4, 5, 7, 8, 11 |
| Double Harmonic Major | 0, 1, 4, 5, 7, 8, 11 |
| Hungarian Minor | 0, 2, 3, 6, 7, 8, 11 |
| Neapolitan Major | 0, 1, 4, 5, 7, 9, 11 |
| Neapolitan Minor | 0, 1, 3, 5, 7, 8, 11 |
| Non-diatonic scales | |
| Major Pentatonic | 0, 2, 4, 7, 9 |
| Minor Pentatonic | 0, 3, 5, 7, 10 |
| Blues | 0, 3, 5, 6, 7, 10 |
| Whole Tone | 0, 2, 4, 6, 8, 10 |
| Octatonic (Half-Whole) | 0, 1, 3, 4, 6, 7, 9, 10 |
| Octatonic (Whole-Half) | 0, 2, 3, 5, 6, 8, 9, 11 |
Pre-built binaries are available on the Releases page.
The macOS builds are universal (Apple Silicon and Intel) and require macOS 10.13 or later.
TeAr is free software and is not signed with an Apple Developer ID (that is a paid Apple subscription). macOS marks anything downloaded through a browser as untrusted, and a DAW will then skip the plugin during its scan, usually with no error at all: it simply never shows up. Clearing that flag is a one-line command and is required whichever package you use.
Using the installer:
-
Download
TeAr-macOS.pkg. macOS will refuse to open it on a double-click, so right-click it and choose Open, then confirm. -
Run the installer (it puts the VST3 in
/Library/Audio/Plug-Ins/VST3, the AU in/Library/Audio/Plug-Ins/Componentsand the CLAP in/Library/Audio/Plug-Ins/CLAP). -
Open Terminal and run:
xattr -dr com.apple.quarantine /Library/Audio/Plug-Ins/VST3/TeAr.vst3 xattr -dr com.apple.quarantine /Library/Audio/Plug-Ins/Components/TeAr.component xattr -dr com.apple.quarantine /Library/Audio/Plug-Ins/CLAP/TeAr.clap
-
Restart your DAW. Logic Pro users may need to trigger a rescan in Plug-in Manager.
Using the zips instead: download TeAr-macOS-universal.zip (it holds VST3/, AU/ and CLAP/), copy TeAr.vst3 to /Library/Audio/Plug-Ins/VST3 and TeAr.component to /Library/Audio/Plug-Ins/Components (or the same paths under ~/Library for a single user), then run the same xattr commands above on the files you copied and restart your DAW. TeAr.clap goes to /Library/Audio/Plug-Ins/CLAP.
If TeAr still does not appear after clearing quarantine, that is a real bug rather than a signing problem, so please open an issue.
Plugin type and usage in Logic Pro / GarageBand
TeAr is shipped as an AU instrument (
aumu) rather than a MIDI FX (aumi), because instrument-with-MIDI-out is the only format that works consistently across every major DAW (Logic, Live, Cubase, Bitwig, Reaper, Studio One, FL Studio). Logic's dedicated MIDI FX slot would be a more natural home for an arpeggiator, but plugins placed there are restricted to AU and unavailable in most other hosts.Recommended workflow in Logic Pro:
- Create a Software Instrument track and load TeAr on it. (TeAr itself produces no audio — its output is silent.)
- Create a second Software Instrument track with the synth/sampler you actually want to hear.
- On the TeAr track, route the MIDI output to the target instrument track using one of:
- External Instrument + IAC bus (most reliable), or
- the MIDI FX → Modifier → Re-route trick on the destination track,
- or any third-party MIDI routing utility you already use.
- Set each TeAr engine's MIDI output channel to match what the destination instrument listens on (default: omni / channel 1).
The same instrument-with-MIDI-out workflow applies in Ableton Live, Bitwig, Cubase, Studio One, Reaper, etc. — consult your DAW's documentation for routing MIDI between two instrument tracks.
- Download
TeAr-Windows-x86_64.zip. - Unzip and copy the
TeAr.vst3directory toC:\Program Files\Common Files\VST3. - Rescan VST3 plugins in your DAW (in Reaper: Options → Preferences → Plug-ins → VST → Re-scan).
For CLAP, copy TeAr.clap from the same zip to C:\Program Files\Common Files\CLAP instead and rescan CLAP plugins.
- Download
TeAr-Linux-x86_64.zip(Intel/AMD) orTeAr-Linux-arm64.zip(ARM). - Unzip and copy the
TeAr.vst3directory to~/.vst3/. - Rescan VST3 plugins in your DAW (in Reaper: Options → Preferences → Plug-ins → VST → Re-scan).
For CLAP, copy TeAr.clap from the same zip to ~/.clap/ instead and rescan CLAP plugins.
This project uses CMake. Formats: VST3, AU (macOS) and CLAP. JUCE 9.0.4, FxmeTools and clap-juce-extensions are pinned in cmake/Dependencies.cmake. CMake uses a sibling clone when there is one (../JUCE, ../FxmeTools, ../clap-juce-extensions) and otherwise fetches the pinned commit; the configure output says which, for each dependency. Pass -DFXME_USE_SIBLINGS=OFF to always build from the pins (releases do).
-
Clone the Repository
git clone https://github.com/odoare/TeAr.git cd TeAr -
Set up dependencies (optional: skip it and CMake fetches the pinned versions; one-time, in the parent directory)
# JUCE git clone --branch 9.0.4 https://github.com/juce-framework/JUCE.git ../JUCE # FxmeTools (shared FX-Mechanics module) git clone https://github.com/odoare/FxmeTools.git ../FxmeTools
-
Configure and build
cmake -B build -DCMAKE_BUILD_TYPE=Release cmake --build build --config Release --parallel
The built plugins will be in
build/TeAr_artefacts/Release/(VST3/,AU/on macOS,CLAP/).
