• No results found

Accumulation with musical objects

In document Open Music Tutorial (Page 164-169)

Topics

Given a starting note and a melodic sequence, construct a random sequence of notes with the same intervals as the melodic sequence but random directions of motion. Use of a lambda patch withinomloopwithacum.

Key Modules Used

omloop, Note, Chord-seq,x->dx,om-random,om=,omif

The Concept:

Given a sequence of intervals (B) we will construct a musical sequence starting from a given note (A). The intervals will be ordered as defined but their direction (up or down) will be random (i.e ascending or descending depending onom-random’s output). In order to do so we will use an accumulative proceedure usingomloop’sacumcollector.

We will also demonstrate the sequence function by simultaneously visualizing our new melodic figure using a BPF factory.

The Patch:

The transformation of the sequence into a new one will be done inomloop(C). This trans-formation is a transtrans-formation of pitch only, soomloop(C) is connected to the second input of Chord-seq (O). To get the rhythmic data we take the ldurandlonsetoutputs of the Chord-seq (B) and copy them directly.

omloop as shown above is in ’eval-once’ mode. This is because omloop is connected to two objects but contains a random function. We want to make sure the same information is given to both the Chord-seq and the BPF, which will not happen unless we ’freeze’ it after one evaluation.

Now let’s look insideomloop.

First of all we must convert the list of midics we will be receiving through theintervals input into a list of relative intervals. This is done, as usual, usingx->dx. We must first use flatsince thelmidicoutput of the Chord-seq is a listandx->dxneeds a flat list.

Each interval of the Chord-seq will thus be enumerated individually and passed to our lambda patch (G) along with the results of the previous calculation.

Here’s the lambda patch:

The lambda patch (G) will take the initial note (H) and will add to it the first interval (I). This interval will have been first multiplied either by 1 (which will leave it as is) or by -1 (which will invert the interval.)

In order to randomly invert the intervals we have usedom-random. As we know,om-random returns random numbers between limits set at its inputs. In our case we had to use a different strategy because we are only interested in having -1 and 1. Simply usingom-randomcould have returned some zeroes. This is whereomifcomes in handy. We usedom-randomwith 0 and 1 as arguments and connected it to the predicateom=in order to transform each zero into a -1. Ifom-randomreturns a zero,om=will return t andomif, in turn, will return -1. If not, 1 is returned.

Once we have added our first interval (usingom+) to the initial note, the result will be a new note which will take the place of the old as the internal state of ouracumcollector. In order to record each note we usecollect, connected to the first output ofacum, as we did in the

previous tutorial.

Lastly, in order to have both factories (the BPFand the Chord-seq) evaluated in a single evaluation we will usesequence.sequenceevaluates all its arguments sequentially, but you will only see one in the Listener. For instance, if we evaluate the first output ofsequence we will obtain the BPF object in the listener. Evaluating the second output will return the Chord-seq object. Both will be evaluated in the patch window, however.

Functions

As we have seen, OM patches can contain calls to functions, factories, etc., nested to any level we like. It is even possible to put a call to itself within a function! A function which contains itself (created by dragging the patch from the Workspace into the patch window itself) is called a recursive function. Recursion is actually extremely useful and a powerful part of

Some computations require recursive functions, while others benefit from the clarity or speed of recursion, though they may be possible other ways. For example, the factorial procedure performed in Tutorial 36 can be performed more elegantly (and more quickly, it turns out) using a recursive function.

The scheme of the recursive function for finding 5! (5 factorial, that is the product 1*2*3*4*5) for example, can be summarized:

First, we reverse our list: 5*4*3*2*1

4 can be represented as (5-1). This means we start by mutiplying 5*(5-1).

3 can be represented as ((5-1) -1 ). So we multiply 5*(5-1)*((5-1) -1)Get the idea?.

The next level of recursion would be (((5-1) -1 ) -1), and so on, until we reach 1.

We can imagine a function that multiplies 5 by a value taken from its last repetition and passes that to itself along with the value to multiply by (minus one). And here we run into a problem- since recursive functions call themselves, they must have a built in ’brake’ in the form of a termination test. Only if the termination test fails should they call themselves. With-out a termination test, the function continues to call itself on into infinity, eventually saturating the available memory and causing an error:

> Error: Stack overflow on control stack.

> To globally increase stack space,

> increase *minimum-stack-overflow-size*

> While executing: "Unknown"

> Type Command-/ to continue, Command-. to abort.

> If continued: Continue with a larger stack See the Restarts menu item for further choices.

In document Open Music Tutorial (Page 164-169)

Related documents