Looking forward to talking about Algorave, live coding, TidalCycles and a cultural grounding for it all in pattern at TEDx Hull tomorrow. I have been a bit unsure whether the showbiz 15 minute talk was for me but preparing for it has been a nice exercise in organising my thoughts, and I am now really looking forward to it. I’ll do some semi-improvised live coding, hopefully won’t crash and burn.. The rest of the line-up is really interesting too.
Things coming up in 2017..
- Running Tidalclub Sheffield with Lucy Cheesman – every third Thursday of the month, the third edition this 16th March
- 17th Mar – Algorave wearefive – celebratory online stream with 48 performances beaming from round the world + clock
- 23 Mar – Algorave Berlin – a really nice line-up, I’ll be playing solo
- 31 Mar – TEDx Hull – a talk about algorave, and algorithmic dance culture
- 22 Apr – Eulerroom 6 – haven’t done one of these for a while.. Hosted by Tidal Club, I’ll be organising with Lucy but not actually playing.
- 28 Apr – Algorave Leeds – another huge line-up, live coding solo again
- 16 May – Taking part in a panel session at Thinking Digital Arts, Gateshead
- 26/27 May – Running a two-day TidalCycles workshop with the multi-channel system at Call&Response in South London
- 2 Jun – Back to the Open Data Institute in London, launching the outcomes of my residency there
- 7 Jun – An evening TidalCycles workshop at London Music Hackspace, Somerset House
- 9 Jun – Algorave activity as part of No Bounds festival, Hope Works Sheffield, I’ll be performing with Joanne
- 23 Jun – Talk and probable algorave activity at Bump festival, Brussels
- 9 Jul – Canute performance at the Bluedot festival algorave, Jodrell Bank
- 18-20 Aug – Another collab with Joanne at the Green Man festival algorave in Einstein’s Garden
- 9 Sep – Organising evening performances at FARM Workshop 2017, Oxford
- 8-12 Nov – Organising Algomech festival in Sheffield again
I’ve just realised that I haven’t posted here about my new job. I have left my post as research/teaching fellow in the University of Leeds, and since February 2017 have started work for a Museum, in particular the Research Institute of the Deutsches Museum, an incredible science museum in Munich — although I am still based in Sheffield UK. I’ll be working part time over the next five years on the PENELOPE research project lead by Ellen Harlizius-Klück, following our previous project Weaving Codes, Coding Weaves.
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 (/)