added very simple chord support
This commit is contained in:
parent
e865c0ba87
commit
e7ea3a5db8
61
synth.html
61
synth.html
|
@ -40,6 +40,12 @@
|
|||
<input id="detunevoice1" type="range" min="-5" max="5" value="0" step=".1" class="slider bg-gray-300 h-2 rounded-full outline-none"/>
|
||||
<span id="detunevoice1display" class="text-sm text-gray-700 ml-2">0</span>
|
||||
</div>
|
||||
|
||||
<div style="padding: 5px">
|
||||
<label for="filtervoice1" class="block text-sm font-medium text-gray-700 mb-1">filter voice</label>
|
||||
<input id="filtervoice1" type="range" min="700" max="1500" value="1000" step="1" class="slider bg-gray-300 h-2 rounded-full outline-none"/>
|
||||
<span id="filtervoice1display" class="text-sm text-gray-700 ml-2">0</span>
|
||||
</div>
|
||||
|
||||
<button id="activateVoice1" class="bg-green-700 hover:bg-green-600 text-white font-bold text-sm py-1 px-2 rounded">On</button>
|
||||
</div>
|
||||
|
@ -127,34 +133,33 @@
|
|||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex">
|
||||
<!-- White Keys -->
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">C</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">D</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">E</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">F</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">G</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">A</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">B</span>
|
||||
</button>
|
||||
<button class="bg-white h-24 w-12 border border-gray-400 relative">
|
||||
<span class="absolute top-2 left-1/2 transform -translate-x-1/2">C</span>
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<form style="padding: 15px">
|
||||
<fieldset>
|
||||
<legend>Chords</legend>
|
||||
<input type="radio" id="chordC" name="chordchoice" value="C" checked>
|
||||
<label for="chordC">C</label>
|
||||
|
||||
<input type="radio" id="chordD" name="chordchoice" value="D">
|
||||
<label for="chordD">D</label>
|
||||
|
||||
<input type="radio" id="chordE" name="chordchoice" value="E">
|
||||
<label for="chordE">E</label>
|
||||
|
||||
<input type="radio" id="chordF" name="chordchoice" value="F">
|
||||
<label for="chordF">F</label>
|
||||
|
||||
<input type="radio" id="chordG" name="chordchoice" value="G">
|
||||
<label for="chordG">G</label>
|
||||
|
||||
<input type="radio" id="chordA" name="chordchoice" value="A">
|
||||
<label for="chordA">A</label>
|
||||
|
||||
<input type="radio" id="chordB" name="chordchoice" value="B">
|
||||
<label for="chordB">B</label>
|
||||
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
65
synth.js
65
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
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue