OpenMusic Tutorials
Prev| Chapter 14. Flow Control IV: Recursive Functions| Next
Tutorial 39: Recursive patch II
Topics
Using a recursive patch to reverse the output of a rhythm tree.
Key Modules Used
omif
, Voice, standard LISP functions
The Concept:
As we saw in Tutorial 24, traditional rhythmic notation in the Voice object is formalized in what’s called a rhythm tree. The rhythm tree is a series of nested lists in the form (D S) where D is the duration and S is the structure of that duration, and S may contain additional lists in the form (D S). Notice that this form is itself recursive, containing the same element on many different structural levels. Taking a retrograde of such a structure is not equivalent to taking the retrograde of the rhythm it represents.
Consider this rhythm:
represented by the rhythm tree:
(? (((4 4) (1 (1 (1 -2 1 1)) 1 1)) ((4 8) (3 -1))))
If we go through the list from beginning to end we will notice that in order to obtain a correct retrograge rhythm some expressions must be reversed and others not. For example, the first element ‘?’ must always figure in the beginning of the list and therefore must be left as is. Measure signatures must also figure in the beginning of each measure-list. In general, all elements in ‘D’ position of a rhythm tree must be left alone. Only ‘S’ elements must be reversed, such as the (1 -2 1 1), it being a low level rhtyhm structure representing a quintolet.
The correct retrograde form is thus:
(? (((4 8) (-1 3)) ((4 4) (1 1 (1 (1 1 -2 1)) 1))))
Representing the notation:
Notice that this is not what we get by putting the original tree through
the LISP function reverse
.
A rhythm tree can have unlimited levels of nesting. In addition, not all
measures need have the same number of levels, so a simple
omloop
won’t do the trick. We must create a recursive
function which calls itself as many times as necessary to descend the levels
of recursion in the rhythm tree. For each element (D S), we will reverse S but
leave D untouched.
The Patch:
Here it is. The actual reversal of elements is accomplished by (E) and (G), which split the (D S) structure into its first and second elements and reverse the second.
The termination test is performed by omif
using a special LISP
predicate, atom
, which returns
t only if its input is not a list. Recursion will thus stop when we reach
the “bottom” of the rhythm tree.
mapcar
is used to call the recursive part of the patch.
mapcar
takes our treereverse
and applies it to all sublists
of the ‘S’ portion of the current level of the tree.
Once the termination test is satisfied and we begin to work back out of the
levels of recursion, the reversed portions of the lists (the ‘S’ portion’)
representing the distribution of rhythmic values will be put back together
with the ‘D’ portions (the time signatures, which we didn’t touch) with the
list
function.
The result is the correct retrograde of the rhythm. To further prove our point about the necessity of the recursive function, let’s look at the incorrect results of a simple non-recursive function which splits the D and S elements apart and reverses the S elements.
This patch has two problems. The first is that it only reverses elements down to two levels of rhythm-tree sublists. If we had smaller rhythmic values as groups within beats of the measures, they would not have been reversed.We don’t so this is not a problem. The second problem, and this one shows up, is that the order of time signatures is not reversed. See for yourself:
Prev | Home | Next |
---|---|---|
Tutorial 38: Recursive patch I | Up | The Maquette II |