JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://mohayonao.github.io/stereo-panner-node/build/stereo-panner-node.js"></script>
<script src="https://mohayonao.github.io/stereo-analyser-node/build/stereo-analyser-node.js"></script>
<button id="play">play</button>
<canvas id="canvas"></canvas>
CSS
#canvas {
display: block;
margin: 10px;
width: 360px;
height: 240px;
background: #999;
}
JavaScript
StereoPannerNode.polyfill();
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext();
var analyser = new StereoAnalyserNode(audioContext);
var timerId = 0;
function loop() {
var destination = analyser;
var playbackTime = audioContext.currentTime;
var duration = tdur(20, sample([
1, 1, 2, 2, 2, 4, 4, 8,
])) * dotn(sample([ 0, 0, 1, 2 ]));
var notes = Array.from({ length: 4 }, function() {
return {
frequency: mtof(sample([
48,
60, 64, 65, 69,
72, 74, 77, 79,
])),
rate: rand(6),
offset: rand2(0.9),
};
});
notes.duration = duration;
chord(destination, playbackTime, notes);
timerId = setTimeout(loop, duration * 1000);
}
function chord(destination, playbackTime, notes) {
var duration = notes.duration;
var t0 = playbackTime;
var t1 = t0 + duration;
var t2 = t1 + duration * 0.5;
var audioContext = destination.context;
var gain = audioContext.createGain();
notes.forEach(function(note) {
var oscillator = audioContext.createOscillator();
var panner = audioContext.createStereoPanner();
oscillator.frequency.value = note.frequency;
oscillator.start(t0);
oscillator.stop(t2);
oscillator.connect(panner);
for (var tx = t0; tx < t2; tx += 0.01) {
var panValue = sample([ -1, +1 ]) * note.offset + rand2(0.1);
panner.pan.setTargetAtTime(panValue, tx, 0.0005);
tx += rand(0.2);
}
panner.connect(gain);
});
gain.gain.setValueAtTime(0.15, t0);
gain.gain.linearRampToValueAtTime(0.10, t1);
gain.gain.linearRampToValueAtTime(0.00, t2);
gain.connect(destination);
}
function mtof(midi) {
return 440 * Math.pow(2, (midi - 69) / 12);
}
function tdur(tempo, length) {
return (60 / tempo) * (4 / length);
}
function dotn(n) {
return 2 - Math.pow(2, -n);
}
function rand(value) {
return Math.random() * value;
}
function rand2(value) {
return (Math.random() * 2 - 1) *...