File: 04_using_patterns.py

package info (click to toggle)
python-renardo-lib 0.9.12-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,220 kB
  • sloc: python: 10,999; sh: 34; makefile: 7
file content (150 lines) | stat: -rw-r--r-- 4,571 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Tutorial 4: Using Patterns


# Player Objects use Python lists, known more commonly as arrays in other languages,
# to sequence themselves. You've already used these previously, but they aren't exactly
# flexible for manipulation. For example, try multiplying a list by two like so:

print([1, 2, 3] * 2)

# Is the result what you expected?

# FoxDot uses a container type called a 'Pattern' to help solve this problem.
# They act like regular lists but any mathematical operation performed on it is done to each item
# in the list and done so pair-wise if using a second pattern. A basic pattern is created as
# you would with a normal list or tuple, but with a 'P' preceeding it.

print(P[1,2,3] * 2)

print(P[1,2,3] + 100)

# In this operation, the output consists of all the combinations of the two patterns i.e.
# [1+3, 2+4, 3+3, 1+4, 2+3, 3+4]
print(P[1,2,3] + [3,4])

# You can use Python's slicing syntax to generate a series of numbers

print(P[:8])

print(P[0,1,2,3:20])

print(P[2:15:3])

# Try some other mathematical operators and see what results you get.
print(P[1,2,3] * (1,2))

# Pattern objects also automatically interlace any nested list.
# Compare
# Normal list:
for n in [0,1,2,[3,4],5]:
    print(n)

# with
# Pattern
for n in P[0,1,2,[3,4],5]:
    print(n)

# Use PGroups if you want this behavior to be avoided. These can be implicitly
# specified as tuples in Patterns:
for n in P[0,1,2,(3,4)]:
    print(n)

# This is a PGroup:
print(P(0,2,4) + 2)

print(type(P(0,2,4) + 2))

# 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.
print(list(range(10))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# You can use PRange(start, stop, step) to create a Pattern object with the equivalent values:
print(PRange(10)) # P[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# P[0, 2, 2, 6, 4, 10, 6, 14, 8, 18]
# [0*1, 1*2, 2*1, 3*2, 4*1, 5*2, 6*1, 7*2, 8*1...]
print(PRange(10) * [1, 2])           # Pattern class behaviour

# Adding a list (or Pattern) to a Pattern will add the values of the
# elements to the other where Python lists would be concatonated.
print(PRange(10) + [0,10])

# To concatonate Patterns, use the pipe operator like so:
print(PRange(10) | [0,10])
# FoxDot automatically converts any object being piped to a Pattern to the base Pattern class
# so you don't have to worry about making sure everything is the right type.

# Plays all the values together
p1 >> pluck(P(4,6,8))
p1 >> pluck(P[0,1,2,P(4,6,8),7,8])

# Spreads the values across the current "dur" e.g. if the dur is 2 beats then it will play each value 2/3 beats apart
p1 >> pluck(P*(0,2,4), dur=1/2)
p1 >> pluck(P*(0,2,4), dur=1)
p1 >> pluck(P*(0,2,4), dur=2)
p1 >> pluck(P[0,1,2,P*(4,6,8),7,8], dur=1)

# Is the same as P* but every other time the notes are played they are spread over the dur value.
p1 >> pluck(P/(0,2,4), dur=1/2)
p1 >> pluck(P/(0,2,4), dur=1)
p1 >> pluck(P/(0,2,4), dur=2)
p1 >> pluck(P[0,1,2,P/(4,6,8),7,8], dur=1)

# Spreads the values across the current "sus" e.g. if the dur is 2 beats and the sus is 3 beats then it will play each value 1 beat apart.
p1 >> pluck(P+(0,2,4), dur=2, sus=3)
p1 >> pluck(P+(0,2,4), dur=2, sus=1)
p1 >> pluck(P[0,1,2,P+(4,6,8),7,8], dur=1, sus=3)

# Spreads the first (length - 1) values with a gap of the last value between each
# Plays 0,2,4 with a gap of 0.5:
p1 >> pluck(P^(0,2,4,0.5), dur=1/2)

# Patterns come with several methods for manipulating the contents
help(Pattern)

# Standard pattern
print(P[:8])

# Shuffle pattern by randomizing it
print(P[:8].shuffle())

# Append a reversed pattern to the pattern
print(P[:8].palindrome())

# Shift the pattern by n (default 1)
print(P[:8].rotate())
print(P[:8].rotate(3))
print(P[:8].rotate(-3))

# Takes the pattern and appends it as many times as needed to reach n number of elements in the pattern
print(P[:8].stretch(12))
print(P[:8].stretch(20))

# Reverses a pattern
print(P[:8].reverse())

# Loops a pattern n number of times
print(P[:8].loop(2))

# Add an offset
print(P[:8].offadd(5))

# Add a multiplied offset
print(P[:8].offmul(5))

# Stutter - Repeat each element n times
print(P[:8].stutter(5))

# Amen
# Merges and laces the first and last two items such that a
# drum pattern "x-o-" would become "(x[xo])-o([-o]-)" and mimics
# the rhythm of the famous "amen break"
d1 >> play(P["x-o-"].amen())
print(P[:8].amen())

# Bubble
# Merges and laces the first and last two items such that a
# drum pattern "x-o-" would become "(x[xo])-o([-o]-)
d1 >> play(P["x-o-"].bubble())
print(P[:8].bubble())