From e7ea3a5db8de05b2bacf7cc72ad6312662f7a363 Mon Sep 17 00:00:00 2001 From: ergz Date: Mon, 9 Oct 2023 22:34:14 -0700 Subject: [PATCH] added very simple chord support --- synth.html | 61 +++++++++++++++++++++++++++----------------------- synth.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 28 deletions(-) diff --git a/synth.html b/synth.html index e591f05..b8a020a 100644 --- a/synth.html +++ b/synth.html @@ -40,6 +40,12 @@ 0 + +
+ + + 0 +
@@ -127,34 +133,33 @@ -
-
- - - - - - - - - -
+
+
+
+ Chords + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/synth.js b/synth.js index 5ce2208..aa2b1e8 100644 --- a/synth.js +++ b/synth.js @@ -19,6 +19,26 @@ function noteToHz(note) { } } +function composeChord(chord) { + switch (chord) { + case "C": { + return ["C", "G", "E"]; + } + case "D": { + return ["D", "F", "A"]; + } + case "E": { + return ["E", "G", "B"]; + } + case "B": { + return ["A", "C", "E"]; + } + default: { + return ["C", "D", "E"]; + } + } +} + class Synth { constructor() { this.audioContext = new AudioContext(); @@ -80,6 +100,14 @@ class Synth { this.stopOsc(osc); } } + + createFilter(type, freq, Q) { + const filter = this.audioContext.createBiquadFilter(); + filter.type = type; + filter.frequency.setValueAtTime(freq, this.audioContext.currentTime); + filter.Q.setValueAtTime(Q, this.audioContext.currentTime); + return filter; + } } function updateFrequency( @@ -114,6 +142,8 @@ function updateFrequency( let octaveDisplay = document.getElementById( "octavedisplay" + (voiceIndex + 1) ); + console.log(octaveDisplay); + console.log("octavedisplay" + (voiceIndex + 1)); octaveDisplay.value = 0; console.log(noteInHz); console.log("current octave for voice: " + oscContainer.currentOctave); @@ -268,4 +298,39 @@ window.onload = function () { console.log(detune); updateFrequency(event, synth, osc, 0, null, null, detune); }); + + const filterSliderVoice1 = document.getElementById("filtervoice1"); + const filtervoice1Display = document.getElementById("filtervoice1display"); + filterSliderVoice1.addEventListener("input", (event) => { + const osc = synth.oscillators[0]; + let selectedFreq = parseFloat(filterSliderVoice1.value); + const lpf = synth.createFilter("lowpass", 500, 1); + osc.osc.connect(lpf); + lpf.connect(synth.gain); + }); + + // handle chord changes + document.querySelectorAll("input[name='chordchoice']").forEach((rb) => { + rb.addEventListener("change", (event) => { + let selectedChord = document.querySelector( + "input[name='chordchoice']:checked" + ).value; + let notesForChord = composeChord(selectedChord); + console.log(notesForChord); + for (let i = 0; i < synth.oscillators.length; i++) { + if (synth.oscillators[i].isPlaying) { + console.log("playing note: " + notesForChord[i] + " on voice: " + i); + updateFrequency( + event, + synth, + synth.oscillators[i], + i, + notesForChord[i], + null, + null + ); + } + } + }); + }); };