Tidal module for sending patterns over MIDI.
PortMIDI variant. Should work on OS X, Linux and Windows
This still is experimental software
Simply do
~$ 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
If you want, you can also install tidal-midi from source. You will have to clone this repository and install from source:
~$ git clone https://github.com/tidalcycles/tidal-midi.git
~$ cd tidal-midi
~/tidal-midi$ cabal install
After that you can import Sound.Tidal.MIDI.Output within Haskell. To make use of tidal-midi within emacs and running along with tidal, depending on your editor you will have to edit the load script for tidal.
Within your tidal.el
script, locate the function tidal-start-haskell
and add:
(tidal-send-string "import Sound.Tidal.MIDI.Output")
after
(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.SimpleSynth")
as well as the initialization commands for streams:
(tidal-send-string "keyStreams <- midiproxy 1 \"SimpleSynth virtual input\" [(keys, 1)]")
(tidal-send-string "[t1] <- sequence keyStreams")
For adding the MIDI device "SimpleSynth virtual input" and control it via MIDI channel 1. With this set up you will be able to use it via e.g. t1 $ note "50"
Synth specific usage instructions can be found below. Note that these are simply assuming you are running tidal-midi directly via ghci command line. If you want any of the other synths within emacs, you will have to edit your tidal.el
accordingly.
in your .ghci
add the following, given you need an additional latency of 1ms, your device name is SimpleSynth virtual input and you want to send commands on MIDI channel 1:
import Sound.Tidal.MIDI.Output
import Sound.Tidal.SimpleSynth
keyStreams <- midiproxy 1 "SimpleSynth virtual input" [(keys, 1)]
[k1] <- sequence keyStreams
You can alter the latency to fit your other sources (e.g. audio buffers etc.), but be aware that there is already 100ms latency added to make sure incoming osc commands can be scheduled in the future. Note that the given latency is directly passed to PortMidi openOutput
which will send real-time MIDI messages for latency 0 which may or may not be what you want.
To find out a particular device name you can use aconnect -o
on linux and the Audio MIDI Setup on Mac OS X.
Channels can be multiple, e.g. for polyphonic synthesizers this makes it possible to have separate streams (like d1-9 for dirt) for each midi channel on the same device.
keys
in this case refers to the ControllerShape
defined by the example simple synth. See other supported synths
Eventually run ghci -XOverloadedStrings
and send MIDI commands to a compliant device (software synth).
k1 $ note "50*4" |+| slow 2 (modwheel (scale 0.2 0.9 tri1))
The simple synth comes with simple MIDI parameters, that any device should understand:
- modwheel
- balance
- expression
- sustainpedal
all of these parameters map the given values from 0..1 to MIDI values ranging from 0..127.
Example:
import Sound.Tidal.MIDI.Output
import Sound.Tidal.VolcaKeys
keyStreams <- midiproxy 1 "VolcaKeys" [(keys, 1)]
[k1] <- sequence keyStreams
Example:
import Sound.Tidal.MIDI.Output
import Sound.Tidal.VolcaBass
bassStreams <- midiproxy 1 "VolcaBass" [(bass, 1)]
[k1] <- sequence bassStreams
Example:
import Sound.Tidal.MIDI.Output
import Sound.Tidal.VolcaBeats
beatStreams <- midiproxy 1 "VolcaBeats" [(beats, 1)]
[k1] <- sequence beatStreams
Example:
import Sound.Tidal.MIDI.Output
import Sound.Tidal.Blofeld
keyStreams <- midiproxy 1 "Waldorf Blofeld" [(keys, 1)]
[k1] <- sequence keyStreams
assumes the following Tetra Global parameters:
Multi mode
: OnM Param Rec
: NRPNMIDI Channel
: 1
import Sound.Tidal.MIDI.Output
import Sound.Tidal.Tetra
keyStreams <- midiproxy 1 "DSI Tetra" [(keys 1),(keys, 2),(keys, 3),(keys, 4)]
[k1,k2,k3,k4] <- sequence keyStreams
- SysEx support is there but really limited to work with the Waldorf Blofeld