Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!doctype html>
<head>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>
<title>Frequency Response | Web Audio API</title>
</head>
<body>
<div id="container">
  <div id="wrapper">
    <div id="content">
      
<div class="post">
  <h2>Frequency Response</h2>
  <p>
    <p>A sample showing the frequency response graphs of various kinds of <code>BiquadFilterNodes</code>.</p>
  </p>
  <p>
    <!-- Slider stuff -->
<script type="text/javascript" src="events.js"></script>
<p><style type="text/css"></style>
<style type="text/css">
  #slider { margin: 10px; }
</style></p>
<script src="/static/js/shared.js"></script>
<script type="text/javascript" src="frequency-response-sample.js"></script>
<div id="info">
</div>
<p><canvas id="canvasID" width="500" height="250" style="float: left;">
</canvas></p>
<p><br><br></p>
<!-- Sliders and other controls will be added here -->
<div style="display: inline-block; margin-left: 10px;" id="controls"> 
<select onchange="changeFilterType(this.value);">
    <option value="lowpass">LowPass</option>
    <option value="highpass">HighPass</option>
    <option value="bandpass">BandPass</option>
    <option value="lowshelf">LowShelf</option>
    <option value="highshelf">HighShelf</option>
    <option value="peaking">Peaking</option>
    <option value="notch">Notch</option>
    <option value="allpass">AllPass</option>
</select>
<div> <input id="frequencySlider" type="range" min="0" max="1" step="0.01" value="0" style="height: 20px; width: 200px;"> <span id="frequency-value" style="position:relative; top:-5px;">frequency = 1277.46 Hz</span> </div> <br>  <div> <input id="QSlider" type="range" min="0" max="20" step="0.01" value="0" style="height: 20px; width: 200px;"> <span id="Q-value" style="position:relative; top:-5px;">Q = 8.59 dB</span> </div> <br>  <div> <input id="gainSlider" type="range" min="0" max="5" step="0.01" value="0" style="height: 20px; width: 200px;"> <span id="gain-value" style="position:relative; top:-5px;">gain = 3.12</span> </div> <br>  </div>
  </p>
</div>
  </body>
</html>
 
body {
  background: black;
  font-family: 'Open Sans', sans-serif;
  color: #ccc;
}
#container {
  margin: 0 auto;
  width: 640px;
  background: #111;
  padding: 20px;
  border: 1px #222 solid;
}
#header h1 { margin: 0; }
#nav ul { margin: 0; }
#nav li {
  font-weight: bold;
  float: right;
  list-style: none;
  margin-left: 10px;
}
#header a, #nav a { color: rgb(28, 161, 202); text-decoration: none; }
#header a:hover, #nav a:hover { color: rgb(157, 204, 255); text-decoration: underline; }
article a { color: #FEFEF2; text-decoration: none; }
article a:hover { color: white; text-decoration: underline; }
a { color: #FEF0C9; text-decoration: none; }
a:hover { color: #FEF6E4; text-decoration: underline; }
article {
  font-weight: bold;
  margin: 20px;
  padding: 20px;
  text-align: center;
  cursor: pointer;
  color: black;
}
#content article:nth-child(6n+1) { background: #FA6B67; }
#content article:nth-child(6n+2) { background: #70CA5D; }
#content article:nth-child(6n+3) { background: #3CC9E4; }
#content article:nth-child(6n+4) { background: #EC945E; }
#content article:nth-child(6n+5) { background: #7189DE; }
#content article:nth-child(6n+6) { background: #E798DC; }
.sample .name {
  font-size: 22px;
  padding-bottom: 5px;
  color: #fee;
}
.sample .info {
  color: #B0F0F8;
}
input[type='range'] {
  -webkit-appearance: none;
  background-color: gray;
  height: 20px;
  border-radius: 15px;
  padding: 0 3px;
}
input[type='range']::-webkit-slider-thumb {
  vertical-align: middle;
  -webkit-appearance: none;
  background-color: #444;
  width: 16px;
  height: 16px;
  border-radius: 16px;
}
input[type="checkbox"] {
  display:none;
}
input[type="checkbox"] + label span {
  display:inline-block;
  width:19px;
  height:19px;
  margin:-1px 4px 0 0;
  vertical-align:middle;
  background:url(/static/images/check_radio_sheet.png) left top no-repeat;
  cursor:pointer;
}
input[type="checkbox"]:checked + label span {
  background:url(/static/images/check_radio_sheet.png) -19px top no-repeat;
}
 
// ------ shared.js
// Start off by initializing a new context.
context = new (window.AudioContext || window.webkitAudioContext)();
var frequencyRenderer;
//---------- events.js
 
  function configureSlider(name, value, min, max, handler) {
      // var controls = document.getElementById("controls");
      // 
      var divName = name + "Slider";
      var slider = document.getElementById(divName);
      slider.min = min;
      slider.max = max;
      slider.value = value;
      slider.oninput = function() { handler(0, this); };
  }
// Events
// init() once the page has finished loading.
window.onload = init;
var filter;
var filters = [];
var frequency = 2000;
var resonance = 5;
var gain = 2;
var canvas;
var canvasContext;
function frequencyHandler(event, ui) {
  var value = ui.value;
  var nyquist = context.sampleRate * 0.5;
  var noctaves = Math.log(nyquist / 10.0) / Math.LN2;
  var v2 = Math.pow(2.0, noctaves * (value - 1.0));
  var cutoff = v2*nyquist;
  
  var info = document.getElementById("frequency-value");
  info.innerHTML = "frequency = " + (Math.floor(cutoff*100)/100) + " Hz";
  filter.frequency.value = cutoff;
  frequencyRenderer.draw(filters);
}
function resonanceHandler(event, ui) {
  var value = ui.value;
  var info = document.getElementById("Q-value");
  info.innerHTML = "Q = " + (Math.floor(value*100)/100) + " dB";
  
  filter.Q.value = value; // !! Q value not same as resonance...
  frequencyRenderer.draw(filters);
}
function gainHandler(event, ui) {
  var value = ui.value;
  var info = document.getElementById("gain-value");
  info.innerHTML = "gain = " + (Math.floor(value*100)/100);
  
  filter.gain.value = value;
  frequencyRenderer.draw(filters);
}
function initAudio() {
    filter = context.createBiquadFilter();
  
    filter.Q.value = 5;
    filter.frequency.value = 2000;
    filter.gain.value = 2;
    filter.connect(context.destination);
  
  filters.push(filter);
  
  // * filters from multiband EQ
  /*
      [60, 170, 350, 1000, 3500, 10000].forEach(function(freq, i) {
          var eq = context.createBiquadFilter();
          eq.frequency.value = freq;
          eq.type = "peaking";
          eq.gain.value = -30+Math.random()*60;
          filters.push(eq);
    });
*/
}
function init() {
    initAudio();
    
    canvas = document.getElementById('canvasID');
    canvasContext = canvas.getContext('2d');
    
  
    configureSlider("frequency", 0.68, 0, 1, frequencyHandler);
    configureSlider("Q", resonance, 0, 30, resonanceHandler);
    configureSlider("gain", gain, -30, 30, gainHandler);
  
    frequencyRenderer = new FilterFrequencyResponseRenderer(canvas, context);
  
    frequencyRenderer.draw(filters);
}
function changeFilterType( value ) {
  filter.type = value;
  frequencyRenderer.draw(filters);
}
// ----------- FILTER RESPONSE RENDERER
function FilterFrequencyResponseRenderer(canvas, audioCxt) {
  var c = canvas;
  var ctx = c.getContext('2d'); 
  var width = c.width;
  var height = c.height;
  var audioContext = audioCxt;
  
  var curveColor = "rgb(224,27,106)";
  var playheadColor = "rgb(80, 100, 80)";
  var gridColor = "rgb(100,100,100)";
  var textColor = "rgb(81,127,207)";
  var dbScale = 60;
  var pixelsPerDb;
  
  var dbToY = function(db) {
    var y = (0.5 * height) - pixelsPerDb * db;
    return y;
  };
  var draw = function(filters) {
    ctx.save();
    ctx.clearRect(0, 0, width, height);
    var frequencyHz = new Float32Array(width);
    var magResponse = new Float32Array(width);
    var phaseResponse = new Float32Array(width);
    var nyquist = 0.5 * audioContext.sampleRate;
    var noctaves = 11;
    
    filters.forEach(function(filt) {
    ctx.strokeStyle = curveColor;
    ctx.lineWidth = 3;
    ctx.beginPath();
    ctx.moveTo(0, 0);
    pixelsPerDb = (0.5 * height) / dbScale;
    
    
    // First get response.
    for (var i = 0; i < width; ++i) {
        var f = i / width;
        
        // Convert to log frequency scale (octaves).
        f = nyquist * Math.pow(2.0, noctaves * (f - 1.0));
        
        frequencyHz[i] = f;
    }
       filt.getFrequencyResponse(frequencyHz, magResponse, phaseResponse);
      /*
    var magResponseOfFilter = new Float32Array(width);
    filt.getFrequencyResponse(frequencyHz, magResponseOfFilter, phaseResponse);
    // sum it to magResponse
    for(var l = 0; l < width; l++) {
      magResponse[l] = magResponseOfFilter[l];
    }
    */
    
    for (var i = 0; i < width; ++i) {
        var f = magResponse[i];
        var response = magResponse[i];
        var dbResponse = 20.0 * Math.log(response) / Math.LN10;
        
        var x = i;
        var y = dbToY(dbResponse);
        
        if ( i === 0 )
            ctx.moveTo(x,y);
        else
            ctx.lineTo(x, y);
    }
    ctx.stroke();
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = gridColor;
    
    // Draw frequency scale.
    for (var octave = 0; octave <= noctaves; octave++) {
        var x = octave * width / noctaves;
        
        ctx.strokeStyle = gridColor;
        ctx.moveTo(x, 30);
        ctx.lineTo(x, height);
        ctx.stroke();
        var f = nyquist * Math.pow(2.0, octave - noctaves);
        var value = f.toFixed(0);
        var unit = 'Hz';
        if (f > 1000) {
          unit = 'KHz';
          value = (f/1000).toFixed(1);
        }
        ctx.textAlign = "center";
        ctx.strokeStyle = textColor;
        ctx.strokeText(value + unit, x, 20);
    }
    // Draw 0dB line.
    ctx.beginPath();
    ctx.moveTo(0, 0.5 * height);
    ctx.lineTo(width, 0.5 * height);
    ctx.stroke();
    
    // Draw decibel scale.
    
    for (var db = -dbScale; db < dbScale - 10; db += 10) {
        var y = dbToY(db);
        ctx.strokeStyle = textColor;
        ctx.strokeText(db.toFixed(0) + "dB", width - 40, y);
        ctx.strokeStyle = gridColor;
        ctx.beginPath();
        ctx.moveTo(0, y);
        ctx.lineTo(width, y);
        ctx.stroke();
    }
      });
    ctx.restore();
  };
  return {
    draw: draw
  };
}
Output

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

Dismiss x
public
Bin info
micbuffapro
0viewers