Theremin
a wave-morphing theremin
by Wray Bowling
HTML
<svg>
<circle cx="50%" cy="50%" r="20%"/>
<circle cx="50%" cy="50%" r="40%"/>
<circle cx="50%" cy="50%" r="60%"/>
<polyline id="scope" points=""/>
<text id="frequency" x="50%" y="50%">000000000 Hz</text>
</svg>
CSS
body{
margin:0;
background-color:black;
}
html,body,svg{
width:100%;
height:100%;
}
polyline,circle{
stroke-width:1px;
stroke:lime;
fill:none;
}
text{
fill:lime;
font-family:monospace;
text-anchor:middle;
}
JavaScript
var room = new window.AudioContext() || window.webkitAudioContext() || window.webAudioContext();
// oscillators
var osc1 = room.createOscillator();
osc1.type = 'square';
var osc2 = room.createOscillator();
osc2.type = 'sawtooth';
var osc3 = room.createOscillator();
osc3.type = 'sine';
var osc4 = room.createOscillator();
osc4.type = 'triangle';
var f = 0;
// volume
var amp1 = room.createGain();
var amp2 = room.createGain();
var amp3 = room.createGain();
var amp4 = room.createGain();
var mix = room.createGain();
mix.gain.value = 0;
// wires
osc1.connect(amp1);
osc2.connect(amp2);
osc3.connect(amp3);
osc4.connect(amp4);
amp1.connect(mix);
amp2.connect(mix);
amp3.connect(mix);
amp4.connect(mix);
mix.connect(room.destination);
// mixing
function mixing(x,y){
f = Math.sqrt(Math.pow(x,2) + Math.pow(y,2))*400 + 10;
osc1.frequency.value = f/2;
osc2.frequency.value = f/3;
osc3.frequency.value = f*3;
osc4.frequency.value = f*2;
var right = Math.atan2(y,x);
var left = Math.atan2(y,-x);
var a;
// lower right half-sector
a = (right + Math.PI*0.25)/Math.PI;
a = Math.min(1.0,a);
a = Math.max(0.0,a);
a = 1 - Math.abs((a - 0.5)*2);
amp1.gain.value = a;
// top right half-sector
a = (right - Math.PI*0.25)/Math.PI;
a = Math.min(0.0,a);
a = Math.max(-1.0,a);
a = 1 - Math.abs((a + 0.5)*2);
amp2.gain.value = a;
//top left half-sector
a = (left - Math.PI*0.25)/Math.PI;
a = Math.min(0.0,a);
a = Math.max(-1.0,a);
a = 1 - Math.abs((a + 0.5)*2);
amp3.gain.value = a;
// lower right half-sector
a = (left + Math.PI*0.25)/Math.PI;
a = Math.min(1.0,a);
a = Math.max(0.0,a);
a = 1 - Math.abs((a - 0.5)*2);
amp4.gain.value = a;
}
var neverStarted = true;
function startup(){
if(neverStarted){
osc1.start(0);
osc2.start(0);
osc3.start(0);
...