Frequently asked questions

What the tool shows, how to use it, and the library and tools behind it. Companion to the paper A Structure of Harmonic Relations.

Contents Concepts Using the tool Library & command line Figures & analysis The project

Concepts

What am I looking at? #

Every positive rational a/b is a node of the Stern–Brocot tree, rooted at 1/1. A chord or scale is a set of ratios, so it appears as a trajectory — a path through the tree. The tool plots that trajectory, names each pitch, and reports several structural properties: the harmonic frame and root, the internal consonance, the nearest 12-TET note, and the prime limit of each interval.

What does an address like RLLR mean? #

It's the path from the root to that node. Starting at 1/1, each L step descends into the left (lower-pitched) child and each R into the right (higher-pitched) child. The length of the address is the node's depth; deeper nodes are more complex ratios. For example RL is 3/2 (depth 2) and RLLL is 5/4 (depth 4).

What are the operators L, R, U, σ, rev? #

They are transformations that move a whole trajectory while preserving its internal shape. They fall into three kinds, according to what happens to the trajectory's anchor — the deepest common ancestor of its nodes.

Anchor-shifting (L, R, U) moves the trajectory as a rigid shape by moving the anchor: L to its left child, R to its right child, U to its parent. U is partial — nothing sits above the root, so it has no effect once the anchor is 1/1, which is the case for any chord containing the tonic.

Anchor-preserving (σ) swaps L↔R in every address. At the value level that is reciprocation a/b → b/a, a reflection of the whole tree about 1/1. Because the letter swap is a monoid automorphism, it carries the anchor to its mirror image and leaves the trajectory's structure intact.

Anchor-destroying (rev) reverses each address. Reversal is an anti-automorphism — it turns a common prefix into a common suffix — so it scatters the trajectory and the image generally has an unrelated anchor.

All of them preserve the depth profile. Only σ preserves consonance, and it does so exactly: since C(a,b) = C(b,a) and reciprocation reverses pitch order, every neighbour pair maps to a neighbour pair with its arguments swapped, leaving C_nn unchanged. L, R and U move the trajectory into genuinely more or less consonant regions — for 3/2 4/3 5/3 5/4, C_nn falls from 1.336 to 0.551 under L and rises to 2.068 under U.

What are the harmonic frame and root? #

The frame is the tightest pair of Farey neighbours p/q ◁ ▷ r/s (satisfying qr − ps = 1) that brackets the chord's pitch range — its natural enclosing region in harmonic space. A chord anchored at 3/2 has frame 1/1 ◁ ▷ 2/1 (the octave); one anchored at 5/3 has frame 3/2 ◁ ▷ 2/1. Chords containing 1/1 have frame 0 ◁ ▷ ∞ — they span all of frequency space. The chord root is the rational sitting at the anchor: the frame is exactly its pair of mediant-parents. It is reported as sounded when it is one of the chord's own pitches and implied when it is not — the difference between a triad with its root in the bass and a rootless voicing implying the same harmony.

What does the reference pitch (and transpose) do? #

Choosing a reference (tonic) divides every ratio so that pitch becomes 1/1 — a transposition. Unlike the operators, this is a global rescaling rather than an anchor shift: it preserves the trajectory's interval content, and therefore its consonance, while relocating its tree position, addresses, and frame. It is the one move the operator family does not contain. Because the root and frame are read from the tree position, they are reported relative to the chosen reference. The tool offers this two ways: the Reference pitch field (a global gauge, applied before any operators) and the transpose field in the transformation box (applied to the image, after the operators).

What is C_nn, and how is consonance measured? #

Each interval gets a consonance value from its reduced ratio. Pairs of notes are scored bidirectionally, and C_nn (nearest-neighbour consonance) sums the average pairwise consonance of notes that are 1, 2, and 3 steps apart in the sorted scale. Because it only couples nearby notes, it rewards scales whose adjacent and near-adjacent pitches harmonise well. Transposition never changes it; only the actual intervals do.

What do the cents colours mean? #

The cents column shows how far each just ratio sits from its nearest 12-TET semitone: ±0–10 is clean, ±10–25 is noticeable, and ±25+ is poorly represented by the equal-tempered grid. The note column adds octave markers ↑n / ↓n when a pitch is n octaves above or below the root.

Why is the syntonic comma at depth 80? #

A node's depth is the sum of its continued-fraction quotients, not the size of its numerator, so nearby-but-complex intervals sit very deep. 81/80 is at depth 80, 64/63 at 63, 531441/524288 at 111, and the schisma 32805/32768 at 894 — while 81/64 is only at depth 11. Addresses are computed exactly to whatever depth is required; the tool never truncates one silently. Long ones are shown in run-length form — 81/80 displays as RL⁷⁹, and the schisma as RL⁸⁸⁵RLRLRL³ — which is lossless, since the run lengths are exactly the continued-fraction quotients. Hover a compacted address to see it in full. The tree plot compresses the same way: levels that carry no node are collapsed into a single break row marked elided, so a deep trajectory stays readable instead of stretching over hundreds of empty rows.

Using the tool

How do I enter a sequence? #

Type space-separated ratios like 1/1 5/4 3/2, or switch to note-name mode and enter names like C E G. The tool parses either into a trajectory and updates everything live as you type.

How do the transformation controls work? #

Build an operator word (a sequence of L, R, U, σ, rev) and the tool shows the original trajectory and its transformed image side by side, both drawn on the tree. The reference and transpose fields rescale the pitches as described above. A transpose with no operator word still moves the image — you'll see its path appear on the tree.

Can I hear it? #

Yes — the play controls sound the sequence, either melodically or as a chord, using the current pitches (after any reference or transpose).

What do the Copy and "Use as input" buttons do? #

Each panel has a copyable ratio string. Copy puts it on the clipboard; Use as input loads those exact ratios back into the input box (resetting the operator word and reference), so you can take a transformed result and keep working from it.

Library & command line

Is there a programmatic version? #

Yes. consonance.js is a pure JavaScript module (no browser needed) whose analyze(sequence, options) returns the same data the tool computes — addresses, depths, frame, root, C_nn, nearest 12-TET, prime limits. See USAGE.md for the full options table and result shape.

How do I run the command-line tool? #

From the repository:

node cli.js "1/1 5/4 3/2" -t LR -r 3/2 -x 1/1

It prints the original and transformed analyses as a text table. Options: -t operator word, -r reference, -x transpose, -m mode, -k the neighbour depth used by C_nn.

What is .mjs — is it Python? #

No — it's JavaScript. The .mjs extension just marks a JavaScript module file (the "m" is for module), run with node. The repo mixes .js and .mjs only because of how Node decides module-vs-script; both are the same language. Python files would end in .py.

What do I need to run these locally? #

Just Node.js. The interactive tool (index.html) needs nothing — open it in a browser. The library, CLI, figures, and solver run with node and have no dependencies.

Figures & analysis

How do I generate the mode figures? #

The generator emits a self-contained SVG of small-multiple panels:

node figures/modes_tree.mjs [depth] [noteCount] [topN] [cols] > modes.svg

depth sets the pitch pool (depth 4 → 7 pitches, 5 → 15, 6 → 31), noteCount the scale size, topN how many panels to draw (ranked by consonance), and cols the grid width. Defaults are 4 8 12 4. Panels widen and dots shrink automatically as the tree deepens.

What is the most consonant scale? #

For an 8-note octave scale under C_nn, the optimum is 1/1 9/8 6/5 4/3 3/2 8/5 16/9 2/1 (a just natural-minor / Aeolian scale), with C_nn = 1.224. Strikingly, it converges at depth 8 — allowing pitches down to depth 9 or 10 yields nothing more consonant. The answer depends on the measure and the note count: the 7-note optimum, for instance, is 1/1 6/5 4/3 3/2 8/5 16/9 2/1.

How is the best scale computed? #

Brute force is impossible at depth — choosing 6 interior pitches from a depth-10 pool of 511 is about 1.9×10¹³ candidate scales. But C_nn only couples notes within 3 scale-steps, so the optimum can be found by a beam search over the sorted pool instead of enumeration. The solver does this:

node tools/best_scale.mjs [depth] [noteCount] [beam]

It validates exactly against brute force at shallow depths and self-checks each result with analyze().

Why does the major diatonic scale need depth 8? #

Most of the just major scale is shallow — 3/2 at depth 2, 4/3 and 5/3 at depth 3, 5/4 at depth 4 — but its major second 9/8 and major seventh 15/8 sit at depth 8. Those two tones set the requirement, which is why the diatonic never appears in shallow mode surveys: it is a genuinely deep scale.

The project

Who made this, and how do I cite it? #

The Consonance Tree is by Richard Taylor, as a companion to the paper A Structure of Harmonic Relations (pending). See the author's Google Scholar page; contact: r_taylor [at] outlook.com.

Where is the source, and what is the licence? #

The full source is on GitHub, released under the MIT License. The interactive tool is a single self-contained HTML file; the library, CLI, figures, and solver live alongside it.

How is it deployed? #

Via GitHub Pages, served straight from the repository — no build step. The tool is just index.html, so it runs anywhere a browser can open a file.