Compare commits
7 Commits
1ecac8d4f6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3273b1e6db | |||
| 3d85edfc98 | |||
| 1ac8df3a3f | |||
| dc1bc9df2d | |||
| 3cb0784e39 | |||
| 37eabc79ca | |||
| 80052bb864 |
96
single-voice-synth.js
Normal file
96
single-voice-synth.js
Normal file
@@ -0,0 +1,96 @@
|
||||
class Synth {
|
||||
constructor(audioContext, waveType = "triangle", frequency = 100) {
|
||||
this.audioContext = audioContext;
|
||||
this.oscWaveType = waveType;
|
||||
this.oscFrequency = frequency;
|
||||
this.isPlaying = false;
|
||||
|
||||
// osc setup
|
||||
this.osc = this.audioContext.createOscillator();
|
||||
this.osc.type = this.oscWaveType;
|
||||
this.osc.frequency.setValueAtTime(this.oscFrequency, this.audioContext.currentTime);
|
||||
this.osc.connect(this.audioContext.destination);
|
||||
}
|
||||
|
||||
setOscWaveType(type) {
|
||||
this.oscWaveType = type;
|
||||
this.osc.type = this.oscWaveType;
|
||||
}
|
||||
|
||||
setOscFrequency(freq) {
|
||||
this.oscFrequency = freq;
|
||||
this.osc.frequency.setValueAtTime(freq, this.audioContext.currentTime);
|
||||
}
|
||||
|
||||
setOscDetune(amount) {
|
||||
this.osc.detune.setValueAtTime(amount, this.audioContext.currentTime);
|
||||
}
|
||||
|
||||
startOsc() {
|
||||
this.osc.start();
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
stopOsc() {
|
||||
// first get all the parameters for this osc
|
||||
let currentFreq = this.osc.frequency.value;
|
||||
let currentType = this.osc.type;
|
||||
|
||||
this.osc.stop();
|
||||
this.osc = this.audioContext.createOscillator();
|
||||
this.osc.type = currentType;
|
||||
this.osc.frequency.setValueAtTime(currentFreq, this.audioContext.currentTime);
|
||||
this.osc.connect(this.audioContext.destination);
|
||||
this.isPlaying = false;
|
||||
}
|
||||
|
||||
toggleOsc() {
|
||||
if (this.isPlaying === false) {
|
||||
this.startOsc();
|
||||
} else {
|
||||
this.stopOsc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let globalAudioContext = new AudioContext();
|
||||
let synth = new Synth(globalAudioContext);
|
||||
|
||||
function toggleOscillator() {
|
||||
synth.toggleOsc();
|
||||
}
|
||||
window.onload = function() {
|
||||
console.log("hello world!");
|
||||
console.log(synth);
|
||||
|
||||
|
||||
var waveTypeChoicesButtons = document.querySelectorAll("input[name='wave']");
|
||||
// waveTypeChoicesButtons.forEach((radio) => {
|
||||
// radio.addEventListener("change", (event) => {
|
||||
// if (event.target.checked) {
|
||||
// let selectedWaveType = event.target.value;
|
||||
// synth.setOscWaveType(selectedWaveType);
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
|
||||
waveTypeChoicesButtons.forEach((rb) => {
|
||||
rb.addEventListener("change", (event) => {
|
||||
let selectedWave = document.querySelector("input[name='wave']:checked").value;
|
||||
synth.setOscWaveType(selectedWave);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
console.info(waveTypeChoicesButtons);
|
||||
console.log("the selected wave:" + waveTypeChoicesButtons);
|
||||
var detune = document.getElementById("detune");
|
||||
detune.addEventListener("input", () => {
|
||||
synth.setOscDetune(parseFloat(detune.value))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
28
single-voice.html
Normal file
28
single-voice.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<!-- <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"> -->
|
||||
<title>simple-synth</title>
|
||||
</head>
|
||||
|
||||
|
||||
<body class="bg-gray-900 p-10 mb-5">
|
||||
|
||||
<script src="single-voice-synth.js"></script>
|
||||
<div class="flex justify-between"></div>
|
||||
<button onclick="toggleOscillator()">Start/Stop</button>
|
||||
<input type="range" min="-40" max="40" value="0" class="slider" id="detune">
|
||||
<form>
|
||||
<input type="radio" id="sine" name="wave" value="sine" checked>
|
||||
<label for="sine">Sine</label><br>
|
||||
<input type="radio" id="triangle" name="wave" value="triangle">
|
||||
<label for="triangle">Triangle</label><br>
|
||||
<input type="radio" id="square" name="wave" value="square">
|
||||
<label for="square">Square</label><br>
|
||||
<input type="radio" id="sawtooth" name="wave" value="sawtooth">
|
||||
<label for="sawtooth">Sawtooth</label>
|
||||
</form>
|
||||
</body>
|
||||
31
synth.js
31
synth.js
@@ -103,8 +103,8 @@ function composeChord(chord) {
|
||||
}
|
||||
|
||||
class Synth {
|
||||
constructor() {
|
||||
this.audioContext = new AudioContext();
|
||||
constructor(audioContext) {
|
||||
this.audioContext = audioContext;
|
||||
this.gain = this.audioContext.createGain();
|
||||
this.oscillators = [
|
||||
this.createOscillator("sine", 261.63, 0),
|
||||
@@ -156,22 +156,22 @@ class Synth {
|
||||
}
|
||||
}
|
||||
|
||||
// the web-audio api destroys an osc when it is stopped, therefore we must create a new one
|
||||
// in its place and set it up as we first do when creating one
|
||||
stopOsc(oscContainer) {
|
||||
if (oscContainer.isPlaying) {
|
||||
let currentFreq = oscContainer.osc.frequency.value;
|
||||
console.log("the current frequency: " + currentFreq);
|
||||
let currentFreq = oscContainer.baseFreq;
|
||||
let currentType = oscContainer.osc.type;
|
||||
console.log("the current type: " + currentType);
|
||||
let currentOctave = oscContainer.currentOctave;
|
||||
oscContainer.osc.stop();
|
||||
|
||||
let newOsc = this.createOscillator(currentType, currentFreq, currentOctave);
|
||||
oscContainer.osc = newOsc.osc;
|
||||
oscContainer.gainNode = newOsc.gainNode;
|
||||
oscContainer.filterNode = newOsc.filterNode;
|
||||
oscContainer.isPlaying = false;
|
||||
oscContainer.osc = this.audioContext.createOscillator();
|
||||
oscContainer.osc.type = currentType;
|
||||
oscContainer.osc.frequency.setValueAtTime(
|
||||
currentFreq,
|
||||
this.audioContext.currentTime
|
||||
);
|
||||
oscContainer.osc.connect(this.gain);
|
||||
console.log(oscContainer);
|
||||
oscContainer.baseFreq = currentFreq;
|
||||
oscContainer.currentOctave = currentOctave;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,8 @@ class Synth {
|
||||
}
|
||||
}
|
||||
|
||||
let synth = new Synth();
|
||||
let audioConext = new AudioContext();
|
||||
let synth = new Synth(audioConext);
|
||||
|
||||
function updateFrequency(
|
||||
event,
|
||||
@@ -280,7 +281,7 @@ window.onload = function () {
|
||||
voiceIds.forEach((id, index) => {
|
||||
document.getElementById(`${id}`).addEventListener("click", (event) => {
|
||||
console.log(`voice: ${id} start clicked`);
|
||||
synth.audioContext.resume();
|
||||
// synth.audioContext.resume();
|
||||
let osc = synth.oscillators[index];
|
||||
if (osc.isPlaying) {
|
||||
synth.stopOsc(osc);
|
||||
|
||||
Reference in New Issue
Block a user