A TidalCycles module for sending patterns over MIDI.
PortMIDI variant. Should work on OS X, Linux and Windows.
This still is experimental software.
- Supported Synthesizers
- How to write your own synth mapping
- Automatic bootup in Emacs
- Known Issues
Depending on your operating system, you will need to install some prerequisites first.
tidal-midi requires the latest version of
tidal. Run these two commands
in your terminal to install the latest version:
cabal update cabal install tidal
Run the following to install
apt-get install libasound2-dev and libportmidi-dev
Mac OS X
brew install portmidi
cabal update cabal install tidal-midi
Note: On OS X with GHC 7.10 it is necessary to reinstall PortMidi again with frameworks correctly linked:
cabal install portmidi --ghc-options="-optl-Wl,-framework,CoreMIDI,-framework,CoreAudio" --reinstall --jobs=1 --force-reinstalls
This guide assumes you are already familiar with Tidal and creating patterns with samples.
Get the names of MIDI devices on your system
In order to use
tidal-midi you will need the exact name of a MIDI
device on your system. You can get a list of MIDI devices on your system
by running some code in a regular
Assuming you're using the Atom editor, create a new file and save it with
.tidal extension (e.g.
midi-test.tidal). Then, type the following in
import Sound.Tidal.MIDI.Context displayOutputDevices >>= putStrLn
Evalulate both of those above lines separately using
Shift+Enter in Atom.
After evaluating the last line, it will output a list of MIDI devices
in your editor (in Atom, at the bottom output panel).
After listing MIDI devices on your system, take note of the device name you will use. Devices names are case-sensitive.
For the purposes of this guide, we'll assume your device name is "USB MIDI Device".
You only need to do this step whenever you want to get a list of devices. Once you take note of your system's device names, you don't need to perform this step ever again (unless you acquire a new MIDI device).
Make sure you're currently working in a file with a
.tidal extension in
your editor (it could be the same file from the device list step above).
Then type these three lines of bootup code:
import Sound.Tidal.MIDI.Context devices <- midiDevices m1 <- midiStream devices "USB MIDI Device" 1 synthController
Evaluate each of those lines (use
Shift+Enter in the Atom
editor). Now Atom is ready to run MIDI patterns using
In the last line of the boot code above, the last three parameters are the most important:
- "USB MIDI Device" is the name of your device
- 1 is the MIDI channel number
- synthController is the type of synthesizer code to use (you can use custom ones)
Playing patterns on your device
The following code will play a very simple pattern on middle-C:
m1 $ note "0"
note param indicates a MIDI note, where
0 equals middle-C. The
following pattern plays a major scale:
m1 $ note "0 2 4 5 7 9 11 12"
Alternatively, you can use
midinote to explicitly use a MIDI note from 0 to 127:
m1 $ midinote "60 62 64 65 67 69 71 72"
You can use normal TidalCycles pattern transform functions to change
m1 $ every 3 (rev) $ every 2 (density 2) $ note "0 2 4 5 7 9 11 12"
Note length, velocity, and other MIDI CC parameters
Note length and velocity are controlled using the
The value of
dur is given in seconds:
m1 $ note "0 2" # dur "0.05 0.2" m1 $ note "0 2" # dur (scale 0.05 0.3 $ slow 1.5 tri1)
legato parameter tells Tidal to scale the note
duration to fill it's "slot" in the pattern. For example, the following
will give four notes each a quarter cycle in duration (values of legato
greater or less than one will multiply the duration):
m1 $ note "0 1 0 2" # legato "1"
velocity has a range from 0 to 1, and equates to MIDI values 0 to 127:
m1 $ note "0 2 4 5 7 9 11 12" # velocity "0.5 0.75 1" m1 $ note "0 2 4 5 7 9 11 12" # velocity (scale 0.5 1 $ slow 1.5 saw1)
synthController has some params that support MIDI Change Control messages,
such as the mod wheel:
m1 $ note "0 2 4 5 7 9 11 12" # modwheel "0.1 0.4 0.9"
Details about the default MIDI CC messages can be found in the default synth controller section below.
MIDI CC params can have decimal values in the range 0 to 1, which map to MIDI CC values 0 to 127.
Custom synthesizer implementations may implement additional MIDI CC parameters. Please refer to the supported synths for more information.
Custom MIDI Channels
Let's review this line from the boilerplate code above:
m1 <- midiStream devices "USB MIDI Device" 1 synthController
The 2nd to last parameter on that line indicates the channel number. Let's say your device is running on channel 7. You can specify channel 7 by changing the 2nd to last parameter:
m1 <- midiStream devices "USB MIDI Device" 7 synthController
Multiple MIDI Channels
tidal-midi supports devices with multiple channels so that you can create
patterns on each channel separately:
m1 <- midiStream devices "USB MIDI Device" 1 synthController m2 <- midiStream devices "USB MIDI Device" 2 synthController m5 <- midiStream devices "USB MIDI Device" 5 synthController m1 $ note (run 4) # velocity "0.5" m2 $ note "0*2 5 7" # dur "0.1" m5 $ midinote "36 60"
Note: at the time of this writing, multiple channels can cause scheduling problems if the synth controller's latency is too low. This is mainly an issue for
tidal-mididevelopers to improve, but users may be impacted. Latency values can be increased by modifying the synth controller's source code (e.g. in
SimpleSynth.hs), then re-compiling
The default synthController (a.k.a "simple synth")
The simple synth comes with simple MIDI parameters, that any device should understand:
- modwheel (MIDI CC #1)
- balance (MIDI CC #8)
- expression (MIDI CC #11)
- sustainpedal (MIDI CC #64)
All of these parameters map the given values from 0..1 to MIDI values ranging from 0..127.
You can use all of these parameters like the familiar synth parameters in TidalCycles:
m1 $ note "0*8" # modwheel "0.25 0.75" # balance "0.1 0.9" # expression (sine1)
All tidal-midi synthesizers "inherit" from the "simple synth" and automatically expose these same parameters.
See the section below on Supported Synthesizers for details on custom controllers for popular hardware synthesizers.
A variety of custom mappings have been created in
tidal-midi for popular hardware synthesizers.
Click on a device below to get details on its usage:
- DSI Tetra
- Elektron Analog RYTM
- Korg Volca Bass
- Korg Volca Beats
- Korg Volca Keys
- Roland System-1M
- Waldorf Blofeld
How to write your own synth mapping
Interested in using
tidal-midi with your own synthesizer? Please read the guide on Writing a new synth mapping.
Automatic startup in Emacs
tidal.el script, locate the function
tidal-start-haskell and add:
(tidal-send-string "import Sound.Tidal.MIDI.Context")
(tidal-send-string "import Sound.Tidal.Context")
Additionally you will have to add lines to import the synth you want to control via MIDI, e.g.
(tidal-send-string "import Sound.Tidal.VolcaKeys") as well as the initialization commands for streams:
(tidal-send-string "devices <- midiDevices") (tidal-send-string "t1 <- midiStream devices \"USB MIDI Device\" 1 synthController")
The above code adds the MIDI device "USB MIDI Device" and controls it via MIDI channel 1.
With this set up you will be able to use it via e.g.
t1 $ note "50"
Known issues and limitations
- SysEx support is there but really limited to work with the Waldorf Blofeld