From ddc2818c6a096db5ff4db91f6538bf829043e563 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sat, 8 Mar 2025 12:05:53 -0500 Subject: js: add bare bones js stuff --- scale.mjs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 scale.mjs (limited to 'scale.mjs') diff --git a/scale.mjs b/scale.mjs new file mode 100644 index 0000000..61319df --- /dev/null +++ b/scale.mjs @@ -0,0 +1,75 @@ +const ringHandler = { + get(target, prop) { + return target[prop % target.length] || Reflect.get(...arguments); + } +}; + +const chromaticScale = new Proxy( + ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'], + ringHandler); + +function scaleFromIntervals(root, intervals) { + const scaleIndex = chromaticScale.indexOf(root); + if (scaleIndex < 0) { + return undefined; + } + + let scale = [root]; + let steps = 0; + let lastBase = root[0]; + for (let i = 0; i < intervals.length; i++) { + steps += intervals[i]; + const note = chromaticScale[scaleIndex + steps]; + // don't display two base notes in a row by changing + // accidentals. + if (note[0] === lastBase) { + const nextBase = chromaticScale[scaleIndex + steps + 1][0]; + scale.push(`${nextBase}b`) + lastBase = nextBase[0]; + } else { + scale.push(note); + lastBase = note[0]; + } + } + return new Proxy(scale, ringHandler); +} + +class Scale { + constructor(root, intervals) { + this.scale = scaleFromIntervals(root, intervals); + return new Proxy(this, { + get(target, prop) { + return target.scale[prop] || Reflect.get(...arguments); + } + }); + } + + get root() { + return this[0]; + } + + get third() { + return this[2]; + } + + get fifth() { + return this[4]; + } + + get length() { + console.debug(`get length`, this.scale.length); + return this.intervals.length; + } +} + +export function MajorScale(root) { + console.debug(`MajorScale(${root})`); + const intervals = [2, 2, 1, 2, 2, 2]; + return new Scale(root, intervals); +} + +export function MinorScale(root) { + console.debug(`MinorScale(${root})`); + const intervals = [2, 1, 2, 2, 1, 2]; + return new Scale(root, intervals); +} -- cgit v1.2.3