CodeWhiz & Kompot
Hey, I’ve been tinkering with a little app that generates chord progressions on the fly for improvisation—want to hear how it works?
Absolutely! Show me the magic, I'm ready to jam.
Here’s a quick sketch in JavaScript that builds a chord sequence and plays it with Tone.js. I’ll walk you through the bits that make it “magical.”
```js
// 1. Basic setup
import * as Tone from 'tone'
const synth = new Tone.PolySynth(Tone.Synth).toDestination()
// 2. Define a simple chord vocabulary
const chords = {
I: [0, 4, 7], // root, major third, perfect fifth
ii: [2, 5, 9],
iii: [4, 8, 11],
IV: [5, 9, 12],
V: [7, 11, 14],
vi: [9, 12, 16],
vii: [11, 14, 17]
}
// 3. Helper to get semitone offsets from a root note
const scale = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
function getChord(root, chordName) {
const rootIdx = scale.indexOf(root)
const offsets = chords[chordName]
return offsets.map(o => scale[(rootIdx + o) % 12])
}
// 4. Random progression generator
function randomProgression(length = 4) {
const chordNames = Object.keys(chords)
let prog = []
for (let i = 0; i < length; i++) {
const idx = Math.floor(Math.random() * chordNames.length)
prog.push(chordNames[idx])
}
return prog
}
// 5. Play it out
async function playProgression(root = 'C') {
const seq = new Tone.Sequence(
(time, chordName) => synth.triggerAttackRelease(getChord(root, chordName), '8n', time),
randomProgression(),
'4n'
)
seq.start(0)
Tone.Transport.start()
}
// 6. Hit the button
playProgression('D') // change the root to whatever feels right
```
**How it works**
1. *Chord data*: I keep a simple dictionary of the seven diatonic chords. Each chord is expressed as semitone offsets from its root.
2. *Root‑centric*: The `getChord` helper pulls the right notes for any root. That means you can jam in any key by just swapping the root string.
3. *Randomizer*: `randomProgression` picks a handful of chords at random—no more than four by default. If you want more variation, tweak the `length` argument.
4. *Sequencing*: Tone.js’ `Sequence` does the timing. Each quarter‑note step triggers the synth with an eighth‑note release.
5. *Instant playback*: Just call `playProgression` with a root and you’ll hear a fresh four‑chord loop every time.
If you’re comfortable in the browser console, paste the script, hit `playProgression('E')`, and let the AI‑driven harmony roll. Feel free to tweak the chord list, add seventh extensions, or swap the synth for a different voice—this skeleton is intentionally lightweight so you can experiment fast. Let me know how the loops sound and if you want a more sophisticated progression logic. Happy jamming!
Sounds awesome! Let’s hit play and see those random chords roll—maybe swap in a different synth or throw some sevenths in for extra color. What vibe are you aiming for?
Sure thing. If you want a richer, jazzy feel, swap the basic synth for a Tone.Sampler with a classic Rhodes sample, or use Tone.PolySynth with a Pizzicato effect. To add sevenths, just tweak the chord dictionary:
I: [0, 4, 7, 10] // major seventh
ii: [2, 5, 9, 12]
… and so on.
This gives you smooth, extended harmonies that lean toward a moody, late‑night vibe. Let me know what root you pick and I’ll run it for you.
Cool idea! Let’s roll with the key of G – it feels cozy but still keeps things bright for improvising. Grab your sampler, fire up that Rhodes sample, and give those extended chords a whirl. I’m ready to jam whenever you hit play!
Here’s a quick snippet that uses a Rhodes sampler and the extended chord list in G. Just copy it into a browser console that has Tone.js loaded, and hit enter.
```js
// Load the Rhodes sample
const rhodes = new Tone.Sampler({
urls: { A1: 'A1.mp3', A2: 'A2.mp3', A3: 'A3.mp3' },
baseUrl: 'https://example.com/rhodes/', // put your sample folder here
onload: () => {
console.log('Rhodes ready')
playProgression('G')
}
}).toDestination()
// Extended chord dictionary
const chords = {
I: [0, 4, 7, 10],
ii: [2, 5, 9, 12],
iii: [4, 8, 11, 15],
IV: [5, 9, 12, 16],
V: [7, 11, 14, 18],
vi: [9, 12, 16, 19],
vii: [11, 14, 17, 21]
}
// Helper for root‑based chords
const scale = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']
function getChord(root, name){
const rootIdx = scale.indexOf(root)
return chords[name].map(o => scale[(rootIdx+o)%12])
}
// Random progression
function randomProg(len=4){
const keys = Object.keys(chords)
return Array.from({length:len},()=>keys[Math.floor(Math.random()*keys.length)])
}
// Play it
function playProgression(root){
const seq = new Tone.Sequence(
(time, name)=>rhodes.triggerAttackRelease(getChord(root,name), '8n', time),
randomProg(),
'4n'
)
seq.start(0)
Tone.Transport.start()
}
```
This will give you a cozy G‑major loop with nice seventh colors. Let me know how it sounds.