new way for moving between octaves
This commit is contained in:
parent
0e1e98b402
commit
98247eb11c
97
synth.html
97
synth.html
|
@ -11,7 +11,7 @@
|
|||
<script src="synth.js"></script>
|
||||
|
||||
<div>
|
||||
<form style="padding: 15px">
|
||||
<form style="padding: 5px">
|
||||
<legend>Voice 1</legend>
|
||||
<input type="radio" id="wave1_sinwave" name="wavechoice1" value="sine" checked>
|
||||
<label for="wave1_sinwave">Sine</label>
|
||||
|
@ -22,35 +22,28 @@
|
|||
<input type="radio" id="wave1_sawtoothwave" name="wavechoice1" value="sawtooth">
|
||||
<label for="wave1_sawtoothwave">Sawtooth</label>
|
||||
</form>
|
||||
<button id="activateVoice1" style="background-color: greenyellow;">Start</button>
|
||||
<form style="padding: 15px">
|
||||
|
||||
<div style="padding: 5px">
|
||||
<fieldset>
|
||||
<legend>Octave Selection</legend>
|
||||
<input type="radio" id="minus2" name="octavechoice1" value="-2">
|
||||
<label for="minus2">-2</label>
|
||||
|
||||
<input type="radio" id="minus1" name="octavechoice1" value="-1">
|
||||
<label for="minus1">-1</label>
|
||||
|
||||
<input type="radio" id="plus0" name="octavechoice1" value="0" checked>
|
||||
<label for="plus0">0</label>
|
||||
|
||||
<input type="radio" id="plus1" name="octavechoice1" value="1">
|
||||
<label for="plus1">+1</label>
|
||||
|
||||
<input type="radio" id="plus2" name="octavechoice1" value="2">
|
||||
<label for="plus2">+2</label>
|
||||
|
||||
<legend>Octave Selection</legend>
|
||||
<button id="octavedown1">-</button>
|
||||
<input type="text" id="octavedisplay1" value="0" readonly style="width: 2em; text-align: center;">
|
||||
<button id="octaveup1">+</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
<label for="detunevoice1">detune voice</label>
|
||||
<input id="detunevoice1" type="range" min="-3" max="3" value="0" step=".1"/>
|
||||
<span id="detunevoice1display">0</span>
|
||||
</div>
|
||||
|
||||
<div style="padding: 5px">
|
||||
<label for="detunevoice1">detune voice</label>
|
||||
<input id="detunevoice1" type="range" min="-5" max="5" value="0" step=".1"/>
|
||||
<span id="detunevoice1display">0</span>
|
||||
</div>
|
||||
|
||||
<button id="activateVoice1" style="background-color: greenyellow;">Start</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<form style="padding: 15px">
|
||||
<form style="padding: 5px">
|
||||
<legend>Voice 2</legend>
|
||||
<input type="radio" id="wave2_sinwave" name="wavechoice2" value="sine" checked>
|
||||
<label for="wave2_sinwave">Sine</label>
|
||||
|
@ -61,32 +54,21 @@
|
|||
<input type="radio" id="wave2_sawtoothwave" name="wavechoice2" value="sawtooth">
|
||||
<label for="wave2_sawtoothwave">Sawtooth</label>
|
||||
</form>
|
||||
<button id="activateVoice2" style="background-color: greenyellow;">Start</button>
|
||||
<form style="padding: 15px">
|
||||
<div style="padding: 5px">
|
||||
<fieldset>
|
||||
<legend>Octave Selection</legend>
|
||||
<input type="radio" id="minus2" name="octavechoice2" value="-2">
|
||||
<label for="minus2">-2</label>
|
||||
|
||||
<input type="radio" id="minus1" name="octavechoice2" value="-1">
|
||||
<label for="minus1">-1</label>
|
||||
|
||||
<input type="radio" id="plus0" name="octavechoice2" value="0" checked>
|
||||
<label for="plus0">0</label>
|
||||
|
||||
<input type="radio" id="plus1" name="octavechoice2" value="1">
|
||||
<label for="plus1">+1</label>
|
||||
|
||||
<input type="radio" id="plus2" name="octavechoice2" value="2">
|
||||
<label for="plus2">+2</label>
|
||||
|
||||
<legend>Octave Selection</legend>
|
||||
<button id="octavedown2">-</button>
|
||||
<input type="text" id="octavedisplay2" value="0" readonly style="width: 2em; text-align: center;">
|
||||
<button id="octaveup2">+</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="activateVoice2" style="background-color: greenyellow;">Start</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<form style="padding: 15px">
|
||||
<form style="padding: 5px">
|
||||
<legend>Voice 2</legend>
|
||||
<input type="radio" id="wave3_sinwave" name="wavechoice2" value="sine" checked>
|
||||
<label for="wave3_sinwave">Sine</label>
|
||||
|
@ -97,27 +79,16 @@
|
|||
<input type="radio" id="wave3_sawtoothwave" name="wavechoice2" value="sawtooth">
|
||||
<label for="wave3_sawtoothwave">Sawtooth</label>
|
||||
</form>
|
||||
<button id="activateVoice3" style="background-color: greenyellow;">Start</button>
|
||||
<form style="padding: 15px">
|
||||
<div style="padding: 5px">
|
||||
<fieldset>
|
||||
<legend>Octave Selection</legend>
|
||||
<input type="radio" id="minus2" name="octavechoice3" value="-2">
|
||||
<label for="minus2">-2</label>
|
||||
|
||||
<input type="radio" id="minus1" name="octavechoice3" value="-1">
|
||||
<label for="minus1">-1</label>
|
||||
|
||||
<input type="radio" id="plus0" name="octavechoice3" value="0" checked>
|
||||
<label for="plus0">0</label>
|
||||
|
||||
<input type="radio" id="plus1" name="octavechoice3" value="1">
|
||||
<label for="plus1">+1</label>
|
||||
|
||||
<input type="radio" id="plus2" name="octavechoice3" value="2">
|
||||
<label for="plus2">+2</label>
|
||||
|
||||
<legend>Octave Selection</legend>
|
||||
<button id="octavedown3">-</button>
|
||||
<input type="text" id="octavedisplay3" value="0" readonly style="width: 2em; text-align: center;">
|
||||
<button id="octaveup3">+</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="activateVoice3" style="background-color: greenyellow;">Start</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
153
synth.js
153
synth.js
|
@ -24,14 +24,14 @@ class Synth {
|
|||
this.audioContext = new AudioContext();
|
||||
this.gain = this.audioContext.createGain();
|
||||
this.oscillators = [
|
||||
this.createOscillator("sawtooth", hzoctave(440, -1)),
|
||||
this.createOscillator("sawtooth", hzoctave(435, -1)),
|
||||
this.createOscillator("sawtooth", hzoctave(440, -3)),
|
||||
this.createOscillator("sawtooth", 440, 0),
|
||||
this.createOscillator("sawtooth", 435, 0),
|
||||
this.createOscillator("sawtooth", 440, 0),
|
||||
];
|
||||
this.gain.connect(this.audioContext.destination);
|
||||
}
|
||||
|
||||
createOscillator(type = "sine", freq = 440) {
|
||||
createOscillator(type = "sine", freq = 440, startOctave) {
|
||||
const osc = this.audioContext.createOscillator();
|
||||
osc.type = type;
|
||||
osc.frequency.setValueAtTime(freq, this.audioContext.currentTime);
|
||||
|
@ -40,7 +40,12 @@ class Synth {
|
|||
osc.connect(this.gain);
|
||||
|
||||
// wrap around the container and add to array
|
||||
const oscContainer = { osc, isPlaying: false, baseFreq: freq };
|
||||
const oscContainer = {
|
||||
osc,
|
||||
isPlaying: false,
|
||||
baseFreq: freq,
|
||||
currentOctave: startOctave,
|
||||
};
|
||||
return oscContainer;
|
||||
}
|
||||
|
||||
|
@ -77,37 +82,68 @@ class Synth {
|
|||
}
|
||||
}
|
||||
|
||||
function hzoctave(freq, octave) {
|
||||
return freq * 2 ** octave;
|
||||
function updateFrequency(
|
||||
event,
|
||||
synth,
|
||||
oscContainer,
|
||||
octaveShift,
|
||||
detuneAmount
|
||||
) {
|
||||
let baseFreq = oscContainer.baseFreq;
|
||||
let currentFreq = baseFreq;
|
||||
if (octaveShift) {
|
||||
if (octaveShift === "up") {
|
||||
currentFreq = baseFreq * 2;
|
||||
oscContainer.baseFreq = currentFreq;
|
||||
} else {
|
||||
currentFreq = baseFreq / 2;
|
||||
oscContainer.baseFreq = currentFreq;
|
||||
}
|
||||
}
|
||||
|
||||
if (detuneAmount) {
|
||||
currentFreq = currentFreq + detuneAmount;
|
||||
}
|
||||
|
||||
console.log(currentFreq);
|
||||
|
||||
oscContainer.osc.frequency.setValueAtTime(
|
||||
currentFreq,
|
||||
synth.audioContext.currentTime
|
||||
);
|
||||
}
|
||||
|
||||
function setupOctaveControls(voiceIndex, synth) {
|
||||
// Get the display element for the current voice
|
||||
let octaveDisplay = document.getElementById(
|
||||
"octavedisplay" + (voiceIndex + 1)
|
||||
);
|
||||
|
||||
// Set up event listener for the octave down button for the current voice
|
||||
document
|
||||
.getElementById("octavedown" + (voiceIndex + 1))
|
||||
.addEventListener("click", (event) => {
|
||||
const osc = synth.oscillators[voiceIndex];
|
||||
osc.currentOctave--;
|
||||
octaveDisplay.value = osc.currentOctave;
|
||||
updateFrequency(event, synth, osc, "down", voiceIndex);
|
||||
});
|
||||
|
||||
// Set up event listener for the octave up button for the current voice
|
||||
document
|
||||
.getElementById("octaveup" + (voiceIndex + 1))
|
||||
.addEventListener("click", (event) => {
|
||||
const osc = synth.oscillators[voiceIndex];
|
||||
osc.currentOctave++;
|
||||
octaveDisplay.value = osc.currentOctave;
|
||||
updateFrequency(event, synth, osc, "up", voiceIndex);
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
let synth = new Synth();
|
||||
// start button
|
||||
|
||||
function updateFrequency(event, oscContainer, octaveSelected, detuneAmount) {
|
||||
let baseFreq = oscContainer.baseFreq;
|
||||
let currentFreq = baseFreq;
|
||||
if (octaveSelected) {
|
||||
console.log("baseFreq: " + baseFreq);
|
||||
console.log("octaveSelected: " + octaveSelected);
|
||||
|
||||
currentFreq = hzoctave(baseFreq, parseFloat(octaveSelected));
|
||||
oscContainer.baseFreq = currentFreq;
|
||||
}
|
||||
|
||||
if (detuneAmount) {
|
||||
currentFreq = baseFreq + detuneAmount;
|
||||
}
|
||||
|
||||
console.log(currentFreq);
|
||||
|
||||
oscContainer.osc.frequency.setValueAtTime(
|
||||
currentFreq,
|
||||
synth.audioContext.currentTime
|
||||
);
|
||||
}
|
||||
|
||||
document
|
||||
.getElementById("activateVoice1")
|
||||
.addEventListener("click", (event) => {
|
||||
|
@ -159,57 +195,10 @@ window.onload = function () {
|
|||
}
|
||||
});
|
||||
|
||||
// update the waveforms
|
||||
// document.querySelectorAll("input[name='wavechoice1']").forEach((radioButton) => {
|
||||
// radioButton.addEventListener("change", (event) => {
|
||||
|
||||
// updateFrequency(event, synth.oscillators[0], null, null, noteSelected)
|
||||
// })
|
||||
// })
|
||||
|
||||
document
|
||||
.querySelectorAll("input[name='notechoice']")
|
||||
.forEach((radioButton) => {
|
||||
console.log("note changed");
|
||||
radioButton.addEventListener("change", updateFrequency, null, null);
|
||||
});
|
||||
|
||||
document
|
||||
.querySelectorAll("input[name='octavechoice1']")
|
||||
.forEach((radioButton) => {
|
||||
console.log("octave changed");
|
||||
radioButton.addEventListener("change", (event) => {
|
||||
let octaveSelected = document.querySelector(
|
||||
"input[name='octavechoice1']:checked"
|
||||
).value;
|
||||
updateFrequency(event, synth.oscillators[0], octaveSelected, 0);
|
||||
});
|
||||
});
|
||||
|
||||
document
|
||||
.querySelectorAll("input[name='octavechoice2']")
|
||||
.forEach((radioButton) => {
|
||||
console.log("octave changed");
|
||||
radioButton.addEventListener("change", (event) => {
|
||||
let octaveSelected = document.querySelector(
|
||||
"input[name='octavechoice2']:checked"
|
||||
).value;
|
||||
updateFrequency(event, synth.oscillators[1], octaveSelected, 0);
|
||||
});
|
||||
});
|
||||
|
||||
document
|
||||
.querySelectorAll("input[name='octavechoice3']")
|
||||
.forEach((radioButton) => {
|
||||
console.log("octave changed");
|
||||
radioButton.addEventListener("change", (event) => {
|
||||
let octaveSelected = document.querySelector(
|
||||
"input[name='octavechoice3']:checked"
|
||||
).value;
|
||||
updateFrequency(event, synth.oscillators[2], octaveSelected, 0);
|
||||
});
|
||||
});
|
||||
|
||||
// Loop through each voice and set up its octave control buttons
|
||||
for (let i = 0; i < synth.oscillators.length; i++) {
|
||||
setupOctaveControls(i, synth); // Call setupOctaveControls for each voice
|
||||
}
|
||||
// detune
|
||||
const detuneSliderVoice1 = document.getElementById("detunevoice1");
|
||||
const detunevoice1Display = document.getElementById("detunevoice1display");
|
||||
|
@ -217,6 +206,6 @@ window.onload = function () {
|
|||
let osc = synth.oscillators[0];
|
||||
let detune = parseFloat(detuneSliderVoice1.value);
|
||||
console.log(detune);
|
||||
updateFrequency(event, osc, null, detune);
|
||||
updateFrequency(event, synth, osc, null, detune);
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue