JSFiddle - React, Tailwind, and code Playground

by replicateur

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<h4 class="title">Simple Oscillator</h4>
<div class="commands">
  <button id="start" class="btn btn-success">
    Start
  </button>
  <button id="stop" class="btn btn-danger">
    Stop
  </button>
  <button id="add" class="btn btn-primary">
    Add oscillator
  </button>
  <div class="board">
    <input class="zoomer" type="range" min="20" max="90" value="75" orient="vertical" />
    <canvas id='scope'></canvas>
  </div>
</div>

CSS

.slider,
.slider2 {
  display: inline-block !important;
  float: left;
  width: 85% !important;
  margin-left: auto;
  margin-right: auto;
  line-height: normal;
  vertical-align: middle;
}

.input-value {
  display: inline-block !important;
  float: left;
  width: 10%;
  text-align: center;
  line-height: normal;
  vertical-align: middle;
}

.wrapper {
  padding: 1em;
}

.commands {
  text-align: center;
}

.title {
  text-align: center;
  text-transform: uppercase;
  font-weight: bold;
}

input[type=range][orient=vertical] {
  writing-mode: bt-lr;
  /* IE */
  -webkit-appearance: slider-vertical;
  /* WebKit */
  width: 8px;
  height: 175px;
  padding: 0 5px;
}

.scope {
  display: inline-block;
  float: right;
}

.zoomer {
  display: inline-block;
  float: left;
  margin-left: 1em;
}

JavaScript

var context = new(window.AudioContext || window.webkitAudioContext)();
var oscRack = {};
var graphSize = 75;
var lineWidth = 3;

var masterGain = context.createGain();
var analyser = context.createAnalyser();

var isPlaying = false;

//routing
masterGain.connect(analyser);
analyser.connect(context.destination);

//draw function for canvas
function drawWave(analyser) {
  var c = document.getElementById('scope');
  var ctx = c.getContext("2d");

  var buffer = new Float32Array(1024);
  var w = $('#scope').width();
  var h = $('#scope').height();

  ctx.strokeStyle = "darkgrey";
  ctx.setTransform(1, 0, 0, -1, 0, h / 2); // flip y-axis and translate to center
  ctx.lineWidth = lineWidth;
  var coef;

  (function loop() {
    analyser.getFloatTimeDomainData(buffer);
    coef = graphSize - Object.keys(oscRack).length + 1 * 10;
    ctx.clearRect(0, -100, w, ctx.canvas.height);

    ctx.beginPath();
    ctx.moveTo(0, buffer[0] * coef);
    for (var x = 2; x < w; x += 2) {
      ctx.lineTo(x, buffer[x] * coef);
    }
    ctx.stroke();

    if (isPlaying) requestAnimationFrame(loop)
  })();
}

function manageOscillator(command, osc_id) {
  if (command === 'create') {
    osc_id = "osc-" + Object.keys(oscRack).length + 1;
    oscRack[osc_id] = context.createOscillator();
    oscRack[osc_id].frequency.value = 300;
    oscRack[osc_id].type = 'sawtooth';
    //cRack[osc_id].connect(masterGain);
    oscRack[osc_id].start();
    isPlaying = true;
  } else if (command === 'start') {
    // Connect sound to speakers
    for (var osc in oscRack) {
      oscRack[osc].connect(masterGain);
    }
    drawWave(analyser, context);
  } else if (command === 'stop') {
    for (var osc in oscRack) {
      oscRack[osc].disconnect(masterGain);
    }
  }
  return osc_id;
}

document.addEventListener('input', changeFrequencyValue, false);

function changeFrequencyValue(event) {
  if (event !== "undefined" &&
    event.target !== "undefined" &&
    event.target.value !== "undefined") {
    if...