JSFiddle - React, Tailwind, and code Playground

by TobyRush

HTML

<button onclick="startOsc();">start</button>

<button onclick="moveSound(0,0,0);">play in current location</button>

<table>
<tr>
<td><button onclick="moveSound(-0.1,0,0);">move left</button></td>
<td><div id=xVal>0</div></td>
<td><button onclick="moveSound(0.1,0,0);">move right</button></td>
</tr>
<tr>
<td><button onclick="moveSound(0,-0.1,0);">move down</button></td>
<td><div id=yVal>0</div></td>
<td><button onclick="moveSound(0,0.1,0);">move up</button></td>
</tr>
<tr>
<td><button onclick="moveSound(0,0,-0.1);">move backward</button></td>
<td><div id=zVal>0</div></td>
<td><button onclick="moveSound(0,0,0.1);">move forward</button></td>
</tr>

CSS

/* press start to initialize */
/* then other buttons to play and move the sound */

JavaScript

var AudioContext = window.AudioContext || window.webkitAudioContext;
var ctx = new AudioContext();
// create a gain node to gate the sound on and off
var g = ctx.createGain();
g.connect(ctx.destination);
g.gain.setValueAtTime(0, ctx.currentTime);
// create a panner to handle sound location
var p = ctx.createPanner();
p.connect(g);
p.positionX.setValueAtTime(0, ctx.currentTime)
// create oscillator to generate the sound
var o = ctx.createOscillator();
o.type = 'sine';
o.frequency.setValueAtTime(440, ctx.currentTime);
o.connect(p);

function startOsc() {
  // start oscillator; we "play" the sound by turning volume up and down
  o.start(0);
}

function moveSound(x,y,z) {
  // move the sound by x, y, and z units
  // first, update displayed values (rounding is to avoid floating-point math)
  document.querySelector('#xVal').innerHTML = Math.round((p.positionX.value + x)*10)/10;
  document.querySelector('#yVal').innerHTML = Math.round((p.positionY.value + y)*10)/10;
  document.querySelector('#zVal').innerHTML = Math.round((p.positionZ.value + z)*10)/10;
  // now position the sound
	p.positionX.value = Math.round((p.positionX.value + x)*10)/10;
	p.positionY.value = Math.round((p.positionY.value + y)*10)/10;
	p.positionZ.value = Math.round((p.positionZ.value + z)*10)/10;
  // now turn volume up and then down 1/2 second later to make a tone
  g.gain.setTargetAtTime(1, ctx.currentTime, 0.02);
  g.gain.setTargetAtTime(0, ctx.currentTime+0.5, 0.02);
}