Advertisement
Guest User

Untitled

a guest
Jan 20th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.67 KB | None | 0 0
  1.  
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta name="description" content="HTML5 Audio Spectrum Visualizer">
  6. <title>HTML5 Audio API showcase | Audio visualizer</title>
  7. <style type="text/css">
  8. html, body {
  9. margin: 0;
  10. font-family: arial, "Microsoft YaHei";
  11. background-color: #272822;
  12. color: #FEFEFE;
  13. }
  14. #fileWrapper{
  15. transition:all 0.5s ease;
  16. }
  17. #fileWrapper:hover{
  18. opacity: 1!important;
  19. }
  20. #visualizer_wrapper{
  21. text-align: center;
  22. }
  23. footer{
  24. position: fixed;
  25. bottom: 2px;
  26. color:#aaa;
  27. }
  28. </style>
  29. </head>
  30. <body>
  31. <div id="wrapper">
  32. <div id="fileWrapper" class="file_wrapper">
  33. <div id="info">
  34. HTML5 Audio API showcase | An Audio Viusalizer
  35. </div>
  36. <label for="uploadedFile">Drag&drop or select a file to play:</label>
  37. <input type="file" id="uploadedFile"></input>
  38. </div>
  39. <div id="visualizer_wrapper">
  40. <canvas id='canvas' width="800" height="350"></canvas>
  41. </div>
  42. </div>
  43. <footer>
  44. <small>Star me on <a href="https://github.com/Wayou/HTML5_Audio_Visualizer" target="_blank">GitHub</a></small>
  45. </footer>
  46. <script type="text/javascript">
  47. /*
  48. * An audio spectrum visualizer built with HTML5 Audio API
  49. * Author:Wayou
  50. * License: MIT
  51. * Feb 15, 2014
  52. */
  53. window.onload = function() {
  54. new Visualizer().ini();
  55. };
  56. var Visualizer = function() {
  57. this.file = null, //the current file
  58. this.fileName = null, //the current file name
  59. this.audioContext = null,
  60. this.source = null, //the audio source
  61. this.info = document.getElementById('info').innerHTML, //this used to upgrade the UI information
  62. this.infoUpdateId = null, //to sotore the setTimeout ID and clear the interval
  63. this.animationId = null,
  64. this.status = 0, //flag for sound is playing 1 or stopped 0
  65. this.forceStop = false,
  66. this.allCapsReachBottom = false
  67. };
  68. Visualizer.prototype = {
  69. ini: function() {
  70. this._prepareAPI();
  71. this._addEventListner();
  72. },
  73. _prepareAPI: function() {
  74. //fix browser vender for AudioContext and requestAnimationFrame
  75. window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
  76. window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;
  77. window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame;
  78. try {
  79. this.audioContext = new AudioContext();
  80. } catch (e) {
  81. this._updateInfo('!Your browser does not support AudioContext', false);
  82. console.log(e);
  83. }
  84. },
  85. _addEventListner: function() {
  86. var that = this,
  87. audioInput = document.getElementById('uploadedFile'),
  88. dropContainer = document.getElementsByTagName("canvas")[0];
  89. //listen the file upload
  90. audioInput.onchange = function() {
  91. if (that.audioContext===null) {return;};
  92.  
  93. //the if statement fixes the file selction cancle, because the onchange will trigger even the file selection been canceled
  94. if (audioInput.files.length !== 0) {
  95. //only process the first file
  96. that.file = audioInput.files[0];
  97. that.fileName = that.file.name;
  98. if (that.status === 1) {
  99. //the sound is still playing but we upload another file, so set the forceStop flag to true
  100. that.forceStop = true;
  101. };
  102. document.getElementById('fileWrapper').style.opacity = 1;
  103. that._updateInfo('Uploading', true);
  104. //once the file is ready,start the visualizer
  105. that._start();
  106. };
  107. };
  108. //listen the drag & drop
  109. dropContainer.addEventListener("dragenter", function() {
  110. document.getElementById('fileWrapper').style.opacity = 1;
  111. that._updateInfo('Drop it on the page', true);
  112. }, false);
  113. dropContainer.addEventListener("dragover", function(e) {
  114. e.stopPropagation();
  115. e.preventDefault();
  116. //set the drop mode
  117. e.dataTransfer.dropEffect = 'copy';
  118. }, false);
  119. dropContainer.addEventListener("dragleave", function() {
  120. document.getElementById('fileWrapper').style.opacity = 0.2;
  121. that._updateInfo(that.info, false);
  122. }, false);
  123. dropContainer.addEventListener("drop", function(e) {
  124. e.stopPropagation();
  125. e.preventDefault();
  126. if (that.audioContext===null) {return;};
  127. document.getElementById('fileWrapper').style.opacity = 1;
  128. that._updateInfo('Uploading', true);
  129. //get the dropped file
  130. that.file = e.dataTransfer.files[0];
  131. if (that.status === 1) {
  132. document.getElementById('fileWrapper').style.opacity = 1;
  133. that.forceStop = true;
  134. };
  135. that.fileName = that.file.name;
  136. //once the file is ready,start the visualizer
  137. that._start();
  138. }, false);
  139. },
  140. _start: function() {
  141. //read and decode the file into audio array buffer
  142. var that = this,
  143. file = this.file,
  144. fr = new FileReader();
  145. fr.onload = function(e) {
  146. var fileResult = e.target.result;
  147. var audioContext = that.audioContext;
  148. if (audioContext === null) {
  149. return;
  150. };
  151. that._updateInfo('Decoding the audio', true);
  152. audioContext.decodeAudioData(fileResult, function(buffer) {
  153. that._updateInfo('Decode succussfully,start the visualizer', true);
  154. that._visualize(audioContext, buffer);
  155. }, function(e) {
  156. that._updateInfo('!Fail to decode the file', false);
  157. console.log(e);
  158. });
  159. };
  160. fr.onerror = function(e) {
  161. that._updateInfo('!Fail to read the file', false);
  162. console.log(e);
  163. };
  164. //assign the file to the reader
  165. this._updateInfo('Starting read the file', true);
  166. fr.readAsArrayBuffer(file);
  167. },
  168. _visualize: function(audioContext, buffer) {
  169. var audioBufferSouceNode = audioContext.createBufferSource(),
  170. analyser = audioContext.createAnalyser(),
  171. that = this;
  172. //connect the source to the analyser
  173. audioBufferSouceNode.connect(analyser);
  174. //connect the analyser to the destination(the speaker), or we won't hear the sound
  175. analyser.connect(audioContext.destination);
  176. //then assign the buffer to the buffer source node
  177. audioBufferSouceNode.buffer = buffer;
  178. //play the source
  179. if (!audioBufferSouceNode.start) {
  180. audioBufferSouceNode.start = audioBufferSouceNode.noteOn //in old browsers use noteOn method
  181. audioBufferSouceNode.stop = audioBufferSouceNode.noteOff //in old browsers use noteOn method
  182. };
  183. //stop the previous sound if any
  184. if (this.animationId !== null) {
  185. cancelAnimationFrame(this.animationId);
  186. }
  187. if (this.source !== null) {
  188. this.source.stop(0);
  189. }
  190. audioBufferSouceNode.start(0);
  191. this.status = 1;
  192. this.source = audioBufferSouceNode;
  193. audioBufferSouceNode.onended = function() {
  194. that._audioEnd(that);
  195. };
  196. this._updateInfo('Playing ' + this.fileName, false);
  197. this.info = 'Playing ' + this.fileName;
  198. document.getElementById('fileWrapper').style.opacity = 0.2;
  199. this._drawSpectrum(analyser);
  200. },
  201. _drawSpectrum: function(analyser) {
  202. var that = this,
  203. canvas = document.getElementById('canvas'),
  204. cwidth = canvas.width,
  205. cheight = canvas.height - 2,
  206. meterWidth = 10, //width of the meters in the spectrum
  207. gap = 2, //gap between meters
  208. capHeight = 2,
  209. capStyle = '#fff',
  210. meterNum = 800 / (10 + 2), //count of the meters
  211. capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame
  212. ctx = canvas.getContext('2d'),
  213. gradient = ctx.createLinearGradient(0, 0, 0, 300);
  214. gradient.addColorStop(1, '#0f0');
  215. gradient.addColorStop(0.5, '#ff0');
  216. gradient.addColorStop(0, '#f00');
  217. var drawMeter = function() {
  218. var array = new Uint8Array(analyser.frequencyBinCount);
  219. analyser.getByteFrequencyData(array);
  220. if (that.status === 0) {
  221. //fix when some sounds end the value still not back to zero
  222. for (var i = array.length - 1; i >= 0; i--) {
  223. array[i] = 0;
  224. };
  225. allCapsReachBottom = true;
  226. for (var i = capYPositionArray.length - 1; i >= 0; i--) {
  227. allCapsReachBottom = allCapsReachBottom && (capYPositionArray[i] === 0);
  228. };
  229. if (allCapsReachBottom) {
  230. cancelAnimationFrame(that.animationId); //since the sound is top and animation finished, stop the requestAnimation to prevent potential memory leak,THIS IS VERY IMPORTANT!
  231. return;
  232. };
  233. };
  234. var step = Math.round(array.length / meterNum); //sample limited data from the total array
  235. ctx.clearRect(0, 0, cwidth, cheight);
  236. for (var i = 0; i < meterNum; i++) {
  237. var value = array[i * step];
  238. if (capYPositionArray.length < Math.round(meterNum)) {
  239. capYPositionArray.push(value);
  240. };
  241. ctx.fillStyle = capStyle;
  242. //draw the cap, with transition effect
  243. if (value < capYPositionArray[i]) {
  244. ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight);
  245. } else {
  246. ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight);
  247. capYPositionArray[i] = value;
  248. };
  249. ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look
  250. ctx.fillRect(i * 12 /*meterWidth+gap*/ , cheight - value + capHeight, meterWidth, cheight); //the meter
  251. }
  252. that.animationId = requestAnimationFrame(drawMeter);
  253. }
  254. this.animationId = requestAnimationFrame(drawMeter);
  255. },
  256. _audioEnd: function(instance) {
  257. if (this.forceStop) {
  258. this.forceStop = false;
  259. this.status = 1;
  260. return;
  261. };
  262. this.status = 0;
  263. var text = 'HTML5 Audio API showcase | An Audio Viusalizer';
  264. document.getElementById('fileWrapper').style.opacity = 1;
  265. document.getElementById('info').innerHTML = text;
  266. instance.info = text;
  267. document.getElementById('uploadedFile').value = '';
  268. },
  269. _updateInfo: function(text, processing) {
  270. var infoBar = document.getElementById('info'),
  271. dots = '...',
  272. i = 0,
  273. that = this;
  274. infoBar.innerHTML = text + dots.substring(0, i++);
  275. if (this.infoUpdateId !== null) {
  276. clearTimeout(this.infoUpdateId);
  277. };
  278. if (processing) {
  279. //animate dots at the end of the info text
  280. var animateDot = function() {
  281. if (i > 3) {
  282. i = 0
  283. };
  284. infoBar.innerHTML = text + dots.substring(0, i++);
  285. that.infoUpdateId = setTimeout(animateDot, 250);
  286. }
  287. this.infoUpdateId = setTimeout(animateDot, 250);
  288. };
  289. }
  290. }
  291. </script>
  292. <script>
  293. (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  294. (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  295. m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  296. })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  297. ga('create', 'UA-46794744-3', 'duapp.com');
  298. ga('send', 'pageview');
  299. </script>
  300. </body>
  301. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement