m18s
a two voice sequencer for monome norns based on the RYK M-185
Here’s a quick example of the crow standalone version of m18s controlling two sequences:
m18s uses the concept of steps and stages to tell time. each step has a specified number of stages, which can be expressed in a way similar to Morse Code.
In the above picture, voice 1, step 1 has 1 stage, and then step 2 has 8. step 3 has 3 sages, but only 2 have dots. this is because it has a different gate mode where only every 2nd stage triggers. there are 8 gate modes like this. these are:
- “off”: don’t trigger any gates during the step
- “single”: only trigger a gate for the first stage of the step
- “all”: trigger a gate for every stage of the step
- “every2”: trigger a gate every other stage
- “every3”: trigger a gate every 3rd stage
- “every4”: trigger a gate every 4th stage
- “random”: (this is represented by the dots of the step dancing along to the beat) 50% chance you trigger a gate for each stage
- “long”: (in the picture, the long solid line for voice 2, step 1) gate should go high on stage 1 and low on the last stage. If the step is 1 stage long, just do a standard gate pulse
There will be a number of programs (which will be able to be changed by scrolling with E1) which you’ll be able to use to interact with and modify the sequence. The first of these, reset is currently the only one currently implemented (so I made E1 just cycle through docs of the current interface for now). While in Reset mode you can restart the sequence to wherever the cursor is currently set to. move the cursors with E2 or E3 and reset the sequence with K2 or K3.
Note that you can change the sequence by randomizing the sequences (do this by holding K2 and K3 together.) This will cause the number of stages, stage gate modes, and note from the scale in the params menu). in the future these will be able to be set within the norns interface.
There are also a number of sequence advancing modes (currently addressable in the params menu. These are:
- forward: go to the end and then restart back at the beginning (note: currently always resets to position 1, not what the cursor highlights. will probably change)
- pingPong: go to the end and then go towards the beginning (note: in reverse the stages are still iterated from lowest to highest…so it’s more of a zigzag than a true reverse. will probably change this. will also probably make the cursor the reset point)
- fixedLength: go a specific number of notes and then reset (this one is great for creating more rigid timings). this is currently the only sequencer advance mode which will restart to the cursor instead of position 1.
- random: randomly jumps to a new note in the sequence after all the stages of the current note have finished.
legacy crow standalone version docs
Requirements
crow, connected to druid or ^^derwydd so that you can modify and modulate the sequence
Documentation
at the bottom of m18s.lua you can find configuration/initialization and setters sections:
configuration/initialization:
you’ll find two sections of variables, one for each voice. these are the variables that crow uses to define the sequences it is running on boot.
here are those variables for voice 1, annotated:
gateLength1 = .01 # length of pulse for non-held stages
mode1 = "forward" # direction of step advancement
# can be "forward", "random",
# "pingPong", or "fixedLength"
oct1 = 0 # octave offset
fixedLength1 = 10 # for "fixedLength" mode, number of stages until reset
scale1 is the possible notes the sequence can be in 12-TET semitones
seq1 is a table of steps. each step is defined as a table of:
- note to play for the step
- number of stages until you advance to the next step
- stage gate mode. this can be:
- “off”: don’t trigger any gates during the step
- “single”: only trigger a gate for the first stage of the step
- “all”: trigger a gate for every stage of the step
- “every2”: trigger a gate every other stage
- “every3”: trigger a gate every 3rd stage
- “every4”: trigger a gate every 4th stage
- “random”: 50% chance you trigger a gate for each stage
- “long”: gate should go high on stage 1 and low on the last stage. If the step is 1 stage long, just do a standard gate pulse
scale1 = { 0, 4, 5, 7, 9, 12, 16, 17 }
seq1 = {
{ scale1[1], 1, "off" },
{ scale1[2], 2, "single" },
{ scale1[3], 3, "all" },
{ scale1[4], 4, "every2" },
{ scale1[5], 5, "every3" },
{ scale1[6], 6, "every4" },
{ scale1[7], 7, "random" },
{ scale1[8], 8, "long" }
}
Note that neither scale, nor seq have to be of length 8 (and they don’t have to be the same length either).
setters:
m18s is not a sequencer you perform with manually. Rather than an interface of knobs and switches, you are given an interface of functions which can be used to modify and modulate the sequences produced in real time. Note that you can also manually change the sequence using any of the variables mentioned in the configuration/initialization section above
Make sure crow is connected to your computer and you have one of the repl environments open, druid in the terminal or the ^^derwydd maxforlive device in ableton.
For all the following functions, _v is the voice paramter, and can be 1 or 2. this specifies which sequence you are targeting.
List of basic setters:
-
setMode(_v, _m): where _m can be “forward”, “random”, “pingPong”, or “fixedLength”
-
setFixedLength(_v, _fL): where _fL will set the fixedLength variable
-
setStepNote(_v, _s, _n): where _s is the step and _n is the note
-
setStageCount(_v, _s, _sC): where _s is the step and _sC is the stage count
-
setStageGateMode(_v, _s, _sGM): where _s is the step and _sGM can be “off”, “single”, “all”, “every2”, “every3”, “every4”, “random”, or “long”
More complex setters:
-
setThisSequenceOntoOther(_v) sets the sequence of _v onto the other sequence, replacing it
-
randomizeMode(_v) sets the sequencer advancement mode to one of the possible ones, randomly
-
randomizeStep(_v, _s) randomly sets a new note (in scale), stage length, and stage gate mode for the specified step (_s)
-
randomizeAllSteps(_v) randomizes every step of the sequence (maintains current sequence length)
Download
Available in the maiden package manager (as soon as the commit to add it is merged!)
V 0.4 (7/26/20)
- Bug Fixes
- Fixed name typo in docstring
- UX improvements (thank you for the feedback @papernoise!)
- Make note indicator (top row) the full width of the note
- Spacing cleanup
- Make note numbers the note names (A, G# etc.)
- Randomizes sequences on startup (instead of playing my test sequence on startup)
- Allow for randomizing sequences independently
- Shuffle of params screen to make things a little easier to use
- Output modes (thanks to all awake contributors…used heavily as a reference for these! output modes are independently configurable and can be layered)
- Audio output (polysub engine) can now be turned on/off
- Midi output and channel selection
- Dual CV/Gate output (1+2 / 3+4) via crow (both v/oct + v-trig and hz/v s-trig supported)
- JF synth mode output with independent octave offset
V 0.3 (5/26/20)
- initial norns version
- move of crow standalone version to lib/crow_standalone subfolder
V 0.2 (5/9/20)
-
BUGFIX: Fix issue where changing sequence lengths could cause unresponsiveness
- Fixed readme which I hadn’t updated the title/description from when I copied/pasted it in from another repo.
- Added scratchpad.lua, which contains an in-prog function for printing sequences so you can paste them back in to m18s.lua
- Added .gitignore for druid log file
TODO:
- figure out what input 2 should do. ideas are start/stop, manual reset, 2nd clock for individually clocking sequences 1 and 2. Currently thinking I might leave this intentionally blank, and then give a number of potentially useful snippets you could add.
- introduce slew, probably per-step, along with setter function
- introduce the concept of muting a sequence, along with setter function
- figure out how to optimize the code length so that I’m not running up against max script length issues as I build out these other features
–
Also just want to shout out the RYK Modular M-185. It seems like a really well thought out module with a lot of useful programming features…there’s quite a bit more configuration and programming that you can do with it than this script touches, not to mention it seems like a very, nice playable interface. Also the manual was very good (I used it as the basis to create a skeleton of the code).