Skip to content

A multi-track & polyphonic arpeggiator plugin that takes both chords and arp patterns as live MIDI data

License

Notifications You must be signed in to change notification settings

YPares/arpligner

Repository files navigation

Build (Windows) Build (OSX) Join the chat at https://gitter.im/arpligner/community

Build (Linux x64) Build (RaspberryPi arm64)


Arpligner logo


Arpligner is a multi-track & polyphonic arpeggiator which will use your own arpeggiation patterns (like 2Rule TugMidiSeq, LibreArp, Xfer Cthulhu, Reason PolyStep Sequencer, or FL's VFX Sequencer). It is packaged as VST3 & LV2 MIDI plugins and as a standalone application.

  • Multi-track: Multiple arpeggiation patterns can play at the same time for a given chord, each one in its own track of your DAW, or on its own MIDI channel,
  • Polyphonic: Each step can play several notes of a chord at the same time. "Steps" can also hold over an arbitrary length of time and overlap. So besides arpeggiation per se, you can do strumming or really any kind of "turning a plain block chord into something more interesting".

To achieve this, the big difference between Arpligner and the aforementioned plugins is that Arpligner does very intentionally not come with its own graphical interface for editing patterns. Instead it will rely on arp patterns being fed to it as regular (and possibly live) MIDI data: you can thus make use of your DAW piano rool and MIDI sequencing capabilities1, play those patterns live, or use an external MIDI sequencer (software or hardware).

Therefore, you can use it as a regular arp, playing your chords against pre-written patterns, or the opposite. Or both can be live data! That would be having two keyboard players: one in charge of the chords and the other one in charge of how to layout those chords2.

See https://youtu.be/IQ9GFEaS4Ag for an overview of the tool and the basic features (this uses the original Lua script but the video remains valid).

Still experimental, please post issues here in case of bugs or questions, or get in touch on Matrix (room #arpligner:gitter.im): just click here to join the chat! :)

How to use it

Arpligner has two modes: Multi-channel and Multi-instance, which affect how Arpligner will receive MIDI data and set what it considers to be a "chord track" and what it considers to be a "pattern track".

General behaviour

Whatever the mode, Arpligner will interpret "notes" playing on pattern tracks as the degrees of the chord which is currently playing on the chord track. Starting from C3 and going up:

  • C3 means "first chord degree"
  • C#3 means "second chord degree"
  • D3 means "third chord degree", etc.

C3 is therefore treated as the reference pattern note, the one from which everything will be derived.

However, you may wonder then what happens if you go below C3. Or if you go "above" the last degree of your chord. Well then, Arpligner will "wrap around" the chord, but transposing the notes up or down as many octaves as needed, so it always has a sensible chord note to play.

You can also select different mapping and wraparound methods. For instance, you can choose that only the white keys will be used to select chord degrees, and leave the black keys to play the entire chord up to the black key you play. See the pattern settings section for more info.

Multi-channel mode

In this mode, you can use as little as one single Arpligner instance in your DAW session. It expects to be fed MIDI data on at least 2 channels:

  • Channel 16 (by default), which will be treated as the chord channel ("track")
  • At least one other channel (say, Channel 1), which will be treated as a pattern channel ("track"). Any channel other than the chord channel will do, they will all be treated equally.

You can perfectly use several Arpligner instances set to that mode at the same time, but they will just be completely independent of one another. They will each receive their own chord track and pattern tracks.

Multi-channel has the advantage of requiring a bit less CPU and RAM, and enables you to have several chord tracks, each one affecting up to 15 patterns tracks.

Multi-instance mode

In this mode, the different instances of the Arpligner plugin in your DAW session can communicate with one another. You would then have one Arpligner instance per relevant track, one being configured as the Global chord instance, and the other ones as Pattern instances. MIDI channels no longer matter to Arpligner in that mode.

Multi-instance has the advantage of alleviating MIDI routing configuration in your DAW, and is not limited by the number of MIDI channels. So you have just one chord track, but it can affect any number of pattern tracks.

Note that it is perfectly possible to have in your DAW session both Multi-instance instances and Multi-channel instances. Only those set to Multi-instance will communicate, the other ones will keep depending solely on the MIDI data you directly feed into them.

Installation

Arpligner is downloadable via the project's itch.io page: ywen.itch.io/arpligner.

Besides, latest builds are available here, from most recent to most ancient (though github only keeps them for a few months). Select in the left panel the Plugin build action corresponding to your OS (Linux, Windows or OSX), then select the latest run that succeeded (green tick) for that action, then go to the Artifacts section at the bottom of the page.

The downloaded archive will contain the VST3, the LV2 and the standalone app for your OS. Just copy the plugin in your usual VST3/LV2 folder (depending on your OS and DAW settings).

Important: Due to a VST3 limitation, Arpligner will be recognized by your DAW as an Audio Fx plugin, whereas it is only a MIDI Fx plugin. So if your DAW sorts or filters plugins by categories, you will have to look for Arpligner under this category.

Then, I recommend to have one track dedicated to chords. After that, if you use the Multi-channel mode, you'll need some way to configure MIDI routing in your DAW so Arpligner receives what it expects. See this section for tips.

Implementation & build

Arpligner is implemented in C++ with JUCE 7, and therefore should support a variety of systems and plugin formats. I'm providing VST3, LV2 and standalone app builds for Linux, Windows and OSX (x64). The project file for Projucer is also provided if you want to generate build files for other platforms or other plugin formats. Arpligner has no plugin-format-specific or OS-specific code so it should be pretty straightforward.

The code on this repository is mostly self-contained. The build files are in the Builds folder. You have the necessary Linux makefile, OSX Xcode project and VisualStudio2022 solution files (generated by JUCE). To build Arpligner on Linux, you will though need to install first the needed JUCE dependencies.

I originally implemented Arpligner as a Lua script for Protoplug, but switched to direct use of JUCE 7 for maintainability and VST3 support. The original script can be found in ProtoplugArpligner.lua but I should no longer be maintaining it.

Tips

General tips

  • Arpligner should give more controllable results if you write/play your chords in their most canonical form: block chords, no inversions, without any octaving of notes. It will really use your chord note data as they come, it won't do anything fancy to try and detect which chord you are actually playing, what is its root, etc. But note that "more controllable" does not necessarily mean better ;)
  • In pattern channels, only note pitches are affected. So your "pattern" notes will stay on the same channel, keep their velocity, etc. That means your patterns may contain velocity variations, pitch bends, CCs or that kind of things :)
  • As it is working with potentially live MIDI data, Arpligner has no notion of things like "start point", "end point" or "loop", and thus cannot do things like "reset the pattern when the chord changes". Therefore, it's up to you to keep your chord and pattern clips in sync (or interestingly out-of-sync). E.g. for a regular arp "emulation", if you work with looping clips, just make your chord clip have a length that is a multiple of that of your pattern clip, so you'll repeat the same pattern several times over different chords.
  • Besides pre-writing chord progressions or playing them live, you can use plugins like Scaler 2 which speed up the process of writing chord progressions, and which can output their chords as MIDI and sync with the host's tempo & transport.
  • Arpligner offers different behaviours for when it is receiving no notes or just one note on the chord channel. Default behaviour is "latch & transpose": it will keep using the last chord if it receives no more notes, and it will transpose it if it receives just one note. See the settings below for more info.

Tips for Multi-channel mode

When using Multi-channel mode, you have two options:

  • Dedicate one MIDI channel to each of your instruments. Then use only one Arpligner instance on your chord track, and route all your MIDI data to it, making sure that this data is properly tagged by channel. Then, split back the MIDI data that Arpligner outputs by MIDI channel, and route each channel to its corresponding instrument. Depending on your DAW, you may have to use 2 tracks per instrument in that fashion: one for the pattern clips for this instrument, and one for the actual instrument.
  • Place one instance of Arpligner on each of your pattern tracks, and route the same chord track to all of them. Each instance will then receive a pattern track on only one MIDI channel, and they will all process their patterns according to the same chord progression. Each instance can then process pattern data on several channels (this can be useful for multi-timbral instruments like Kontakt or Omnisphere, or if your DAW supports layering several instruments on the same track).

For example in Bitwig, you can put the Note Receiver device in a track to route MIDI events from another track, and you can use the Channel Map device in the Source FX section of this Note Receiver to make every incoming note go to the right MIDI channel. Do not forget to deactivate the Inputs button in the "Mutes" so that MIDI events from the track pass through too.

Tips for Multi-instance mode

In Multi-instance mode, when some chord notes and pattern notes start at the exact same time (which is a ubiquitous case when using MIDI clips or sequencers), you will probably need one of the following two options (don't do both at the same time):

  • Either introduce some delay on each one of your pattern tracks: if your DAW has a feature to delay MIDI notes by a few milliseconds on pattern tracks, it can be used here (in Bitwig, that's the Note Delay device, which can go as low as 10ms delay, which in my tests was enough)
  • Or make sure the Global chord track lookahead on your chord track has a non-zero value: increasing this delay parameter (in milliseconds) on your Global chord instance should have an effect similar to the first option (but requires a change on only one track, not on all your pattern tracks). The lookahead time on the Global chord instance is 10ms by default. You probably will need to reload (deactivate/reactivate) your Global chord instance if you change it, so your DAW may register the change. This will tell your DAW that this Global chord instance needs a bit of extra time, and it will delay all the other tracks in consequence.

If you do not do that, your pattern instances may process their notes before the chord instance has noticed that the chord has changed, and you would get some final result which is still using the previous chord. This is perfectly expected and cannot be avoided in situations where your MIDI is sequenced. It comes from the fact that you have no guarantee over the order in which your DAW will execute your plugins' logic, and therefore over which instance will notice first some perfectly synchronized MIDI events. Therefore we need to delay a little bit (by inaudible amounts) the pattern tracks with respect to the chord track to make sure everything is updated in the right order. In live situations, such perfect synchronization never occurs, so it's much less of a concern.

Note that Multi-channel mode does not raise this concern at all (live or not). In that mode, given all events are processed by the same instance, I can make sure to update the current chord prior to processing pattern notes.

Available settings

Arpligner's GUI shows a few parameters that you can change to make Arpligner fit your usage and workflow. These parameters are also exposed to the host, and can be automated3.

Parameter name Default value Possible values Documentation
Instance behaviour [Multi-chan] Chords on chan 16 Choose from: The main behaviour of this Arpligner instance
Bypass Do nothing and just pass all MIDI events through
[Multi-chan] Chords on chan XX Sets to Multi-channel mode, and use channel XX as the chord track (and any other channel as a pattern track)
[Multi-instance] Global chord instance Sets this instance as the one that receives chord notes (any MIDI input, whatever its channel) and sets the current chord for all other connected instances
[Multi-instance] Pattern instance Sets this instance as a "follower" of the one set to Global chord instance. Any MIDI input, whatever its channel, is considered a pattern event, and will stay on the same channel

Chord parameters

These parameters are used only in Multi-chan mode or by Chord instances.

Parameter name Default value Possible values Documentation
When no chord note Latch last chord Choose from: What to do when no note is playing on the chord track
Silence Ignore the pattern notes
Use pattern notes as final notes Consider the pattern "notes" as real notes, and pass them through without any change
Latch last chord Keep using the previous chord that played (Silence if no previous chord is known)
When single chord note Transpose last chord Choose from: What to do when a single note n is playing on the chord track
Silence Same as for "no chord note"
Use pattern notes as final notes Same as for "no chord note"
Use as one-note chord Use n as just a "one-note chord". Tread carefully, the end result may go up in octaves pretty fast
Powerchord Turn n into a "2-note chord": n and the note a fifth above
Transpose last chord Transpose last chord so that its lowest note becomes n (Silence if no previous chord is known)
Global chord track lookahead 10ms A delay between 0 and 50ms Only used by a Global chord instance. Triggers your DAW Plugin Delay Compensation (if above zero) to deal with perfectly synchronized chord and pattern events. See this section for when to use this

Pattern parameters

These parameters are used only in Multi-chan mode or by Pattern instances. When using the Multi-instance mode, you can therefore select a different behaviour for each Pattern instance. This can be useful for instance if some instruments are to be played live and others via MIDI sequencing, or if different live players have different preferences.

Parameter name Default value Possible values Documentation
Reference pattern note 60 (C3) A MIDI note On pattern tracks, the note that will always be mapped to the first (lowest) degree of the currently playing chord
Pattern notes mapping Semitone to degree Choose from: How to map midi note codes on pattern tracks to actual notes
Always leave unmapped No pattern note is mapped, and therefore always use the Unmapped notes behaviour
Semitone to degree Going up/down one semitone in the pattern track means going up/down one degree in the chord
White note to degree Going up/down one white key in the pattern track means going up/down one degree in the chord. Black keys are not mapped
Pattern octave wraparound [Dynamic] After all chord degrees Choose from: When should your pattern wrap around the chord, ie. play it at a higher/lower octave. (Used depending on the mapping setting above)
No wraparound Never. Pattern notes past the last chord degree are unmapped, as well as notes below the Reference note
[Dynamic] After all chord degrees Repeatedly go up one octave (and back to the first chord degree) as soon as we're past the last chord degree, or down one octave (and to the last chord degree) in the other direction. No pattern note is therefore ever left unmapped.
[Fixed] Every XXth pattern note Use a fixed wraparound setting. You will go up one octave (and back to the first chord degree) every time your pattern goes up XX notes, and down one octave (and to the last chord degree) every time your pattern goes down XX notes. Intermediary pattern notes that do not correspond to chord degrees are unmapped.
Unmapped notes behaviour Silence Choose from: What to do when the mapping or wraparound settings above have left some pattern notes unmapped
Silence Do not output any note
Use as is Output the pattern note as it is
Transpose from 1st degree Use Arpligner as a "dynamic" transposer: ignore all chord degrees besides the first (lowest) one. Pattern notes are just transposed accordingly. This allows you to play notes that are outside the current chord, but keeping your patterns centered around the reference note
Play all degrees up to note Play the full chord, using the played note as a filter (all chord degrees above will be silenced)

Current limitations

  • Arpligner is quite strict for now regarding the timing of notes on the chord channel. When your chords are played from already quantized MIDI clips or by a sequencer it's not a problem, but for "classical" live arp usage, i.e. when playing chords live against a preset pattern, it can be. So in this scenario, I recommend to use some sort of beat quantizer on your chord channel before Arpligner, and to play around with the various settings until you get a satisfying result.
  • I would love to be able to support MPE in patterns: given in Multi-instance mode you can use as many channels as you want for your patterns, this would allow you to play your patterns on any MPE instrument, with glides, polyphonic bends, expression changes, etc, record them and be able to keep these in your final arpeggios while re-using them over a different harmony :). Sadly my JUCE skills are not up to this task yet, but any help is welcome!

Footnotes

  1. I use Bitwig and the piano roll editor and MIDI operators to manipulate notes are just so much better and so much more flexible than everything I've seen in plugins

  2. And if someone ever makes a jazz jam session out of that, definitely record it and send me the video ^^

  3. WARNING: In some cases, automation of some of these parameters while Arpligner is processing notes may cause stuck notes, please report an issue here if this happens to you, preferably with a set of MIDI files that will help me reproduce the problem