Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Live Programming Music With Tidal: A Quick Hands-on Intro

DZone's Guide to

Live Programming Music With Tidal: A Quick Hands-on Intro

Not to be confused with the music streaming service called Tidal, the Tidal programming language is for creating music programmatically and it's built with Haskell. Now you can try it in this tutorial!

· Java Zone
Free Resource

The single app analytics solutions to take your web and mobile apps to the next level.  Try today!  Brought to you in partnership with CA Technologies

Earlier this year one of my favorite musicians, Paul Wolinski from the band 65daysofstatic, wrote an article and tweeted about his experiments with live coding music using Tidal, a language for programming music on the fly written in Haskell.

A quick dive onto youtube showed that live coding music is getting really popular, with gigs sprouting up around the world with nothing but a console window, a projector and some speakers. And some of it is really, really good.


There are also other languages available, such as Overtone for Clojure. For this article I stick with Tidal because it’s really easy to get started, and I’ve never used Haskell before. So irrelevant of what language you’ve experience in, it’s time to get stuck in and make some music.

Getting Started

Tidal already has an exceptionally good getting started section which you should head to and check out here. I won’t repeat them, but in summary you need:

- Dirt, a synth/sampler which can be installed using Brew

- Jack, an audio connector library, also installed using Brew

- Haskell (and yes, you can use Brew for that too).

- Tidal

These will only take a few command line arguments to install, and once they’re set up you won’t need to touch them again. The last thing we need is an editor. There’s support for vim, emacs and sublime, but I’m choosing to use Atom, the editor from Github. As long as you follow the instructions on the page, it shouldn’t really matter what you use.

Let’s make some noise

Here’s a very basic example Tidal command:

d1 $ sound "sn cp"

There are 9 outputs you can use, d1 through d9. We start the command with which output to send to. We then use the $ sign as the connector to what we’re going to send; in this case we’re using two sounds from the sample library, sn (snare) and clap (clap). With everything set up, we should be able to hit command enter and here a snare, followed by a clap, on repeat. Congratulations! You’ve got your first song.

This sequence simply fits one sn and one cp into a bar, then repeats. If we put more sounds in, then the beat will sound faster as it needs to fit 4 samples into the same space.

d1 $ sound “sn cp sn cp”

This might be a good point to say that, if you want everything to silence, you just use the command “hush”.

To build up a song, you simply put sounds to different outputs to have them play at the same time. The below should give a nice low drone, with a clap keeping time

d1 $ sound "cp"

d2 $ sound "arp"

This is boring so far as it's just one sound per beat. You can have multiple sounds per beat using square brackets; everything in the square brackets will get played in the time frame of a single beat.

d1 $ sound "cp [sn sn sn sn] [bd bd]"

You can even create polyrhythms using curley braces.

d1 $ sound "{cp sn sn, bd crow}"

So we’ve so far figured out how to make interesting enough patterns and beats. You can use any sample from the dirt library (installed in ~/Dirt/samples) which gives you a huge creative palette to play with. Here’s a small songlet using only what we’ve learnt up to this point.

d4 $ slow 2 $ sound "alphabet:7 alphabet:4 [alphabet:11 alphabet:11] alphabet:14"

d1 $ sound "ades3:2*4"

d2 $ slow 1 $ sound "{hh*4, bd:4 sn:2}"

d3 $ slow 1.5 $ sound "arpy*8 arpy:1*8"

The slow command allows the pattern to be spread over multiple bars, which is a nice way to avoid quickly repetitive patterns.

By itself this will get repetitive quite quickly. One of the reasons I enjoy watching the algorave videos on youtube is watching as the coder changes things on the fly; no preview, just type and execute. This leads to some interesting results.

The Tidal palette is much greater than this fortunately. There are a lot more transformative commands to allow a variation in the patterns.

d1 $ every 4 (0.5 <~) $ slow 0.5 $ sound "{~ ~ sn:2, hh hh bd:3 hh}"

In this pattern, every 4 bars we shift the pattern half a bar backwards. This makes the beat a little more interesting, and I think sounds a little bit like Radiohead.

d1 $ sound "bd sn sn"

|+| pan "0 0.5 1"

This additive command unsurpringly pans the sounds around; use headphones for the best effect.

d1 $ chop 246 $ sound "arpy*4 arp*4" |+| speed "[1 2 4 9 1 3 1]/2"

The chop command cuts the sound into the specified number of pieces. This degrades the sound in a variety of interesting ways depending on the chop number. There are a number of granulating functions in tidal, such as striate, which can make an infinite number of interesting sounds.

The speed command changes the speed of the sample, multiplying by the amount. This allows you to change the note being played of things like the arp sample.

Hopefully this has given you a brief insight into how easy it can be to start programming live music. I highly recommend checking out the plethora of videos on youtube, as I’ve found the best way to learn is by copying. There’s also the great Tidal Cycles twitter feed which is a nice aggregation of news and interesting links, videos and code samples.

CA App Experience Analytics, a whole new level of visibility. Learn more. Brought to you in partnership with CA Technologies.

Topics:
haskell ,music ,clojure ,atom ,atom.io

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}