Some experiments: Reified duration, multi-parameter sequences in a single String, and chord sequences

These are a few new language features in an experimental branch of Tidal[1]. It uses a variant of the Pattern type called Epic. (It’s called an Epic because rather than having an implicit fixed duration of one, it can have an explicit duration of any length, including potentially infinite.)

Reified duration allows an Epic a of duration n can be glued (using the +- operator) to an Epic of duration k, to create one of duration n+k. (The duration of an Epic can be determined using the “period” function.)

Here’s the multi-parameter sequence idiom:

melody = p0 “t1%8 _bow d0 ,, d2 ,, _flute ,, t1%4 d5”

p0 turns the string into a ParamEpic, that is, something of type Epic ParamMap. The string descrbes four events, in sequence, separated by the “,,” symbol. The “t1%8” says “the following events have duration 1/8”. The subsequent “_bow d0” says “play the bow sample on scale degree 0.” The “,,” indicates that that’s the end of the description of the first event. The next event uses scale degree 2. Since the sample (bow) and duration (1/8) were specified already, those parameters carry over, so the next event is just like the first except it differs in scale degree. Then the flute plays, on (since it isn’t specified) degree 2 again, and again for a duration of 1/8. Last the duration switches to 1/4, and (because it’s not specified) the flute plays, on scale degree 5.

Other parameters (gain, speed, sustain …) can be specified in that notation — see Sound.Tidal.Epic.Parse.Cmd to see how each is written.

Here’s the scale sequence idiom:

scaleCycle = cata 1 [dim,lyd,aug]

“cata t as” turns a list (“as”) into the type “Epic a”, where each “a” has a duration of “t”. In this case, we’re creating a cycle of three scales — diminished, lydian and augmented — each with a duration of 1.

The scale cycle can be applied to the melody like this:

scaledMelody = scaleCycle <*> melody

or this:

v3 $ scaleCycle <*> melody

This code is very incomplete. In the issue tracker[2] I’ve listed some of the directions in which I’d like to take the code. Suggestions, quesitons and contributions are eagerly invited.