Emulating Csound score parser's ramping feature

Now we want to add a little movement to the trivial cloud and we'll see how to imitate the behaviour of Csound score parser in presence of the ramping characters (< and >).

In particular we want our instrument to perform a crescendo from 40 dB to 80 db and sweeping frequencies an octave up from 261 Hz. We want the both variations to be linear, even if we know that only the intensity level scale is perceived as linear by humans.

Here follows a script (let's name it trivialcloud2.py) which shows how such a thing can be done using OMDE/pmask:

# trivialcloud2

import pmask, omde.csound
from pmask.bpf import LinearSegment

level = LinearSegment((0, 40), (10, 80))
frequency = LinearSegment((0, 261), (10, 261*2))
score = pmask.cloud(0, 10, 1, 1.0, 0.4, level, frequency)

omde.csound.save('trivialcloud2.sco', score)

When you make repeated use of the same values and especially when they have a important meaning, you may want to give them an explicit name. This has two advantages: the meaning of that value is evident and you can change globally that value without search and replace.

Using explicit names for the start and end time of the cloud, we can write the same program like this:

# trivialcloud2

import pmask, omde.csound
from pmask.bpf import LinearSegment

begin, end = 0, 10
level = LinearSegment((begin, 40), (end, 80))
frequency = LinearSegment((begin, 261), (end, 261*2))
score = pmask.cloud(begin, end, 1, 1.0, 0.4, level, frequency)

omde.csound.save('trivialcloud2.sco', score)

Using one style or the other is often matter of taste and habit.

In both cases, you end with a trivialcloud2.sco file containing the following score

i 1 0 0.4 40.0 261.0 i 1 1.0 0.4 44.0 287.1 i 1 2.0 0.4 48.0 313.2 i 1 3.0 0.4 52.0 339.3 i 1 4.0 0.4 56.0 365.4 i 1 5.0 0.4 60.0 391.5 i 1 6.0 0.4 64.0 417.6 i 1 7.0 0.4 68.0 443.7 i 1 8.0 0.4 72.0 469.8 i 1 9.0 0.4 76.0 495.9

In this script we introduced a new pmask symbol: LinearSegment. This is the first example of the so-called «generators».

At this point we may want to consider generators as objects that can be used in placed of fixed values in the pmask.cloud() call, representing values that change with time.

The line

level = LinearSegment((begin, 40), (end, 80))

says that level goes from 40 at the begin of this cloud to 80 at the end of the cloud. We know that level is expressed in dB.

As seen in the previous version of this script we can directly type numbers instead of begin and end, but this way we can easily and quickly change the begin time and/or the end time of the cloud.

Similarly the line

frequency = LinearSegment((begin, 261), (end, 261*2))

says that frequency goes from 261 Hz at the begin of this cloud to the higher octave at the end of the cloud.

LinearSegment belongs to a special group of generators, the "break point function" (BPF) generators. Such generators allow the user to indicate the value of the function in a finite set of points and interpolate the value of the functions in the other points. Different kind of BPF generators use a different interpolating functions.

LinearSegment uses linear interpolation, just like the simple ramping operators in Csound.

You can find LinearSegment and other BPF generators in the pmask.bpf module. As usual you have to import LinearSegment as in the following line, taken from the script above:

from pmask.bpf import LinearSegment