This chapter explains how to implement and use musical patterns, like finger picking and the like.
MidicaPL Tutorial, Chapter 6: Patterns
Patterns
A pattern is a way how to play a given chord, or to be more general, a certain set of notes. The chord may change but the pattern stays the same.
An example can be a certain guitar picking pattern. The right hand of the guitar player plays the same pattern while the left hand frets different chords.
In order to use a pattern, it must be defined somewhere. It can be defined before or after using it, just like a function.
A pattern definition is a block beginning with the keyword PATTERN
, followed by whitespace(s) and a pattern name.
The block ends with the keyword END
.
Later it's used inside of a normal channel command, instead of a note length.
The following example defines an empty pattern called do_nothing
.
This pattern is used later with different chords.
CHORD amin a-2 e- a- c e CHORD cmaj c- g- c e g CHORD dmaj d- a- d f# a CHORD fmaj f-2 c- f- a- c PATTERN do_nothing END 0 amin do_nothing 0 cmaj do_nothing 0 dmaj do_nothing 0 fmaj do_nothing
However this whole code does not produce any sound because the pattern is empty and does nothing with the chords. We will change that in the next section.
Pattern Block
A pattern block contains information what to do with the chord. It can consist of:
- lines producing a note
- lines producing a sub chord
- lines producing a rest
- nestable blocks
- nested patterns
Notes in a Pattern
The most important content of a pattern is the information what to do with a single note of the chord. Therefore it's important to know that each note of the chord must be addressed by a note index.
The notes in the chord are sorted by pitch, from low to high. The lowest note has note index 0.
Let's investigate the following chord:
CHORD amin a-2 e- a- c e
In this case, a-2
has note index 0, e-
has index 1, a-
has index 2, c
has index 3
and e
has index 4.
A regular pattern line consists of the following elements, separated by white space(s):
- note index
- note length
- options (optional)
With this knowledge we try to change the above 'do nothing' example to something else: The first bar of "House of the Rising Sun". The following two examples are equivalent. The first one uses the pattern, the second one doesn't.
CHORD amin a-2 e- a- c e PATTERN basic 0 /8 1 /16 2 /16 3 /8 4 /8 3 /8 2 /8 END 0 amin basic
0 a-2 /8 0 e- /16 0 a- /16 0 c /8 0 e /8 0 c /8 0 a- /8
We renamed the pattern from do_nothing
to basic
because now it's actually doing something.
Then we defined what to do with the A minor chord. As we only care about the first bar here, we didn't need more chords so far.
The colors make clear where which part comes from.
The channel (marked in blue) is only defined in the channel command 0 amin basic
.
The pattern itself doesn't contain a channel. (It could be used from several channels.)
The note indices are marked in red. In the second example you see how the indices are translated into notes.
Now we want to add the next three bars. So we just add the missing chords again and apply the pattern on them. But we leave the pattern definition unchanged:
CHORD amin a-2 e- a- c e CHORD cmaj c- g- c e g CHORD dmaj d- a- d f# a CHORD fmaj f-2 c- f- a- c PATTERN basic 0 /8 1 /16 2 /16 3 /8 4 /8 3 /8 2 /8 END 0 amin basic 0 cmaj basic 0 dmaj basic 0 fmaj basic
It already sounds pretty well like the original song. But if you are really picky and listen carefully, you may notice that
only the first two bars are correct.
The 3rd and 4th bar need a slightly different pattern. We will implement it with the name alternate
:
CHORD amin a-2 e- a- c e CHORD cmaj c- g- c e g CHORD dmaj d- a- d f# a CHORD fmaj f-2 c- f- a- c PATTERN basic 0 /8 1 /16 2 /16 3 /8 4 /8 3 /8 2 /8 END PATTERN alternate 0 /8 1 /16 2 /16 3 /8 3 /8 2 /8 1 /8 END 0 amin basic 0 cmaj basic 0 dmaj alternate 0 fmaj alternate
Chords in a Pattern
A pattern can also contain a chord, consisting of more than one note in a line. Instead of comma-separating note names, like in normal channel commands, the note indices must be comma-separated to achieve that. The following examples show how that works. The first example uses a chord inside of a pattern, while the second one shows how this very same thing would look with normal channel commands:
CHORD cmaj c- e- g- c PATTERN travis 0,3 /4 1 /8 2 /8 0 /8 3 /8 1 /8 2 /8 END 0 cmaj travis
0 c-,c /4 0 e- /8 0 g- /8 0 c- /8 0 c /8 0 e- /8 0 g- /8
This pattern is called travis
because it implements the famous Travis Pattern, a finger picking pattern
named after Merle Travis.
The note indices 0,3
, marked in blue, are translated to the chord c-,c
.
In order to create the first 8 bars of "Dust in the wind", we only need to add a few more chords and use this pattern with them:
CHORD cmaj c- e- g- c CHORD cmaj7 c- e- g- b- CHORD cadd9 c- e- g- d CHORD asus2 a-2 e- a- b- CHORD asus4 a-2 e- a- d CHORD amin a-2 e- a- c PATTERN travis 0,3 /4 1 /8 2 /8 0 /8 3 /8 1 /8 2 /8 END 0 cmaj travis 0 cmaj7 travis 0 cadd9 travis 0 cmaj travis 0 asus2 travis 0 asus4 travis 0 amin travis 0 asus2 travis
Rests in a Pattern
In order to create a rest inside a pattern, just replace the note index with a dash: -
.
The next example shows a small variation of the travis pattern, containing a rest:
CHORD cmaj c- e- g- c PATTERN travis_2 0,3 /8 - /8 1 /8 2 /8 0 /8 3 /8 1 /8 2 /8 END 0 cmaj travis_2
Blocks in a Pattern
A pattern can contain nestable blocks. The next two examples are equivalent. The first one uses nestable blocks in a pattern, while the second one shows how this would look without a pattern:
CHORD cmaj c- e- g- c PATTERN block-pattern { q=2 { m 0 /4 1 /8 2 /8 } 3 /2 } END 0 cmaj block-pattern
{ q=2 { m 0 c- /4 0 e- /8 0 g- /8 } 0 c /2 }
The inner block has a multiple
option (m
), so the note indices 0
, 1
and 2
(notes c-
, e-
and g-
) are played together with note index 3
(note c
).
The outer block has the quantity option q=2
, so it's repeated twice.
Options
As already mentioned, a normal note index line inside a pattern can have options. Such a line will be transformed into a channel command, so only channel command options are allowed here.
But the line using the pattern is also a channel command. So it can also contain options. This makes things a bit complicated, and not all combinations are allowed.
The options in a line using a pattern are called outer options, while the options inside a pattern are called inner options.
The Pattern Options table shows which options are allowed as inner or outer option.
Long Name | Short Name | Outer Option | Inner Option | Peculiarity |
---|---|---|---|---|
velocity | v | yes | yes | inner: lexical scoping |
duration | d | yes | yes | inner: lexical scoping |
quantity | q | yes | yes | - |
multiple | m | yes | yes | - |
lyrics | l | yes | no | syllable appears in pattern begin tick |
tremolo | tr | no | yes | - |
shift | s | yes | no | - |
The following example shows how a chord can be played like an arpeggio, from the lowest to the highest pitch, with a length of a full note and a distance of a thirty-second:
CHORD cmaj c- e- g- c PATTERN upstroke { m 0 /1 m - /32 1 /1 m - /32 2 /1 m - /32 3 /1 m } - /1 END 0 cmaj upstroke q=2
Inside of the pattern, each note index line has a multiple
option (as an inner option, marked in blue)
because the notes shall be played "more or less" simultaneously.
But not completely simultaneously, so we need very small rests between the notes.
The whole thing shall still cover exactly a full note's length. So we wrap everything inside a multiple
block
and add a full note rest at the end.
The line using this pattern has the quantity
option as an outer option, marked in red, to play the pattern twice.
Inner Velocity & Duration
There is a perculiarity for velocity
and duration
, if used as an inner option.
The pattern begins with the velocity and duration values from before the pattern usage (or the one supplied as outer option, if given). When it's changed inside the pattern (as an inner option), the new value is valid until the end of the pattern. After the pattern, the value from before the pattern usage is restored again. (Or the one from the outer option, if given.)
The following example demonstrates how this works:
CHORD cmaj c- e- g- PATTERN demo 0 /8 1 /8 2 /4 d=40% 1 /4 2 /4 END 0 c- /2 v=50, d=90% 0 c- /2 0 cmaj demo v=95 0 c- /2 q=2
Everything begins with a velocity of 50 (piano) and a duration of 90%.
The velocity is switched to 95 (forte) in the outer option of the pattern usage.
That means, the pattern begins with velocity = 95 and duration = 90%.
The 3rd line of the pattern switches the duration to 40% (staccato) with an inner option.
After the pattern ends, the duration is restored to 90%. But the velocity is not restored because it has been set with an outer option. So it continues to be 95 (forte).
Inline Chords
When we introduced note indices, we learned that the chord's notes are sorted by pitch before being addressed via note index. But this is only true for predefined chords. When we use inline chords, the notes stay in the same order as they are written. The following example demonstrate the difference between predefined and inline chords:
CHORD crd_1 c e g c+ CHORD crd_2 c+ g e c CHORD crd_3 g c c+ e PATTERN demo 0 /8 1 /8 2 /8 3 /8 END 0 crd_1 demo 0 crd_2 demo 0 crd_3 demo 0 c,e,g,c+ demo 0 c+,g,e,c demo 0 g,c,c+,e demo
We apply the same pattern first to three predefined chords and than to three inline chords. All six chords contain the same notes. Only the order is different.
However the predefined chords produce the same sequence because they are sorted by pitch implicitely. But the inline chords produce different sequences.
With this knowledge we can use our upstroke
pattern from above to create an upstroke as well as a downstroke:
PATTERN upstroke { m 0 /1 m - /32 1 /1 m - /32 2 /1 m - /32 3 /1 m } - /1 END 0 c-,e-,g-,c upstroke 0 c,g-,e-,c- upstroke
Nested Patterns
downstroke
pattern using the upstroke
pattern,
that also works with predefined chords:
CHORD cmaj c- e- g- c PATTERN upstroke { m 0 /1 m - /32 1 /1 m - /32 2 /1 m - /32 3 /1 m } - /1 END PATTERN downstroke 3,2,1,0 upstroke END 0 cmaj upstroke 0 cmaj downstroke
The downstroke
pattern just reverses the given chord and applies the upstroke
pattern to it.
But more complicated nestings are also possible. The following example assumes that the previously defined patterns travis
,
upstroke
and downstroke
are available:
CHORD cmaj c- e- g- c e CHORD amin a-2 e- a- c e PATTERN main 4 *2 m 0,1,2,3 travis q=2 0,1,2,3,4 upstroke 0,1,2,3,4 downstroke END 0 cmaj main 0 amin main
The pattern main
uses the nested patterns travis
, upstroke
and downstroke
.
The nested pattern downstroke
uses upstroke
as a nested pattern. So we have two levels of nesting here.
Pattern Parameters
Patterns can have parameters, just like functions. Pattern parameters are added in round braces after the pattern name, when using the pattern. They work exactly like function parameters. That means, there are indexed and named parameters.
The following two examples are equivalent. They both rewrite the upstroke
pattern so that the note length and note distance
are provided as parameters. The first example uses indexed parameters, while the second one uses named parameters:
CHORD cmaj c- e- g- c CHORD amin a-2 e- a- c PATTERN upstroke { m 0 $[0] m - $[1] 1 $[0] m - $[1] 2 $[0] m - $[1] 3 $[0] m } - $[0] END 0 cmaj upstroke(/1, /8) 0 cmaj upstroke(/4, /32) q=2 0 amin upstroke(/8, /32) q=4
CHORD cmaj c- e- g- c CHORD amin a-2 e- a- c PATTERN upstroke { m 0 ${len} m - ${dist} 1 ${len} m - ${dist} 2 ${len} m - ${dist} 3 ${len} m } - ${len} END 0 cmaj upstroke( len = /1, dist = /8 ) 0 cmaj upstroke(len=/4, dist=/32) q=2 0 amin upstroke(dist=/32, len=/8) q=4
Then we can implement a parametrized downstroke
pattern that uses upstroke
as nested pattern. So we need to pass the
parameters over to the nested pattern:
CHORD cmaj c- e- g- c CHORD amin a-2 e- a- c PATTERN downstroke 3,2,1,0 upstroke($[0], $[1]) END 0 cmaj downstroke(/1, /8) 0 cmaj downstroke(/4, /32) q=2 0 amin downstroke(/8, /32) q=4
Remeber our "House of the Rising Sun" example above.
The two patterns basic
and alternate
are pretty similar.
They only differ in the last three notes. So we can use only one, parametrized pattern.
The following two examples are equivalent. The first one uses this new approach, while the second one is the one from above, just for comparison:
CHORD amin a-2 e- a- c e CHORD cmaj c- g- c e g CHORD dmaj d- a- d f# a CHORD fmaj f-2 c- f- a- c PATTERN basic 0 /8 1 /16 2 /16 3 /8 { if ${alternate} 3 /8 2 /8 1 /8 } { else 4 /8 3 /8 2 /8 } END 0 amin basic 0 cmaj basic() 0 dmaj basic(alternate=1) 0 fmaj basic(alternate=1)
CHORD amin a-2 e- a- c e CHORD cmaj c- g- c e g CHORD dmaj d- a- d f# a CHORD fmaj f-2 c- f- a- c PATTERN basic 0 /8 1 /16 2 /16 3 /8 4 /8 3 /8 2 /8 END PATTERN alternate 0 /8 1 /16 2 /16 3 /8 3 /8 2 /8 1 /8 END 0 amin basic 0 cmaj basic 0 dmaj alternate 0 fmaj alternate
As you can see, the parantheses in the pattern usage are optional, if no parameters are used.
So 0 amin basic
and 0 amin basic()
are equivalent.
This is just the same behaviour as in a function call.