Day 3 · Wednesday 2 September 2026 · RTA 307

Pitch as Architecture

The Western classical answer to "what is music": pitches locked in ratios, stacked into chords, marching through time toward resolution. It is the most machine-friendly music theory ever devised — by this afternoon your code composes with it.

10:00 ugly/pretty listening 10:30 the harmonic series → 12 notes 12:00 a history in 40 minutes 14:00 the formula, in code 15:00 Tone.js + generative melody 17:00 end
By the end of today you can

10:00 — Ugly / Pretty

Homework playback, ugliest first, timestamps declared. After each pretty sketch, one question: what made it pretty? Collect the answers on the board — they will almost all turn out to be about which frequencies (today's subject) and when they change (Thursday's).

10:30 — From One String to Twelve Notes

Yesterday's spectrum demo showed that a single note is a stack of harmonics: a fundamental f, plus 2f, 3f, 4f, 5f… That physical fact is the seed of all Western harmony:

RatioIntervalWhere it comes from
2 : 1octave2nd harmonic — so alike we give both notes the same name
3 : 2perfect fifth3rd harmonic (folded down an octave)
4 : 3perfect fourthoctave minus fifth
5 : 4major third5th harmonic (folded down two octaves)
Hear the series

Each button plays a pure sine at a multiple of 110 Hz. Play 1× then 2× — hear "the same note, higher." Then hold combinations in your ear: 2× with 3× is a fifth; 4× with 5× is a major third. Harmony is audible arithmetic.

The problem: build a scale from pure ratios and the math never closes — twelve perfect fifths overshoot seven octaves by a small, audible gap (the Pythagorean comma). Every tuning system in history is a different answer to "where do we hide the gap?"

The Western answer (c. 1700s, universal by the 1800s): smear it equally. Divide the octave into twelve exactly equal steps, each multiplying frequency by 21/12 ≈ 1.0595. Now no interval except the octave is perfectly pure — the fifth lands at 1.4983 instead of 1.5 — but every key is equally usable, and any instrument can play with any other. Equal temperament is a lossy compression codec for harmony: a little purity traded for total interoperability. (Tomorrow we meet a tradition that refused the trade.)

The twelve steps

One octave from A (220 Hz) to A (440 Hz). Every neighbouring pair has the identical ratio 21/12. The white-named buttons are A major's seven; hear how the twelve-step grid contains the scale.

Scales are subsets of the twelve: major picks steps 0 2 4 5 7 9 11, natural minor picks 0 2 3 5 7 8 10. Chords are subsets of scales (1st, 3rd, 5th degrees). Cadence — tension, then home — is the syntax that makes a chord progression feel like a sentence. That is the whole apparatus: ratios → grid → subsets → syntax.

12:00 — A History in Forty Minutes

Why this tradition exports so well to machines: it spent eight centuries making itself discrete. Notation quantized pitch to symbols; equal temperament quantized tuning to one formula; the metronome quantized time. By 1983, MIDI could reduce "play middle C" to the number 60 — because the reduction had already been done on paper.

14:00 — The Formula

Everything above compresses into one line of JavaScript:

function freqOf(n) {                  // n semitones above A4
  return 440 * Math.pow(2, n / 12);   // 440 × 2^(n/12)
}

// freqOf(0)  → 440      A4
// freqOf(12) → 880      A5, one octave up
// freqOf(3)  → 523.25   C5
// freqOf(-9) → 261.63   C4, middle C

And a scale is an array of steps applied from a root:

let root  = -9;                        // middle C, as semitones from A4
let major = [0, 2, 4, 5, 7, 9, 11];    // the major-scale subset

// the C major scale, computed rather than memorized:
for (let i = 0; i < major.length; i++) {
  print( freqOf(root + major[i]) );
}

Sit with what just happened: 500 years of European music theory became two arrays and one formula. Swap the array, get minor. Add 7 to the root, you've transposed to G. This is why the machines took to it so readily.

15:00 — Tone.js and the Generative Melody

Tone.js is a framework over the browser's audio engine: ready-made synths, a musical clock, effects. To use it in the p5 editor: open the sketch's index.html (left panel ▸) and replace the p5.sound script line with:

<script src="https://unpkg.com/tone@14.7.77/build/Tone.js"></script>
One audio library per sketch

p5.sound (Days 1–2) and Tone.js (today onward) conflict if loaded together — a sketch uses one or the other, never both. From today, new sound sketches are Tone sketches: swap the script line, and unlock audio with Tone.start() instead of userStartAudio(). p5 itself stays — it still draws every pixel and reads every touch.

First sound — a synth object (Day 2: objects take messages):

let synth;

function setup() {
  createCanvas(400, 400);
  synth = new Tone.Synth().toDestination();  // build it, wire it to speakers
}

function mousePressed() {
  Tone.start();                              // audio unlock, once
  synth.triggerAttackRelease("C4", "8n");    // note name, eighth-note long
}

Tone speaks both note names ("C4") and raw hertz — so our freqOf() plugs straight in. Now the piece that composes itself:

let synth;
let major = [0, 2, 4, 5, 7, 9, 11];
let root  = -9;                                  // C major
let degree = 0;                                  // where the melody stands

function freqOf(n) { return 440 * Math.pow(2, n / 12); }

function setup() {
  createCanvas(400, 400);
  synth = new Tone.Synth().toDestination();
}

function mousePressed() {
  Tone.start();
  Tone.Transport.bpm.value = 96;                 // the clock's tempo

  new Tone.Loop((time) => {
    // random walk: melodies move mostly by step, occasionally leap
    let move = random([-1, -1, 1, 1, 1, -2, 2, 4]);
    degree = constrain(degree + move, 0, 13);    // two octaves of room

    let oct  = floor(degree / 7) * 12;           // which octave of the scale
    let step = major[degree % 7];                // which scale member
    synth.triggerAttackRelease(freqOf(root + oct + step), "8n", time);
  }, "8n").start(0);                             // run every eighth note

  Tone.Transport.start();
}

Listen first. Then experiment, one change at a time:

Assignment A1, part 1 — due Friday 10:00

A generative melody study in a Western scale. Start from today's random walk and make it yours: choose scale, tempo, rhythm, rests, register, maybe a second voice. Save the sketch with a finish timestamp. Tomorrow the same sketch learns a raga — part 2 — and Friday morning we hear both versions of each.

Day 2← A Crash Course in JavaScript