Skip to content
roomi fields

Music and formalisms · M12 · Design

From structure to sound

Discover how BP3 unifies form, harmony, groove, and musical gesture through its layers of abstraction.

Published 12 February 2026 · updated 15 February 2026 · Lire en français

BP3 and Abstraction Layers

How a Single Language Encodes Form, Harmony, Groove, and Gesture — Illustrated by a Flamenco Rumba

In M3, we saw that digital music tools each operate at a different level of abstraction: MIDI describes events (level 3), MusicXML captures notation (level 4), BP3 generates from rules (level 5). Most tools are confined to only one of these levels — a MIDI file doesn’t know “sonata form,” and a MusicXML score knows nothing about groove.

BP3 does things differently. Thanks to its mechanisms — grammars, scripts, polymetry — it naturally crosses several levels of abstraction within a single program. A composer can encode formal structure, harmony, groove, instrumental gesture, and sound in two files of a few dozen lines, without changing paradigms.

The idea in one sentence: BP3 is a generative language that simultaneously encodes structure, harmony, accents, rhythm, gesture, and sound — without leaving level 5.

Demonstration by example: a flamenco rumba compas.


Three Levels, Six Layers

From top (most abstract) to bottom (most concrete), a BP3 grammar can encode six layers of musical information, distributed across three levels of the M3 taxonomy:

M3 LevelLayerQuestionBP3 Mechanism
Generative (5)StructureWhat form?Grammar rules
Notational (4)HarmonyWhat possible notes?_script() (shared variables)
Event-based (3)AccentsWhat dynamic profile?_script($ACCENT)
(idem)RhythmWhich beats are played?_script($PLAY)
(idem)GestureHow to play physically?Poly_ratio {1, ...} (strum)
(idem)SoundWhat MIDI events?_note(), _vel()

The key point: BP3 generates at level 5 of the M3 taxonomy, but it encodes information from levels 3 and 4 within its terminal objects and variables. It’s like an architect drawing a blueprint (structure) that contains electrical specifications (technical) and material choices (material) — the blueprint is the most abstract level, but it carries the concrete levels within it.


The Example: A Flamenco Rumba Compas

Musical Context

Flamenco rumba is one of the most popular flamenco styles. Its rhythmic energy relies on a characteristic motif: the 3-3-2 pattern.

Deciphering — The 3-3-2 pattern: Take 8 beats. Instead of grouping them regularly (4+4 or 2+2+2+2), group them as 3+3+2: ! . . ! . . o . — a strong accent every 3 eighth notes, then a weak accent after 2. This asymmetrical grouping creates a characteristic “bounce” found in rumba, son cubano, bossa nova, and many popular music styles. It’s the rhythmic DNA of rumba.

The right-hand technique is rasgueado: a rapid alternation of sweeping the strings downwards (D — down-strum) and upwards (U — up-strum). Each finger sweeps all 6 guitar strings in an instant.

Deciphering — Rasgueado: A flamenco guitar technique where the right hand rapidly sweeps all the strings. A down-strum goes from low to high (string 6 → string 1), an up-strum does the opposite. The result is a “strummed” chord in a few milliseconds. Many rasgueado techniques exist; for the “simplicity” of the example, we will consider a simple gesture where the downstroke is done with a single finger (which is quite simple and would produce a somewhat thin sound, let’s say the middle finger) and the upstroke with the thumb (which, however, is quite classic).

Our example uses a typical harmonic progression: i – V7 – V7 – i (Em – B7 – B7 – Em) — the minor color and dominant tension characteristic of flamenco.

The Grammar File — -gr.Rumba

The grammar file defines the structure and organization of the layers:

-gr.Rumba

// ═══ STRUCTURE — the form of the piece [Generative] ═══
S --> SETUP_GUITARE SEQUENCE
SEQUENCE --> MESURE_1 MESURE_2 MESURE_3 MESURE_4

// ═══ HARMONY — the i–V7–V7–i progression [Notational] ═══
MESURE_1 --> POS_Em COMPAS
MESURE_2 --> POS_B7 COMPAS
MESURE_3 --> POS_B7 COMPAS
MESURE_4 --> POS_Em COMPAS

// ═══ ACCENTS — the 3-3-2 dynamic profile [Event-based] ═══
COMPAS --> { ACCENT_MAP, RHYTHM_MAP, MECHANICS }
ACCENT_MAP --> O . . O . . o .

// ═══ RHYTHM — which beats are played [Event-based] ═══
RHYTHM_MAP --> x - x x - x x x

// ═══ GESTURE — right-hand alternation [Event-based] ═══
MECHANICS --> D U D U D U D U

Five blocks, one per layer (the Sound layer is implemented in the data file). Each block answers a single question:

  • Structure: SEQUENCE → MESURE_1 ... MESURE_4 — how many measures, in what order.
  • Harmony: MESURE_N → POS_X COMPAS — which chord for each measure (then delegates to rhythm).
  • Accents: ACCENT_MAP → O . . O . . o . — what dynamic profile (the 3-3-2 pattern).
  • Rhythm: RHYTHM_MAP → x - x x - x x x — which beats are played or muted.
  • Gesture: MECHANICS → D U D U D U D U — what right-hand movement.

The polymetry { ACCENT_MAP, RHYTHM_MAP, MECHANICS } (B5) superimposes three layers in parallel — the 8 accents, the 8 beats, and the 8 strums align one by one.

The Data File — -da.Rumba

The data file gives body to each terminal and non-terminal of the grammar:

-da.Rumba

// ═══ HARMONY — instrument (tuning) [Notational] ═══

SETUP_GUITARE _script(
    $S6 = 40;
    $S5 = 45;
    $S4 = 50;
    $S3 = 55;
    $S2 = 59;
    $S1 = 64;
)

// ═══ HARMONY — chord positions (F = fret, V = voiced) [Notational] ═══

POS_Em _script(
    $F6=0; $V6=1;
    $F5=2; $V5=1;
    $F4=2; $V4=1;
    $F3=0; $V3=1;
    $F2=0; $V2=1;
    $F1=0; $V1=1;
)

POS_B7 _script(
    $F6=0; $V6=0;
    $F5=2; $V5=1;
    $F4=1; $V4=1;
    $F3=2; $V3=1;
    $F2=0; $V2=1;
    $F1=2; $V1=1;
)

// ═══ ACCENTS — dynamic profile [Event-based] ═══

O _script($ACCENT = 127)   // strong accent
o _script($ACCENT = 80)    // weak accent
. _script($ACCENT = 60)    // normal note

// ═══ RHYTHM — which beats are played [Event-based] ═══

x _script($PLAY = 1)       // played beat
- _script($PLAY = 0)       // muted beat

// ═══ GESTURE — right hand [Event-based] ═══

// Down-strum: velocity = accent × rhythm, then 6 notes low→high
D _vel($ACCENT*$PLAY) {1, _note($V6*($S6+$F6)) _note($V5*($S5+$F5)) _note($V4*($S4+$F4)) _note($V3*($S3+$F3)) _note($V2*($S2+$F2)) _note($V1*($S1+$F1))}

// Up-strum: velocity = accent × rhythm, then 6 notes high→low
U _vel($ACCENT*$PLAY) {1, _note($V1*($S1+$F1)) _note($V2*($S2+$F2)) _note($V3*($S3+$F3)) _note($V4*($S4+$F4)) _note($V5*($S5+$F5)) _note($V6*($S6+$F6))}

Cross-Reading: Each Layer Dissected

Structure Layer — Grammar as Musical Form

At the top of abstraction, the structural rules outline the form of the piece — without mentioning any chords:

S --> SETUP_GUITARE SEQUENCE
SEQUENCE --> MESURE_1 MESURE_2 MESURE_3 MESURE_4

The structure doesn’t know if it’s Em or B7. It only says: “there are 4 measures, in this order.” To change to 8 measures or an AABA form, you only modify this part.

Derivation (B3, ORD mode) hierarchically decomposes the piece:

SSETUPGUITARESEQUENCEMESURE1POSEmCOMPASMESURE2POSB7COMPASMESURE3POSB7COMPASMESURE4POSEmCOMPAS

Figure 1 — Derivation tree of the Rumba grammar. The structure is hierarchically decomposed: S produces SEQUENCE, which is divided into 4 measures, each associating a chord position (orange) and a rhythmic compas (yellow).

This is the same mechanism as a syntax tree (L4), but the nodes bear musical names, not computer science ones. The Structure layer delegates to the Harmony layer, which delegates to the Rhythm — each within its own block.

Harmony Layer — _script() as Instrumental Memory

The harmony layer uses _script() to configure the guitar’s state via shared variables (B4).

SETUP_GUITARE tunes the 6 strings. Each $Sn variable contains the MIDI number of the open string:

VariableNoteMIDI
$S6E240
$S5A245
$S4D350
$S3G355
$S2B359
$S1E464

Chord positions (POS_Em, POS_B7) place the fingers on the fretboard. Each string receives a fret ($Fn) and a voicing indicator ($Vn: 1 = played, 0 = muted):

Em (E minor): all open strings except frets 2 on A and D.

EmEADGBefr1fr2fr3B7EADGBefr1fr2fr3X

Figure 2 — Em (E minor) and B7 (B seventh) chord diagrams. The colored dots indicate where to place fingers on the fretboard. Green circles = open strings. X = muted string.

Deciphering — Reading a Tablature: Each horizontal line is a string (from low E at the bottom to high e at the top). Numbers or ● indicate which fret to place fingers on. ○ = open string (fret 0). ✕ = muted string (not played).

In numbered tablature, with MIDI correspondence:

Em (E minor)                  B7 (B seventh)
e ──0──  E4  (64+0 = 64)       e ──2──  F#4 (64+2 = 66)
B ──0──  B3  (59+0 = 59)       B ──0──  B3  (59+0 = 59)
G ──0──  G3  (55+0 = 55)       G ──2──  A3  (55+2 = 57)
D ──2──  E3  (50+2 = 52)       D ──1──  D#3 (50+1 = 51)
A ──2──  B2  (45+2 = 47)       A ──2──  B2  (45+2 = 47)
E ──0──  E2  (40+0 = 40)       E ──✕──  (muted, $V6=0)

The key mechanism is decoupling: chord variables persist after POS_Em executes and remain active until the next POS_B7. To change the harmonic progression (e.g., Am–G–F–E instead of Em–B7–B7–Em), you only modify the Harmony block of the grammar — neither the structure, nor the accents, nor the rhythm, nor the gesture are affected.

An important detail: _script() is a zero-duration operation in BP3. When writing MESURE_1 → POS_Em COMPAS, the position change executes instantaneously before the first beat of the compas — not on the beat. This is exactly what happens in reality: a guitarist places the fingers of their left hand before the right hand strikes. The sequentiality of the code faithfully models this causal dependency between the two hands.

Accents Layer — The 3-3-2 Dynamic Profile

The Accents layer defines the dynamic profile — how much energy on each beat, regardless of whether it is played or not:

ACCENT_MAP --> O . . O . . o .
SymbolMeaning$ACCENT
OStrong accent127
oWeak accent80
.Normal note60

The 3-3-2 pattern appears in the distribution of strong and weak accents: positions 1, 4, 7 (groups of 3+3+2):

Position:   1   2   3   4   5   6   7   8
Accent:     O   .   .   O   .   .   o   .
Group:    |  ── 3 ──  |  ── 3 ──  | ─ 2 ─ |

The dynamic profile is pure: it says “here it’s strong, here it’s soft” without stating what is played or not. It’s the rhythmic DNA of rumba — the 3-3-2 feeling — separated from any playing decision.

Rhythm Layer — Which Beats Are Played

The Rhythm layer decides which beats sound — independently of their dynamics:

RHYTHM_MAP --> x - x x - x x x
SymbolMeaning$PLAY
xPlayed beat1
-Muted beat0

This is where decoupling becomes powerful. With the same 3-3-2 accent profile, different rhythms can be played — each variation only affects this line:

x - x x - x x x   ← classic rumba (our example)
x - x x x x x x   ← fuller variation
x x x x - x x x   ← silence displacement
x x x x x x x x   ← all beats played

The dynamic profile remains identical (O . . O . . o .) — the 3-3-2 feeling is preserved, only the rhythm changes. This is a separation impossible in traditional encoding where accent and rhythm are merged into a single symbol.

Each symbol in both layers is a terminal that acts as a state command: it does not produce sound itself, but modifies a variable ($ACCENT or $PLAY) which will be read by the Gesture layer when producing MIDI notes.

Gesture Layer — Polymetry and Micro-timing

The gesture layer models the physical movement of the right hand:

MECHANICS --> D U D U D U D U

D and U are defined in two steps — like the real gesture:

D _vel($ACCENT*$PLAY) {1, _note(...) _note(...) _note(...) ... }
U _vel($ACCENT*$PLAY) {1, _note(...) _note(...) _note(...) ... }

First, _vel($ACCENT * $PLAY) sets the force of the gesture — only once, because a rasgueado is a single gesture. Velocity combines two layers: dynamics ($ACCENT, Accents layer) and rhythm ($PLAY, Rhythm layer). If the beat is muted ($PLAY = 0), the velocity is zero regardless of the accent — the strum is silent. Then {1, 6 notes} is a poly_ratio (B5) that compresses the 6 notes into 1 unit of time — the micro-timing that transforms 6 discrete events into a “strummed” chord of a few milliseconds.

Deciphering — Poly_ratio: The expression {1, seq} compresses the sequence seq into exactly 1 unit of time. For a guitar strum, this means that the 6 notes are played sequentially but very quickly — like a real string sweep.

The strum direction is encoded in the order of notes:

  • D (down-strum): low → high, so string 6 → string 1 ($S6+$F6 first).
  • U (up-strum): high → low, so string 1 → string 6 ($S1+$F1 first).

Voicing (which strings sound) is managed by the left-hand $Vn variables: _note($Vn * ($Sn+$Fn)). If $Vn = 0 (muted string), the MIDI note is 0 — silence. This is a pragmatic shortcut: strictly speaking, MIDI note 0 is not a silence but a C-1, and a production grammar would separate voicing and pitch. But for our demonstration, this shortcut has the advantage of clearly showing how the left hand (voicing) and the right hand (dynamics) each contribute to the final result without mixing.

The superposition of the three layers is achieved by 3-voice polymetry:

COMPAS --> { ACCENT_MAP, RHYTHM_MAP, MECHANICS }

This means: playing the 8 accents, the 8 played/muted choices, and the 8 strums in parallel, temporally aligned. At beat 1, the accent (!), the rhythm (x), and the gesture (D) coincide — and the resulting velocity is $ACCENT × $PLAY = 127 × 1 = 127. At beat 2, the accent (.), the rhythm (-), and the gesture (U) coincide — and the velocity is 60 × 0 = 0 (silence). The three sequences have the same length (8 elements), so the ratio is 1:1:1.

Sound Layer — MIDI Terminals

At the very bottom of the stack, the _note() and _vel() terminals produce MIDI events (B2). Each strum decomposes into:

  • _vel($ACCENT * $PLAY) — placed before the poly_ratio, zero duration: the force of the gesture, combining dynamics (Accents layer) and the played/muted choice (Rhythm layer).
  • _note($Vn * ($Sn + $Fn)) — inside the poly_ratio: the MIDI note = voicing × (string + fret).

The code faithfully models the physical reality of the gesture:

Real gestureBP3 CodeWhy
Left hand places the chord before the beatPOS_X` (duration 0) *then* `COMPAS_script()` is instantaneous
Right hand sweeps with uniform force_vel(...)` once before the strumone gesture = one velocity
Accent depends on the 3-3-2 pattern$ACCENT` (Accents layer) in velocitythe dynamic profile
Some beats are muted$PLAY` (Rhythm layer) in velocitythe played/muted rhythm
Some strings muted by the left hand$Vn` in `_note($Vn * ...)}it's the left hand, not the right
Strings swept in rapid sequence{1, _note(...) _note(...) ...}poly_ratio = micro-timing

This is the destination point: all the abstraction of the upper layers resolves into MIDI events. The variables $V, $S, $F, $ACCENT, and $PLAY — originating from five different layers — converge here. The sequentiality of the code (POS → _vel → _note) reflects the sequentiality of the gesture (placing fingers → preparing the strike → sweeping the strings).


BP3 Mechanisms Mobilized — Summary Table

BP3 MechanismLayer servedRoleArticle
Grammar rulesStructureHierarchical decomposition of formB3
_script()Harmony, Accents, RhythmShared state between layers (persistent variables)B7
Polymetry {A, B, C}Accents + Rhythm + GestureSuperposition of three temporal flowsB5
Poly_ratio {n, seq}GestureMicro-timing (6-note strum in 1 beat)B5
Variables $AllIndirection and decoupling between layersB4
_note(), _vel()SoundProduction of terminal MIDI eventsB2

Six mechanisms. Six layers across three levels. Two files. One language.


What It Shows

Layer Traversal

BP3 operates at level 5 (generative) of the M3 taxonomy, but it encodes information from levels 3 and 4 within its objects. The grammar generates the structure (level 5), the _script() calls carry the harmony (level 4), and the _note(), _vel() terminals produce the events (level 3). A single program traverses three levels of abstraction — where normally a different tool would be needed for each level.

Decoupling

Each layer is independently modifiable — each modification affects only one block of the grammar:

  • Change the structure (8 measures instead of 4) → modify only the Structure block.
  • Change the progression (Am–G–F–E instead of Em–B7–B7–Em) → modify only the Harmony block.
  • Change the accents and switch from a Rumba to a Tango (O . . O . . o . → O . O . O . . .) → modify only the Accents block.
  • Change the rhythm (x - x x - x x x → x x x x x x x x) → modify only the Rhythm block.
  • Change the gesture (rasgueado → arpeggio) → modify only the Gesture block.

This is the consequence of two mechanisms: block separation in the grammar, and the variable system (B4) which allows layers to communicate via names ($ACCENT, $PLAY, $Sn, $Fn, $Vn), not hardcoded values.

Composability

Decoupling implies recombination: layers can be freely assembled. Same groove + different instrument (replace SETUP_GUITARE with an oud setup). Same structure + different harmony (Am–G–F–E progression instead of Em–B7–B7–Em). Same gesture + different groove (reggaeton pattern on the same strumming mechanics).

A Single Language

Where a classic workflow would require a DAW for structure, a score editor for harmony, a sequencer for groove, and a VST plugin for sound, BP3 unifies everything into two text files — a grammar and its data. No conversion between formats, no loss of information between levels.

This is the promise of the generative level (M3) fully realized: a language that describes how to build music, not how it appears at a given level.

Outlook: BP3 could go further. Via _script() controlling SuperCollider SynthDefs, it could also encode timbre — descending to level 1 (signal) of the M3 taxonomy. This is the direction outlined by time-objects (B9): when the grammar no longer just generates notes, but directly controls sound synthesis.


Glossary

  • Compas: Rhythmic cycle in flamenco, structured by accents that define the identity of each palo (style). In rumba, the compas is a 4-beat cycle (or 8 eighth notes) with a 3-3-2 accent pattern.
  • 3-3-2 Pattern: Rhythmic grouping of 3+3+2 = 8 beats, typical of rumba, son cubano, and many popular music styles. The asymmetry creates a characteristic rhythmic tension between the groups of 3 and the final group of 2.
  • Poly_ratio: A single-voice polymetric expression {n, seq} compressing or stretching a sequence into n time units. Here, {1, 6 notes} plays 6 notes in 1 beat — a micro-timing.
  • Rasgueado: A flamenco guitar technique consisting of rapid string sweeps, typically alternating downward (down-strum) and upward (up-strum) movements.
  • Strum: A rapid sweep across guitar strings. A down-strum (D) goes from low to high; an up-strum (U) goes from high to low.

← Back to Index