about arca

Arca is an experimental and totally undocumented musical programming language that is currently in the 'proof-of-concept' stage. It exists as a downloadable python module, which works adequately, and as a website, which is very experimental and rickety. There are many things the website does badly; what surprises me is that it works at all!

The Arca philosophy is that the python module is for complicated work; it is endlessly extensible and can be used with music21. The website and the text interface are convenient shorthands that allow you to do some simple things quickly. I am going to try to keep those parts of the project simple. If you really get into it, you will want to work in python.

Here are some pieces modeled with Arca. Click on the links to run them in the browser. Or instantiate them in python by writing p = arca.Program(filename.txt); p.show().

You can download these and other Arca programs here.

Arca lines are delimited by carriage returns or semicolons; any line that begins with a tab is considered a continuation of the preceding line. Any text after a double slash is ignored as a comment.

Arca works with an internal "basic duration"; by default this is an eighth note, but you can change it. Floating point durations are fine.

An Arca program usually starts by defining global parameters. For instance, this line declares a time signature of 3/4, changes the basic duration to a sixteenth note (basic durations are always expressed in units of a quarter note), and defaults to using flats. This last command is a hack; my goal is eventually to inherit spelling from scales.

TimeSignature = 3/4; BeatDuration = .25; Spelling = flats

Then an arca program declares a series of objects.

A Scale is an octave repeating collection that may be contained in other scales. Here we have Bb major.

Scale = Scale(Bb C D Eb F G A)

A Chord is a concrete collection of notes. Every chord has a default "arpeggiation pattern" that can contain nonharmonic tones. Here the chord's notes are Bb3, D4 and F4. We enclose the notes in brackets to indicate that the associated arpeggiation pattern will play them at the same time. We give it the (circular) duration list 2, 1 which says that the output will cycle through those two durations in order. (This pattern belongs to the arpeggiation pattern, and is passed along by the chord.) The container keyword indicates that the chord is contained inside the scale we just defined.

Chord = Chord([Bb3 D4 F4], durations = 2 1, container = Scale)

Then we define a Stream or Timeline to play our object. The exclamation point outputs the object. A capital T transposes along the scale; a little t transposes along the chord. The name of the stream, which is the text preceding the initial "stream:" keyword, defines the initial object for the stream. That can be changed during the stream (using NewObjectName:). Here we output the motive twice, transpose down along the scale, output the motive four times, transpose up along the scale and down along the chord. Run it here.

ChordStream: ! ! T-1 ! ! ! ! T1t-1 ! !

Now try removing the brackets from the chord definition.

Now we will add a melody by defining another arpeggiation pattern for our same chord. N0+1 is a neighbor note, one scale step above (+1) the first note in the pattern (0). Notes are always numbered from zero, following Python convention. The third note in the melody, N3+1, is a neighbor to the fourth note in the melody (Bb4, an octave doubling of the chordal Bb3). The dashes indicate repeats. This arpeggiation pattern is attached to our previously defined Chord, and assigned some durations.

Melody = Arpeggiation(D5 N0+1 N3+1 Bb4 - - -, chord = Chord, durations = 3 1 2 2 4 4 8)

To make a chromatic neighbor type CNx+y or CNx-y; to make a chordal skip type CSx+y. To make a neighbor at level z of a hierarchy of embedded scales type zNx+y.

Now we play the melody. A timeline has a "cursor" that defines when events happen. The @ keyword moves the cursor to a specific timepoint measured in basic durations; this happens before notes are played. @mx moves to measure x. @mx+y or @mx-y moves to measure x and adds or subtracts y beats. @+ and @- advance the cursor at runtime; this limits what you can do with @-, as events may have already happened. The command +Bb2 adds an extra note Bb2 to the next chord. The MelodyStream contains a t1 that moves the motive upward by one chordal step, so that it repeats starting on Eb.

ChordStream: @12 ! @24 T-1 ! @36 ! @48 T1t-1 +Bb2 !

MelodyStream: @8 ! t1 !

The result resembles the opening of the minuet from Mozart's K. 282. What is interesting is that the motive appears, on the surface, to be transposed up one scale step (from an initial note of D to Eb). In the Arca program, however, it is transposed up by chordal step along a chordal pattern that is itself descending. This sort of analysis, where a musical surface is represented as a nonobvious product of motion at different musical levels, originates with Schenker, and is characteristic to a lot of twentieth-century music theory. Arca allows us to very precisely model this sort of analysis.