diff --git a/wobulator/index.html b/wobulator/index.html new file mode 100644 index 0000000..13c04e3 --- /dev/null +++ b/wobulator/index.html @@ -0,0 +1,23 @@ + + +
+ + +A remake (2024) of this artcle on the wobbulator from the BBC Radiophonic workshop.
+ + + + + + + + + \ No newline at end of file diff --git a/wobulator/wobbulator.js b/wobulator/wobbulator.js new file mode 100644 index 0000000..d7e07cc --- /dev/null +++ b/wobulator/wobbulator.js @@ -0,0 +1,50 @@ +let ac = new AudioContext(); + +// There are four main audio nodes in our webaudio API patchbay +// The primary oscillator + the modulating oscillator. +// The amplitude of the modulation oscillator (its 'depth') is modified by passing the output through a GainNode. +// Another GainNode controls the main volume. +let oscillator = ac.createOscillator(); +let modulator = ac.createOscillator(); +let modulation_gain = ac.createGain(); +let main_gain = ac.createGain(); + +// Make the patches! +modulator.connect(modulation_gain); +modulation_gain.connect(oscillator.frequency); +oscillator.connect(main_gain); +main_gain.connect(ac.destination); + +// Once an OscillatorNode is stopped it cannot be restarted. +// We turn both oscillators on from the beginning, +// and achieve the on/off effect by modifying the main gain. +oscillator.start(0); +modulator.start(0); + +// inputs +let freq_input = document.querySelector("#freq"); +let modfreq_input = document.querySelector("#modfreq") +let moddepth_input = document.querySelector("#moddepth") +let vol_input = document.querySelector("#vol"); +let power_checkbox = document.querySelector("#power"); +let waveform_select = document.querySelector("#waveform"); + +oscillator.frequency.value = freq_input.value; +modulation_gain.gain.value = moddepth_input.value; +modulator.frequency.value = modfreq_input.value; +main_gain.gain.value = power_checkbox.checked ? vol_input.value : 0; + +freq_input.addEventListener("input", e => { oscillator.frequency.value = freq_input.value; }); +power_checkbox.addEventListener("change", e => { + main_gain.gain.value = power_checkbox.checked ? vol_input.value : 0; + // check if context is in suspended state (autoplay policy) + if (ac.state === "suspended") { ac.resume(); } +}); +modfreq_input.addEventListener("input", e => { modulator.frequency.value = modfreq_input.value }); +moddepth_input.addEventListener("input", e => { modulation_gain.gain.value = moddepth_input.value }); +vol_input.addEventListener("input", e => { main_gain.gain.value = power_checkbox.checked ? vol_input.value : 0 }); + +oscillator.type = waveform_select.value; +waveform_select.addEventListener("input", e => { + oscillator.type = waveform_select.value; +}); \ No newline at end of file