Case Study I: Modus Operandi for Piano

Case Study I: Modus Operandi for Piano#

Modus Operandi for Piano is the most fixed composition in the repository. It is a three-movement solo piano work organized around three modes on F: Dorian, Phrygian, and Lydian. Each movement has a clear tempo, meter, and registral profile. The right hand carries the main line, and the left hand provides a slower accompaniment. Even though the score is produced with Abjad and LilyPond, the work itself is not built as an open-ended generator. It is closer to a score written in code than to a random composition system.

This package is important because it shows that the repository is not limited to generative experiments. It can also support a more traditional compositional process in which the musical material is already decided, but the score is still generated and rendered programmatically. That gives the project a wider scope. It is not only about algorithmic output. It is also about representing finished musical decisions cleanly in code.

The implementation reflects that role. The CLI writes a LilyPond file, compiles it, and then merges the per-movement MIDI files that LilyPond emits. This extra step is necessary because the piece is built from multiple score blocks. The WAV render is then handled through a separate script that downloads and caches a piano SoundFont on first use.

Download#

Listen#

Score Preview#

First page preview of Modus Operandi for Piano

The movement-building code is direct enough to read almost like score notation. It is still too long to reproduce in full in the body of the paper, so only the opening of the movement is shown here:

Opening construction pattern for the first movement of Modus Operandi.#

# ============================================================
# Movement I — F Dorian, 4/4, Lento
# ============================================================


def make_movement_i():
    # ---- Right Hand ----
    rh = abjad.Voice(name="RH_Voice")

    # Key, time, tempo, clef
    rh_notes = abjad.Container()

    # Bar 1: f4\p( ees d c)
    bar = abjad.Container("f'4 ef'4 d'4 c'4")
    abjad.attach(abjad.Clef("treble"), bar[0])
    abjad.attach(
        abjad.KeySignature(abjad.NamedPitchClass("f"), abjad.Mode("dorian")), bar[0]
    )
    abjad.attach(abjad.TimeSignature((4, 4)), bar[0])
    abjad.attach(
        abjad.MetronomeMark(
            reference_duration=abjad.Duration(1, 4),
            units_per_minute=46,
            textual_indication="Lento",
        ),
        bar[0],
    )
    abjad.attach(abjad.Dynamic("p"), bar[0])
    abjad.attach(abjad.StartSlur(), bar[0])
    abjad.attach(abjad.StopSlur(), bar[3])
    rh_notes.append(bar)

    # Bar 2: bes4( c d\< ees\!)
    bar = abjad.Container("bf'4 c'4 d'4 ef'4")
    abjad.attach(abjad.StartSlur(), bar[0])
    abjad.attach(abjad.StartHairpin("<"), bar[2])
    abjad.attach(abjad.StopHairpin(), bar[3])
    abjad.attach(abjad.StopSlur(), bar[3])
    rh_notes.append(bar)

    # Bar 3: f4( g\< aes bes\!)
    bar = abjad.Container("f'4 g'4 af'4 bf'4")
    abjad.attach(abjad.StartSlur(), bar[0])
    abjad.attach(abjad.StartHairpin("<"), bar[1])
    abjad.attach(abjad.StopHairpin(), bar[3])
    abjad.attach(abjad.StopSlur(), bar[3])
    rh_notes.append(bar)

That directness is one of the useful contrasts in the report. Modus Operandi shows what the system looks like when the composition is fixed. The quartet packages show what the same repository looks like when the composition logic is open to controlled variation.