Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Sine wave</title>
</head>
<body>
  
  <div class="flex">
    <span id="range-value"></span>
    <input type="range" id="freq" min=440 max=12000 value=440>
  </div>
  <div class="flex">
    <span id="volume-value"></span>
    <input type="range" id="volume" min=0 max=100 value=0>
  </div>
  
  <button>Toggle sound</button>
  
  <main><canvas></canvas></main>
</body>
</html>
 
* {
  box-sizing: border-box;
  background: white;
  font-family: sans-serif;
  font-size: 14px;
}
input[type=range] {
  width: 100%;
}
.flex {
  display: flex;
}
div {
  position: relative;
}
#range-value,
#volume-value {
  width: 80px;
  text-align: right;
}
#range-value:after {
  content: 'hz'
}
#volume-value:after {
  content: '%'
}
#volume-value:before {
  content: 'vol '
}
button {
  margin: 10px 0;
  cursor: pointer;
  border: 0;
  background: rgb(3, 169, 244);
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
}
button:hover {
  background: #1976d2;
}
canvas {
  border: 1px solid rgb(3, 169, 244);
}
 
//noprotect
// apologies for the horrible code, I was being lazy
// globalsFTW ¯\_(ツ)_/¯
let gainNode;
let context;
let audio;
let analyser;
let bufferLength;
let dataArray;
const updatePosition = (input, output) => () => {
  output.innerHTML = input.value;
  output.style.left = `calc(${(input.value - input.min) / (input.max - input.min) * 95}%)`;
}
function getAudio() {
  // create web audio api context
  context = new (window.AudioContext || window.webkitAudioContext)();
  
  // create Oscillator node
  const oscillator = context.createOscillator();
  oscillator.type = 'sine';
  oscillator.frequency.value = range.value; // value in hertz
  // oscillator.connect(audioCtx.destination);
  
  gainNode = context.createGain();
  // Connect the source to the gain node.
  oscillator.connect(gainNode);
  // Connect the gain node to the destination.
  gainNode.connect(context.destination);
  const fraction = parseInt(volume.value) / parseInt(volume.max);
  gainNode.gain.value = fraction * fraction;
  
  analyser = context.createAnalyser();
  gainNode.connect(analyser);
  
  bufferLength = analyser.frequencyBinCount;
  dataArray = new Uint8Array(bufferLength);
  analyser.fftSize = 1024;
  
  oscillator.start();
  return oscillator;
}
function draw() {
  requestAnimationFrame(draw);
  
  if (!analyser) {
    return;
  }
  
  ctx.clearRect(0, 0, WIDTH, HEIGHT);
  // analyser.getByteTimeDomainData(dataArray);
  analyser.getByteFrequencyData(dataArray);
  var barWidth = ((WIDTH) / bufferLength) * 1.5;
  var barHeight;
  var x = 0;
  
  for (var i = 0; i < bufferLength; i++) {
    barHeight = dataArray[i];
    ctx.fillStyle = 'rgb(3,169,244)';
    ctx.fillRect(x+.5,HEIGHT-barHeight/2+.5,barWidth,barHeight);
    x += barWidth + 1;
  }
  
}
const $$ = q => Array.from(document.querySelectorAll(q));
const $ = document.querySelector.bind(document);
//-----
const position = $('#range-value');
const range = $('#freq');
const updateFreq = updatePosition(freq, position);
range.oninput = () => {
  updateFreq();
  if (audio) audio.frequency.value = range.value; // value in hertz
}
updateFreq();
const vposition = $('#volume-value');
const volume = $('#volume');
const updateVolume = updatePosition(volume, vposition);
volume.oninput = () => {
  updateVolume();
  const fraction = parseInt(volume.value) / parseInt(volume.max);
  gainNode.gain.value = fraction * fraction;
}
updateVolume();
// button
const button = $('button');
let running = false;
button.onclick = function () {
  if (running) {
    audio.stop();
  } else {
    audio = getAudio();
  }
  running = !running;
}
// canvas
const canvas = $('canvas');
const ctx = canvas.getContext('2d');
const WIDTH = canvas.width = canvas.parentNode.offsetWidth;
const HEIGHT = canvas.height = canvas.parentNode.offsetHeight;
draw();
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
rempro
0viewers