Demonstration 1
Literal Selection

Introduction

Demonstration 1 provided the practical component for Chapter 3: “Literal Selection” of my unpublished textbook on composing programs. It illustrates the basic design of a complete composing program. In particular it shows how a composer might implement literal strategies to derive not only the musical details, but also the broader level of musical structure.

From the perspective of my production framework, the process as a whole is a single problem interleaving decisions about phrase attributes with decisions about note attributes. What distinguishes this Demonstration from all others is that its decisions implement the degenerate scenario known as Hobson's choice. Except that this composing program does not have the luxury of trying another stable.

   
Figure 1 (a): Pitch row.   Figure 1 (b): Period row.   Figure 1 (c): Articulation row.

Compositional Directives

The piece derives entirely from the three rows depicted in Figures 1 (a), 1 (b), and 1 (c). It has three levels of structure: the local level consists of individual notes; the median level consists of 24-note phrases; and the global level consists of the piece as a whole, which spans four entire phrases.


Figure 2: Derivation of a melodic resultant.

Each phrase in Demonstration 1 constitutes a resultant created by phasing four cycles of the pitch row against three cycles of the period row. Figure 2 illustrates how the opening resultant of the piece is derived. Concurrent with each cycle of periods is a cycle of the nine articulations. Notice that the cycles of pitches and periods come back into alignment at the end of the phrase because one element in each cycle of articulations is always a rest.


Measure Pitches Periods
1 High Register
Retrograde
No augmentation
Prime form
7 Low Register
Retrograde - inversion
Augmentation by 2
Inversion
25 Medium Register
Inversion
Augmentation by 3
Retrograde - inversion
37 High Register
Prime form
No augmentation
Retrograde

Table 1: Global recipe for Demonstration 1.

Table 1 gives the layout of Demonstration 1 and details which transformations have been applied to the pitch and period rows in each phrase. Here are the outcomes from a decision-making process which, rather than being delegated to the computer, was undertaken prior to the automated phase of production. But you can see criteria at work which, with greater programming sophistication, could conceivably have been programmed. For example, the series forms (prime, inversion, retrograde, retrograde-inversion) are each employed once for pitches and once for durations; also, pitch and rhythm never employ the same series form in the same phrase. Also, registers cycle through high, low, and medium before recapping with high register in the fourth phrase. Likewise, augmentations cycle through 1×, 2×, and 3× before recapping with 1×.

The complete musical product appears in Figure 3.


Figure 3: Transcription of Demonstration 1.

Implementation

The explanations to follow focus on three musical attributes: pitch, timing (approached through the notion of periods between consecutive attacks), and articulation. Their purpose is to tease out the strands of code that affect a particular attribute, and thus to reveal the mechanics of literal selection in play. The explanations are peppered with line numbers identifying where precisely the various declarations, data initializations, loops, branches, calculations, and subroutine calls may be found in the printed listing. Yet these line numbers will distract your focus from attribute-specific strands to the greater mass of code. You are by no means expected to chase down every line of code. Rather, you should follow through with line numbers only when you have a specific question that the narrative is not answering.

The design of DEMO1 reflects a structure of phrases and notes:

Phrases

Lines 7-10 of program DEMO1 implements the layout through four calls to subroutine PHRASE. PHRASE receives information from Table 1 through seven explicit arguments:

  1. ITIME — Phrase start time in sixteenth notes.
  2. IREG — Register expressed as an offset; 0 indicates 32' C.
  3. IAUG — Augmentation factor, used to multiply note durations.
  4. INCPCH — Increment for pitch row: 1 indicates forward; -1 indicates retrograde.
  5. INCPER — Increment for period row: 1 indicates forward; -1 indicates retrograde.
  6. ISGN — Direction for pitch row: 1 indicates original; -1 indicates inversion.
  7. RHYFLG — Flag for period inversion: If false, original period values are used; if true, period values (1, 2, or 4) are divided into 4.

A final call to subroutine WNOTE (line 11) acts to close the piece on a quarter-note C5 with normal articulation.


Listing 1: Program DEMO1.

The source code for subroutine PHRASE appears as Listing 2. The symbols in PHRASE are associated with musical attributes through three abbreviations:

  1. PCH — pitch, expressed as an offset from the first note in the row. Parameter MPCH (line 2) sets the length of the pitch row to 6. Array VALPCH holds the pitch row. This array is populated in line 5, with contents expressed as offsets relative to the starting pitch. Variable IDXPCH tracks the current pitch-row position.
  2. PER — period between consecutive attacks. Parameter MPER (line 2) sets the length of the period row to 9. Array VALPER holds the period row. This array is populated in line 6, with values indicating 1, 2, or 4 sixteenth notes. Variable IDXPER tracks the current period-row position.
  3. ART — articulation. Parameter MART (line 2) sets the length of the articulation row to 9. Array VALART holds the articulation row. This array is populated in line 7, with values indicating 0 (rest), 1 (staccato), 2 (normal), 3 (slur). Variable IDXART tracks the current articulation-row position.

Listing 2: Subroutine PHRASE.

Sequences

The library subroutine SEQUEN1 is modeled on the SEQUENCE feature of G.M. Koenig's Project Two. It implements the most basic of literal procedures; that is, sampling elements in order from a row. Calls to SEQUEN require five arguments:

  1. RESULTSEQUEN selects a new element from a row and returns the row value in this location.
  2. VALUE — Supply of values arranged in position order. Duplicate values are permitted. VALUE must be an array in the calling program whose dimension in the calling program is NUM (argument #5 below).
  3. IDX — Index to pending selection. IDX must be an integer in the calling program. Before anything else, SEQUEN increments IDX by INC (argument #4 below). Whenever IDX threatens to move outside the range from 1 to NUM, SEQUEN performs wrap-around arithmetic to restore IDX into range. SEQUEN completes by setting RESULT=VALUE(IDX). Initializing IDX to 1-INC causes the first call to SEQUEN to return the first element of VALUE.
  4. INC — Sampling increment. INC must be an integer in the calling program. It can be either positive or negative (setting INC to -1 produces the retrograde) but it should always be relatively prime to NUM.
  5. NUM — Number of row elements (dimension of array VALUE in the calling program).

Notes

The length of each row is given by a parameter starting with the letter M; values of the prime row-forms reside in arras beginning with VAL. Each row also has an associated index beginning with IDX.

The transformations used to generate additional material for Demonstration 1 break down as follows:

Rotation

The library subroutine ROTATE2 accepts an array of arbitrary dimension and shifts the elements of the array by an arbitrary number of positions. Calls to ROTATE require three arguments:

  1. VALUE — Array of values, arranged in position order. VALUE in the calling program must be an array of dimension NUM (argument #3 below).
  2. NSHIFT — Number of positions each element is to shift. If NSHIFT is positive, then the shift will be rightward/clockwise; if NSHIFT is negative, then the shift will be leftward/counter-clockwise.
  3. NUM — Number of row elements (dimension of array VALUE in the calling program).

Text Output

The mechanics of subroutine WNOTE bear close attention because they serve for most the of Demonstrations in this series. When it calls WNOTE to append a note to the human-readable listing, DEMO1 provides four arguments:

  1. ITIME — Start time in sixteenth notes.
  2. DUR — Duration in sixteenth notes.
  3. IPCH — Pitch, expressed as in integer offset from 32'C.
  4. IART — Articulation: (0) rest, (1) staccato, (2) normal, (3) slur.

The first task of WNOTE is to place ITIME in a measure (lines 8-19). The author finds it most convenient to begin measures on beat 0. Conversion of numeric degrees to letter names is easily accomplished using the character array LETTER. The convention is to express registers in octaves above 32'C (making 32'C C0; middle C is C4; A 440 is A4, and so on). The character array ARTIC converts numeric articulations into readable text indications.


Listing 3: Subroutine WNOTE.

Comments

  1. Subroutine SEQUEN is described in Automated Composition, Chapter 3, pp. 3-8 to 3-9.
  2. Subroutine ROTATE is presented in Automated Composition, Chapter 3, pp. 3-13 to 3-15.

© Charles Ames Original Text: 1984-11-01 Page created: 2017-03-12 Last updated: 2017-03-12