Skip to content

Polymetric Patterns

Polymetric patterns let groups of different lengths play at different rates within the same cycle. This creates textures where voices phase against each other — the same notes cycling at different speeds over a shared grid.

Use {...} for polymetric groups. Without a subdivision modifier, each element takes one step, so the group spans as many cycles as it has elements:

{C4 D4 E4} // One note per cycle across 3 cycles

Compare with [] which fits all notes into one cycle:

[C4 D4 E4] // All three in one cycle

The %N modifier controls how many steps a polymetric group spans per cycle. The fundamental formula is:

speed_factor = N / L

where N is the subdivision count and L is the number of elements in the group.

When N equals L, the group plays at normal speed — identical to a regular sequence. When N exceeds L, the group plays faster. When N is less than L, it plays slower:

PatternNLFactorEffectEvents/cycleDuration each
{C4 D4 E4}131/3Slow: spans 3 cycles11 cycle
{C4 D4 E4}%3331Normal: = [C4 D4 E4]31/3 cycle
{C4 D4 E4}%6632Fast: 2x speed61/6 cycle
{C4 D4 E4}%9933Very fast: 3x speed91/9 cycle

Without %N on a single group, N defaults to 1 — the group produces one event per cycle, taking L cycles to complete.

When N doesn’t divide evenly by L, the content wraps within the cycle. For example, {C4 D4}%3 has factor 3/2:

  • 2 elements sped up by 3/2 → 3 onsets per cycle
  • Onset times: 0, 1/3, 2/3
  • Cycle 1 content: C4, D4, C4 (wraps back to start)
  • Cycle 2 content: D4, C4, D4

The content shifts by one position each cycle, creating a phasing effect. After 2 cycles, the content realigns — the phase period equals L cycles for a factor of N/L.

A single element with %N simply repeats it N times per cycle:

{C4}%4 // C4 four times per cycle (= [C4 C4 C4 C4])
{bd}%8 // Eighth-note pulse

When you separate groups with commas inside {}, all voices play on the same onset grid but their content cycles at different rates. This is the core of polymetric patterns.

Without %N, N defaults to the first group’s length. These are equivalent:

{C4 D4 E4, F4 G4} // N = 3 (first group's length)
{C4 D4 E4, F4 G4}%3 // Explicitly N = 3

Both voices are wrapped as Fast(N/L, Sequence(group)):

  • Voice 1: 3 elements, factor = 3/3 = 1 → normal speed, 3 events per cycle
  • Voice 2: 2 elements, factor = 3/2 → sped up, also 3 events per cycle

Both voices produce events at the same times — they share one grid:

TimeVoice 1 (3 elements, factor 1)Voice 2 (2 elements, factor 3/2)
0C4F4
1/3D4G4
2/3E4F4 (content wraps)

Voice 1 completes its content once per cycle. Voice 2’s 2-element content repeats every 2/3 of a cycle, so it completes 1.5 times per master cycle. Over 2 cycles, Voice 1 plays its content 2 times while Voice 2 plays its content 3 times — the content realigns every 2 cycles.

An explicit %N overrides the default, setting the grid size for all voices:

{C4 D4 E4, F4 G4}%6 // Both voices produce 6 events per cycle
  • Voice 1: factor = 6/3 = 2, cycles through C-D-E twice
  • Voice 2: factor = 6/2 = 3, cycles through F-G three times

The larger N creates a denser shared grid while maintaining the same content-phasing relationship.

The {} and [,] syntaxes both layer voices, but they produce fundamentally different rhythmic structures.

  • Polymetric: different meters running simultaneously — voices share a pulse grid but their content cycles at different rates, creating content phasing
  • Polyrhythm: different subdivisions of the same time span — voices have independent onset grids, creating rhythmic conflict

Polymetric {} forces all voices onto one N-step grid. Each voice’s content is sped up by N/L so that every voice produces exactly N onsets per cycle. The “poly” effect comes from content repeating at different rates:

{C4 D4 E4, F4 G4} // Both voices: onsets at 0, 1/3, 2/3
// Voice 2's content phases against Voice 1

Parallel [,] gives each voice its own grid based on its element count. Voices can have different numbers of onsets per cycle:

[C4 D4 E4, F4 G4] // Voice 1: onsets at 0, 1/3, 2/3
// Voice 2: onsets at 0, 1/2

The comparison:

Polymetric {a b c, d e}Parallel [a b c, d e]
Voice 1 onsets0, 1/3, 2/30, 1/3, 2/3
Voice 2 onsets0, 1/3, 2/30, 1/2
GridShared (3-step)Independent
EffectContent phasingOnset conflict

The classic polymetric relationship:

{C4 E4 G4, F4 A4} // N = 3, both voices on 3-step grid
TimeVoice 1Voice 2
0C4F4
1/3E4A4
2/3G4F4

Voice 2’s content phases by one position each cycle. After 2 cycles, both voices realign:

CycleVoice 1 contentVoice 2 content
1C4 E4 G4F4 A4 F4
2C4 E4 G4A4 F4 A4

For true 3-against-2 onset polyrhythm (3 onsets vs 2 onsets), use parallel:

[C4 E4 G4, F4 A4] // Voice 1: 3 onsets, Voice 2: 2 onsets
{C4 D4 E4 F4, G4 A4 B4} // N = 4, both voices on 4-step grid
TimeVoice 1 (4 elements)Voice 2 (3 elements, factor 4/3)
0C4G4
1/4D4A4
2/4E4B4
3/4F4G4 (wraps)

Voice 2 completes its 3-element content every 3/4 of a cycle. Over 3 cycles, Voice 1 plays 3 times while Voice 2 plays 4 times — content realigns every 3 cycles.

Combine polymetric drums with a regular melodic pattern:

let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("cr78")));
let bass = AudioTrack("bass");
bass.load_instrument(SamplerMelodic(Kit("keys")));
// 4-against-3 polymetric drums
drums << {bd sd bd sd, hh hh hh};
// Steady bass line underneath
bass << [C3 _ G2 _];
PLAY;

Polymetric patterns compose with other modifiers:

// With compact notation modifiers
{bd*2 sd, hh hh hh} // Fast modifier inside polymetric
// With alternating patterns
{<C4 E4> <D4 F4> G4, A4 B4} // Alternating elements phase independently
// With weight modifiers
{C4@2 D4 E4, F4 G4}%6 // Weighted elements within polymetric grid

Rests work normally inside polymetric groups:

{_ C4 D4}%3 // Rest on beat 1

Sequential and parallel patterns can appear inside polymetric groups as single elements:

{[C4 D4] E4 F4} // Sequential [C4 D4] is one element, stretched
{<C4 E4> D4 F4} // Parallel chord is one element
{C4(3,8) D4 E4} // Euclidean inside polymetric
[{C4 D4 E4}%3 G4] // Polymetric fills its slot in a sequence
{{C4 D4}%2 E4 F4} // Inner polymetric cycles at double speed

All standard pattern methods work on polymetric patterns:

let base = {C4 D4 E4}%3;
base.fast(2) // Double the speed
base.slow(2) // Half the speed
base.transpose(7) // Up a fifth
base.reverse() // Reverse the sequence