I really enjoyed mentoring Lizzie’s project last year as part of the ‘summer of haskell’, which is in turn part of the Google Summer of Code. Every year Google pay students to spend a couple of months over the summer contributing to a free/open source project, and Lizzie spent the time exploring automatic generation of Tidal code. It was a fun time, and sparked off a nice collaboration with Shawn and Jeremy around their awesome Cibo project (which we should really pick up again soon)..
It’s sometimes a bit lonely working on Tidal, as Haskell has the perception of being difficult to learn, especially if you’re used to another language.. But it’s also super interesting and rewarding, a great language to think deeply about representations. Over the last year or so there have been more contributors pop up though with great PRs coming in, so I think a community is slowly forming around the innards, helped by cleaner code, a more complete test suite etc.
Anyway the Summer of Haskell folks are getting ready to accept submissions, and I’ve contributed a Tidal idea to the list – to make Tidal easier to install. The reason this hasn’t been done before is because making a binary distribution of a Haskell interpreter is no mean feat.. But I think it’s possible, would have some interesting aspects and would attract the profound gratitude of a lot of people (Tidal isn’t the easiest to install). I’d be very happy to hear about other Tidal-related projects I could helpfully mentor too.
More info on the summer of haskell here.
Back in the glory days of slub I used to live code with Perl, and wrote a text editor (also in Perl) for it called ‘feedback.pl’. It was a strange thing, where you wrote self-modifying code to store data in the sourcecode for the music you were writing, and therefore visualise it. I’ve been intending to make something similar for tidal for ages, and took some time to finally start work. I’ve experimented with a weird visual editor for tidal before, and have been fiddling around with a web-based editor as well, but this time decided to write something that worked in the terminal, using the fantastic ncurses framework. This is partly so it’ll run nicely on the Pi Zero, for my ongoing Spicule project, but partly because it just makes sense for a text editor to work in text mode, and it’s good to start from basics without taking on the many assumptions of an existing ‘general purpose’ text editor. I’m just seeing where it takes me but I’m pretty happy with it so far, it has some structured editing around patterns already, some ascii VU meters going on, and every edit is automatically recorded + timestamped. It’s far from being in a usable state, but here’s a quick demo:
You can find it on github but I’m not inviting patches until it’s a bit more fully formed.
Ok this post is going to look quite dry, but is actually very exciting, at least for users of TidalCycles. So first here’s a video demonstrating the simplified syntax the below blurb will allow in a future version (version 1.0, which will probably be released soon after the upcoming 0.9).
If you want to see more videos like this check the playlists on the TidalCycles youtube channel.
Anyway.. Something I’ve noticed at Tidal workshops is that beginners have problems with this sort of code:
density 2 "1 2 3 4"
There’s the pattern
1 2 3 4, denoted by quotes, and the number
2 without quotes. This says ‘make the pattern twice as dense’, so you end up with this every cycle:
1 2 3 4 1 2 3 4.
Fairly straightforward, but why is the
2 a number, not a pattern? With more complicated, higher-order patterns this becomes increasingly unclear. There are ways to treat that number like a pattern:
spread' (density) "2 5" $ "1 2 3 4"
do n <- "2 5"
density n "1 2 3 4"
… but now you’re converting between numbers and patterns of numbers instead of engaging with the music you’re making.
So I asked about this on haskell-art, in particular how to make it so a function like
density could take either a number, or a pattern of numbers. One suggestion from Henning Thielemann was surprising – that Tidal’s
Pattern type could be defined as a Haskell
To cut this short it turned out that simply by evaluating a small amount of very simple code, Tidal’s syntax suddenly becomes far more expressive.
d1 $ sound "bass3" # speed "1.2"
you can just do
d1 $ sound "bass3" # speed 1.2
d1 $ sound "bass3*4" # speed (scale 1.2 3.2 $ ((+) <$> (slow 4 tri1) <*> sine1))
you can just do:
d1 $ sound "bass3*4" # speed ((slow 4 tri1) + sine1 * 2 + 1.2)
d1 $ up (every 3 ((+12) <$>) "1 8 [7 ~ 4]") # sound "bd"
d1 $ up (every 3 (+12) "1 8 [7 ~ 4]") # sound "bd"
and with a quick re-jig of the definition of functions like
d1 $ n ((+) <$> ((+) <$> "1 2 3" <*> slow 3 "0 1") <*> slow 2 "3 1") # sound "voodoo"
d1 $ n ("1 2 3" + slow 3 "0 1" + slow 2 "3 1") # sound "voodoo"
and much more…
density and friends, e.g.:
let density tp p = unwrap $ (\tv -> withResultTime (/ tv) $ withQueryTime (* tv) p) <$> tp
It’s then possible to fulfil my original aim:
d1 $ density "1 [2 3] [1 3]/2" $ sound "bd [sn:2 mt]/2"
while still supporting the original syntax:
d1 $ density 1.5 $ sound "bd [sn:2 mt]/2"
Basically, it turns out that if you let Haskell treat patterns of numbers as numbers, it provides extremely expressive means for working with them. This makes sense — patterns of numbers are numbers, just numbers which are polyphonic, and vary over (rational) time.
Lovely. This is a huge and unexpected win, which greatly simplifies pattern combination and manipulation, in the process greatly extending the possibilities that are within reach of a few keystrokes. This renews my suspicion that Haskell is full of much wondrous stuff just waiting to be discovered..
 Here’s that ‘small amount of very simple code’, if you want to try this at home:
instance Num a => Num (Pattern a) where
negate = fmap negate
(+) = liftA2 (+)
(*) = liftA2 (*)
fromInteger = pure . fromInteger
abs = fmap abs
signum = fmap signum
instance (Fractional a) => Fractional (Pattern a) where
fromRational = pure . fromRational
(/) = liftA2 (/)
Something I did ages ago on a residency, made a video a while back but forgot to put it here, here it is:
I collaborated with xname on a performance as xynaaxmue on Saturday, audio+video up soon I hope.. xname performs with circuits that turn light into sound, improvising noise using stroboscopic lights. I was live coding with tidalcycles, as ever.
In the past I’ve created flashing patterns on an external monitor for xname’s circuits to feed off, check here for a recording of that one. This time I wanted to control a pair of RGB flash panels over DMX.. I used a tinkerit DMX hat for the arduino, officially retired but you can still find them online and the library is downloadable on github.
I hacked together a Tidal interface the night + morning before the conference, and it worked pretty well.. The Haskell and Arduino code is here.
With everything loaded up, Tidal code like this triggers flashes of light as well as sound:
x2 $ every 2 (slow 2) $ (jux (rev) $ foldEvery [5,7] (slow 2) $ (slowspread (chop) [64,128,32] $ sound "bd*2 [arpy:2 arpy] [mt claus*3] [voodoo ind]")) # dur "0.02" # nudge (slow 4 sine1) The basic features:
- sound – (sample name) is translated into colour in a semi-arbitrary way (a mapping which falls back on some crypto hashing)
- pan – (kind of) pans between the two lights
- dur – controls the duration of the flash
- the flashes have a linear fade, which works across chop and striate
Will update with documentation of the performance itself when it’s up.
Here’s Broken, a new two-sided single out on Chordpunch.
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
I’ve continued with the Tidal cycles project, pushing forward with at least one cycle per weekday, apart from one day when I made a longer recording (to appear on chordpunch soon). All the audio is downloadable and creative commons licensed (CC-BY), check the descriptions for the tweet-sized tidal code for each cycle, and follow on twitter or soundcloud for updates.
brak $ let x = "bd [sn [[sn bd] sn]]*1/3" in interlace (sound $ slow 3 $ x) (sound $ every 3 (append "[bd]*6") x)
weave 4 (speed $ (1+) sinewave1) [density 4 $ every 5 ((0.25 <~) . rev) $ striate 16 $ sound"[bd sn/2]/2", sound "bd [~ hc]*3"]
Texture v.2 is getting interesting now, reminds me of fabric travelling around a loom..
Everything apart from the DSP is implemented in Haskell. The functional approach has worked out particularly well for this visualisation — because musical patterns are represented as functions from time to events (using my Tidal EDSL), it’s trivial to get at future events across the graph of combinators. Still much more to do though.