Skip to content

Instantly share code, notes, and snippets.

@mathieu-fanduel
Created November 19, 2018 22:17
Show Gist options
  • Save mathieu-fanduel/0a12ff55961340e95e7df2a1e67a508e to your computer and use it in GitHub Desktop.
Save mathieu-fanduel/0a12ff55961340e95e7df2a1e67a508e to your computer and use it in GitHub Desktop.
function drawBuffer( width, height, context, data ) {
var step = Math.ceil( data.length / width );
var amp = height / 2;
context.fillStyle = "silver";
context.clearRect(0,0,width,height);
for(var i=0; i < width; i++){
var min = 1.0;
var max = -1.0;
for (j=0; j<step; j++) {
var datum = data[(i*step)+j];
if (datum < min)
min = datum;
if (datum > max)
max = datum;
}
context.fillRect(i,(1+min)*amp,1,Math.max(1,(max-min)*amp));
}
}
<!DOCTYPE html>
<!-- saved from url=(0058)https:/webaudiodemos.appspot.com/AudioRecorder/index.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Audio Recorder</title>
<script src="audiodisplay.js"></script>
<script src="recorder.js"></script>
<script src="main.js"></script>
<style>
html { overflow: hidden; }
body {
font: 14pt Arial, sans-serif;
background: lightgrey;
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
margin: 0 0;
}
canvas {
display: inline-block;
background: #202020;
width: 95%;
height: 95%;
box-shadow: 0px 0px 10px blue;
}
#controls {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
height: 20%;
width: 100%;
}
#record { height: 15vh; }
#record.recording {
background: red;
background: -webkit-radial-gradient(center, ellipse cover, #ff0000 0%,lightgrey 75%,lightgrey 100%,#7db9e8 100%);
background: -moz-radial-gradient(center, ellipse cover, #ff0000 0%,lightgrey 75%,lightgrey 100%,#7db9e8 100%);
background: radial-gradient(center, ellipse cover, #ff0000 0%,lightgrey 75%,lightgrey 100%,#7db9e8 100%);
}
#save, #save img { height: 10vh; }
#save { opacity: 0.25;}
#save[download] { opacity: 1;}
#viz {
height: 80%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
@media (orientation: landscape) {
body { flex-direction: row;}
#controls { flex-direction: column; height: 100%; width: 10%;}
#viz { height: 100%; width: 90%;}
}
#max{
font-size: 200%;
}
</style>
</head>
<body>
<div id="viz">
<canvas id="analyser" width="1024" height="500"></canvas>
</div>
<div id="max"></div>
</body></html>
/* Copyright 2013 Chris Wilson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext();
var audioInput = null,
realAudioInput = null,
inputPoint = null;
var rafID = null;
var analyserContext = null;
var canvasWidth, canvasHeight;
var recIndex = 0;
console.log("audioContext.sampleRate = "+audioContext.sampleRate);
/* TODO:
- offer mono option
- "Monitor input" switch
*/
function gotBuffers( buffers ) {
var canvas = document.getElementById( "wavedisplay" );
console.log("LOL");
drawBuffer( canvas.width, canvas.height, canvas.getContext('2d'), buffers[0] );
}
var maxMagnitureIndex = 0;
var maxMagnitureValue = 0;
setInterval(function(){
document.getElementById("max").innerHTML = "Max:<br/>"+maxMagnitureValue;
}, 1000);
function updateAnalysers(time) {
if (!analyserContext) {
var canvas = document.getElementById("analyser");
canvasWidth = canvas.width;
canvasHeight = canvas.height;
analyserContext = canvas.getContext('2d');
}
// analyzer draw code here
{
var SPACING = 1;
var BAR_WIDTH = 1;
var numBars = Math.round(canvasWidth / SPACING) * 16;
var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);
analyserNode.getByteFrequencyData(freqByteData);
analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
analyserContext.fillStyle = '#F6D565';
analyserContext.lineCap = 'round';
var multiplier = analyserNode.frequencyBinCount / numBars;
maxMagnitureIndex = 0;
maxMagnitureValue = 0;
gain = 2;
for (var i = 0; i < numBars; ++i) {
var magnitude = 0;
var offset = Math.floor( i * multiplier );
// gotta sum/average the block, or we miss narrow-bandwidth spikes
for (var j = 0; j< multiplier; j++)
magnitude += freqByteData[offset + j];
magnitude = magnitude / multiplier;
magnitude = magnitude * gain;
if(maxMagnitureValue < magnitude){
maxMagnitureIndex = i ;
maxMagnitureValue = magnitude;
}
analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
}
}
rafID = window.requestAnimationFrame( updateAnalysers );
}
function gotStream(stream) {
inputPoint = audioContext.createGain();
// Create an AudioNode from the stream.
realAudioInput = audioContext.createMediaStreamSource(stream);
audioInput = realAudioInput;
audioInput.connect(inputPoint);
analyserNode = audioContext.createAnalyser();
analyserNode.fftSize = 1024*16;
inputPoint.connect( analyserNode );
zeroGain = audioContext.createGain();
zeroGain.gain.value = 0.0;
inputPoint.connect( zeroGain );
zeroGain.connect( audioContext.destination );
updateAnalysers();
}
function initAudio() {
if (!navigator.getUserMedia)
navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
if (!navigator.cancelAnimationFrame)
navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
if (!navigator.requestAnimationFrame)
navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;
navigator.getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
}, gotStream, function(e) {
alert('Error getting audio');
console.log(e);
});
}
window.addEventListener('load', initAudio );
# install
# > gem install sinatra
# Run
# > ruby sin.rb -o 0.0.0.0
# Access
# http://127.0.0.1:4567/
# http://<IP>:4567/
require 'rubygems'
require 'sinatra'
require 'json'
get '/' do
File.read(File.join( 'index.html'))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment