Paul Adenot (@padenot), Mozilla, JSConf.Asia 2015
My simpl(e|istic) definition.
A note each beat for a quarter beat, 140 times a minute
A4 - B4 - E4 - A3 - B3
Harsh - pure - pitched - metallic - vocal - bowed
AudioContext + AudioNode + AudioParam
partial interface AudioContext {
readonly attribute AudioNode destination;
readonly attribute double currentTime;
// play audio buffers
AudioBufferSourceNode createBufferSource();
// change volume
GainNode createGain();
// play simple wave forms (sine, square, etc.)
OscillatorNode createOscillator();
// filter the sounds
BiquadFilterNode createBiquadFilter();
}
partial interface OscillatorNode {
AudioNode connect(AudioNode node);
void disconnect(AudioNode node);
readonly AudioParam frequency;
readonly AudioParam detune;
enum OscillatorType type;
void start(double startTime);
void stop(double stopTime);
}
partial interface AudioParam {
attribute float value;
void setValueAtTime(float value, double time);
void exponentialRampToValueAtTime(float value, double time);
void linearRampToValueAtTime(float value, double time);
void setTargetAtTime(float value, double time, float constant);
}
var osc = ac.createOscillator();
var gain = ac.createGain();
osc.type = "sine";
osc.frequency.value = 440.; // A4
input1.oninput = (e) => osc.frequency.value = e.target.value
input2.oninput = (e) => gain.gain.value = e.target.value
osc.connect(gain);
gain.connect(ac.destination);
osc.start();
var osc = ac.createOscillator();
osc.frequency.value = 100;
var gain = ac.createGain();
osc.connect(gain);
gain.connect(ac.destination)
osc.start();
setInterval(function() {
gain.gain.setValueAtTime(1.0, ac.currentTime);
gain.gain.setTargetAtTime(0.0, ac.currentTime, 0.3);
}, 500);
var osc = ac.createOscillator();
var gain = ac.createGain();
osc.connect(gain);
gain.connect(ac.destination)
osc.start();
setInterval(function() {
gain.gain.setValueAtTime(1.0, ac.currentTime);
gain.gain.setTargetAtTime(0.0, ac.currentTime, 0.12);
osc.frequency.setValueAtTime(100.0, ac.currentTime);
osc.frequency.setTargetAtTime(45.0, ac.currentTime, 0.07);
}, 300);
var osc1 = ac.createOscillator();
var osc2 = ac.createOscillator();
osc1.type = "sawtooth";
osc2.type = "sawtooth";
osc1.frequency.value = osc2.frequency.value = 80;
input1.oninput = (e) => osc2.detune.value = e.target.value
input2.oninput = (e) => osc1.frequency.value = osc2.frequency.value = e.target.value
osc1.connect(ac.destination);
osc2.connect(ac.destination);
osc1.start();
osc2.start();
var osc = ac.createOscillator();
var gain = ac.createGain();
osc.type = "sine";
osc.frequency.value = 440.; // A4
input1.oninput = (e) => osc.frequency.value = e.target.value
input2.oninput = (e) => gain.gain.value = e.target.value
osc.connect(gain);
gain.connect(ac.destination);
osc.start();
var osc = ac.createOscillator(); var osc2 = ac.createOscillator();
var gain = ac.createGain();
var biquad = ac.createBiquadFilter();
osc.type = "sawtooth";
osc.frequency.value = osc1.frequency.value = 110.; // A2
osc2.detune.value = 30;
biquad.type = "lowpass";
input1.oninput = (e) => biquad.frequency.value = e.target.value
input2.oninput = (e) => biquad.gain.value = e.target.value
input3.oninput = (e) => biquad.Q.value = e.target.value
option.onchange = (e) => biquad.type = e.target.value
osc.connect(gain).connect(biquad).connect(ac.destination);
osc.start(); osc2.start();
var source = ac.createBufferSource();
var buffer = ac.createBuffer(1, 1 * ac.sampleRate, ac.sampleRate);
var channel = buffer.getChannelData(0);
/* [-1, 1] */
for (var i = 0; i < channel.length; i++) {
channel[i] = Math.random() * 2 - 1;
}
source.loop = true;
source.buffer = buffer;
source.connect(ac.destination);
source.start();
fetch('clap.ogg').then((response) => {
response.arrayBuffer().then((arraybuffer) => {
ac.decodeAudioData(arraybuffer).then((buffer) => {
var source = ac.createBufferSource();
source.buffer = buffer;
source.loop = true;
source.connect(ac.destination);
source.start();
});
});
});
(More or less) the live coded program in literate style:
https://padenot.github.io/litsynth
Search for "Synths secrets" to learn more about synthesis !
{Twitter, GitHub}: @padenot
<padenot@mozilla.com>