#include
"cscore.h"
cscore()
{
/* VARIABLE DECLARATIONS
*/
/* PROGRAM BODY */
}
The include statement will define the event and list structures for the program. The following C program will read from a standard numeric score, up to (but not including) the first s or e statement, then write that data (unaltered) as output.
#include
"cscore.h"
cscore()
{
EVLIST *a;
/* a is allowed to point to an event list */
a = lget();
/* read events in, return the list pointer */
lput(a);
/* write these events out (unchanged) */
putstr("e");
/* write the string e to output */
}
After execution of lget(), the variable a points to a list of
event addresses, each of which points to a stored event. We have
used that same pointer to enable another list function (lput) to
access and write out all of the events that were read. If we now
define another symbol e to be an event pointer, then the statement
e = a->e[4];will set it to the contents of the 4th slot in the evlist structure. The contents is a pointer to an event, which is itself comprised of an array of parameter field values. Thus the term e->p[5] will mean the value of parameter field 5 of the 4th event in the evlist denoted by a. The program below will multiply the value of that pfield by 2 before writing it out.
#include
"cscore.h"
cscore()
{
EVENT
*e; /* a pointer to an event
*/
EVLIST *a;
a = lget();
/* read a score as a list of events */
e = a->e[4];
/* point to event 4 in event list a */
e->p[5]
*= 2; /* find pfield 5, multiply its value by 2 */
lput(a);
/* write out the list of events */
putstr("e");
/* add a "score end" statement */
}
Now consider the following score, in which p[5] contains frequency
in cps.
As an extension to the above, we could decide to use a and e to examine each of the events in the list. Note that e has not preserved the numeral 4, but the contents of that slot. To inspect p5 of the previous listed event we need only redefine e with the assignment
e = a->e[3];More generally, if we declare a new variable f to be a pointer to a pointer to an event, the statement
f = &a->e[4];will set f to the address of the fourth event in the event list a, and *f will signify the contents of the slot, namely the event pointer itself. The expression
(*f)->p[5],like e->p[5], signifies the fifth pfield of the selected event. However, we can advance to the next slot in the evlist by advancing the pointer f. In C this is denoted by f++.
In the following program we will use the same input score. This time we will separate the ftable statements from the note statements. We will next write the three note-events stored in the list a, then create a second score section consisting of the original pitch set and a transposed version of itself. This will bring about an octave doubling.
By pointing the variable f to the first note-event and incrementing
f inside a while block which iterates n times (the number of events
in the list), one statement can be made to act upon the same pfield
of each successive event.
a = lget();
/* read score into event list "a" */
b = lsepf(a);
/* separate f statements */
lput(b);
/* write f statements out to score */
lrelev(b);
/* and release the spaces used */
e = defev("t 0 120");
/* define event for tempo statement */
putev(e);
/* write tempo statement to score */
lput(a);
/* write the notes */
putstr("s");
/* section end */
putev(e);
/* write tempo statement again */
b = lcopyev(a);
/* make a copy of the notes in "a" */
n = b->nevents;
/* and get the number present */
f = &a->e[1];
while (n--)
/* iterate the following line n times: */
(*f++)->p[5]
*= .5; /* transpose pitch down one octave */
a = lcat(b,a);
/* now add these notes to original pitches */
lput(a);
putstr("e");
The output of this program is:
#include
"cscore.h"
cscore()
{
a = lget();
b = lsepf(a);
lput(b);
lrelev(b);
e = defev("t 0 120");
putev(e);
lput(a);
putstr("s");
putev(e);
/* write out another tempo statement */
b = lcopyev(a);
n = b->nevents;
dim = 0;
/* initialize dim to 0 */
f = &a->e[1];
while (n--){
(*f)->p[6]
-= dim; /* subtract current value of dim */
(*f++)->p[5]
*= .5; /* transpose, move f to next event */
dim
+= 2000; /* increase
dim for each note */
}
a = lcat(b,a);
lput(a);
putstr("e");
The increment of f in the above programs has depended on certain precedence rules of C. Although this keeps the code tight, the practice can be dangerous for beginners. Incrementing may alternately be written as a separate statement to make it more clear.
#include
"cscore.h"
int cue[3]={0,10,17};
/* declare an array of 3 integers */
cscore()
{
EVENT *e,
**f;
EVLIST *a,
*b;
int n, dim,
cuecount, holdn; /* declare new variables */
Using the identical input file, the C program above will generate:
; diagnostic: cue = 0
i 1 1 3 0 440 10000
i 1 4 3 0 256 10000
i 1 7 3 0 880 10000
; diagnostic: cue = 10
i 1 11 3 0 440 8000
i 1 14 3 0 256 8000
i 1 17 3 0 880 8000
; diagnostic: cue = 17
i 1 28 3 0 440 4000
i 1 31 3 0 256 4000
i 1 34 3 0 880 4000
e;