Tidal Midi

script it…walk away.

I remember a time when I used to come up with witty or comical titles for my posts, but now it’s pretty much just that which my brain is left with after somewhat agonizing experimentation.

This post is about Tidal MIDI which is really just Tidal patterns utilizing MIDI functions from SuperDirt.  At the time of this post the stable MIDI features (for me at least) are found in the 1.0-Dev branches of SuperDirt and Tidal.  Getting these installed can be kind of a PITA so I’ll try to document that as well.

When I first found out about Tidal, MIDI was immediately something I hoped I would be able to use.  I quite enjoy working with DAWs and the instruments that come with, but usually the sequencing tools available are not fun or interesting to me.  Tidal patterns brought a new enjoyment for creating patterns so naturally I wanted to use it to control the DAW.

Before you start, please note that at the time of writing the latest commit I’m running is:


I really have no idea if further commits are working or not, so use 1.0-Dev at your own risk.

First things first you need to get your SuperDirt version updated.  This wasn’t too bad, as you are pretty much just cloning the dev branch and updating your stuff in the SuperCollider folder.   I cracked open Terminal and navigated to

/Users/digitalohm/Library/Application Support/SuperCollider/downloaded-quarks

where you should see your SuperDirt folder.  From there just clone the dev branch into this folder (you are basically over writing things) and then restart SuperDirt.  There is possibly a way to run the stable and dev versions side by side, but don’t be scurd, just do it.

Once you’ve verified that SuperDirt is still working it’s time to move on to Tidal.    This was a bit similar but requires a little bit of cabal.  You will need to navigate to your tidal folder, for mac users it will be


if you installed via cabal (if you didn’t, then head over to Lurk and see if someone can help you out).  From there I deleted the Tidal directory, cloned the dev branch, navigated into the new Tidal directory and ran ‘cabal install –force-reinstalls’   this updated things (however you’ll notice for whatever reason if you run ‘cabal list tidal’ it will report version 0.9.6, I’m assuming some version number isn’t updated yet).

If you did this correctly (or more correct than I explained because maybe my updating was all luck)…IF you did this correctly in some fashion you should be ready to do some STUFF, except first we need to configure some options in SuperCollider for SuperDirt and also declare some stuff in Tidal.

First there are some new items you’ll want to add to your startup file in SuperCollider, which are the new SuperDirt MIDI Options.

~midiOut = MIDIOut.newByName("IAC Driver", "IAC Bus 1");
~midiOut.latency = 0.0;
~dirt.soundLibrary.addMIDI(\midi, ~midiOut);

Initially I ran the above commands line by line to make sure everything would work one by one.  The second line that is commented out is how you will identify your MIDI interface that will be used in the line after.  I’m using the built in IAC driver on macOS.

If SuperDirt started successfully then go into your Tidal editor and add:

(midicmd, midicmd_p) = pS "midicmd" (Nothing)
(midichan, midichan_p) = pF "midichan" (Nothing)
(progNum, progNum_p) = pF "progNum" (Nothing)
(val, val_p) = pF "val" (Nothing)
(uid, uid_p) = pF "uid" (Nothing)
(array, array_p) = pF "array" (Nothing)
(frames, frames_p) = pF "frames" (Nothing)
(seconds, seconds_p) = pF "seconds" (Nothing)
(minutes, minutes_p) = pF "minutes" (Nothing)
(hours, hours_p) = pF "hours" (Nothing)
(frameRate, frameRate_p) = pF "frameRate" (Nothing)
(songPtr, songPtr_p) = pF "songPtr" (Nothing)
(ctlNum, ctlNum_p) = pF "ctlNum" (Nothing)
(control, control_p) = pF "control" (Nothing)

I think it’s possible to add the above to your boot.tidal file, but for now I’m just running it (line by line) in the editor.  At this point you should be able to execute a little diddy called random notes, like so:

d1 $ _discretise 4 (note ((irand 8 ))) # legato 1 # midichan 1 # s "midi"

If you hear stuff on MIDI Channel 2 (because in Tidal we count from 0), and more notably, you hear random notes, then things should be working for you and we can move on to some kewl stuff.

So with the configurations and testing out the way we can start to check out some of the neat things to do with Tidal MIDI.  Here is the way that we can stack notes and call out the midi channel.  Here is something to read:

d1 $ stack [
  every 3 (slow 2) (note "c3*4 g3"),
  every 7 (brak) (every 3 (fast 2) (note "[fs3*8]/2")),
  every 9 (fast 2) (note "as3*4")
] # midichan 0 # s "midi"
d1 silence

So with the new Tidal we can declare the channel per command which is great IMHO.  The #midichan 0 tells us that the preceding stack is meant for MIDI channel 1.  The # s “midi” tells us it’s a MIDI command…and everything else inside is pretty self explanatory, since it’s all notes.  Well maybe it’s not.

Here is a simpler pattern that is just notes but can show you how great stacking midi can be.  Try sending this to a layered pad and piano:

d1 $ stack [
  note "c3",
  note "~ ~ ~ c6" # legato 1,
  note "d4",
  note "c7 d3 e5 c2" # legato 1
] # midichan 1 # s "midi"

This shows you how one can get kind of a multi hand pattern happening with very little effort.  The #legato is useful for holding the note for the duration of the cycle.

Notes are cool, but for my purposes i really needed to be able to send control change values.  If you’ve been keeping up on my life, I’ve shed all my MIDI controllers and hardware.  I still have an APC 40 which is the first controller I had ever purchased, but everything else I sold.  I was trying to find a way to control things without needing a controller.

With the previous version of Tidal MIDI this was very unstable for me.  It would work sometimes and then for whatever reason start failing and dropping notes or MIDI would just stop working completely.  The current 1.0-Dev branch has brought a completely exciting level of stability and so far I haven’t had any issues sending note and cc data across multiple MIDI channels.  Here is an example of a properly structured command for sending a smooth sine wave to a control change value

d2 $ control (_discretise 128 $ slow 16 (scale 0 127 $ (sine1))) # midichan 3 # s "midi" # midicmd "control" # ctlNum 0

Some things to note, the MIDI scale is now 0 to 127 where previously it was 0 to 1.  This is a little more natural to those of us that use MIDI.  Once again the MIDI Channel is specified by the #midichan (which in this case is channel 4 …counting from 0), and this time around we’ve added the #midicmd “control” and the #ctlNum.  This tells SuperDirt that we are sending a control message and what the CC Number is.

Finally I’d like to share an example of stacking note and cc data since you’ll probably want to do both.

d2 $ stack[
  _discretise 16 (note ((irand 16 ) - 24)) # legato 1,
  control (_discretise 128 $ slow 16 (scale 32 64 $ (sine1))) # midicmd "control" # ctlNum 0,
  control (_discretise 128 $ slow 64 (scale 0 16 $ (sine1))) # midicmd "control" # ctlNum 1,
  control (_discretise 128 $ slow 64 (scale 0 24 $ (sine1))) # midicmd "control" # ctlNum 2,
  control (_discretise 128 $ slow 16 (scale 0 8 $ (sine1))) # midicmd "control" # ctlNum 3,
  control (_discretise 128 $ slow 64 (scale 0 16 $ (sine1))) # midicmd "control" # ctlNum 4,
  control (_discretise 128 $ slow 64 (scale 0 24 $ (sine1))) # midicmd "control" # ctlNum 5,
  control (_discretise 128 $ slow 16 (scale 0 8 $ (sine1))) # midicmd "control" # ctlNum 6,
  control (_discretise 128 $ slow 64 (scale 0 16 $ (sine1))) # midicmd "control" # ctlNum 7
] # midichan 1 # s "midi"

Here I’m just sending some random notes out along with CC 0-7, each carrying a sine wave of data at different scales and speeds.

I hope this post can help some of you out if you are looking to get familiar with sending MIDI from Tidal.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.