Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ <h1 class="sub-text"></h1>

<div class="button-container"><button id="button" class="green-button"><span class="fa fa-play"></span> Start Listen</button></div>

<script src="js/Mic.js"></script>
<script src="js/index.js"></script>

</body>
Expand Down
65 changes: 65 additions & 0 deletions js/Mic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Heavy credit to https://github.com/apm1467/html5-mic-visualizer
* Couldn't have done this without him.
*/
function Mic(){
this.DB = 0;
this.audioContent;
this.started = false;
this.hasPermission = false;
this.fftSize = 1024;
this.updateTime = 50;
this._soundAllowed = (stream) => {
this.hasPermission = true;
let audioStream = this.audioContent.createMediaStreamSource( stream );
let analyser = this.audioContent.createAnalyser();

analyser.fftSize = this.fftSize;
audioStream.connect(analyser);

let bufferLength = analyser.frequencyBinCount;
let frequencyArray = new Uint8Array(bufferLength);

let showVolume = () => {
setTimeout(showVolume, this.updateTime);
if (this.started) {
analyser.getByteFrequencyData(frequencyArray);
if(typeof this.onFrequency === "function") this.onFrequency(frequencyArray);
let total = 0
for(let i = 0; i < 255; i++) {
let x = frequencyArray[i];
total += x * x;
}
let rms = Math.sqrt(total / bufferLength);
let db = 20 * ( Math.log(rms) / Math.log(10) );
db = Math.max(db, 0); // sanity check
if(db !== this.DB){
this.DB = db;
if(typeof this.onDBChange === "function") this.onDBChange(this.DB);
}
}
}
showVolume();
}

this._soundNotAllowed = (error) => {
console.error('You must allow your microphone.');
console.log(error);
}
}
Mic.prototype.start = function(){
if (this.started) {
this.started = false;
}
else {
if (!this.hasPermission) {
this.audioContent = new AudioContext();
navigator.mediaDevices.getUserMedia({audio:true})
.then(this._soundAllowed)
.catch(this._soundNotAllowed);
}
this.started = true;
}
}
Mic.prototype.onDBChange = function(){}
Mic.prototype.onFrequency = function(){}
149 changes: 42 additions & 107 deletions js/index.js
Original file line number Diff line number Diff line change
@@ -1,112 +1,47 @@
window.onload = function () {
"use strict";
var paths = document.getElementsByTagName('path');
var visualizer = document.getElementById('visualizer');
var mask = visualizer.getElementById('mask');
var h = document.getElementsByTagName('h1')[0];
var hSub = document.getElementsByTagName('h1')[1];
var AudioContext;
var audioContent;
var start = false;
var permission = false;
var path;
var seconds = 0;
var loud_volume_threshold = 30;

var soundAllowed = function (stream) {
permission = true;
var audioStream = audioContent.createMediaStreamSource( stream );
var analyser = audioContent.createAnalyser();
var fftSize = 1024;

analyser.fftSize = fftSize;
audioStream.connect(analyser);

var bufferLength = analyser.frequencyBinCount;
var frequencyArray = new Uint8Array(bufferLength);

visualizer.setAttribute('viewBox', '0 0 255 255');

for (var i = 0 ; i < 255; i++) {
path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('stroke-dasharray', '4,1');
mask.appendChild(path);
}
var doDraw = function () {
requestAnimationFrame(doDraw);
if (start) {
analyser.getByteFrequencyData(frequencyArray);
var adjustedLength;
for (var i = 0 ; i < 255; i++) {
adjustedLength = Math.floor(frequencyArray[i]) - (Math.floor(frequencyArray[i]) % 5);
paths[i].setAttribute('d', 'M '+ (i) +',255 l 0,-' + adjustedLength);
}
}
else {
for (var i = 0 ; i < 255; i++) {
paths[i].setAttribute('d', 'M '+ (i) +',255 l 0,-' + 0);
}
}
let mic = new Mic();
var h = document.getElementsByTagName("h1")[0];
var hSub = document.getElementsByTagName("h1")[1];
let seconds = 0;
mic.onDBChange = function(DB){
h.innerHTML = Math.round(DB) + " dB";
if (DB >= 30) {
seconds += 1/mic.updateTime;
if (seconds >= 5) {
hSub.innerHTML = "You’ve been in loud environment for<span> " + Math.floor(seconds) + " </span>seconds." ;
}
var showVolume = function () {
setTimeout(showVolume, 500);
if (start) {
analyser.getByteFrequencyData(frequencyArray);
var total = 0
for(var i = 0; i < 255; i++) {
var x = frequencyArray[i];
total += x * x;
}
var rms = Math.sqrt(total / bufferLength);
var db = 20 * ( Math.log(rms) / Math.log(10) );
db = Math.max(db, 0); // sanity check
h.innerHTML = Math.floor(db) + " dB";

if (db >= loud_volume_threshold) {
seconds += 0.5;
if (seconds >= 5) {
hSub.innerHTML = "You’ve been in loud environment for<span> " + Math.floor(seconds) + " </span>seconds." ;
}
}
else {
seconds = 0;
hSub.innerHTML = "";
}
}
else {
h.innerHTML = "";
hSub.innerHTML = "";
}
}

doDraw();
showVolume();
}

var soundNotAllowed = function (error) {
h.innerHTML = "You must allow your microphone.";
console.log(error);
else {
seconds = 0;
hSub.innerHTML = "";
}
};
mic.onFrequency = function(frequencyArray){
let adjustedLength;
for(let i = 0; i < 255; i++){
adjustedLength = Math.floor(frequencyArray[i]) - (Math.floor(frequencyArray[i]) % 5);
paths[i].setAttribute("d", "M " + (i) + ",255 l 0,-" + adjustedLength);
}
};
var paths = document.getElementsByTagName("path");
var visualizer = document.getElementById("visualizer");
var mask = visualizer.getElementById("mask");
document.getElementById("button").onclick = function(){
mic.start();
if(!mic.started){


document.getElementById('button').onclick = function () {
if (start) {
start = false;
this.innerHTML = "<span class='fa fa-play'></span>Start Listen";
this.className = "green-button";
}
else {
if (!permission) {
navigator.mediaDevices.getUserMedia({audio:true})
.then(soundAllowed)
.catch(soundNotAllowed);

AudioContext = window.AudioContext || window.webkitAudioContext;
audioContent = new AudioContext();
}
start = true;
this.innerHTML = "<span class='fa fa-stop'></span>Stop Listen";
this.className = "red-button";
this.innerHTML = "<span class='fa fa-play'></span>Start Listen";
this.className = "green-button";
}
else{
h.innerHTML = "Listening";
visualizer.setAttribute("viewBox", "0 0 255 255");
let path;
for(var i = 0; i < 255; i++){
path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("stroke-dasharray", "4,1");
mask.appendChild(path);
}
};
};
this.innerHTML = "<span class='fa fa-stop'></span>Stop Listen";
this.className = "red-button";
}
};