This is Mike Hodnick with my first article on audiocookbook.org. I recently added the Roland System-1M semi-modular synth to my studio and live setups recently, and as with any new instrument in my studio I wanted to take it to extremes and see what it could do. It was the perfect occasion to document on audiocookbook.org!
I’m not your typical producer or performer. I write computer code, often improvised, to produce sound both live and in the studio. I use a language and live-coding environment called Tidal to trigger samples, play MIDI devices, and create sequences. Instead of a DAW or sequencer to create sound, I use a text language.
My first real experiment with the System-1M was to automate all of its MIDI Control Change parameters from code simultaneously. It’s kind of like running a few dozen LFO’s at once. I like to do this with all of my instruments to take them to an extreme and maybe even get some interesting sounds out. As an added twist, I thought it would be fun to also live-patch the modular inputs and outputs on the System-1M while the MIDI automation was taking place. Here is the result:
The source code used for this performance experiment is at the bottom of this post. The only parameters that were not automated in this example were the Oscillator 1 level (kept at 100%), the Mono/Poly toggle (kept on Monophonic), Legato toggle (off), amp crusher (off), and LFO key retrigger (off). Details about the System-1M’s MIDI implementation can be found at roland.com/support/by_product/system-1/owners_manuals/8789.
There are some brilliant sounds coming out of this thing!
By far, my favorite features of this synth are the two oscillators and their controls. Each oscillator supports multiple wave forms, modulation control (oscillator 2 can be ring-modulated from oscillator 1, and oscillator 1 can be cross-modulated from oscillator 2), and a “color” parameter which can be modulated from the LFO or filter/amplitude envelopes. Oscillator 2 also has a fine-tune control. With all of these combined, the possibilities are enormous.
Stay connected at kindohm.com, @kindohm or facebook.com/kindohm for info about Mike’s studio experiments, releases, and performances.
Here’s the source code used to control the System-1M:
-- play a m9 arpeggio, starting from MIDI notes 45, 33, or 57
m $ slow 2 $ (|+| note "[45 33 57]*4") $ mel m9 10 "0*16?"
|+| dur (scale 0.05 0.2 $ slow 1.9666 sine1)
|+| rlpcutoff (scale 0 1 $ density 1.01 sine1)
|+| rhpcutoff (scale 0 1 $ density 1.132 sine1)
|+| rfilteratk (scale 0 0.5 $ slow 1.2 sine1)
|+| rfilterdecay (scale 0.05 0.5 $ density 1.5181 sine1)
|+| rfiltersustain (scale 0.1 1 $ density 1.277777 sine1)
|+| rfilterrelease (scale 0.05 0.5 $ slow 1.523 sine1)
|+| rres (scale 0 0.7 $ density 1.313 sine1)
|+| rfilterenv (scale 0.1 0.9 $ density 1.111 sine1)
|+| rcrush "0"
|+| rampatk (scale 0 0.5 $ slow 1.213 sine1)
|+| rampdecay (scale 0.05 0.7 $ density 1.333 sine1)
|+| rampsustain (scale 0 1 $ slow 2.313 sine1)
|+| ramprelease (scale 0.05 0.3 $ slow 2.877 sine1)
|+| rpitchenv (scale 0.2 0.8 $ density 1.987 sine1)
|+| rport (scale 0 0.5 $ slow 1.77777 sine1)
|+| rpitchatk (scale 0 0.5 $ density 3.4111 sine1)
|+| rpitchdecay (scale 0 0.5 $ density 1.2222 sine1)
|+| rosc1 "1"
|+| rosc2 (scale 0 1 $ slow 2.6665 sine1)
|+| rosc2tune (scale 0.2 0.8 $ slow 3 sine1
|+| rsub (scale 0 1 $ slow 1.919 sine1)
|+| rnoise (scale 0 1 $ density 3.71771 sine1)
|+| rnoisetype "[0 1]*3"
|+| rsubtype "[0 1]*5"
|+| rlegato "0"
|+| rmono "0.5"
|+| rosc1type (scale 0 1 $ slow 1.77777 sine1)
|+| rosc1range (scale 0 1 $ slow 2.8888 sine1)
|+| rosc1color (scale 0 1 $ density 1.4344 sine1)
|+| rosc1xmod (scale 0 1 $ density 1.30010010 sine1)
|+| rosc1mod (scale 0 1 $ density 3 sine1)
|+| rosc2type (scale 0 1 $ slow 0.9999 sine1)
|+| rosc2range (scale 0 1 $ slow 3.151 sine1)
|+| rosc2color (scale 0 1 $ slow 5.131 sine1)
|+| rosc2ring "[0 1]*9"
|+| rosc2mod (scale 0 1 $ slow 3.141 sine1)
|+| rosc2sync "[0 1]*7"
|+| rlforate (scale 0 1 $ slow 2.17717 sine1)
|+| rlfofilter (scale 0 1 $ slow 3.3333 sine1)
|+| rlfoamp (scale 0 1 $ slow 1.21 sine1)
|+| rlfotype rand
|+| rlfokeytrig "0"
|+| rdelay (scale 0 1 $ sine1)
|+| rdelaytime (scale 0 1 $ slow 3.888 sine1)
|+| rreverb (scale 0 0.4 $ density 1.2331121 sine1)
any insights into the audio implementation – seems really powerful but i can’t find any documentation to take advantage of it
Are you asking about Tidal or about the Roland? I’m going to assume for now that you’re asking about Tidal, since documentation _is_ a little difficult to find. You can get details about installing and using Tidal at http://tidal.lurk.org.
Thanks for a great demonstration, @Mike! Since I’m not a Tidal coder, can you explain the concept behind the code? It looks like lots of things are being scaled. But it sounds like some parameters are being randomized. Is it a linear process? Are thing being looped as well as scaled? Does randomization enter into it?
Tidal is all about running patterns inside a cycle of time. It’s like a continuous loop, but Tidal has logic that allows patterns to change over time. For simplicity though, you could think of Tidal as a sequencer.
At the top of the code, I’m defining a 16th note sequence that plays a m9 arpeggio beginning at MIDI note octaves 33, 45, and 57.
The rest of the code looks complex, but (nearly) each line is based on the same strategy, which is to oscillate some MIDI CC value between 0 and 127 (which is mapped from a value between 0 and 1 in code).
For example, to simply vary the low pass filter cutoff and its resonance from 0 to 127 you could write this:
|+| rlpcutoff (scale 0 1 $ sine1)
|+| rres (scale 0 1 $ sine1)
But this would result in the cutoff and resonance always having the same values as each other. In order to get the two parameters to vary at different rates, I either speed up or slow down one of the parameters:
|+| rlpcutoff (scale 0 1 $ slow 1.5 sine1)
|+| rres (scale 0 1 $ sine1)
Since there are dozens of parameters, I chose to use many unique decimal values to ensure that all of the parameters were being changed at different rates.
One important thing to note is that while the sine1 function is continuous, Tidal only sends the MIDI CC changes at the time a note is played, so it steps to new, discrete CC values when a new note is played.
Sometimes I don’t want to scale a parameter all the way from its minimum to its maximum. For example, the resonance can be a bit much at the top, so I can limit how high it goes:
|+| rres (scale 0 0.8 $ sine1)
There is a “rand” function in Tidal that can produce a random number between 0 and 1:
|+| rres rand
It also works with a range:
|+| rres (scale 0.2 0.7 $ rand)
However, Tidal generates random numbers based on the exact time that a note is played; it is not truly random. For example, this would result in the same values for both the cutoff and resonance:
|+| rlpcutoff (rand)
|+| rres (rand)
Thus, I don’t use the rand function very often. There are ways around this, but maybe outside the scope of this comment!
There are many other interesting facets of Tidal that I’m not using in this code. This code mainly focuses on the MIDI CC changes, but there are many other things you can do with scales, Euclid sequences, beat rotation, and logical functions.
That’s great. Thanks for the clarifications. What if you wanted to change CC values while a note is playing? I understand the Tidal MIDI implementation is new, but that would be very useful for longer notes or drones.
Tidal is strictly based on discrete pattern events. This means it can only play a sample, send a message, or change a value at a point in time when a note is played (rather than continuously, between points). Thus, it cannot change a CC value after a note is triggered but still playing. This is a very restrictive limitation of Tidal, but I also think it’s one of those quirks that causes (or forces) creativity in unexpected ways.
This is fantastical. That is such a smart way to use a simple synth and get some very cool results. I love it.
I am a computer programmer and a musician and I therfore tried to do the same. Unfortunately I just couldn’t complete a full Tidal on my mac. Sounds like El Capitan is not helping too. Lot of time spent in the terminal and non luck. Too bad.
Anyway, thanks for the post. This has inspired me to build a patch in Pure Data to run 100 LFOs into my synth!
Hey Pascal – agree, installing Tidal can be difficult. I use Windows and can’t offer help on Mac. If you want to give it a try again, consider joining the Tidal forum/mailing list and feel free to ask questions: http://tidal.lurk.org/community.html
fantastic work! since im new to tidal and have a system 1m since 2 weeks this is a perfect example for me what is possible.
im specialy interested involving my hardware in tidal programming.
thank you very much!
Hi!
I’m enjoying your tracks and this interesting experiment with the system 1m. Maybe a didn’t read carefully, but did you use a library to control de system 1m? I mean, I’ve connected Tidal with my own system 1m, but I just could control the notes and not the other parameters (filter, lfo, etc).
As far as I know is needed to import a library to control, i.e., the korg volcas. thanks!
@Alejandro – yes, there is a specific System-1M implementation in the tidal-midi package. It is published with tidal-midi 0.8, which is the latest version of tidal-midi. The source for it is here: https://github.com/tidalcycles/tidal-midi/blob/master/Sound/Tidal/MIDI/System1M.hs
Thank you very much!
Alejandro