Skip to content

Music Theory

Scales are both data and composition tools. As data, scale() returns an array of notes you can inspect, index, and iterate. As a tool, scales constrain pitch choices — feed a scale into a generator or choose from it randomly and every note stays in key.

scale(root, name) returns an array of notes spanning one octave from the given root:

ParameterTypeDescription
rootNote or NumberStarting pitch (e.g. C4, 60)
nameStringScale type (e.g. "major", "dorian")
ReturnsArray of NotesOne octave of the scale from the root
let c_major = scale(C4, "major");
PRINT c_major;
// [C4, D4, E4, F4, G4, A4, B4]

Turn a scale into a playable pattern with Sequence():

let melody = Sequence(scale(C4, "major"));

Resonon ships with 14 built-in scale types. Different scales have different lengths.

ScaleAliasesNotesIntervals (semitones)Character
"major""ionian"70 2 4 5 7 9 11Bright, happy, resolved
"minor""aeolian"70 2 3 5 7 8 10Dark, melancholic
"dorian"70 2 3 5 7 9 10Minor with a bright 6th
"phrygian"70 1 3 5 7 8 10Spanish, exotic
"lydian"70 2 4 6 7 9 11Dreamy, floating
"mixolydian"70 2 4 5 7 9 10Bluesy major, rock
"locrian"70 1 3 5 6 8 10Unstable, diminished
"harmonic_minor"70 2 3 5 7 8 11Classical tension
"melodic_minor"70 2 3 5 7 9 11Jazz minor
"pentatonic_major"50 2 4 7 9Open, folk
"pentatonic_minor"50 3 5 7 10Blues, rock riffs
"blues"60 3 5 6 7 10Gritty, soulful
"whole_tone"60 2 4 6 8 10Dreamlike, ambiguous
"chromatic"120 1 2 3 4 5 6 7 8 9 10 11All semitones

scale_names() returns an array of all available scale name strings:

PRINT scale_names();
// ["major", "minor", "dorian", "phrygian", "lydian", "mixolydian",
// "locrian", "harmonic_minor", "melodic_minor", "pentatonic_major",
// "pentatonic_minor", "blues", "whole_tone", "chromatic"]

The seven diatonic modes are each available by name. Pass any root note to build the mode in that key:

let d_dorian = scale(D4, "dorian");
PRINT d_dorian;
// [D4, E4, F4, G4, A4, B4, C5]

scale_degree(root, name, degree) returns a single note from the scale:

ParameterTypeDescription
rootNote or NumberScale root pitch
nameStringScale type
degreeNumber1-indexed position (1 = root)
ReturnsNoteThe note at that degree
PRINT scale_degree(C4, "major", 1); // C4 (root)
PRINT scale_degree(C4, "major", 3); // E4 (third)
PRINT scale_degree(C4, "major", 5); // G4 (fifth)

Degrees above the scale length wrap into higher octaves.

Scale is a first-class value that represents a set of intervals. Built-in scales are available by name, and you can define custom scales from semitone arrays — including microtonal tunings with fractional semitones.

// From a built-in name
let major = Scale("major");
// From a semitone interval array (must start with 0, ascending)
let custom = Scale(#[0, 2, 4, 5, 7, 9, 11]); // same as major
// Microtonal: fractional semitones
let neutral = Scale(#[0, 1.5, 3.5, 5, 7, 8.5, 10]);
MethodReturnsDescription
s.name()StringScale name ("major", "custom", etc.)
s.intervals()ArrayInterval array in semitones
s.period()NumberRepeat period in semitones (12 for standard octave)
s.length()NumberNumber of scale degrees
s.degree(n)NumberInterval at the nth degree (1-indexed, wraps at period)
s.mode(n)ScaleRotate to the nth mode
s.contains(n)BooleanDoes the scale contain this interval?

Chords are both data and harmony tools. As data, chord() returns an array of notes you can inspect, invert, and iterate. As a tool, chords stack pitches vertically — combine them with patterns to build progressions, arpeggios, and accompaniments.

chord(root, quality, inversion?) returns an array of notes:

ParameterTypeDescription
rootNote or NumberStarting pitch (e.g. C4, 60)
qualityStringChord type (e.g. "major", "min7")
inversionNumber (optional)Positive = raise lowest notes, negative = drop highest
ReturnsArray of NotesThe chord tones from root position or inverted
let c_maj = chord(C4, "major");
PRINT c_maj;
// [C4, E4, G4]

Resonon ships with 18 built-in chord qualities.

QualityAliasesNotesIntervals (semitones)Character
"major""maj"30 4 7Bright, stable
"minor""min"30 3 7Dark, melancholic
"dim"30 3 6Tense, unstable
"aug"30 4 8Bright, unsettled
"7""dom7"40 4 7 10Bluesy, wants to resolve
"maj7"40 4 7 11Lush, jazzy
"min7"40 3 7 10Smooth, mellow
"dim7"40 3 6 9Dramatic, symmetrical
"aug7"40 4 8 10Altered dominant
"sus2"30 2 7Open, ambiguous
"sus4"30 5 7Suspended, tense
"6"40 4 7 9Warm, vintage
"min6"40 3 7 9Bittersweet
"9"50 4 7 10 14Rich dominant
"maj9"50 4 7 11 14Lush, expansive
"min9"50 3 7 10 14Smooth, complex
"add9"40 4 7 14Bright, open
"power""5"20 7Neutral, heavy

Within patterns, chords can be written directly using compact notation:

Root:Quality~Inversion
// These are equivalent:
let a = [C4:maj E4:min A3:min7];
let b = [Stack(chord(C4, "major")) Stack(chord(E4, "minor")) Stack(chord(A3, "min7"))];

The optional third argument to chord() (or ~n in inline notation) rearranges chord tones across octaves.

PRINT chord(C4, "major"); // [C4, E4, G4]
PRINT chord(C4, "major", 1); // [E4, G4, C5]
PRINT chord(C4, "major", 2); // [G4, C5, E5]
PRINT chord(C4, "major", -1); // [G3, C4, E4]

Use Stack() to play all chord notes at once. Use <> to alternate chords each cycle:

// Simultaneous
Stack(chord(C4, "major"));
// Progression
let progression = <Stack(chord(C4, "major")) Stack(chord(F4, "major")) Stack(chord(G4, "major"))>;

Intervals are both data and transformation tools. As data, interval() returns a single note at a precise distance from a given root. As a tool, intervals transpose notes by name.

interval(note, name) returns a single note offset from the given note by the named interval:

ParameterTypeDescription
noteNote or NumberStarting pitch (e.g. C4, 60)
nameStringInterval name (e.g. "P5", "m3")
ReturnsNoteA single note the given interval above the input
PRINT interval(C4, "P5"); // G4
PRINT interval(C4, "m3"); // Eb4
PRINT interval(C4, "M3"); // E4
PRINT interval(C4, "P8"); // C5
NameAliasesIntervalSemitones
"m2"Minor 2nd1
"M2"Major 2nd2
"m3"Minor 3rd3
"M3"Major 3rd4
"P4"Perfect 4th5
"tritone""TT"Tritone6
"P5"Perfect 5th7
"m6"Minor 6th8
"M6"Major 6th9
"m7"Minor 7th10
"M7"Major 7th11
"P8""oct"Octave12

Collect interval() results into an array to construct scales not in the built-in library:

// Whole-half diminished scale (8 notes)
let root = C4;
let dim_scale = [
root,
interval(root, "M2"),
interval(root, "m3"),
interval(root, "P4"),
interval(root, "tritone"),
interval(root, "m6"),
interval(root, "M6"),
interval(root, "M7")
];

Stack intervals into an array and wrap with Stack() to build chords not in the built-in library:

let root = C4;
let major_triad = Stack(
root,
interval(root, "M3"),
interval(root, "P5")
);
  • Patterns — Sequencing and pattern operations
  • Script Patterns — Class-based patterns that can index into scales and chords
  • Streams — Stateful patterns for walking through scales over time