Skip to content

Chords (31EDO)

chords31(beats, scale, progression)

Returns a ChordPattern that steps through a chord progression in 31-tone equal temperament. All intervals are calculated in 31EDO steps; chord tones are not constrained to 12EDO semitones.

chords31(beats: number, scale: ScalePattern | string, progression: string): ChordPattern

The scale argument should come from scales31().

Progression format

Space- or comma-separated chord tokens:

'Ineu IVneu V^maj Ineu'

Each token has the form:

<Roman><microShift?><quality?><slash?><octave?><ties?>

Roman numerals

I through VII, or lowercase i through vii. Case does not imply a minor quality: write min explicitly. Unambiguous mixed case such as iV and Vi is also accepted.

Microtonal accidentals (microShift)

The standard notation places modifiers after the Roman numeral, before the quality. Multiple symbols on that side accumulate. Existing prefix forms ^IVmaj, vV7, and bIIIneu remain supported for compatibility and produce the same pitches as IV^maj, Vv7, and IIIbneu. Do not mix prefix and postfix modifiers in one token; that is an error.

SymbolStep changeCentsExample
^+1+39V^maj → V raised 39 cents
^^+2+77IV^^neu
v−1−39Iv → I lowered 39 cents
vv−2−77IIIvvmaj
#+5+194IV#maj (chromatic sharp)
b−5−194IIIbneu (chromatic flat)

Symbols can be combined: Iv^ = −1 + 1 = net 0; IVb^ = −5 + 1 = −4 steps.

Chord qualities

Triads

QualityStepsSound
maj0, 10, 18Major (387 cent third)
min0, 8, 18Minor (310 cent third)
neu0, 9, 18Neutral (348 cent third) — exclusive to 31EDO
dim0, 8, 16Diminished
aug0, 10, 21Augmented

Seventh chords

QualityStepsSound
maj70, 10, 18, 28Major 7th
min70, 8, 18, 27Minor 7th
neu70, 9, 18, 27Neutral triad + neutral 7th
70, 10, 18, 27Dominant 7th (major triad + neutral 7th)

Unknown quality names (including 7neu; use neu7) are errors.

Omitting a quality gives a diatonic triad built from the current scale’s intervals.

Ties

~ appended to a chord, or a separate ~/_ token, extends it by one step (same as chords()):

chords31(4, key, 'Ineu~~ Vmaj') // Ineu for 3 beats, Vmaj for 1

Octave shift

Append < (down) or > (up) to shift all chord tones by one octave (31 steps). Repeat for multiple octaves, or use <N> with a signed integer.

SyntaxOctaves
IVmaj<−1
IVmaj>+1
IVmaj<<−2
IVmaj<-2>−2 (explicit)

Compatible with microShift — IV^^maj< raises the root 2 steps and voices the chord one octave lower.

// Neutral chord voiced an octave lower for bass texture
const prog = chords31(4, key, 'Ineu IVneu< Vmaj Ineu')

Inversions & slash chords

Identical syntax to chords():

  • Imaj/1 — first inversion (bottom tone raised one octave)
  • Vmaj/I — V major over I bass

Examples

Basic neutral progression

const key = scales31(4, 'D4:neutral')
const prog = chords31(4, key, 'Ineu IVneu Vmaj Ineu')
yield cast(pad, prog, seq(4, '{0,2,4},~,~,~'), ctx)

Microtonal root inflection

// V^maj: dominant root raised 39 cents — adds upward pull before resolution
// IV^neu: subdominant root raised 39 cents with neutral quality — dreamlike colour
const progA = chords31(8, key, 'Ineu IVneu V^maj Ineu')
const progB = chords31(8, key, 'Imaj IV^neu Vvmaj Imaj')

Exposing the neutral third via arpeggio

When cast() uses a ChordPattern, sequence degree 1 is the chord’s third. With neu quality that third is the 31EDO-exclusive 348-cent interval:

// degree 0 = root, degree 1 = 3rd (neu/maj/min), degree 2 = 5th
yield cast(harp, prog, seq(8, '0,_,_,1,_,_,2,_'), ctx)

Alternating between Ineu and Imaj progressions makes the tuning difference clearly audible through this arpeggio.

Chromatic flat to reach a distant root

// IIIbneu: degree III (step 9 in neutral) shifted −5 steps → step 4
// Neutral triad built on that lowered root
chords31(8, key, 'Imaj IVmaj IIIbneu Vmaj')

Combining with scales31()

function* song(ctx) {
const c = ctx.cycle
const mode = Math.floor(c / 8) % 2 === 0 ? 'neutral' : 'major'
const key = scales31(8, `E4:${mode}`)
const prog = mode === 'neutral'
? chords31(8, key, 'Ineu IVneu V^maj Ineu')
: chords31(8, key, 'Imaj IV^neu Vvmaj Imaj')
yield cast(modalStrings({ attack: 1.4, gain: 0.20 }), prog,
seq(8, '{0,2,4},~,~,~,~,~,~,~'), ctx)
}

See the Seventh Shore preset for a complete working example.