Category Archives: haskell

Tidal cycles continued

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.

I should note that this is of course inspired by the long-lived sctweets tradition in the supercollider community.

Tidal cycles

I’ve started a twitter feed called @tidalcycles, with minimal tidal programs and their output. I’ll try to add one a day, but lets see how things go. Here’s the first couple:

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"]

Colourful texture

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.

Vocal

A quick improv from Sheffield:

Here’s the state of my editor at the end:

d1 $ slow 2 $ sound "bd [sn sn bd]/2"

let x = density 2 $ striate' 8 0.75 $ sound (slow 4 $ "[bd bd/4] [ht mt lt]") in
d2 $ stack [every 3 rev $ every 4 (0.75 <~) x
            |+| pan "0.2",
            every 4 rev $ every 3 (0.5 <~) x
            |+| pan "0.8"
           ]
  |+| speed "1"
  |+| shape "0.6"

d4 $ every 4 (density 2) $ echo 0.5 $ brak $ every 3 (0.25 <~) $ sound "[future,odx,bd]*3"
  |+| shape "0.7"


let perc = 0.2 in
d3 $ slow 2 $ whenmod 10 12 (echo 0.25) $ density 2 $ sound (pick <$> "~ [operaesque]" <*> (slow 5 $ run 24))
  |+| slow 16 ((begin $ (*(1-perc)) <$>  sinewave1) |+| (end $ (+perc) <$> sinewave1))
  |+| speed (slow 2 "0.75 0.7")
  |+| pan "0.6"
  |+| shape "0.6"

let perc = 0.2 in
d4 $ slow 3 $ every 2 (rev) $ whenmod 10 12 (echo 0.25) $ density 2 $ sound (pick <$> "~ [operaesque]*3" <*> (slow 10 $ run 16))
  |+| slow 16 ((begin $ (*(1-perc)) <$>  sinewave1) |+| (end $ (+perc) <$> sinewave1))
  |+| speed "0.75"
  |+| pan "0.4"
  |+| vowel "i"

hush

d6 $ whenmod 10 12 (density 2) $ whenmod 12 4 (rev) $ slow 2 $ sound "[futuremono]*3 [odx/3]"


d7 $ whenmod 6 4 (0.25 <~) $ every 4 (density (3/2)) $ slow 2 $ sound "[jungle/2]*2 [jungle/3]*2"
  |+| shape "0.7"


d7 $ (whenmod 2 4 ((|+| speed "0.9") . rev) $ every 2 (0.25 <~) $ sound "odx [sn/2 ~ sn/2]")

d2 silence


d8 $ ((slow 8 $ double (0.25 <~) $ striate 12 $ sound "[diphone2/1 ~ diphone2/3]*4")
  |+| (slow 4 $ speed ((*) <$> "[2 1] 1.5" <*> ((+0) <$> ((+0.4) <$> (slow 4 $ sinewave1))))))
  |+| vowel "i"

d9 $ slow 2 $ sound "[[odx]*4]/3 [[odx]*4 [odx]*8]/3"
  |+| speed "1"
  |+| cutoff "0.04"
  |+| resonance "0.7"
  |+| shape "0.8"

bps 1

Texture 2.0 bug exposure

Texture 2.0 (my Haskell based visual live programming language) is working a bit more. It has reached gabber zero – the point at which a programming language is able to support the production of live techno. Also I’ve made some small steps towards getting some of my live visualisation ideas working. Here’s a video which exposes some nice bugs towards the end:

This is an unsupported, very pre-alpha experiment, but if you want to try to get it working, first install Tidal (and if you want sound, the associated “dirt” sampler). Then download the code from here:

https://github.com/yaxu/hstexture

.. and run it with something like runhaskell Main.hs

 

Release of tidal 0.2.1

For me the best part of my workshops during my residency here at Hangar was getting the participants to try out Tidal. In the final workshop there were around 12 of us jamming together, each with a speaker in a kind of drumming circle, at several points it was sounding really great.

In between workshops I’ve been cleaning up my various bits of code, and have now tied it all together into the first semi-documented release of Tidal. You can get the docs and the source over here.

Let me know if have feedback, or would like me to run workshops in your town…

Demonstrating tidal

After posting at length about the history of my musical pattern representation, I thought I’d better show some demos and explain a bit about how it works in practice.

Demonstrating music tech is difficult, because it seems to be impossible to listen to demos without making aesthetic judgements. The below is not meant to be good music, but if you find yourself enjoying any of it, please think sad thoughts. If you find yourself reacting badly to the broken rhythms, try humming a favourite tune over the top. Or alternatively, don’t bother reading this paragraph at all, and go and tell your friends about how the idea is kind of interesting, but the music doesn’t make you weep hot tears like S Club did back in the day.

Anyway, this demo video shows how polyrhythmic patterns can be quickly sequenced:

Strings in this context are automatically parsed into Patterns, where comma-separated patterns are stacked on top of each other. Subpatterns can be specified inside square brackets to arbitrary depth, and then the speed of those can be modified with an asterisk.

In the above example the patterns are of sample library names, where bd=bass drum, sn=snare, etc.

By the way, the red flashes indicate when I trigger an evaluation. Lately people have associated live coding with evaluate-per-keypress. This doesn’t work outside well-managed rigged demos and educational sandboxes; computer language generally doesn’t work on a character level, it works on a word and sentence level. I had an evaluate-per-keypress mode in my old Perl system ten years ago, but always kept it switched off, because I didn’t want to evaluate 1 and 12 on the way to 120. *Some* provisionality is not necessarily a bad thing; mid-edits may be both syntactically valid and disastrous.

That rant aside, this video demonstrates brak, a fairly straightforward example of a pattern manipulation:

Here’s the code for brak:

brak :: Pattern a -> Pattern a
brak = every 2 (((1%4) <~) . (\x -> cat [x, silence]))

In other words, every 2nd repetition, squash some silence on to the end of the pattern, and then shift the whole thing 1/4 of a cycle to the left. This turns any pattern into a simple breakbeat.

Let’s have a closer look at every in action:

This demonstrates how a function can be applied to a pattern conditionally, in the above shifting (with <~) or reversing (with rev) every specified number of repetitions.

These demos all trigger sounds using a software sampler, but it’s possible to get to subsample level:

The striate function cuts a sample into bits for further manipulation, in the above case through reversal. This is a technique called granular synthesis.

Here’s the code for striate:

striate :: Int -> OscPattern -> OscPattern
striate n p = cat $ map (\x -> off (fromIntegral x) p) [0 .. n-1]
  where off i p = p 
                  |+| begin (atom (fromIntegral i / fromIntegral n)) 
                  |+| end (atom (fromIntegral (i+1) / fromIntegral n))

It takes n copies of the pattern, and concatenates them together, but selecting different portions of the patterns to play with the begin and end synthesiser parameters. The |+| operator knits together different synth parameters into a whole synth trigger message, which is then sent to the synth over the network (the actual sound is not rendered with Haskell here).

This video demonstrates the |+| combinator a little more, blending parameters to pan the sounds using a sine function, do a spot of waveshaping, and to apply a vowel formant filter:

 

Finally (for now) here’s a video demonstrating Haskell’s “do syntax” for monads:

A pattern of integers is used to modulate the speed of a pattern of samplenames, as one way of creating a stuttering rhythm.

That’s it, hopefully this discharges some flavour of what is possible — any kind of feedback always very welcome.

Haskell patterns ad nauseam

TL;DR I’m now describing algorave music as functions from time ranges to lists of events, with arbitrary time precision, where you can query continuously varying patterns for more detail by specifying narrower time ranges.

For more practical demo-based description of my current system see this post.

I’ve been restructuring and rewriting my Haskell pattern library for quite some time now. I’ve just done it again, and thought it would be a useful point to compare the different approaches I’ve taken. In all of the following my underlying aim has been to get people to dance to my code, while I edit it live (see this video for an example). So the aim has been to make an expressive language for describing periodic, musical structures quickly.

First some pre-history – I started by describing patterns with Perl. I wrote about this about ten years ago, and here’s a short video showing it in action. This was quite frustrating, particularly when working with live instrumentalists — imperative language is just too slow to work with for a number of reasons.

When I first picked up Haskell, I tried describing musical patterns in terms of a tree structure:

data Event = Sound String
           | Silence
data Structure = Atom Event
               | Cycle [Structure]
               | Polymetry [Structure]

(For brevity, I will just concentrate on the types — in each case there was a fair amount of code to allow the types to be composed together and used).

Cycles structure events into a sequence, and polymetries overlay several structures, which as the name suggests, may have different metres.

The problem with this structure is that it doesn’t really lend itself to live improvisation. It represents musical patterns as lists embedded within lists, with no random access — to get at the 100th metric cycle (or musical loop) you have to generate the 99 cycles before it. This is fine for off-line batch generation, but not so good for live coding, and is restrictive in other ways — for example transforming events based on future or past events is awkward.

So then I moved on to representing patterns as functions, starting with this:

data Pattern a = Pattern {at :: Int -> [a], period :: Int}

So here a pattern is a function, from integers to lists. This was quite a revelation for me, and might have been brought on by reading Conal Eliot’s work on functional reactive programming, I don’t clearly remember. I still find it strange and wonderful that it’s possible to manipulate this kind of pattern, as a trivial example reversing it, without turning it into a list of first order values first. Because these patterns are functions from time to values, you can manipulate time without having to touch the values. You can still generate music from recursive tree structures, but with functions within functions instead of in the datatypes. Great!

In the above representation, the pattern kept note of its “period”. This was to keep track of the duration of the cycle, useful when combining patterns of different lengths. This made things fiddly though, and was a code smell for an underlying problem — I was representing time with an integer. This meant I always had to work to a predefined “temporal atom” or “tatum”, the lowest possible subdivision.

Having a fixed tatum is fine for acid house and other grid-based musics, but at the time I wanted to make structures more expressive on the temporal level. So in response, I came up with this rather complex structure:

data Pattern a = Atom {event :: a}
                 | Arc {pattern :: Pattern a,
                        onset :: Double,
                        duration :: Maybe Double
                       }
                 | Cycle {patterns :: [Pattern a]}
                 | Signal {at :: Double -> Pattern a}

So lists are back in the form of Cycles. However, time is represented with floating point (Double) values, where a Cycle is given a floating point onset and duration as part of an Arc.

Patterns may also be constructed as a Signal, which represents constantly varying patterns, such as sinewaves. I found this a really big deal – representing discrete and continuous patterns in a single datatype, and allowing them to be composed together into rich structures.

As with all the other representations, this did kind of work, and was tested and developed through live performance and audience/collaborator feedback. But clearly this representation had got complex again, so had the supporting code, and the use of doubles presented the ugly problem of floating point precision.

So simplifying again, I arrived at this:

  data Pattern a = Sequence {arc :: Range -> [Event a]}
                 | Signal {at :: Rational -> [a]}
  type Event a = (Range, a)
  type Range = (Rational, Rational)

This is back to a wholly higher-order representation and is much more straightforward. Now we have Sequences of discrete events (where each event is a value which has a start and end time), and Signals of continuously varying values. Time is now represented as fractions, with arbitrary precision. An underlying assumption is that metric cycles have a duration of 1, so that all time values with a denominator of 1 represent the end of one cycle and the beginning of the next.

A key insight behind the above was that we can represent patterns of discrete events with arbitrary temporal precision, by representing them as functions from time ranges to events. This is important, because if we can only ask for discrete events occurring at particular points in time, we’ll never know if we’ve missed some short-lived events which begin and end in between our “samples” of the structure. When it comes to rendering the music (e.g. sending the events to a synthesiser), we can render the pattern in chunks, and know that we haven’t missed any events.

At this point, things really started to get quite beautiful, and I could delete a lot of housekeeping code. However, I still wasn’t out of the woods..

Having both Sequence and Signal part of the same type meant that it was somehow not possible to specify patterns as a clean instance of Applicative Functor. It meant the patterns could “change shape” when they are combined in various ways, causing problems. So I split them out into their own types, and defined them as instances of a type class with lots of housekeeping functions so that they could be treated the same way:

data Sequence a = Sequence {range :: Range -> [Event a]}
data Signal a = Signal {at :: Time -> [a]}

class Pattern p where
  pt :: (p a) -> Time -> [a]
  atom :: a -> p a
  silence :: p a
  toSignal :: p a -> Signal a
  toSignal p = Signal $ \t -> pt p t
  squash :: Int -> (Int, p a) -> p a
  combine' :: p a -> p a -> p a
  mapOnset :: (Time -> Time) -> p a -> p a
  mapTime :: (Time -> Time) -> p a -> p a
  mapTime = mapOnset
  mapTimeOut :: (Time -> Time) -> p a -> p a

I’ll save you the instance declarations, but things got messy. But! Yesterday I had the insight that a continuous signal can be represented as a discrete pattern, which just gets more detailed the closer you look. So both discrete and continuous patterns can be represented with the same datatype:

type Time = Rational
type Arc = (Time, Time)
data Pattern a = Pattern {arc :: Arc -> [Event a]}

Much simpler! And I could delete about half of the supporting code. Here’s an example of what a “continuous” pattern looks like:

sig :: (Time -> a) -> Pattern a
sig f = Pattern f'
  where f' (s,e) | s > e = []
                 | otherwise = [((s,e), f s)]

sinewave :: Pattern Double
sinewave = sig $ \t -> sin $ pi * 2 * (fromRational t)

It just gives you a single value for the range you ask for (the start value in the range, although on reflection perhaps the middle one or an average value would be better), and if you want more precision you just ask for a smaller range. If you want a value at a particular point, you just give a zero-length range.

I’ve found that this representation actually makes sense as a monad. This has unlocked some exciting expressive possibilities, for example taking one pattern, and using it to manipulate a second pattern, in this case changing the density of the pattern over time:

listToPat [1%1, 2%1, 1%2] >>= (flip density) (listToPat ["a", "b"])

Well this isn’t fully working yet, but I’ll work up some clearer examples soon.

So I hope that’s it for now, it’s taken me a ridiculous amount of effort to get to this point, and I’ve ended up with less code than I begun with. I’ve found programming with Haskell a remarkably humbling experience, but an enjoyable one. I really hope that this representation will stick though, so I can concentrate more on making interesting functions for transforming patterns.

In case you’re wondering what the mysterious “a” type is in the above definitions of “Pattern a“, well of course it could be anything. In practice what I end up with is a pattern of hashes, which represent synthesiser control messages. I can represent all the different synthesiser parameters as their own patterns (which are of different types depending on their function), and combine them into a pattern of synthesiser event, and manipulate that further until they eventually end up with a scheduler which sends the messages to the synth. For a close up look at an earlier version of my system in use, here’s a video.

The current state of the sourcecode is here if you fancy a look, I’ve gone back to calling it “tidal”. It’s not really in a state that other people could use it, but hopefully one day soon.. Otherwise, it’s coming to an algorave near you soon.

As ever, thanks to those who have given me advice along the way.