Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <meta name="description" content="HTML5 Audio Spectrum Visualizer">
- <title>HTML5 Audio API showcase | Audio visualizer</title>
- <style type="text/css">
- html, body {
- margin: 0;
- font-family: arial, "Microsoft YaHei";
- background-color: #272822;
- color: #FEFEFE;
- }
- #fileWrapper{
- transition:all 0.5s ease;
- }
- #fileWrapper:hover{
- opacity: 1!important;
- }
- #visualizer_wrapper{
- text-align: center;
- }
- footer{
- position: fixed;
- bottom: 2px;
- color:#aaa;
- }
- </style>
- </head>
- <body>
- <div id="wrapper">
- <div id="fileWrapper" class="file_wrapper">
- <div id="info">
- HTML5 Audio API showcase | An Audio Viusalizer
- </div>
- <label for="uploadedFile">Drag&drop or select a file to play:</label>
- <input type="file" id="uploadedFile"></input>
- </div>
- <div id="visualizer_wrapper">
- <canvas id='canvas' width="800" height="350"></canvas>
- </div>
- </div>
- <footer>
- <small>Star me on <a href="https://github.com/Wayou/HTML5_Audio_Visualizer" target="_blank">GitHub</a></small>
- </footer>
- <script type="text/javascript">
- /*
- * An audio spectrum visualizer built with HTML5 Audio API
- * Author:Wayou
- * License: MIT
- * Feb 15, 2014
- */
- 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 vender 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 noteOn 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 = 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, 0, 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 top 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, 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, meterWidth, 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, meterWidth, 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);
- };
- }
- }
- </script>
- <script>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
- ga('create', 'UA-46794744-3', 'duapp.com');
- ga('send', 'pageview');
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement