# Difference between revisions of "What is a pattern?"

(Created page with " In Tidal, what ''is'' a pattern? There are a lot of ways of answering this question. A technical definition is that under the hood, a pattern is a function from time to event...") |
m (removed last superfluous 'A', and double period) |
||

(9 intermediate revisions by 4 users not shown) | |||

Line 1: | Line 1: | ||

− | + | <translate> | |

+ | <!--T:1--> | ||

In Tidal, what ''is'' a pattern? There are a lot of ways of answering this question. A technical definition is that under the hood, a pattern is a function from time to events. You give a pattern a start and end time, and it gives you back the events that are active (in part or in whole) during that timespan. An event is itself a value with a start and end time. | In Tidal, what ''is'' a pattern? There are a lot of ways of answering this question. A technical definition is that under the hood, a pattern is a function from time to events. You give a pattern a start and end time, and it gives you back the events that are active (in part or in whole) during that timespan. An event is itself a value with a start and end time. | ||

+ | <!--T:2--> | ||

This is mostly hidden when it comes to using Tidal to make music, but lets have a closer look at the innards of a really simple pattern: | This is mostly hidden when it comes to using Tidal to make music, but lets have a closer look at the innards of a really simple pattern: | ||

+ | <!--T:3--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

"1 2 3" | "1 2 3" | ||

</syntaxhighlight> | </syntaxhighlight> | ||

− | The above might look like a string, but Tidal quietly parses it into a pattern for you (using a hidden function called parseBP_E). We can ask that pattern for values | + | <!--T:4--> |

+ | The above might look like a string, but Tidal quietly parses it into a pattern for you (using a hidden function called parseBP_E). We can ask that pattern for values by casting the string pattern to a Tidal pattern by appending <syntaxhighlight lang="Haskell" inline>:: Pattern String</syntaxhighlight> to the pattern string. You're kind of telling Tidal to treat this string as a pattern and show you what it sees: | ||

+ | <!--T:5--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

− | + | "1 2 3" :: Pattern String | |

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:6--> | ||

If you run the above, you should see the contents of the first cycle in the output buffer: | If you run the above, you should see the contents of the first cycle in the output buffer: | ||

+ | <!--T:7--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

− | + | (0>⅓)|"1" | |

− | + | (⅓>⅔)|"2" | |

− | + | (⅔>1)|"3" | |

− | |||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:8--> | ||

From that we can see the first event <syntaxhighlight lang="Haskell" inline>1</syntaxhighlight> is active for the first third of the cycle, and so on. | From that we can see the first event <syntaxhighlight lang="Haskell" inline>1</syntaxhighlight> is active for the first third of the cycle, and so on. | ||

+ | <!--T:9--> | ||

So a pattern is a function from a timespan (also known as an ''arc''), to values with each have a beginning and end. A function like <syntaxhighlight lang="Haskell" inline>rev</syntaxhighlight>, is therefore a combinator, which takes such a function as input, and gives a new function as output (with input and output timing manipulations baked-in, in order to reverse the pattern). | So a pattern is a function from a timespan (also known as an ''arc''), to values with each have a beginning and end. A function like <syntaxhighlight lang="Haskell" inline>rev</syntaxhighlight>, is therefore a combinator, which takes such a function as input, and gives a new function as output (with input and output timing manipulations baked-in, in order to reverse the pattern). | ||

− | = The Pattern types = | + | = The Pattern types = <!--T:10--> |

− | That's the basics, lets have a look at some code. The core representation for patterns is in the | + | <!--T:11--> |

+ | That's the basics, lets have a look at some code. The core representation for patterns is in the [https://github.com/tidalcycles/Tidal/blob/master/src/Sound/Tidal/Pattern.hs Sound.Tidal.Pattern] module. The core representation is in the ten or so lines at the top. Lets step through it. Some Haskell knowledge will be helpful here, but you will hopefully get the gist even without software development experience. | ||

+ | <!--T:12--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | Time is rational | -- | Time is rational | ||

Line 36: | Line 46: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:13--> | ||

The above states that time is rational. This means that rather than representing time as integers (whole numbers), or as floating point numbers, Tidal represents time as a ratio of ''two'' integers. This means that for example a third can be represented precisely, as one over three. Music is of course full of such ratios, and not representing them as such can cause a great deal of problems.. Basically, this means that if you add three one-thirds together, you'll get a whole. Seems obvious but not all systems do this! | The above states that time is rational. This means that rather than representing time as integers (whole numbers), or as floating point numbers, Tidal represents time as a ratio of ''two'' integers. This means that for example a third can be represented precisely, as one over three. Music is of course full of such ratios, and not representing them as such can cause a great deal of problems.. Basically, this means that if you add three one-thirds together, you'll get a whole. Seems obvious but not all systems do this! | ||

+ | <!--T:14--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | A time arc (start and end) | -- | A time arc (start and end) | ||

Line 43: | Line 55: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:15--> | ||

This is the representation of an arc, or timespan. We like to call this a time arc rather than a time span, because in Tidal the notion of time is cyclic. Here the two time values are simply the beginning and end of an arc. | This is the representation of an arc, or timespan. We like to call this a time arc rather than a time span, because in Tidal the notion of time is cyclic. Here the two time values are simply the beginning and end of an arc. | ||

+ | <!--T:16--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | The second arc (the part) should be equal to or fit inside the | -- | The second arc (the part) should be equal to or fit inside the | ||

Line 51: | Line 65: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:17--> | ||

Tidal often needs to represent ''part'' of an arc. It does so with two arcs, the first representing the whole of the part, and the second the part itself. Often both arcs will be the same, which simply means that we have a whole that has a single part. | Tidal often needs to represent ''part'' of an arc. It does so with two arcs, the first representing the whole of the part, and the second the part itself. Often both arcs will be the same, which simply means that we have a whole that has a single part. | ||

+ | <!--T:18--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | An event is a value that's active during a timespan | -- | An event is a value that's active during a timespan | ||

Line 58: | Line 74: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:19--> | ||

An ''event'' then, consists of a part, and a value of type <syntaxhighlight lang="Haskell" inline>a</syntaxhighlight>. This <syntaxhighlight lang="Haskell" inline>a</syntaxhighlight> can stand for ''any'' type (but you can only have events of the same type in any one pattern). For example you can have a pattern of words, of numbers, of colours or even of other patterns.. | An ''event'' then, consists of a part, and a value of type <syntaxhighlight lang="Haskell" inline>a</syntaxhighlight>. This <syntaxhighlight lang="Haskell" inline>a</syntaxhighlight> can stand for ''any'' type (but you can only have events of the same type in any one pattern). For example you can have a pattern of words, of numbers, of colours or even of other patterns.. | ||

+ | <!--T:20--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

data State = State {arc :: Arc, | data State = State {arc :: Arc, | ||

Line 66: | Line 84: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

− | + | <!--T:21--> | |

+ | Since version 1.0.0, Tidal patterns can also respond to changing state as well as progressing time. So the above represents the entire input to a Tidal pattern, the current timespan, and the current state of external controllers (whether MIDI controllers, or other software). What is interesting is that the current time (the <syntaxhighlight lang="Haskell" inline>arc</syntaxhighlight> isn't a point in time, but an arc, or timespan. This aligns with the idea of the psychological 'specious present' having a duration. | ||

+ | <!--T:22--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | A function that represents events taking place over time | -- | A function that represents events taking place over time | ||

Line 73: | Line 93: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:23--> | ||

Here is that function from time to events we were talking about earlier. We simplified a bit - it's a function from a timespan plus some additional state, to events. Notice the <syntaxhighlight lang="Haskell" inline>a</syntaxhighlight> is carried from the type of the events to the type of the query. This again shows how a particular pattern can only represent events of the same type. | Here is that function from time to events we were talking about earlier. We simplified a bit - it's a function from a timespan plus some additional state, to events. Notice the <syntaxhighlight lang="Haskell" inline>a</syntaxhighlight> is carried from the type of the events to the type of the query. This again shows how a particular pattern can only represent events of the same type. | ||

+ | <!--T:24--> | ||

Notice also that a list of events is returned (denoted by the square brackets). This simply means that tidal supports polyphony - many events can take place at the same time. Remember though that each event has its own arc; two events might be returned for the same timespan, but they may well not start and end at the same time, and might not overlap at all. | Notice also that a list of events is returned (denoted by the square brackets). This simply means that tidal supports polyphony - many events can take place at the same time. Remember though that each event has its own arc; two events might be returned for the same timespan, but they may well not start and end at the same time, and might not overlap at all. | ||

+ | <!--T:25--> | ||

It may also be that the arc of an event might extend outside the arc in the query state. This is one case where we get part of an arc back - the part will be the intersection of the arc of the query and that of the event. | It may also be that the arc of an event might extend outside the arc in the query state. This is one case where we get part of an arc back - the part will be the intersection of the arc of the query and that of the event. | ||

+ | <!--T:26--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | Also known as Continuous vs Discrete/Amorphous vs Pulsating etc. | -- | Also known as Continuous vs Discrete/Amorphous vs Pulsating etc. | ||

Line 85: | Line 109: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:27--> | ||

An important feature of Tidal is that you can accurately compose analogue (continuous) and digital (discrete) patterns together. For example it can be nice to multiply a discrete pattern of notes by a continuously varying sinewave. It's a bit of a myth that computers can only represent digital structures, but when it comes to combining analogue and digital patterns together, it's useful to be able to know which is which, hence the above datatype for doing that. | An important feature of Tidal is that you can accurately compose analogue (continuous) and digital (discrete) patterns together. For example it can be nice to multiply a discrete pattern of notes by a continuously varying sinewave. It's a bit of a myth that computers can only represent digital structures, but when it comes to combining analogue and digital patterns together, it's useful to be able to know which is which, hence the above datatype for doing that. | ||

+ | <!--T:28--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

-- | A datatype that's basically a query, plus a hint about whether its events | -- | A datatype that's basically a query, plus a hint about whether its events | ||

Line 93: | Line 119: | ||

</syntaxhighlight> | </syntaxhighlight> | ||

+ | <!--T:29--> | ||

Here finally we arrive at the <syntaxhighlight lang="Haskell" inline>Pattern</syntaxhighlight> datatype, which simply consists of an either digital or analogue nature, plus a query for calculating events for a particular timespan. | Here finally we arrive at the <syntaxhighlight lang="Haskell" inline>Pattern</syntaxhighlight> datatype, which simply consists of an either digital or analogue nature, plus a query for calculating events for a particular timespan. | ||

+ | <!--T:30--> | ||

The only thing we haven't done is define what the <syntaxhighlight lang="Haskell" inline>ControlMap</syntaxhighlight> type is that we saw earlier. As well as being used to represent controller state, it's part of the definition of one more type, the <syntaxhighlight lang="Haskell" inline>ControlPattern</syntaxhighlight>, here we go: | The only thing we haven't done is define what the <syntaxhighlight lang="Haskell" inline>ControlMap</syntaxhighlight> type is that we saw earlier. As well as being used to represent controller state, it's part of the definition of one more type, the <syntaxhighlight lang="Haskell" inline>ControlPattern</syntaxhighlight>, here we go: | ||

+ | <!--T:31--> | ||

<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||

data Value = VS { svalue :: String } | data Value = VS { svalue :: String } | ||

Line 103: | Line 132: | ||

deriving (Eq,Ord,Typeable,Data) | deriving (Eq,Ord,Typeable,Data) | ||

+ | <!--T:32--> | ||

type ControlMap = Map.Map String Value | type ControlMap = Map.Map String Value | ||

type ControlPattern = Pattern ControlMap | type ControlPattern = Pattern ControlMap | ||

</syntaxhighlight> | </syntaxhighlight> | ||

− | A <syntaxhighlight lang="Haskell" inline>ControlMap</syntaxhighlight> is simply a dictionary (or map) for storing some values by name (using a string). As well as using it for external control values within the | + | <!--T:33--> |

− | . | + | A <syntaxhighlight lang="Haskell" inline>ControlMap</syntaxhighlight> is simply a dictionary (or map) for storing some values by name (using a string). As well as using it for external control values within the <syntaxhighlight lang="Haskell" inline>State</syntaxhighlight> datatype, we also use it to make <syntaxhighlight lang="Haskell" inline>ControlPattern</syntaxhighlight>s. They are simply patterns of controlmaps, and are used for representing patterns of synthesiser messages. So for example the <syntaxhighlight lang="Haskell" inline>speed</syntaxhighlight> function in <syntaxhighlight lang="Haskell" inline>sound "bd sn" # speed "2 3"</syntaxhighlight>) turns a pattern of numbers into a pattern of controlmaps, the <syntaxhighlight lang="Haskell" inline>sound</syntaxhighlight> turns a pattern of words into a pattern of controlmaps, and the <syntaxhighlight lang="Haskell" inline>#</syntaxhighlight> composes them together into a new pattern of controlmaps. |

Feel free to comment on the discussion page if something is unclear! | Feel free to comment on the discussion page if something is unclear! | ||

+ | [[Category:Reference|Pattern]] | ||

+ | </translate> |

## Latest revision as of 12:36, 28 May 2020

In Tidal, what *is* a pattern? There are a lot of ways of answering this question. A technical definition is that under the hood, a pattern is a function from time to events. You give a pattern a start and end time, and it gives you back the events that are active (in part or in whole) during that timespan. An event is itself a value with a start and end time.

This is mostly hidden when it comes to using Tidal to make music, but lets have a closer look at the innards of a really simple pattern:

```
"1 2 3"
```

The above might look like a string, but Tidal quietly parses it into a pattern for you (using a hidden function called parseBP_E). We can ask that pattern for values by casting the string pattern to a Tidal pattern by appending `:: Pattern String`

to the pattern string. You're kind of telling Tidal to treat this string as a pattern and show you what it sees:

```
"1 2 3" :: Pattern String
```

If you run the above, you should see the contents of the first cycle in the output buffer:

```
(0>⅓)|"1"
(⅓>⅔)|"2"
(⅔>1)|"3"
```

From that we can see the first event `1`

is active for the first third of the cycle, and so on.

So a pattern is a function from a timespan (also known as an *arc*), to values with each have a beginning and end. A function like `rev`

, is therefore a combinator, which takes such a function as input, and gives a new function as output (with input and output timing manipulations baked-in, in order to reverse the pattern).

# The Pattern types

That's the basics, lets have a look at some code. The core representation for patterns is in the Sound.Tidal.Pattern module. The core representation is in the ten or so lines at the top. Lets step through it. Some Haskell knowledge will be helpful here, but you will hopefully get the gist even without software development experience.

```
-- | Time is rational
type Time = Rational
```

The above states that time is rational. This means that rather than representing time as integers (whole numbers), or as floating point numbers, Tidal represents time as a ratio of *two* integers. This means that for example a third can be represented precisely, as one over three. Music is of course full of such ratios, and not representing them as such can cause a great deal of problems.. Basically, this means that if you add three one-thirds together, you'll get a whole. Seems obvious but not all systems do this!

```
-- | A time arc (start and end)
type Arc = (Time, Time)
```

This is the representation of an arc, or timespan. We like to call this a time arc rather than a time span, because in Tidal the notion of time is cyclic. Here the two time values are simply the beginning and end of an arc.

```
-- | The second arc (the part) should be equal to or fit inside the
-- first one (the whole that it's a part of).
type Part = (Arc, Arc)
```

Tidal often needs to represent *part* of an arc. It does so with two arcs, the first representing the whole of the part, and the second the part itself. Often both arcs will be the same, which simply means that we have a whole that has a single part.

```
-- | An event is a value that's active during a timespan
type Event a = (Part, a)
```

An *event* then, consists of a part, and a value of type `a`

. This `a`

can stand for *any* type (but you can only have events of the same type in any one pattern). For example you can have a pattern of words, of numbers, of colours or even of other patterns..

```
data State = State {arc :: Arc,
controls :: ControlMap
}
```

Since version 1.0.0, Tidal patterns can also respond to changing state as well as progressing time. So the above represents the entire input to a Tidal pattern, the current timespan, and the current state of external controllers (whether MIDI controllers, or other software). What is interesting is that the current time (the `arc`

isn't a point in time, but an arc, or timespan. This aligns with the idea of the psychological 'specious present' having a duration.

```
-- | A function that represents events taking place over time
type Query a = (State -> [Event a])
```

Here is that function from time to events we were talking about earlier. We simplified a bit - it's a function from a timespan plus some additional state, to events. Notice the `a`

is carried from the type of the events to the type of the query. This again shows how a particular pattern can only represent events of the same type.

Notice also that a list of events is returned (denoted by the square brackets). This simply means that tidal supports polyphony - many events can take place at the same time. Remember though that each event has its own arc; two events might be returned for the same timespan, but they may well not start and end at the same time, and might not overlap at all.

It may also be that the arc of an event might extend outside the arc in the query state. This is one case where we get part of an arc back - the part will be the intersection of the arc of the query and that of the event.

```
-- | Also known as Continuous vs Discrete/Amorphous vs Pulsating etc.
data Nature = Analog | Digital
deriving Eq
```

An important feature of Tidal is that you can accurately compose analogue (continuous) and digital (discrete) patterns together. For example it can be nice to multiply a discrete pattern of notes by a continuously varying sinewave. It's a bit of a myth that computers can only represent digital structures, but when it comes to combining analogue and digital patterns together, it's useful to be able to know which is which, hence the above datatype for doing that.

```
-- | A datatype that's basically a query, plus a hint about whether its events
-- are Analogue or Digital by nature
data Pattern a = Pattern {nature :: Nature, query :: Query a}
```

Here finally we arrive at the `Pattern`

datatype, which simply consists of an either digital or analogue nature, plus a query for calculating events for a particular timespan.

The only thing we haven't done is define what the `ControlMap`

type is that we saw earlier. As well as being used to represent controller state, it's part of the definition of one more type, the `ControlPattern`

, here we go:

```
data Value = VS { svalue :: String }
| VF { fvalue :: Double }
| VI { ivalue :: Int }
deriving (Eq,Ord,Typeable,Data)
type ControlMap = Map.Map String Value
type ControlPattern = Pattern ControlMap
```

A `ControlMap`

is simply a dictionary (or map) for storing some values by name (using a string). As well as using it for external control values within the `State`

datatype, we also use it to make `ControlPattern`

s. They are simply patterns of controlmaps, and are used for representing patterns of synthesiser messages. So for example the `speed`

function in `sound "bd sn" # speed "2 3"`

) turns a pattern of numbers into a pattern of controlmaps, the `sound`

turns a pattern of words into a pattern of controlmaps, and the `#`

composes them together into a new pattern of controlmaps.
Feel free to comment on the discussion page if something is unclear!