Music Theory
Scales & Modes
Section titled “Scales & Modes”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.
Building a Scale
Section titled “Building a Scale”scale(root, name) returns an array of notes spanning one octave from the given root:
| Parameter | Type | Description |
|---|---|---|
root | Note or Number | Starting pitch (e.g. C4, 60) |
name | String | Scale type (e.g. "major", "dorian") |
| Returns | Array of Notes | One 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"));Available Scales
Section titled “Available Scales”Resonon ships with 14 built-in scale types. Different scales have different lengths.
| Scale | Aliases | Notes | Intervals (semitones) | Character |
|---|---|---|---|---|
"major" | "ionian" | 7 | 0 2 4 5 7 9 11 | Bright, happy, resolved |
"minor" | "aeolian" | 7 | 0 2 3 5 7 8 10 | Dark, melancholic |
"dorian" | — | 7 | 0 2 3 5 7 9 10 | Minor with a bright 6th |
"phrygian" | — | 7 | 0 1 3 5 7 8 10 | Spanish, exotic |
"lydian" | — | 7 | 0 2 4 6 7 9 11 | Dreamy, floating |
"mixolydian" | — | 7 | 0 2 4 5 7 9 10 | Bluesy major, rock |
"locrian" | — | 7 | 0 1 3 5 6 8 10 | Unstable, diminished |
"harmonic_minor" | — | 7 | 0 2 3 5 7 8 11 | Classical tension |
"melodic_minor" | — | 7 | 0 2 3 5 7 9 11 | Jazz minor |
"pentatonic_major" | — | 5 | 0 2 4 7 9 | Open, folk |
"pentatonic_minor" | — | 5 | 0 3 5 7 10 | Blues, rock riffs |
"blues" | — | 6 | 0 3 5 6 7 10 | Gritty, soulful |
"whole_tone" | — | 6 | 0 2 4 6 8 10 | Dreamlike, ambiguous |
"chromatic" | — | 12 | 0 1 2 3 4 5 6 7 8 9 10 11 | All semitones |
Discovering Scales with scale_names()
Section titled “Discovering Scales with scale_names()”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 Degrees
Section titled “Scale Degrees”scale_degree(root, name, degree) returns a single note from the scale:
| Parameter | Type | Description |
|---|---|---|
root | Note or Number | Scale root pitch |
name | String | Scale type |
degree | Number | 1-indexed position (1 = root) |
| Returns | Note | The 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.
The Scale Type
Section titled “The Scale Type”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 namelet 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 semitoneslet neutral = Scale(#[0, 1.5, 3.5, 5, 7, 8.5, 10]);| Method | Returns | Description |
|---|---|---|
s.name() | String | Scale name ("major", "custom", etc.) |
s.intervals() | Array | Interval array in semitones |
s.period() | Number | Repeat period in semitones (12 for standard octave) |
s.length() | Number | Number of scale degrees |
s.degree(n) | Number | Interval at the nth degree (1-indexed, wraps at period) |
s.mode(n) | Scale | Rotate to the nth mode |
s.contains(n) | Boolean | Does the scale contain this interval? |
Chords
Section titled “Chords”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.
Building a Chord
Section titled “Building a Chord”chord(root, quality, inversion?) returns an array of notes:
| Parameter | Type | Description |
|---|---|---|
root | Note or Number | Starting pitch (e.g. C4, 60) |
quality | String | Chord type (e.g. "major", "min7") |
inversion | Number (optional) | Positive = raise lowest notes, negative = drop highest |
| Returns | Array of Notes | The chord tones from root position or inverted |
let c_maj = chord(C4, "major");PRINT c_maj;// [C4, E4, G4]Available Chords
Section titled “Available Chords”Resonon ships with 18 built-in chord qualities.
| Quality | Aliases | Notes | Intervals (semitones) | Character |
|---|---|---|---|---|
"major" | "maj" | 3 | 0 4 7 | Bright, stable |
"minor" | "min" | 3 | 0 3 7 | Dark, melancholic |
"dim" | — | 3 | 0 3 6 | Tense, unstable |
"aug" | — | 3 | 0 4 8 | Bright, unsettled |
"7" | "dom7" | 4 | 0 4 7 10 | Bluesy, wants to resolve |
"maj7" | — | 4 | 0 4 7 11 | Lush, jazzy |
"min7" | — | 4 | 0 3 7 10 | Smooth, mellow |
"dim7" | — | 4 | 0 3 6 9 | Dramatic, symmetrical |
"aug7" | — | 4 | 0 4 8 10 | Altered dominant |
"sus2" | — | 3 | 0 2 7 | Open, ambiguous |
"sus4" | — | 3 | 0 5 7 | Suspended, tense |
"6" | — | 4 | 0 4 7 9 | Warm, vintage |
"min6" | — | 4 | 0 3 7 9 | Bittersweet |
"9" | — | 5 | 0 4 7 10 14 | Rich dominant |
"maj9" | — | 5 | 0 4 7 11 14 | Lush, expansive |
"min9" | — | 5 | 0 3 7 10 14 | Smooth, complex |
"add9" | — | 4 | 0 4 7 14 | Bright, open |
"power" | "5" | 2 | 0 7 | Neutral, heavy |
Inline Chord Notation
Section titled “Inline Chord Notation”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"))];Inversions and Voicings
Section titled “Inversions and Voicings”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]Playing Chords
Section titled “Playing Chords”Use Stack() to play all chord notes at once. Use <> to alternate chords each cycle:
// SimultaneousStack(chord(C4, "major"));
// Progressionlet progression = <Stack(chord(C4, "major")) Stack(chord(F4, "major")) Stack(chord(G4, "major"))>;Intervals
Section titled “Intervals”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.
Transposing a Note
Section titled “Transposing a Note”interval(note, name) returns a single note offset from the given note by the named interval:
| Parameter | Type | Description |
|---|---|---|
note | Note or Number | Starting pitch (e.g. C4, 60) |
name | String | Interval name (e.g. "P5", "m3") |
| Returns | Note | A single note the given interval above the input |
PRINT interval(C4, "P5"); // G4PRINT interval(C4, "m3"); // Eb4PRINT interval(C4, "M3"); // E4PRINT interval(C4, "P8"); // C5Available Intervals
Section titled “Available Intervals”| Name | Aliases | Interval | Semitones |
|---|---|---|---|
"m2" | — | Minor 2nd | 1 |
"M2" | — | Major 2nd | 2 |
"m3" | — | Minor 3rd | 3 |
"M3" | — | Major 3rd | 4 |
"P4" | — | Perfect 4th | 5 |
"tritone" | "TT" | Tritone | 6 |
"P5" | — | Perfect 5th | 7 |
"m6" | — | Minor 6th | 8 |
"M6" | — | Major 6th | 9 |
"m7" | — | Minor 7th | 10 |
"M7" | — | Major 7th | 11 |
"P8" | "oct" | Octave | 12 |
Building Custom Scales and Chords
Section titled “Building Custom Scales and Chords”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"));See Also
Section titled “See Also”- 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