Three notes sound together. Move just the middle one a small step down, and the combined sound changes. The top and bottom notes have not moved. What changed inside the chord?
Major and minor triads can share a root and fifth while differing in their third. This lesson makes that relationship audible, then separates a chord’s root from its lowest sounding note. Allow about ten minutes. Use the staff-reading skills from the earlier lessons to check the chord spellings.
Listen inside the stack
Compare Major · together with Minor · together. Do not worry about attaching an emotion to either sound. First ask whether you can notice a difference. Then use the two “one by one” versions to find which pitch moved.
Preparing the visual
Change the third, keep the outer notes
C4 and G4 stay fixed. E4 becomes E♭4: root-to-third distance changes from four to three semitones; root-to-fifth stays seven.
{"id":"music-triad-quality","title":"Change the third, keep the outer notes","summary":"C4 and G4 stay fixed. E4 becomes E♭4: root-to-third distance changes from four to three semitones; root-to-fifth stays seven.","height":760,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"mf-intro\" data-i18n=\"intro\"></p>\n<div id=\"variants\" class=\"mf-options\" role=\"group\" data-i18n-label=\"choose\"></div>\n<p id=\"facts\" class=\"mf-facts\" aria-live=\"polite\"></p>\n<svg id=\"plot\" class=\"mf-plot\" viewBox=\"0 0 540 200\" aria-hidden=\"true\"></svg>\n<div class=\"mf-axis\"><span data-i18n=\"axis\"></span><span id=\"duration\"></span></div>\n<div id=\"groups\" class=\"mf-groups\"></div><p id=\"notation\" class=\"mf-notation\"></p><p class=\"mf-key\" data-i18n=\"key\"></p>\n<div id=\"envelope-panel\" hidden><svg id=\"envelope-plot\" class=\"mf-plot\" viewBox=\"0 0 540 120\" aria-hidden=\"true\"></svg><p class=\"mf-key\" data-i18n=\"envelope\"></p></div>\n<div class=\"mf-actions\"><button id=\"play\" data-i18n=\"play\"></button><button id=\"stop\" data-i18n=\"stop\" disabled></button></div>\n<div class=\"mf-progress\" aria-hidden=\"true\"><span id=\"progress\"></span></div><p id=\"status\" class=\"mf-status\" role=\"status\" data-i18n=\"idle\"></p>\n<div class=\"mf-volume\"><label for=\"volume\" data-i18n=\"volume\"></label><input id=\"volume\" type=\"range\" min=\"0\" max=\"100\" value=\"65\"></div>\n","css":"body{padding:24px}h2{font-size:22px;line-height:1.4}.mf-intro{color:var(--muted);margin:10px 0 18px;line-height:1.7}.mf-options{display:flex;gap:8px;flex-wrap:wrap}.mf-options button{flex:1 1 125px;min-height:46px;font-size:16px;white-space:normal;line-height:1.45;text-align:left;padding:10px 12px}.mf-options button[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}.mf-facts{margin:16px 0;padding:14px;border-left:3px solid var(--accent);background:var(--surface);font-size:16px;line-height:1.75;min-height:4em}.mf-plot{width:100%;height:auto;display:block;margin:12px 0 0;background:var(--surface);border:1px solid var(--rule);border-radius:8px}.mf-axis{display:flex;justify-content:space-between;font-size:13px;color:var(--muted);gap:16px;margin:6px 0}.mf-notation{font-size:15px;line-height:1.8;overflow-wrap:anywhere;margin:10px 0;color:var(--ink)}.mf-groups{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0}.mf-groups span{padding:6px 10px;border:1px solid var(--rule);border-radius:5px;font-size:15px;white-space:pre}.mf-actions{display:flex;gap:8px;margin:18px 0 12px}.mf-actions button{min-height:46px;font-size:16px;flex:1}.mf-progress{height:3px;background:var(--rule);overflow:hidden}.mf-progress span{display:block;height:100%;background:var(--accent);width:0}.mf-status{font-size:14px;line-height:1.7;margin:10px 0;min-height:3.4em;color:var(--muted)}.mf-volume{display:flex;gap:12px;align-items:center;margin-top:12px;border-top:1px solid var(--rule);padding-top:12px;font-size:14px}.mf-volume input{min-width:60px;max-width:180px}.mf-volume label{white-space:nowrap}.mf-key{color:var(--muted);font-size:14px;line-height:1.6;margin:12px 0}@media(max-width:420px){body{padding:20px 14px}h2{font-size:20px}.mf-options button{flex-basis:105px}.mf-facts{padding:12px}}\n\n.mf-groups span.is-current{border-color:var(--accent);background:var(--accent-soft);box-shadow:inset 0 -2px 0 var(--accent)}\n\n[hidden]{display:none!important}\n#blind-answers{flex-wrap:wrap}#blind-answers button{flex:1 1 100px;white-space:normal;line-height:1.5;min-width:0;padding:10px}\n","js":"const MODEL = {\"mode\":\"notes\",\"min\":60,\"max\":67,\"blind\":false,\"variants\":[{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":60,\"hz\":261.625565,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":64,\"hz\":329.627557,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":67,\"hz\":391.995436,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"C4 · E4 · G4\",\"groups\":[]},{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":60,\"hz\":261.625565,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":63,\"hz\":311.126984,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":67,\"hz\":391.995436,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"C4 · E♭4 · G4\",\"groups\":[]},{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":60,\"hz\":261.625565,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":64,\"hz\":329.627557,\"beat\":1,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":67,\"hz\":391.995436,\"beat\":2,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"C4 → E4 → G4\",\"groups\":[]},{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":60,\"hz\":261.625565,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":63,\"hz\":311.126984,\"beat\":1,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":67,\"hz\":391.995436,\"beat\":2,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"C4 → E♭4 → G4\",\"groups\":[]}]};\nconst $ = s => document.querySelector(s);\nconst variants = MODEL.variants;\nlet selected = 0;\nlet quizRevealed = !MODEL.blind;\nfunction visibility(){for(const q of ['#facts','#plot','.mf-axis','#groups','#notation','.mf-key'])$(q).toggleAttribute('hidden',!quizRevealed);document.body.dataset.quizRevealed=String(quizRevealed);}\nconst svgNS = 'http://www.w3.org/2000/svg';\nfunction node(tag, attrs = {}) { const el = document.createElementNS(svgNS, tag); for (const [k,v] of Object.entries(attrs)) el.setAttribute(k,v); return el; }\nfunction draw() {\n const v = variants[selected], plot = $('#plot'); plot.replaceChildren();\n $('#facts').textContent = viz.t('fact'+selected);\n $('#duration').textContent = viz.t('clip') + ' ' + (v.score.beats * 60 / v.score.bpm).toFixed(1) + ' ' + viz.t('seconds');\n $('#notation').textContent = v.notation;\n if (MODEL.mode === 'partials') {\n const e=v.score.events[0], p=e.partials;\n $('#envelope-panel').hidden=false;\n const envelope=$('#envelope-plot');envelope.replaceChildren();\n const attack=Math.min(e.attack,e.duration/2),points=[[12,108],[12+516*attack/e.duration,12]];\n for(let i=1;i<=60;i++){const t=attack+(e.duration-attack)*i/60,amplitude=Math.pow(.0001/(.05*e.gain),(t-attack)/(e.duration-attack));points.push([12+516*t/e.duration,108-amplitude*96]);}\n points.push([528,108]);envelope.append(node('polyline',{points:points.map(p=>p.join(',')).join(' '),fill:'none',stroke:'var(--accent)','stroke-width':3}));\n for(let i=0;i<4;i++) {\n plot.append(node('rect',{x:40+i*125,y:160-(p[i]||0)*125,width:58,height:(p[i]||0)*125,fill:'var(--accent)'}));\n const t=node('text',{x:69+i*125,y:185,'text-anchor':'middle',fill:'var(--ink)','font-size':18}); t.textContent=(i+1)+'×';plot.append(t);\n }\n } else {\n const events=v.score.events, min=MODEL.min??Math.min(...events.map(e=>e.midi)), max=MODEL.max??Math.max(...events.map(e=>e.midi));\n for(let i=0;i<=v.score.beats;i++) plot.append(node('line',{x1:12+i/v.score.beats*516,x2:12+i/v.score.beats*516,y1:16,y2:170,stroke:'var(--rule)'}));\n for(const e of events){\n const x=12+e.beat/v.score.beats*516;\n if(MODEL.mode==='pulse') plot.append(node('rect',{x,y:166-e.gain*140,width:Math.max(4,516/v.score.beats*.38),height:e.gain*140,rx:3,fill:'var(--accent)'}));\n else { const y=160-(e.midi-min)/Math.max(1,max-min)*130; plot.append(node('rect',{x,y:y-4,width:Math.max(4,Math.min(528-x,e.duration*v.score.bpm/60/v.score.beats*516)),height:8,rx:3,fill:e.layer==='bass'?'var(--ink)':'var(--accent)',opacity:e.layer==='chord'?'.45':'1'})); }\n }\n }\n if(MODEL.mode!=='partials') plot.append(node('line',{id:'cursor',x1:12,x2:12,y1:10,y2:177,stroke:'var(--ink)','stroke-width':2,visibility:'hidden'}));\n const groups=$('#groups'); groups.replaceChildren();\n for (const label of v.groups || []) {const chip=document.createElement('span');chip.textContent=label;groups.append(chip);}\n if(MODEL.blind)visibility();\n [...$('#variants').children].forEach((b,i)=>b.setAttribute('aria-pressed',String(i===selected)));\n}\nconst player=viz.audio({onState(state){document.body.dataset.audioState=state;$('#play').disabled=state!=='idle';$('#stop').disabled=state==='idle';$('#status').textContent=viz.t(state==='idle'?'idle':state==='starting'?'starting':'playing');},onTick(beat){const fraction=beat<0?0:Math.min(1,beat/variants[selected].score.beats);$('#progress').style.width=(fraction*100)+'%';const cursor=$('#cursor');if(cursor){cursor.setAttribute('x1',12+fraction*516);cursor.setAttribute('x2',12+fraction*516);cursor.setAttribute('visibility',beat<0?'hidden':'visible');}const chips=[...$('#groups').children];chips.forEach((el,i)=>el.classList.toggle('is-current',beat>=0&&i===Math.min(chips.length-1,Math.floor(fraction*chips.length))));},onError(){$('#status').textContent=viz.t('error');}});\nvariants.forEach((v,i)=>{const b=document.createElement('button');b.type='button';b.dataset.variant=i;b.textContent=viz.t('option'+i);b.onclick=()=>{player.stop();selected=i;draw();};$('#variants').append(b);});\n$('#play').onclick=()=>player.play(variants[selected].score);\n$('#stop').onclick=()=>player.stop();\n$('#volume').oninput=e=>player.setVolume(Number(e.target.value)/100);\ndocument.body.dataset.audioState='idle';draw();\n\nif(MODEL.blind){\n const panel=document.createElement('div');panel.className='mf-actions';panel.id='blind-answers';\n const result=document.createElement('p');result.className='mf-facts';result.id='blind-feedback';result.setAttribute('role','status');result.textContent=viz.t('before');\n for(const [key,correct]of [['choose_p',true],['choose_q',false],['reveal',null]]){const b=document.createElement('button');b.type='button';b.textContent=viz.t(key);b.dataset.blindAnswer=key;b.onclick=()=>{player.stop();quizRevealed=true;visibility();result.textContent=(correct===null?'':viz.t(correct?'correct':'wrong')+' ')+viz.t('comparison_correct');};panel.append(b);}\n $('#variants').after(panel,result);\n}\n","audio":true,"strings":{"axis":"Time → · higher marks = higher pitch","choose":"Choose a version","clip":"Clip:","envelope":"Amplitude over time → (1.4 seconds). The curve rises to a peak, then decays. Compare how much time the attack occupies.","error":"Audio could not start. Try again, or use the diagram and written explanation.","fact0":"C4 E4 G4: 0, 4, 7 semitones above the root.","fact1":"C4 E♭4 G4: 0, 3, 7 semitones above the root.","fact2":"Same C-major notes; onsets are spread across three beats.","fact3":"Same C-minor notes; compare only the middle pitch with the major version.","heading":"Change the third, keep the outer notes","idle":"Choose a version, then play. Editing stops playback; each clip ends automatically.","intro":"Compare C major and C minor as a stack, then listen to their notes one at a time.","key":"Read left to right. A bar shows a note’s onset and scheduled length. Simultaneous marks are stacked; use the note names and explanation as a text alternative.","option0":"Major · together","option1":"Minor · together","option2":"Major · one by one","option3":"Minor · one by one","play":"Play this version","playing":"Playing. You can stop at any time.","seconds":"seconds","starting":"Preparing audio…","stop":"Stop","volume":"Volume"}}
The major triad is C–E–G. The minor triad is C–E♭–G. In both, C to G spans seven semitones. What changes is C to the middle note: four semitones for E, three for E♭.
When we arrange a triad in consecutive thirds, we call its notes the root, third, and fifth. These are names for chord members. “Third” does not mean three semitones: a major third spans four semitones, while a minor third spans three. Introduction to triads
Triad
Root
Third
Fifth
Semitones above root
C major
C
E
G
0, 4, 7
C minor
C
E♭
G
0, 3, 7
F major
F
A
C
0, 4, 7
F minor
F
A♭
C
0, 3, 7
Try following just the top note in the first pair. It stays G. Then follow the lowest: it stays C. Finally attend to the changing middle. This is a useful listening habit: a whole sonority can change because one internal relationship changes.
The broken versions spread the same notes across three beats, producing an arpeggio, or broken chord. They alter the onset pattern, so compare major with minor within the same playback style. Comparing a simultaneous major chord with an arpeggiated minor chord would change two things at once.
The root is an identity; the bass is a position
It is tempting to call the lowest note “the root” every time. That works for root position, but a chord can put another member at the bottom.
Play the three arrangements below. Read the pitches from low to high and track the lowest one. The pitch classes remain C, E, and G throughout, although particular notes move to different octaves.
Preparing the visual
The root is not always the bass
C4 E4 G4, E4 G4 C5, and G3 C4 E4 are root position, first inversion, and second inversion of C major.
{"id":"music-triad-bass","title":"The root is not always the bass","summary":"C4 E4 G4, E4 G4 C5, and G3 C4 E4 are root position, first inversion, and second inversion of C major.","height":760,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"mf-intro\" data-i18n=\"intro\"></p>\n<div id=\"variants\" class=\"mf-options\" role=\"group\" data-i18n-label=\"choose\"></div>\n<p id=\"facts\" class=\"mf-facts\" aria-live=\"polite\"></p>\n<svg id=\"plot\" class=\"mf-plot\" viewBox=\"0 0 540 200\" aria-hidden=\"true\"></svg>\n<div class=\"mf-axis\"><span data-i18n=\"axis\"></span><span id=\"duration\"></span></div>\n<div id=\"groups\" class=\"mf-groups\"></div><p id=\"notation\" class=\"mf-notation\"></p><p class=\"mf-key\" data-i18n=\"key\"></p>\n<div id=\"envelope-panel\" hidden><svg id=\"envelope-plot\" class=\"mf-plot\" viewBox=\"0 0 540 120\" aria-hidden=\"true\"></svg><p class=\"mf-key\" data-i18n=\"envelope\"></p></div>\n<div class=\"mf-actions\"><button id=\"play\" data-i18n=\"play\"></button><button id=\"stop\" data-i18n=\"stop\" disabled></button></div>\n<div class=\"mf-progress\" aria-hidden=\"true\"><span id=\"progress\"></span></div><p id=\"status\" class=\"mf-status\" role=\"status\" data-i18n=\"idle\"></p>\n<div class=\"mf-volume\"><label for=\"volume\" data-i18n=\"volume\"></label><input id=\"volume\" type=\"range\" min=\"0\" max=\"100\" value=\"65\"></div>\n","css":"body{padding:24px}h2{font-size:22px;line-height:1.4}.mf-intro{color:var(--muted);margin:10px 0 18px;line-height:1.7}.mf-options{display:flex;gap:8px;flex-wrap:wrap}.mf-options button{flex:1 1 125px;min-height:46px;font-size:16px;white-space:normal;line-height:1.45;text-align:left;padding:10px 12px}.mf-options button[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}.mf-facts{margin:16px 0;padding:14px;border-left:3px solid var(--accent);background:var(--surface);font-size:16px;line-height:1.75;min-height:4em}.mf-plot{width:100%;height:auto;display:block;margin:12px 0 0;background:var(--surface);border:1px solid var(--rule);border-radius:8px}.mf-axis{display:flex;justify-content:space-between;font-size:13px;color:var(--muted);gap:16px;margin:6px 0}.mf-notation{font-size:15px;line-height:1.8;overflow-wrap:anywhere;margin:10px 0;color:var(--ink)}.mf-groups{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0}.mf-groups span{padding:6px 10px;border:1px solid var(--rule);border-radius:5px;font-size:15px;white-space:pre}.mf-actions{display:flex;gap:8px;margin:18px 0 12px}.mf-actions button{min-height:46px;font-size:16px;flex:1}.mf-progress{height:3px;background:var(--rule);overflow:hidden}.mf-progress span{display:block;height:100%;background:var(--accent);width:0}.mf-status{font-size:14px;line-height:1.7;margin:10px 0;min-height:3.4em;color:var(--muted)}.mf-volume{display:flex;gap:12px;align-items:center;margin-top:12px;border-top:1px solid var(--rule);padding-top:12px;font-size:14px}.mf-volume input{min-width:60px;max-width:180px}.mf-volume label{white-space:nowrap}.mf-key{color:var(--muted);font-size:14px;line-height:1.6;margin:12px 0}@media(max-width:420px){body{padding:20px 14px}h2{font-size:20px}.mf-options button{flex-basis:105px}.mf-facts{padding:12px}}\n\n.mf-groups span.is-current{border-color:var(--accent);background:var(--accent-soft);box-shadow:inset 0 -2px 0 var(--accent)}\n\n[hidden]{display:none!important}\n#blind-answers{flex-wrap:wrap}#blind-answers button{flex:1 1 100px;white-space:normal;line-height:1.5;min-width:0;padding:10px}\n","js":"const MODEL = {\"mode\":\"notes\",\"min\":55,\"max\":72,\"blind\":false,\"variants\":[{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":60,\"hz\":261.625565,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":64,\"hz\":329.627557,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":67,\"hz\":391.995436,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"C4 · E4 · G4\",\"groups\":[]},{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":64,\"hz\":329.627557,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":67,\"hz\":391.995436,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":72,\"hz\":523.251131,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"E4 · G4 · C5\",\"groups\":[]},{\"score\":{\"bpm\":90,\"beats\":4,\"events\":[{\"midi\":55,\"hz\":195.997718,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":60,\"hz\":261.625565,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"},{\"midi\":64,\"hz\":329.627557,\"beat\":0,\"duration\":1.1,\"gain\":0.75,\"wave\":\"triangle\",\"layer\":\"chord\"}]},\"notation\":\"G3 · C4 · E4\",\"groups\":[]}]};\nconst $ = s => document.querySelector(s);\nconst variants = MODEL.variants;\nlet selected = 0;\nlet quizRevealed = !MODEL.blind;\nfunction visibility(){for(const q of ['#facts','#plot','.mf-axis','#groups','#notation','.mf-key'])$(q).toggleAttribute('hidden',!quizRevealed);document.body.dataset.quizRevealed=String(quizRevealed);}\nconst svgNS = 'http://www.w3.org/2000/svg';\nfunction node(tag, attrs = {}) { const el = document.createElementNS(svgNS, tag); for (const [k,v] of Object.entries(attrs)) el.setAttribute(k,v); return el; }\nfunction draw() {\n const v = variants[selected], plot = $('#plot'); plot.replaceChildren();\n $('#facts').textContent = viz.t('fact'+selected);\n $('#duration').textContent = viz.t('clip') + ' ' + (v.score.beats * 60 / v.score.bpm).toFixed(1) + ' ' + viz.t('seconds');\n $('#notation').textContent = v.notation;\n if (MODEL.mode === 'partials') {\n const e=v.score.events[0], p=e.partials;\n $('#envelope-panel').hidden=false;\n const envelope=$('#envelope-plot');envelope.replaceChildren();\n const attack=Math.min(e.attack,e.duration/2),points=[[12,108],[12+516*attack/e.duration,12]];\n for(let i=1;i<=60;i++){const t=attack+(e.duration-attack)*i/60,amplitude=Math.pow(.0001/(.05*e.gain),(t-attack)/(e.duration-attack));points.push([12+516*t/e.duration,108-amplitude*96]);}\n points.push([528,108]);envelope.append(node('polyline',{points:points.map(p=>p.join(',')).join(' '),fill:'none',stroke:'var(--accent)','stroke-width':3}));\n for(let i=0;i<4;i++) {\n plot.append(node('rect',{x:40+i*125,y:160-(p[i]||0)*125,width:58,height:(p[i]||0)*125,fill:'var(--accent)'}));\n const t=node('text',{x:69+i*125,y:185,'text-anchor':'middle',fill:'var(--ink)','font-size':18}); t.textContent=(i+1)+'×';plot.append(t);\n }\n } else {\n const events=v.score.events, min=MODEL.min??Math.min(...events.map(e=>e.midi)), max=MODEL.max??Math.max(...events.map(e=>e.midi));\n for(let i=0;i<=v.score.beats;i++) plot.append(node('line',{x1:12+i/v.score.beats*516,x2:12+i/v.score.beats*516,y1:16,y2:170,stroke:'var(--rule)'}));\n for(const e of events){\n const x=12+e.beat/v.score.beats*516;\n if(MODEL.mode==='pulse') plot.append(node('rect',{x,y:166-e.gain*140,width:Math.max(4,516/v.score.beats*.38),height:e.gain*140,rx:3,fill:'var(--accent)'}));\n else { const y=160-(e.midi-min)/Math.max(1,max-min)*130; plot.append(node('rect',{x,y:y-4,width:Math.max(4,Math.min(528-x,e.duration*v.score.bpm/60/v.score.beats*516)),height:8,rx:3,fill:e.layer==='bass'?'var(--ink)':'var(--accent)',opacity:e.layer==='chord'?'.45':'1'})); }\n }\n }\n if(MODEL.mode!=='partials') plot.append(node('line',{id:'cursor',x1:12,x2:12,y1:10,y2:177,stroke:'var(--ink)','stroke-width':2,visibility:'hidden'}));\n const groups=$('#groups'); groups.replaceChildren();\n for (const label of v.groups || []) {const chip=document.createElement('span');chip.textContent=label;groups.append(chip);}\n if(MODEL.blind)visibility();\n [...$('#variants').children].forEach((b,i)=>b.setAttribute('aria-pressed',String(i===selected)));\n}\nconst player=viz.audio({onState(state){document.body.dataset.audioState=state;$('#play').disabled=state!=='idle';$('#stop').disabled=state==='idle';$('#status').textContent=viz.t(state==='idle'?'idle':state==='starting'?'starting':'playing');},onTick(beat){const fraction=beat<0?0:Math.min(1,beat/variants[selected].score.beats);$('#progress').style.width=(fraction*100)+'%';const cursor=$('#cursor');if(cursor){cursor.setAttribute('x1',12+fraction*516);cursor.setAttribute('x2',12+fraction*516);cursor.setAttribute('visibility',beat<0?'hidden':'visible');}const chips=[...$('#groups').children];chips.forEach((el,i)=>el.classList.toggle('is-current',beat>=0&&i===Math.min(chips.length-1,Math.floor(fraction*chips.length))));},onError(){$('#status').textContent=viz.t('error');}});\nvariants.forEach((v,i)=>{const b=document.createElement('button');b.type='button';b.dataset.variant=i;b.textContent=viz.t('option'+i);b.onclick=()=>{player.stop();selected=i;draw();};$('#variants').append(b);});\n$('#play').onclick=()=>player.play(variants[selected].score);\n$('#stop').onclick=()=>player.stop();\n$('#volume').oninput=e=>player.setVolume(Number(e.target.value)/100);\ndocument.body.dataset.audioState='idle';draw();\n\nif(MODEL.blind){\n const panel=document.createElement('div');panel.className='mf-actions';panel.id='blind-answers';\n const result=document.createElement('p');result.className='mf-facts';result.id='blind-feedback';result.setAttribute('role','status');result.textContent=viz.t('before');\n for(const [key,correct]of [['choose_p',true],['choose_q',false],['reveal',null]]){const b=document.createElement('button');b.type='button';b.textContent=viz.t(key);b.dataset.blindAnswer=key;b.onclick=()=>{player.stop();quizRevealed=true;visibility();result.textContent=(correct===null?'':viz.t(correct?'correct':'wrong')+' ')+viz.t('comparison_correct');};panel.append(b);}\n $('#variants').after(panel,result);\n}\n","audio":true,"strings":{"axis":"Time → · higher marks = higher pitch","choose":"Choose a version","clip":"Clip:","envelope":"Amplitude over time → (1.4 seconds). The curve rises to a peak, then decays. Compare how much time the attack occupies.","error":"Audio could not start. Try again, or use the diagram and written explanation.","fact0":"Root C; bass C. Root position.","fact1":"Root C; bass E. First inversion. Moving C up an octave does not change it into an E-major chord.","fact2":"Root C; bass G. Second inversion. The pitch classes remain C, E, G.","heading":"The root is not always the bass","idle":"Choose a version, then play. Editing stops playback; each clip ends automatically.","intro":"All three choices contain C, E, and G. Follow the lowest note as the spacing changes.","key":"Read left to right. A bar shows a note’s onset and scheduled length. Simultaneous marks are stacked; use the note names and explanation as a text alternative.","option0":"C in the bass","option1":"E in the bass","option2":"G in the bass","play":"Play this version","playing":"Playing. You can stop at any time.","seconds":"seconds","starting":"Preparing audio…","stop":"Stop","volume":"Volume"}}
With C at the bottom, the chord is in root position. With E at the bottom, it is in first inversion. With G at the bottom, it is in second inversion. The root is C in all three. The chord’s overall register, spacing, and bass change, so the versions need not feel identical.
This explains chord symbols such as C/E: a C-major chord with E in the bass. It does not mean “a C note followed by an E chord.” In later listening, a bass line can move smoothly through chord inversions while the chord identity stays the same.
Transfer the construction, not the mood label
Here are two new checks. First, change F–A–C from major to minor while preserving its root and fifth. Second, name the root and bass of A–C–F, arranged from low to high.
Check the notes and the inversion
For F minor, lower A to A♭. F and C stay fixed. Relative to F, the chord members now lie 0, 3, and 7 semitones above the root.
A–C–F contains the notes of F major, with A in the bass. Its root is F, and it is in first inversion. Do not classify it as A minor just because A is lowest: A minor would contain A, C, and E, not F.
Does major mean happy and minor mean sad?
Those are common associations in some listening contexts, not definitions. Tempo, rhythm, register, articulation, lyrics, and expectations all affect the result. A fast minor passage can feel energetic; a slow major passage can feel poignant. The interval pattern gives you a checkable definition even when emotional descriptions differ.
There are also diminished and augmented triads, as well as chords with more than three pitch classes. This lesson concentrates on the two constructions needed for the next experiments; it does not claim every harmony fits either one.
Build it yourself, then read the stack
Use the staff-reading skill from earlier: a triad in root position skips alternate letter positions. Choose F major, change only its quality to minor, then put its third in the bass. Predict both the written notes and the lowest note before playing.
Preparing the visual
Build and read a triad
The builder spells the root, third, and fifth on the staff. Major uses 0/4/7 semitones; minor uses 0/3/7. Inversion changes the bass while keeping chord identity.
For that sequence, F–A–C becomes F–A♭–C, then A♭–C–F. The flat belongs to A, not to the neighboring line: the third's spelling remains visible. Try D minor next and explain why its third is F rather than F♭.
When you hear a chord change in a song, ask whether the bass moved, whether an upper note moved, or whether both did. You may not be able to name every note yet. Even hearing that distinction prepares you to understand how a melody interacts with the harmony beneath it—the subject of the next lesson.