MidicaPL Tutorial, Chapter 6: Patterns

This chapter explains how to implement and use musical patterns, like finger picking and the like.

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.

MidicaPL
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.

MidicaPL
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
MidicaPL
0 a-2 /8
0 e-  /16
0 a-  /16
0 c   /8
0 e   /8
0 c   /8
0 a-  /8
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
MidicaPL



0  c-,c  /4
0  e-    /8
0  g-    /8
0  c-    /8
0  c     /8
0  e-    /8
0  g-    /8
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
MidicaPL



{ q=2
	{ m
		0  c-  /4
		0  e-  /8
		0  g-  /8
	}
	0  c  /2
}
Result (Score)

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.

Pattern Options
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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

Nested Patterns

Patterns can be nested. That means that inside of a pattern you can use another pattern. The following example uses this technique to create a downstroke pattern using the upstroke pattern, that also works with predefined chords:
MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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
MidicaPL
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
Result (Score)

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:

MidicaPL
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
Result (Score)

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:

MidicaPL
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)
MidicaPL
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
Result (Score)

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.