如何解决JavaScript 音频可视化工具
我找到了这样一个音频可视化器,我有一个问题要从代码中删除此输入和此信息,以及如何从标签下载音频,如果画布标签是 useMic = "true" 它将使用麦克风.我也想把这个 Visualizer 的外观改成图片中的样子
HTML
<div id="fileWrapper" class="file_wrapper">
<div id="info"></div>
<input type="file" id="uploadedFile"></input>
</div>
<audio src="file.mp3" controls="">
<div id="visualizer_wrapper">
<canvas id='canvas' width="800" height="350" useMic="false"></canvas>
</div>
CSS
html,body {
font-family: helvetica,arial,sans-serif;
background-color: #272822;
color: #fefefe;
}
#fileWrapper {
transition: all 0.5s ease;
}
#fileWrapper:hover {
opacity: 1 !important;
}
#visualizer_wrapper {
text-align: center;
}
JavaScript
window.onload = function() {
new Visualizer().ini();
};
var Visualizer = function() {
this.file = null; //the current file
this.fileName = null; //the current file name
this.audioContext = null;
this.source = null; //the audio source
this.info = document.getElementById('info').innerHTML; //this used to upgrade the UI information
this.infoUpdateId = null; //to sotore the setTimeout ID and clear the interval
this.animationId = null;
this.status = 0; //flag for sound is playing 1 or stopped 0
this.forceStop = false;
this.allCapsReachBottom = false;
};
Visualizer.prototype = {
ini: function() {
this._prepareAPI();
this._addEventListner();
},_prepareAPI: function() {
//fix browser vendor for AudioContext and requestAnimationFrame
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;
window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame;
try {
this.audioContext = new AudioContext();
} catch (e) {
this._updateInfo('!Your browser does not support AudioContext',false);
console.log(e);
}
},_addEventListner: function() {
var that = this,audioInput = document.getElementById('uploadedFile'),dropContainer = document.getElementsByTagName("canvas")[0];
//listen the file upload
audioInput.onchange = function() {
if (that.audioContext===null) {return;};
//the if statement fixes the file selction cancle,because the onchange will trigger even the file selection been canceled
if (audioInput.files.length !== 0) {
//only process the first file
that.file = audioInput.files[0];
that.fileName = that.file.name;
if (that.status === 1) {
//the sound is still playing but we upload another file,so set the forceStop flag to true
that.forceStop = true;
};
document.getElementById('fileWrapper').style.opacity = 1;
that._updateInfo('Uploading',true);
//once the file is ready,start the visualizer
that._start();
};
};
//listen the drag & drop
dropContainer.addEventListener("dragenter",function() {
document.getElementById('fileWrapper').style.opacity = 1;
that._updateInfo('Drop it on the page',true);
},false);
dropContainer.addEventListener("dragover",function(e) {
e.stopPropagation();
e.preventDefault();
//set the drop mode
e.dataTransfer.dropEffect = 'copy';
},false);
dropContainer.addEventListener("dragleave",function() {
document.getElementById('fileWrapper').style.opacity = 0.2;
that._updateInfo(that.info,false);
},false);
dropContainer.addEventListener("drop",function(e) {
e.stopPropagation();
e.preventDefault();
if (that.audioContext===null) {return;};
document.getElementById('fileWrapper').style.opacity = 1;
that._updateInfo('Uploading',true);
//get the dropped file
that.file = e.dataTransfer.files[0];
if (that.status === 1) {
document.getElementById('fileWrapper').style.opacity = 1;
that.forceStop = true;
};
that.fileName = that.file.name;
//once the file is ready,start the visualizer
that._start();
},false);
},_start: function() {
//read and decode the file into audio array buffer
var that = this,file = this.file,fr = new FileReader();
fr.onload = function(e) {
var fileResult = e.target.result;
var audioContext = that.audioContext;
if (audioContext === null) {
return;
};
that._updateInfo('Decoding the audio',true);
audioContext.decodeAudioData(fileResult,function(buffer) {
that._updateInfo('Decode succussfully,start the visualizer',true);
that._visualize(audioContext,buffer);
},function(e) {
that._updateInfo('!Fail to decode the file',false);
console.log(e);
});
};
fr.onerror = function(e) {
that._updateInfo('!Fail to read the file',false);
console.log(e);
};
//assign the file to the reader
this._updateInfo('Starting read the file',true);
fr.readAsArrayBuffer(file);
},_visualize: function(audioContext,buffer) {
var audioBufferSouceNode = audioContext.createBufferSource(),analyser = audioContext.createAnalyser(),that = this;
//connect the source to the analyser
audioBufferSouceNode.connect(analyser);
//connect the analyser to the destination(the speaker),or we won't hear the sound
analyser.connect(audioContext.destination);
//then assign the buffer to the buffer source node
audioBufferSouceNode.buffer = buffer;
//play the source
if (!audioBufferSouceNode.start) {
audioBufferSouceNode.start = audioBufferSouceNode.noteOn //in old browsers use noteOn method
audioBufferSouceNode.stop = audioBufferSouceNode.noteOff //in old browsers use noteOff method
};
//stop the previous sound if any
if (this.animationId !== null) {
cancelAnimationFrame(this.animationId);
}
if (this.source !== null) {
this.source.stop(0);
}
audioBufferSouceNode.start(0);
this.status = 1;
this.source = audioBufferSouceNode;
audioBufferSouceNode.onended = function() {
that._audioEnd(that);
};
this._updateInfo('Playing ' + this.fileName,false);
this.info = 'Playing ' + this.fileName;
document.getElementById('fileWrapper').style.opacity = 0.2;
this._drawSpectrum(analyser);
},_drawSpectrum: function(analyser) {
var that = this,canvas = document.getElementById('canvas'),cwidth = canvas.width,cheight = canvas.height - 2,meterWidth = 10,//width of the meters in the spectrum
gap = 2,//gap between meters
capHeight = 2,capStyle = '#fff',meterNum = 255;//800 / (10 + 2),//count of the meters
capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame
ctx = canvas.getContext('2d'),gradient = ctx.createLinearGradient(0,300);
gradient.addColorStop(1,'#0f0');
gradient.addColorStop(0.5,'#ff0');
gradient.addColorStop(0,'#f00');
var drawMeter = function() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
if (that.status === 0) {
//fix when some sounds end the value still not back to zero
for (var i = array.length - 1; i >= 0; i--) {
array[i] = 0;
};
allCapsReachBottom = true;
for (var i = capYPositionArray.length - 1; i >= 0; i--) {
allCapsReachBottom = allCapsReachBottom && (capYPositionArray[i] === 0);
};
if (allCapsReachBottom) {
cancelAnimationFrame(that.animationId); //since the sound is stoped and animation finished,stop the requestAnimation to prevent potential memory leak,THIS IS VERY IMPORTANT!
return;
};
};
var step = Math.round(array.length / meterNum); //sample limited data from the total array
ctx.clearRect(0,cwidth,cheight);
for (var i = 0; i < meterNum; i++) {
var value = array[i * step];
if (capYPositionArray.length < Math.round(meterNum)) {
capYPositionArray.push(value);
};
ctx.fillStyle = capStyle;
//draw the cap,with transition effect
if (value < capYPositionArray[i]) {
ctx.fillRect(i * 12,cheight - (--capYPositionArray[i]),meterWidth,capHeight);
} else {
ctx.fillRect(i * 12,cheight - value,capHeight);
capYPositionArray[i] = value;
};
ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look
ctx.fillRect(i * 12 /*meterWidth+gap*/,cheight - value + capHeight,cheight); //the meter
}
that.animationId = requestAnimationFrame(drawMeter);
}
this.animationId = requestAnimationFrame(drawMeter);
},_audioEnd: function(instance) {
if (this.forceStop) {
this.forceStop = false;
this.status = 1;
return;
};
this.status = 0;
var text = 'HTML5 Audio API showcase | An Audio Viusalizer';
document.getElementById('fileWrapper').style.opacity = 1;
document.getElementById('info').innerHTML = text;
instance.info = text;
document.getElementById('uploadedFile').value = '';
},_updateInfo: function(text,processing) {
var infoBar = document.getElementById('info'),dots = '...',i = 0,that = this;
infoBar.innerHTML = text + dots.substring(0,i++);
if (this.infoUpdateId !== null) {
clearTimeout(this.infoUpdateId);
};
if (processing) {
//animate dots at the end of the info text
var animateDot = function() {
if (i > 3) {
i = 0
};
infoBar.innerHTML = text + dots.substring(0,i++);
that.infoUpdateId = setTimeout(animateDot,250);
}
this.infoUpdateId = setTimeout(animateDot,250);
};
}
}
Visualizer Screen #1 Visualizer Screen #2
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。