# 1 - Getting Started
### 1.1. Player Object Intro
**Picking a sound**
When FoxDot boots up it reserves all lower-case, two-character variable names, e.g. aa, p1, and bd, to be used as "players". These are the objects that play sounds for us based on instructions we give them. The first instruction we give it telling it what instrument (synth) to play. To see a list of all available synths, evaluate the following:
`print(SynthDefs)`
This is short for Synth Definition. Choose one and assign it to a FoxDot player object using two "greater than" signs, aka a "double arrow". If my chosen SynthDef was “pluck” and my chosen player object was p1 then I would assign “pluck” to p1 like so:
`p1 >> pluck()`
Make sure you include the brackets at the end of “pluck” or it won’t work. To stop an individual player object, simply execute p1.stop(). To stop all player objects, you can press Ctrl+., which is a shortcut for the command Clock.clear().
**Assigning Instructions**
The >> in Python is usually reserved for a type of operation, like how a ‘+’ symbol is used for addition, but it is not the case in FoxDot, and the reason will become clear shortly. By adding arguments in the brackets, you can change the notes being played back. The first argument, the note pitch (sometimes referred to as degree), doesn’t need to be named explicitly, but you’ll need to specify other attributes (such as duration) if you want to change them. These values can be a single value or a list of values that the player will play in turn. For example, the code below plays three notes in turn continuously until p1 is stopped:
`p1 >> pluck([0, 2, 4], dur=[1, 1/2, 1/2], amp=0.75)`
The first argument is the pitch of the note we want to play, which is a list of 3 numbers; 0, 2, and 4. The player will play each of these in turn. By default all players will use the C-Major scale, which we can think of as a Python list:
CMajor = [C, D, E, F, G, A, B]
The numbers we use for pitch refer to the index of the notes we want to pick from this scale. So, with our list of pitches [0, 2, 4] our notes would be:
CMajor[0] => C
CMajor[2] => E
CMajor[4] => G
The duration of these notes are derived from the dur keyword argument, which is also a list of three numbers; 1, 1/2, and 1/2. The position of these values relate to the position of the values we supplied for pitch. So the first note will last for 1 beat and the next two notes will last for half of 1 beat. The last keyword argument, amp is used to set the amplitude (loudness) of the note, where 0 is silent and 1 is louder. You’ll be able to find out about other keywords you can use in the Players Attributes section.
You can also add values to the Player to create variation in your sequences or even play chords. For example, the code below will play every 3 note 4 pitches higher:
`p1 >> pluck([0, 1, 2, 3], dur=2) + [0, 0, 4]`
To create chords, use a tuple in place of a list. The code below will add a basic triad to each note played:
`p1 >> pluck([0, 1, 2, 3], dur=2) + (0, 2, 4)`
**Playing Samples**
FoxDot can also play audio samples, such as percussion, using a special SynthDef called play. Instead of taking a list of numbers as its first argument it takes a string of characters where each character relates to a different sound. Here’s an example of a very basic drum pattern:
`d1 >> play("x-o-")`
The string can also contain information about how the sequence should be played, which is done by using different types of brackets. Putting two or more characters in round brackets will alternate which sound to play on each loop through the sequence:
`d1 >> play("(x-)(-x)o-")`
Putting multiple characters in square brackets will play them successively in the space of one step. This example plays a triplet of hi-hats during its fourth step:
`d1 >> play("x-o[---]", dur=1)`
You can also use curly braces to pick a sound at random, to add a little variety to your sequence:
`d1 >> play("x-o{-=*}")`
These can all be used and nested together to create complex patterns:
`d1 >> play("(x[--])xo{-[--][-x]}")`
### 1.2. Pattern Basics
Why use Patterns?
Player objects use Python lists, often known as arrays in other programming languages, to create sequences of values, such as pitch and durations. However, lists aren’t the most intuitive data structures for transformations. For example, try multiplying a list – what happens?
`print([1, 2, 3] * 2)`
The result is the same list repeated twice! If you want to manipulate the internal values (e.g. double them) in Python, then here’s how you might do it:
`values = [1, 2, 3]`
```
# Use a loop
my_list = []
for i in values:
my_list.append(i * 2)
print(my_list)
```
```
# List comprehension
print([i*2 for i in values])
```
For both methods, it requires having to loop through all the values and multiply each one individually. Things get even more complicated if you also want to multiply every second value by a different number. This requires quite a lot of work, especially if you don’t know what numbers you’ll be using. This is where the Pattern class comes in.
Patterns act like regular Python lists but any mathematical transformation performed on it is done to each item in the list. The simplest way to create a pattern is just to add an upper-case P to the start of a list:
```
my_list = [0, 1, 2, 3]
my_pattern = P[0, 1, 2, 3]
```
Now when you perform an operation, such as multiplication, you’ll get the transformed pattern:
```
>>> print(my_pattern * 2)
P[0, 2, 4, 6]
```
You can also create a pattern as you would create any other Python object by using the class name followed by brackets with arguments:
`my_pattern = Pattern([0, 1, 2, 3])`
Patterns are also “modulo index-able” which means that no matter what value we use as an index when accessing a Pattern’s data, as long as it’s an integer we get a value returned. If the index is greater than the length of the Pattern, then we just go back to the start of the Pattern and start looking:
```
>>> pat = P[0, 1, 2]
>>> print(pat[2])
2
>>> print(pat[3])
0
```
**Transformations**
You can perform an operation on a pattern using a list or another pattern to create more complex transformations. For example, adding together the patterns P[0, 1, 2, 3] and P[4, 7] will perform the operation in turn meaning the resulting pattern will be the result P[0 + 4, 1 + 7, 2 + 4, 3 + 7], which is P[4, 8, 6, 10]. Using patterns of lengths with no common divisor will create a new pattern that contains all the combinations values:
```
>>> P[0, 1, 2, 3] + P[4, 5, -2]
P[4, 6, 0, 7, 5, -1, 6, 8, -2, 5, 7, 1]
```
Patterns also have specific methods for transformation such as rotate, reverse, and sort that can be used to manipulate order:
```
>>> P[4, 1, 3, 2].rotate()
P[1, 3, 2, 4]
>>> P[4, 1, 3, 2].reverse()
P[2, 3, 1, 4]
>>> P[4, 1, 3, 2].sort()
P[1, 2, 3, 4]
```
You can evaluate help(Pattern) to see more information about the methods.
Pattern Functions
There are a number of functions that return different Patterns. These generate longer Patterns only using a few arguments. To see a list of Pattern functions, you can evaluate help(Patterns.Sequences).
In Python, you can generate a range of integers with the syntax range(start, stop, step). By default, start is 0 and step is 1. You can use PRange(start, stop, step) to create a Pattern object with the equivalent values:
```
>>> print(list(range(0, 10 2)))
[0, 2, 4, 6, 8]
>>> print(PRange(0, 10, 2))
P[0, 2, 4, 6, 8]
```
And because these return instances of Pattern we can treat them as Pattern objects and use Pattern methods and perform arithmetic operations on them like so:
```
>>> print(PRange(0, 10, 2).reverse() + [1, 2])
P[9, 8, 5, 4, 1, 10, 7, 6, 3, 2]
```
**Concatenating Patterns**
In Python, you would usually concatenate two lists (append one to another) by using the + operator but we’ve already seen that doing this with Patterns would add the values from one pattern to the contents of another. To concatenate two Pattern objects together, you can use the pipe symbol, |, which Linux users might be familiar with – it is used to connect command line programs by sending output from one process as input to another.
```
>>> print(PRange(4) | [1,7,6])
P[0, 1, 2, 3, 1, 7, 6]
```
**Pattern lacing and PGroups**
What happens when a Pattern contains a nested list like so?
```
>>> pat = P[0, 2, [3, 5]]
>>> print(pat)
P[0, 2, P[3, 5]]
```
First of all, the nested list is converted into a pattern (and any nested lists it might have contained are also converted). If we try and access the nested pattern here is what happens:
```
>>> print(pat[0])
0
>>> print(pat[1])
2
>>> print(pat[2])
3
```
That’s strange…? You’d be forgiven for thinking the last line would return P[3, 5] because that’s the object in the third slot of pat but that’s not how Patterns behave. Patterns are laced which means that the values of the nested Patterns are returned when its parent Pattern is accessed. To access the second value of the nested pattern in the example above we need to loop through the Pattern a second time i.e. use an index value greater than the length of the Pattern:
```
>>> for i in range(6):
>>> print(pat[i],)
0, 2, 3, 0, 2, 5
```
Due to this, when print the length of a Pattern, you will see the size of the Pattern as if it was expanded as it is above. If you use round brackets and nested a tuple of values, you will find something very different happens:
```
>>> pat = P[0, 2, (3, 5)]
>>> print(pat)
P[0, 2, P(3, 5)]
```
The last item in the pattern is known as a PGroup and is used to keep values within a pattern together i.e. not laced:
```
>>> print(pat[0])
0
>>> print(pat[1])
2
>>> print(pat[2])
P(3, 5)
```
Grouping values together means that they are played at the same time and this comes in really handy when you want to play notes together e.g. chords:
`p1 >> pluck([(0, 2, 4), (0, 3, 5)], dur=4)`
You can add tuples/ PGroups to a Pattern to create a new pattern of PGroup items:
```
>>> pat = P[0, 3, 5, 4]
>>> print(pat + (0, 2))
P[P(0, 2), P(3, 5), P(5, 7), P(4, 6)]
>>> print(pat + [(0, 2), (2, 4)])
P[P(0, 2), P(5, 7), P(5, 7), P(6, 8)]
```
### 1.3. Time Dependant Variables
**Programming in time**
When you are live coding music you will often want things to change over time. One good way to demonstrate this is using chord sequences. Let’s say you have the sequence C-F-C-G, which we can represent as the Python list [0, 3, 0, 4], and we want to play the chords for 8 beats each but with a player that is playing notes every quarter beats. How do we do this? One solution might be to use the Pattern stutter method that repeats values in a Pattern “n” times:
```
>>> print(P[0, 3, 0, 4].stutter(4) + (0, 2, 4))
P[P(0, 2, 4), P(0, 2, 4), P(0, 2, 4), P(0, 2, 4), P(3, 5, 7), P(3, 5, 7),
P(3, 5, 7), P(3, 5, 7), P(0, 2, 4), P(0, 2, 4), P(0, 2, 4), P(0, 2, 4),
P(4, 6, 8), P(4, 6, 8), P(4, 6, 8), P(4, 6, 8)]
```
So to play the chord sequence above with a “pluck” sound we might do something like this:
`p1 >> pluck(P[0, 3, 0, 4].stutter(32), dur=1/4) + (0, 2, 4)`
At 4 notes per beat and 8 beats per chord we can easily work out that we need to stutter each pitch value 32 times. The problem is we have to change that value whenever we change the duration. If we change our duration to [1/2, 1/4, 1/4] we would need to do some maths in our head (or using Python) to calculate how many times to stutter the pitch values. To avoid this we can use variables that change their value over time so after 8 beats we automatically start playing a different pitch. These are known as “time-dependent variables” or “TimeVar” for short.
A TimeVar has a series of values that it changes between after a pre-defined number of beats and is created using a var object with the syntax var([list_of_values],[list_of_durations]). Example:
```
# Duration can be single value
>>> a = var([0,3],4)
# 'a' initially has a value of 0 when 0 beats have elapsed
>>> print(int(Clock.now()), a)
0, 0
# After 4 beats, the value changes to 3
>>> print(int(Clock.now()), a)
4, 3
# After another 4 beats, the value changes back to 0
>>> print(int(Clock.now()), a)
8, 0
```
So to solve our original problem with playing a chord sequence, we could use the following code with any value for duration and we would still here the sequence play for 8 beats per chord:
`p1 >> pluck(var([0, 3, 0, 4], 8), dur=[1,1/4,1/4,1/2]) + (0, 2, 4`)