JSFiddle - React, Tailwind, and code Playground

by davidmurdoch

HTML

<!doctype html>
<html>
  <head>
    <style> 
    input,button {
      font-size: 40px;
    }
    </style>
  </head>
  <body>
  
    <button>sin</button>
    <button>tan</button>
  
    <label for="freq"><input type="number" size="4" id="freq" value="440">Hz</label>
  
    <button>Play</button>
    <button>Pause</button>

  </body>
</html>

JavaScript

// https://wiki.mozilla.org/Audio_Data_API
// http://chromium.googlecode.com/svn/trunk/samples/audio/specification/specification.html


  var // setup ui/controls module
  controller = (function() {
    var _2pi = 2 * Math.PI
    var controls = {
      math: "",
      hz: 0, 
      freq: function() {
        controller.hz = _2pi * document.getElementById("freq").value;
      }, 
      play: function() {
        controller.freq();
        node.connect( context.destination );
      },
      pause: function() { 
        node.disconnect();
      }
    };
    
    ["sin", "tan"].forEach(function( math ) {
      controls[ math ] = function() {
        controller.math = math;
      };
    });

    return controls;
      
  })();

  // Event Setup
  
  // button events for controlling tone play
  [].forEach.call( document.querySelectorAll("button"), function( button ) {

    // Button labels are same as `controller` property methods for demo
    button.addEventListener( "click", function( event ) {
      controller[ event.target.innerHTML.toLowerCase() ]( event );
    }, false );
  });       

  // frequency events
  document.getElementById("freq").addEventListener("input", controller.freq , false);  
  

  // Audio Processing
  
  var // create a new audio api context
  context = new webkitAudioContext(),

  // create a buffer with 1 input and 1 output
  // 256, 512, 1024, 2048, 4096, 8192, 16384
  // This value controls how frequently the onaudioprocess event 
  // handler is called and how many sample-frames need to be processed each call
  node = context.createJavaScriptNode( 2048, 1, 1 );
  
  // global sine-tone value
  sine = 0, mSin = Math.sin;

  // NOTE: node does not implement addEventListener?
  // TODO: wrap in deferred? methodize?
  node.onaudioprocess = function( event ) {
    
    var audioBuffer = event.outputBuffer, 
        left = audioBuffer.getChannelData( 0 ), 
        right = audioBuffer.getChannelData( 1 ),
        len = left.length - 1,
       ...