Audio Visualizer

HTML
<!DOCTYPE html> <!-- Audiovisualization using the html canvas element. ©2017, Dominik Hofacker https://www.behance.net/dominikhofacker Please consider supporting this project on behance: https://www.behance.net/gallery/49260123/Web-Audio-Visualization --> <head> <meta charset="utf-8"> <meta content='IE=8' http-equiv='X-UA-Compatible'> <title>Frequcency analysis using HTML5 Audio and Web Audio API</title> <meta name="viewport" content="width=device-width"> <!-- Das favicon.ico und das apple-touch-icon.png in das root Verzeichnis --> <link rel="stylesheet" href="css/style.css"> <link href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,700' rel='stylesheet' type='text/css' /> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="src/bufferloader.js"></script> <script src="src/id3-minimized.js"></script> <script src="src/audiovisualisierung.js"></script> </head> <body> <input type="file" id="input" onchange="handleFiles(this.files)"/> <button id="playSampleButton" type="button" onClick="playSample()">Play Sample File</button> <button id="useMicButton" type="button" onClick="useMic()">Use Microphone</button> <span id="loading"></span> <div id="song_info_wrapper"> <div id="artist">Unknown Artist</div> <div id="title">Unknown Titel</div> <div id="album">Unknown Album</div> </div> <canvas id="freq" width="1024" height="525"></canvas> </body> </html>
CSS
/* * Audiovisualization using the html canvas element. * ©2017, Dominik Hofacker * https://www.behance.net/dominikhofacker * Please consider supporting this project on behance: * https://www.behance.net/gallery/49260123/Web-Audio-Visualization */ @keyframes hue { 0% { filter: hue-rotate(0deg); -webkit-filter: hue-rotate(0deg); } 100% { filter: hue-rotate(-360deg); -webkit-filter: hue-rotate(-360deg); } } #freq { background: linear-gradient(#ff0088, red); position: absolute; left: 0; right: 0; margin: 0 auto; } body { background:#000; overflow: hidden; } #freq.animateHue, body.animateHue { animation-name: hue; animation-duration: 500s; animation-delay: 1s; animation-iteration-count: infinite; -webkit-animation-name: hue; -webkit-animation-duration: 500s; -webkit-animation-delay: 1s; -webkit-animation-iteration-count: infinite; } #title, #artist, #album { position: relative; text-align: center; width: 100%; z-index: 999; font-weight: 100; font-family: "Roboto", sans-serif; /*font-size: 100px;*/ color: #fff; visibility: hidden; letter-spacing: -.05em; text-shadow: 0px 0px 8px rgba(0, 0, 0, 0.5); margin-bottom: 15px; } #song_info_wrapper { position: absolute; width: 100%; text-align: center; } #title { font-size: 10vw; } #artist { font-size: 3vw; } #album { font-size: 3vw; /*font-size: 40px;*/ margin-bottom: 0; } input, button, #loading { position: absolute; top: 10px; left: 5px; display: block; z-index: 999; } #playSampleButton { top: 40px; } #useMicButton { top: 70px; } #loading { display: inline-block; top: 44px; left: 110px; font-family: "Roboto", sans-serif; font-size: 12px; } html, body { width: 100%; height: 100%; margin: 0px; } @media screen and (min-width: 1000px) { #title { font-size: 100px; } #artist, #album { font-size: 40px; } } @media screen and (max-width: 500px) { #artist, #album { font-weight: 300; font-size: 4vw; } } @media screen and (max-width: 436px) { #artist, #album { font-weight: 300; font-size: 4.5vw; } #title { } }
JAVASCRIPT
/* * Audiovisualization using the html canvas element. * ©2017, Dominik Hofacker * https://www.behance.net/dominikhofacker * Please consider supporting this project on behance: * https://www.behance.net/gallery/49260123/Web-Audio-Visualization */ var rafID = null; var analyser = null; var c = null; var cDraw = null; var ctx = null; var microphone = null; var ctxDraw = null; var loader; var filename; var fileChosen = false; var hasSetupUserMedia = false; //handle different prefix of the audio context var AudioContext = AudioContext || webkitAudioContext; //create the context. var context = new AudioContext(); //using requestAnimationFrame instead of timeout... if (!window.requestAnimationFrame) window.requestAnimationFrame = window.webkitRequestAnimationFrame; $(function () { "use strict"; loader = new BufferLoader(); initBinCanvas(); }); function handleFiles(files) { if(files.length === 0){ return; } fileChosen = true; setupAudioNodes(); var fileReader = new FileReader(); fileReader.onload = function(){ var arrayBuffer = this.result; console.log(arrayBuffer); console.log(arrayBuffer.byteLength); filename = files[0].name.toString(); filename = filename.slice(0, -4); console.log(filename); var url = files[0].urn || files[0].name; ID3.loadTags(url, function() { var tags = ID3.getAllTags(url); // console.log(tags.title.toString().length); // if (tags.title.length > 14) { // var newTitle = tags.title.substring(0,14); // newTitle += "..."; // $("#title").html(newTitle); // } // else { // $("#title").html(tags.title); // } if (tags.title.length > 14 && tags.title.length <= 17) { $("#title").css("font-size", "7.5vh"); } if (tags.title.length > 17 && tags.title.length <= 20) { $("#title").css("font-size", "6.5vh"); } if (tags.title.length > 20) { $("#title").css("font-size", "5vh"); } $("#title").html(tags.title); onWindowResize(); $("#title").css("visibility", "visible"); $("#artist").html(tags.artist); $("#artist").css("visibility", "visible"); $("#album").html(tags.album); $("#album").css("visibility", "visible"); }, { tags: ["title","artist","album","picture"], dataReader: ID3.FileAPIReader(files[0]) }); }; fileReader.readAsArrayBuffer(files[0]); var url = URL.createObjectURL(files[0]); var request = new XMLHttpRequest(); request.addEventListener("progress", updateProgress); request.addEventListener("load", transferComplete); request.addEventListener("error", transferFailed); request.addEventListener("abort", transferCanceled); request.open('GET', url, true); request.responseType = 'arraybuffer'; // When loaded decode the data request.onload = function() { // decode the data context.decodeAudioData(request.response, function(buffer) { // when the audio is decoded play the sound sourceNode.buffer = buffer; sourceNode.start(0); $("#freq, body").addClass("animateHue"); //on error }, function(e) { console.log(e); }); }; request.send(); $("button, input").prop("disabled",true); } function playSample() { fileChosen = true; setupAudioNodes(); var request = new XMLHttpRequest(); request.addEventListener("progress", updateProgress); request.addEventListener("load", transferComplete); request.addEventListener("error", transferFailed); request.addEventListener("abort", transferCanceled); request.open('GET', 'src/Infinite.mp3', true); request.responseType = 'arraybuffer'; // When loaded decode the data request.onload = function() { $("#title").html("Infinite"); $("#album").html("Infinite"); $("#artist").html("Valence"); onWindowResize(); $("#title, #artist, #album").css("visibility", "visible"); // decode the data context.decodeAudioData(request.response, function(buffer) { // when the audio is decoded play the sound sourceNode.buffer = buffer; sourceNode.start(0); $("#freq, body").addClass("animateHue"); //on error }, function(e) { console.log(e); }); }; request.send(); $("button, input").prop("disabled",true); } function useMic() { "use strict"; if (!navigator.mediaDevices.getUserMedia) { alert("Your browser does not support microphone input!"); console.log('Your browser does not support microphone input!'); return; } navigator.mediaDevices.getUserMedia({audio: true, video: false}) .then(function(stream) { hasSetupUserMedia = true; //convert audio stream to mediaStreamSource (node) microphone = context.createMediaStreamSource(stream); //create analyser if (analyser === null) analyser = context.createAnalyser(); //connect microphone to analyser microphone.connect(analyser); //start updating rafID = window.requestAnimationFrame( updateVisualization ); $("#title").html("Mic"); $("#album").html("Input"); $("#artist").html("Using"); onWindowResize(); $("#title, #artist, #album").css("visibility", "visible"); $("#freq, body").addClass("animateHue"); }) .catch(function(err) { /* handle the error */ alert("Capturing microphone data failed! (currently only supported in Chrome & Firefox)"); console.log('capturing microphone data failed!'); console.log(err); }); } // progress on transfers from the server to the client (downloads) function updateProgress (oEvent) { if (oEvent.lengthComputable) { $("button, input").prop("disabled",true); var percentComplete = oEvent.loaded / oEvent.total; console.log("Loading music file... " + Math.floor(percentComplete * 100) + "%"); $("#loading").html("Loading... " + Math.floor(percentComplete * 100) + "%"); } else { // Unable to compute progress information since the total size is unknown console.log("Unable to compute progress info."); } } function transferComplete(evt) { console.log("The transfer is complete."); $("#loading").html(""); //$("button, input").prop("disabled",false); } function transferFailed(evt) { console.log("An error occurred while transferring the file."); $("#loading").html("Loading failed."); $("button, input").prop("disabled", false); } function transferCanceled(evt) { console.log("The transfer has been canceled by the user."); $("#loading").html("Loading canceled."); } function initBinCanvas () { //add new canvas "use strict"; c = document.getElementById("freq"); c.width = window.innerWidth; c.height = window.innerHeight; //get context from canvas for drawing ctx = c.getContext("2d"); ctx.canvas.width = window.innerWidth; ctx.canvas.height = window.innerHeight; window.addEventListener( 'resize', onWindowResize, false ); //create gradient for the bins var gradient = ctx.createLinearGradient(0, c.height - 300,0,window.innerHeight - 25); gradient.addColorStop(1,'#00f'); //black gradient.addColorStop(0.75,'#f00'); //red gradient.addColorStop(0.25,'#f00'); //yellow gradient.addColorStop(0,'#ffff00'); //white ctx.fillStyle = "#9c0001"; } function onWindowResize() { ctx.canvas.width = window.innerWidth; ctx.canvas.height = window.innerHeight; var containerHeight = $("#song_info_wrapper").height(); var topVal = $(window).height() / 2 - containerHeight / 2; $("#song_info_wrapper").css("top", topVal); console.log(topVal); if($(window).width() <= 500) { //TODO: not yet working $("#title").css("font-size", "40px"); } } var audioBuffer; var sourceNode; function setupAudioNodes() { // setup a analyser analyser = context.createAnalyser(); // create a buffer source node sourceNode = context.createBufferSource(); //connect source to analyser as link sourceNode.connect(analyser); // and connect source to destination sourceNode.connect(context.destination); //start updating rafID = window.requestAnimationFrame(updateVisualization); } function reset () { if (typeof sourceNode !== "undefined") { sourceNode.stop(0); } if (typeof microphone !== "undefined") { microphone = null; } } function updateVisualization () { // get the average, bincount is fftsize / 2 if (fileChosen || hasSetupUserMedia) { var array = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(array); drawBars(array); } // setTextAnimation(array); rafID = window.requestAnimationFrame(updateVisualization); } function drawBars (array) { //just show bins with a value over the treshold var threshold = 0; // clear the current state ctx.clearRect(0, 0, c.width, c.height); //the max count of bins for the visualization var maxBinCount = array.length; //space between bins var space = 3; ctx.save(); ctx.globalCompositeOperation='source-over'; //console.log(maxBinCount); //--> 1024 ctx.scale(0.5, 0.5); ctx.translate(window.innerWidth, window.innerHeight); ctx.fillStyle = "#fff"; var bass = Math.floor(array[1]); //1Hz Frequenz var radius = 0.45 * $(window).width() <= 450 ? -(bass * 0.25 + 0.45 * $(window).width()) : -(bass * 0.25 + 450); var bar_length_factor = 1; if ($(window).width() >= 785) { bar_length_factor = 1.0; } else if ($(window).width() < 785) { bar_length_factor = 1.5; } else if ($(window).width() < 500) { bar_length_factor = 20.0; } console.log($(window).width()); //go over each bin for ( var i = 0; i < maxBinCount; i++ ){ var value = array[i]; if (value >= threshold) { //draw bin //ctx.fillRect(0 + i * space, c.height - value, 2 , c.height); //ctx.fillRect(i * space, c.height, 2, -value); ctx.fillRect(0, radius, $(window).width() <= 450 ? 2 : 3, -value / bar_length_factor); ctx.rotate((180 / 128) * Math.PI/180); } } for ( var i = 0; i < maxBinCount; i++ ){ var value = array[i]; if (value >= threshold) { //draw bin //ctx.fillRect(0 + i * space, c.height - value, 2 , c.height); //ctx.fillRect(i * space, c.height, 2, -value); ctx.rotate(-(180 / 128) * Math.PI/180); ctx.fillRect(0, radius, $(window).width() <= 450 ? 2 : 3, -value / bar_length_factor); } } for ( var i = 0; i < maxBinCount; i++ ){ var value = array[i]; if (value >= threshold) { //draw bin //ctx.fillRect(0 + i * space, c.height - value, 2 , c.height); //ctx.fillRect(i * space, c.height, 2, -value); ctx.rotate((180 / 128) * Math.PI/180); ctx.fillRect(0, radius, $(window).width() <= 450 ? 2 : 3, -value / bar_length_factor); } } ctx.restore(); } //function setTextAnimation(array) //{ // var bass = Math.floor(array[1]); //4Hz Frequenz // // // var fontSize = bass * 0.25 + 50; // // ctx.save(); // ctx.globalCompositeOperation='destination-over'; // ctx.fillStyle = "#fff"; // ctx.filter = "blur(16px)"; // // var neueFontsize = 70; // if (fontSize > neueFontsize) { // neueFontsize = fontSize; // } // // //ctx.font = neueFontsize.toString() + "px Arial"; // if (navigator.userAgent.indexOf("Chrome/53.0.2764.0") > -1) { //besserer Look in Chrome Canary // console.log("Chrome Canary User Agent detected"); // ctx.font="normal normal 300 350px Roboto"; // if (filename !== undefined) { // ctx.fillText(filename, 0, c.height - 200); // } // } // ctx.filter = "blur(0px)"; // //ctx.font="normal normal 100 " + neueFontsize.toString() + "px Roboto"; // ctx.font="normal normal 100 70px Roboto"; // if (filename !== undefined) { // ctx.fillText(filename, window.innerWidth / 2 - 125, c.height / 2); // } // ctx.restore(); //} /** * Buffer Loader.js * * A small abstraction around the HTML5 buffer loader interface * https://www.behance.net/dominikhofacker * Please consider supporting this project on behance: * https://www.behance.net/gallery/49260123/Web-Audio-Visualization * */ var reader; window.AudioContext = window.AudioContext || window.webkitAudioContext; var BufferLoader = function(sources) { this.buffers = { }; this.context = null; this.buffer = null; this.init(); }; BufferLoader.prototype.init = function() { try { window.AudioContext = window.AudioContext || window.webkitAudioContext; this.context = new AudioContext(); } catch(_) { alert('Web Audio API is not supported in this browser'); } }; BufferLoader.prototype.onBufferLoadError = function(_) { console.error('Error loading buffer'); }; BufferLoader.prototype.onBufferLoad = function(bufferName, srcBuffer, callback) { this.context.decodeAudioData(srcBuffer, function onSuccess(buffer) { this.buffers[bufferName] = buffer; if (typeof callback === 'function') { callback(); // Aufruf der Wiedergabefunktion } }.bind(this), this.onBufferError); }; BufferLoader.prototype.load = function(bufferName, file, callback) { reader = new FileReader(); reader.onload = function(data) { if(data.target && data.target.result) { this.onBufferLoad(bufferName, data.target.result, callback); }else{ console.dir(data); } }.bind(this); reader.readAsArrayBuffer(file); }; BufferLoader.prototype._playBuffer = function(name, gain, time) { var source = this.context.createBufferSource(); source.buffer = this.buffer; var analyser = this.context.createAnalyser(); source.connect(analyser); source.connect(this.context.destination); source.start(time); }; BufferLoader.prototype.play = function (name, gain, time) { // Default values for time and gain gain = typeof gain !== 'undefined' ? gain : 1; time = typeof time !== 'undefined' ? time : 0; this.buffer = this.buffers[name]; if (this.buffer) { this._playBuffer(name, time, gain); } else { throw new Error("Buffer does not exist"); } }; (function(A){if("object"===typeof exports&&"undefined"!==typeof module)module.f=A();else if("function"===typeof define&&define.M)define([],A);else{var g;"undefined"!==typeof window?g=window:"undefined"!==typeof global?g=global:"undefined"!==typeof self?g=self:g=this;g.ID3=A()}})(function(){return function g(l,h,f){function c(b,d){if(!h[b]){if(!l[b]){var e="function"==typeof require&&require;if(!d&&e)return e(b,!0);if(a)return a(b,!0);e=Error("Cannot find module '"+b+"'");throw e.code="MODULE_NOT_FOUND", e;}e=h[b]={f:{}};l[b][0].call(e.f,function(a){var e=l[b][1][a];return c(e?e:a)},e,e.f,g,l,h,f)}return h[b].f}for(var a="function"==typeof require&&require,b=0;b<f.length;b++)c(f[b]);return c}({1:[function(g,l){var h=g("./stringutils");if("undefined"!==typeof document){var f=document.createElement("script");f.type="text/vbscript";f.textContent="Function IEBinary_getByteAt(strBinary, iOffset)\r\n\tIEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\nEnd Function\r\nFunction IEBinary_getLength(strBinary)\r\n\tIEBinary_getLength = LenB(strBinary)\r\nEnd Function\r\n"; document.getElementsByTagName("head")[0].appendChild(f)}else g("btoa"),g("atob");l.f=function(c,a,b){var m=a||0,d=0;"string"==typeof c?(d=b||c.length,this.a=function(a){return c.charCodeAt(a+m)&255}):"unknown"==typeof c&&(d=b||IEBinary_getLength(c),this.a=function(a){return IEBinary_getByteAt(c,a+m)});this.s=function(a,b){for(var d=Array(b),m=0;m<b;m++)d[m]=this.a(a+m);return d};this.l=function(){return d};this.g=function(a,b){return 0!=(this.a(a)&1<<b)};this.F=function(a){a=(this.a(a+1)<<8)+this.a(a); 0>a&&(a+=65536);return a};this.m=function(a){var b=this.a(a),d=this.a(a+1),m=this.a(a+2);a=this.a(a+3);b=(((b<<8)+d<<8)+m<<8)+a;0>b&&(b+=4294967296);return b};this.w=function(a){var b=this.a(a),d=this.a(a+1);a=this.a(a+2);b=((b<<8)+d<<8)+a;0>b&&(b+=16777216);return b};this.c=function(a,b){for(var d=[],m=a,c=0;m<a+b;m++,c++)d[c]=String.fromCharCode(this.a(m));return d.join("")};this.h=function(a,b,d){a=this.s(a,b);switch(d.toLowerCase()){case "utf-16":case "utf-16le":case "utf-16be":d=h.J(a,d);break; case "utf-8":d=h.K(a);break;default:d=h.I(a)}return d};this.i=function(a,b){b()}}},{"./stringutils":9,atob:void 0,btoa:void 0}],2:[function(g,l){var h=g("./binaryfile");l.f=function(f,c,a){function b(a,b,d,e,c,f){var k=m();k?("undefined"===typeof f&&(f=!0),b&&("undefined"!=typeof k.onload?(k.onload=function(){"200"==k.status||"206"==k.status?(k.fileSize=c||k.getResponseHeader("Content-Length"),b(k)):d&&d({error:"xhr",xhr:k});k=null},d&&(k.onerror=function(){d({error:"xhr",xhr:k});k=null})):k.onreadystatechange= function(){4==k.readyState&&("200"==k.status||"206"==k.status?(k.fileSize=c||k.getResponseHeader("Content-Length"),b(k)):d&&d({error:"xhr",xhr:k}),k=null)}),k.open("GET",a,f),k.overrideMimeType&&k.overrideMimeType("text/plain; charset=x-user-defined"),e&&k.setRequestHeader("Range","bytes="+e[0]+"-"+e[1]),k.setRequestHeader("If-Modified-Since","Sat, 01 Jan 1970 00:00:00 GMT"),k.send(null)):d&&d({error:"Unable to create XHR object"})}function m(){var a=null;"undefined"===typeof window?a=new (g("xmlhttprequest").XMLHttpRequest): window.XMLHttpRequest?a=new window.XMLHttpRequest:window.ActiveXObject&&(a=new window.ActiveXObject("Microsoft.XMLHTTP"));return a}function d(a,b,d){var e=m();e?(b&&("undefined"!=typeof e.onload?(e.onload=function(){"200"==e.status||"206"==e.status?b(this):d&&d({error:"xhr",xhr:e});e=null},d&&(e.onerror=function(){d({error:"xhr",xhr:e});e=null})):e.onreadystatechange=function(){4==e.readyState&&("200"==e.status||"206"==e.status?b(this):d&&d({error:"xhr",xhr:e}),e=null)}),e.open("HEAD",a,!0),e.send(null)): d&&d({error:"Unable to create XHR object"})}function e(d,e){var m,c;function f(a){var b=~~(a[0]/m)-c;a=~~(a[1]/m)+1+c;0>b&&(b=0);a>=blockTotal&&(a=blockTotal-1);return[b,a]}function g(c,f){for(;n[c[0]];)if(c[0]++,c[0]>c[1]){f&&f();return}for(;n[c[1]];)if(c[1]--,c[0]>c[1]){f&&f();return}var h=[c[0]*m,(c[1]+1)*m-1];b(d,function(a){parseInt(a.getResponseHeader("Content-Length"),10)==e&&(c[0]=0,c[1]=blockTotal-1,h[0]=0,h[1]=e-1);a={data:a.W||a.responseText,offset:h[0]};for(var b=c[0];b<=c[1];b++)n[b]= a;f&&f()},a,h,k,!!f)}var k,l=new h("",0,e),n=[];m=m||2048;c="undefined"===typeof c?0:c;blockTotal=~~((e-1)/m)+1;for(var p in l)l.hasOwnProperty(p)&&"function"===typeof l[p]&&(this[p]=l[p]);this.a=function(a){var b;g(f([a,a]));return(b=n[~~(a/m)])&&"string"==typeof b.data?b.data.charCodeAt(a-b.offset)&255:b&&"unknown"==typeof b.data?IEBinary_getByteAt(b.data,a-b.offset):""};this.i=function(a,b){g(f(a),b)}}(function(){d(f,function(a){a=parseInt(a.getResponseHeader("Content-Length"),10)||-1;c(new e(f, a))},a)})()}},{"./binaryfile":1,xmlhttprequest:void 0}],3:[function(g,l){var h=g("./binaryfile");l.f=function(f,c){return function(a,b){var m=c||new FileReader;m.onload=function(a){b(new h(a.target.result))};m.readAsBinaryString(f)}}},{"./binaryfile":1}],4:[function(g,l){function h(b){return"ftypM4A"==b.c(4,7)?f:"ID3"==b.c(0,3)?a:c}var f=g("./id4"),c=g("./id3v1"),a=g("./id3v2"),b=g("./bufferedbinaryajax"),m=g("./filereader");"undefined"!==typeof window&&(window.FileAPIReader=m);var d={},e={},r=[0, 7];d.B=function(a){delete e[a]};d.A=function(){e={}};d.H=function(a,d,c){c=c||{};(c.dataReader||b)(a,function(b){b.i(r,function(){var m=h(b);m.u(b,function(){var f=c.tags,h=m.v(b,f),f=e[a]||{},r;for(r in h)h.hasOwnProperty(r)&&(f[r]=h[r]);e[a]=f;d&&d()})})},c.onError)};d.D=function(a){if(!e[a])return null;var b={},d;for(d in e[a])e[a].hasOwnProperty(d)&&(b[d]=e[a][d]);return b};d.G=function(a,b){return e[a]?e[a][b]:null};d.FileAPIReader=m;d.loadTags=d.H;d.getAllTags=d.D;d.getTag=d.G;d.clearTags=d.B; d.clearAll=d.A;l.f=d},{"./bufferedbinaryajax":2,"./filereader":3,"./id3v1":5,"./id3v2":6,"./id4":8}],5:[function(g,l){var h={},f="Blues;Classic Rock;Country;Dance;Disco;Funk;Grunge;Hip-Hop;Jazz;Metal;New Age;Oldies;Other;Pop;R&B;Rap;Reggae;Rock;Techno;Industrial;Alternative;Ska;Death Metal;Pranks;Soundtrack;Euro-Techno;Ambient;Trip-Hop;Vocal;Jazz+Funk;Fusion;Trance;Classical;Instrumental;Acid;House;Game;Sound Clip;Gospel;Noise;AlternRock;Bass;Soul;Punk;Space;Meditative;Instrumental Pop;Instrumental Rock;Ethnic;Gothic;Darkwave;Techno-Industrial;Electronic;Pop-Folk;Eurodance;Dream;Southern Rock;Comedy;Cult;Gangsta;Top 40;Christian Rap;Pop/Funk;Jungle;Native American;Cabaret;New Wave;Psychadelic;Rave;Showtunes;Trailer;Lo-Fi;Tribal;Acid Punk;Acid Jazz;Polka;Retro;Musical;Rock & Roll;Hard Rock;Folk;Folk-Rock;National Folk;Swing;Fast Fusion;Bebob;Latin;Revival;Celtic;Bluegrass;Avantgarde;Gothic Rock;Progressive Rock;Psychedelic Rock;Symphonic Rock;Slow Rock;Big Band;Chorus;Easy Listening;Acoustic;Humour;Speech;Chanson;Opera;Chamber Music;Sonata;Symphony;Booty Bass;Primus;Porn Groove;Satire;Slow Jam;Club;Tango;Samba;Folklore;Ballad;Power Ballad;Rhythmic Soul;Freestyle;Duet;Punk Rock;Drum Solo;Acapella;Euro-House;Dance Hall".split(";"); h.u=function(c,a){var b=c.l();c.i([b-128-1,b],a)};h.v=function(c){var a=c.l()-128;if("TAG"==c.c(a,3)){var b=c.c(a+3,30).replace(/\0/g,""),m=c.c(a+33,30).replace(/\0/g,""),d=c.c(a+63,30).replace(/\0/g,""),e=c.c(a+93,4).replace(/\0/g,"");if(0==c.a(a+97+28))var h=c.c(a+97,28).replace(/\0/g,""),g=c.a(a+97+29);else h="",g=0;c=c.a(a+97+30);return{version:"1.1",title:b,artist:m,album:d,year:e,comment:h,track:g,genre:255>c?f[c]:""}}return{}};l.f=h},{}],6:[function(g,l){function h(a,c){var d=c.a(a),e=c.a(a+ 1),f=c.a(a+2);return c.a(a+3)&127|(f&127)<<7|(e&127)<<14|(d&127)<<21}var f=g("./id3v2frames");f.frames={BUF:"Recommended buffer size",CNT:"Play counter",COM:"Comments",CRA:"Audio encryption",CRM:"Encrypted meta frame",ETC:"Event timing codes",EQU:"Equalization",GEO:"General encapsulated object",IPL:"Involved people list",LNK:"Linked information",MCI:"Music CD Identifier",MLL:"MPEG location lookup table",PIC:"Attached picture",POP:"Popularimeter",REV:"Reverb",RVA:"Relative volume adjustment",SLT:"Synchronized lyric/text", STC:"Synced tempo codes",TAL:"Album/Movie/Show title",TBP:"BPM (Beats Per Minute)",TCM:"Composer",TCO:"Content type",TCR:"Copyright message",TDA:"Date",TDY:"Playlist delay",TEN:"Encoded by",TFT:"File type",TIM:"Time",TKE:"Initial key",TLA:"Language(s)",TLE:"Length",TMT:"Media type",TOA:"Original artist(s)/performer(s)",TOF:"Original filename",TOL:"Original Lyricist(s)/text writer(s)",TOR:"Original release year",TOT:"Original album/Movie/Show title",TP1:"Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group", TP2:"Band/Orchestra/Accompaniment",TP3:"Conductor/Performer refinement",TP4:"Interpreted, remixed, or otherwise modified by",TPA:"Part of a set",TPB:"Publisher",TRC:"ISRC (International Standard Recording Code)",TRD:"Recording dates",TRK:"Track number/Position in set",TSI:"Size",TSS:"Software/hardware and settings used for encoding",TT1:"Content group description",TT2:"Title/Songname/Content description",TT3:"Subtitle/Description refinement",TXT:"Lyricist/text writer",TXX:"User defined text information frame", TYE:"Year",UFI:"Unique file identifier",ULT:"Unsychronized lyric/text transcription",WAF:"Official audio file webpage",WAR:"Official artist/performer webpage",WAS:"Official audio source webpage",WCM:"Commercial information",WCP:"Copyright/Legal information",WPB:"Publishers official webpage",WXX:"User defined URL link frame",AENC:"Audio encryption",APIC:"Attached picture",COMM:"Comments",COMR:"Commercial frame",ENCR:"Encryption method registration",EQUA:"Equalization",ETCO:"Event timing codes",GEOB:"General encapsulated object", GRID:"Group identification registration",IPLS:"Involved people list",LINK:"Linked information",MCDI:"Music CD identifier",MLLT:"MPEG location lookup table",OWNE:"Ownership frame",PRIV:"Private frame",PCNT:"Play counter",POPM:"Popularimeter",POSS:"Position synchronisation frame",RBUF:"Recommended buffer size",RVAD:"Relative volume adjustment",RVRB:"Reverb",SYLT:"Synchronized lyric/text",SYTC:"Synchronized tempo codes",TALB:"Album/Movie/Show title",TBPM:"BPM (beats per minute)",TCOM:"Composer",TCON:"Content type", TCOP:"Copyright message",TDAT:"Date",TDLY:"Playlist delay",TENC:"Encoded by",TEXT:"Lyricist/Text writer",TFLT:"File type",TIME:"Time",TIT1:"Content group description",TIT2:"Title/songname/content description",TIT3:"Subtitle/Description refinement",TKEY:"Initial key",TLAN:"Language(s)",TLEN:"Length",TMED:"Media type",TOAL:"Original album/movie/show title",TOFN:"Original filename",TOLY:"Original lyricist(s)/text writer(s)",TOPE:"Original artist(s)/performer(s)",TORY:"Original release year",TOWN:"File owner/licensee", TPE1:"Lead performer(s)/Soloist(s)",TPE2:"Band/orchestra/accompaniment",TPE3:"Conductor/performer refinement",TPE4:"Interpreted, remixed, or otherwise modified by",TPOS:"Part of a set",TPUB:"Publisher",TRCK:"Track number/Position in set",TRDA:"Recording dates",TRSN:"Internet radio station name",TRSO:"Internet radio station owner",TSIZ:"Size",TSRC:"ISRC (international standard recording code)",TSSE:"Software/Hardware and settings used for encoding",TYER:"Year",TXXX:"User defined text information frame", UFID:"Unique file identifier",USER:"Terms of use",USLT:"Unsychronized lyric/text transcription",WCOM:"Commercial information",WCOP:"Copyright/Legal information",WOAF:"Official audio file webpage",WOAR:"Official artist/performer webpage",WOAS:"Official audio source webpage",WORS:"Official internet radio station homepage",WPAY:"Payment",WPUB:"Publishers official webpage",WXXX:"User defined URL link frame"};var c={title:["TIT2","TT2"],artist:["TPE1","TP1"],album:["TALB","TAL"],year:["TYER","TYE"],comment:["COMM", "COM"],track:["TRCK","TRK"],genre:["TCON","TCO"],picture:["APIC","PIC"],lyrics:["USLT","ULT"]},a=["title","artist","album","track"];f.u=function(a,c){a.i([0,h(6,a)],c)};f.v=function(b,m){var d=0,e=b.a(d+3);if(4<e)return{version:">2.4"};var r=b.a(d+4),g=b.g(d+5,7),l=b.g(d+5,6),w=b.g(d+5,5),x=h(d+6,b),d=d+10;if(l)var q=b.m(d),d=d+(q+4);var e={version:"2."+e+"."+r,major:e,revision:r,flags:{unsynchronisation:g,extended_header:l,experimental_indicator:w},size:x},k;if(g)k={};else{for(var x=x-10,g=b,r=m, l={},w=e.major,q=[],u=0,n;n=(r||a)[u];u++)q=q.concat(c[n]||[n]);for(r=q;d<x;){q=null;u=g;n=d;var p=null;switch(w){case 2:k=u.c(n,3);var t=u.w(n+3),z=6;break;case 3:k=u.c(n,4);t=u.m(n+4);z=10;break;case 4:k=u.c(n,4),t=h(n+4,u),z=10}if(""==k)break;d+=z+t;if(!(0>r.indexOf(k))){if(2<w)var p=u,y=n+8,p={message:{Y:p.g(y,6),R:p.g(y,5),V:p.g(y,4)},format:{T:p.g(y+1,7),N:p.g(y+1,3),P:p.g(y+1,2),L:p.g(y+1,1),C:p.g(y+1,0)}};n+=z;p&&p.format.C&&(h(n,u),n+=4,t-=4);p&&p.format.L||(k in f.b?q=f.b[k]:"T"==k[0]&& (q=f.b["T*"]),q=q?q(n,t,u,p):void 0,q={id:k,size:t,description:k in f.frames?f.frames[k]:"Unknown",data:q},k in l?(l[k].id&&(l[k]=[l[k]]),l[k].push(q)):l[k]=q)}}k=l}for(var B in c)if(c.hasOwnProperty(B)){a:{t=c[B];"string"==typeof t&&(t=[t]);z=0;for(d=void 0;d=t[z];z++)if(d in k){b=k[d].data;break a}b=void 0}b&&(e[B]=b)}for(var C in k)k.hasOwnProperty(C)&&(e[C]=k[C]);return e};l.f=f},{"./id3v2frames":7}],7:[function(g,l){function h(a){var b;switch(a){case 0:b="iso-8859-1";break;case 1:b="utf-16"; break;case 2:b="utf-16be";break;case 3:b="utf-8"}return b}var f={b:{}},c="32x32 pixels 'file icon' (PNG only);Other file icon;Cover (front);Cover (back);Leaflet page;Media (e.g. lable side of CD);Lead artist/lead performer/soloist;Artist/performer;Conductor;Band/Orchestra;Composer;Lyricist/text writer;Recording Location;During recording;During performance;Movie/video screen capture;A bright coloured fish;Illustration;Band/artist logotype;Publisher/Studio logotype".split(";");f.b.APIC=function(a,b, m,d,e){e=e||"3";d=a;var f=h(m.a(a));switch(e){case "2":var g=m.c(a+1,3);a+=4;break;case "3":case "4":g=m.h(a+1,b-(a-d),""),a+=1+g.j}e=m.a(a,1);e=c[e];f=m.h(a+1,b-(a-d),f);a+=1+f.j;return{format:g.toString(),type:e,description:f.toString(),data:m.s(a,d+b-a)}};f.b.COMM=function(a,b,c){var d=a,e=h(c.a(a)),f=c.c(a+1,3),g=c.h(a+4,b-4,e);a+=4+g.j;a=c.h(a,d+b-a,e);return{language:f,X:g.toString(),text:a.toString()}};f.b.COM=f.b.COMM;f.b.PIC=function(a,b,c,d){return f.b.APIC(a,b,c,d,"2")};f.b.PCNT=function(a, b,c){return c.S(a)};f.b.CNT=f.b.PCNT;f.b["T*"]=function(a,b,c){var d=h(c.a(a));return c.h(a+1,b-1,d).toString()};f.b.TCON=function(a,b,c){return f.b["T*"].apply(this,arguments).replace(/^\(\d+\)/,"")};f.b.TCO=f.b.TCON;f.b.USLT=function(a,b,c){var d=a,e=h(c.a(a)),f=c.c(a+1,3),g=c.h(a+4,b-4,e);a+=4+g.j;a=c.h(a,d+b-a,e);return{language:f,O:g.toString(),U:a.toString()}};f.b.ULT=f.b.USLT;l.f=f},{}],8:[function(g,l){function h(a,b,f,d){var e=a.m(b);if(0==e)d();else{var g=a.c(b+4,4);-1<["moov","udta","meta", "ilst"].indexOf(g)?("meta"==g&&(b+=4),a.i([b+8,b+8+8],function(){h(a,b+8,e-8,d)})):a.i([b+(g in c.o?0:e),b+e+8],function(){h(a,b+e,f,d)})}}function f(a,b,h,d,e){e=void 0===e?"":e+" ";for(var g=h;g<h+d;){var l=b.m(g);if(0==l)break;var v=b.c(g+4,4);if(-1<["moov","udta","meta","ilst"].indexOf(v)){"meta"==v&&(g+=4);f(a,b,g+8,l-8,e);break}if(c.o[v]){var w=b.w(g+16+1),x=c.o[v],w=c.types[w];if("trkn"==v)a[x[0]]=b.a(g+16+11),a.count=b.a(g+16+13);else{var v=g+16+4+4,q=l-16-4-4,k;switch(w){case "text":k=b.h(v, q,"UTF-8");break;case "uint8":k=b.F(v);break;case "jpeg":case "png":k={format:"image/"+w,data:b.s(v,q)}}a[x[0]]="comment"===x[0]?{text:k}:k}}g+=l}}var c={types:{0:"uint8",1:"text",13:"jpeg",14:"png",21:"uint8"},o:{"\u00a9alb":["album"],"\u00a9art":["artist"],"\u00a9ART":["artist"],aART:["artist"],"\u00a9day":["year"],"\u00a9nam":["title"],"\u00a9gen":["genre"],trkn:["track"],"\u00a9wrt":["composer"],"\u00a9too":["encoder"],cprt:["copyright"],covr:["picture"],"\u00a9grp":["grouping"],keyw:["keyword"], "\u00a9lyr":["lyrics"],"\u00a9cmt":["comment"],tmpo:["tempo"],cpil:["compilation"],disk:["disc"]},u:function(a,b){a.i([0,7],function(){h(a,0,a.l(),b)})},v:function(a){var b={};f(b,a,0,a.l());return b}};l.f=c},{}],9:[function(g,l){l.f={J:function(h,f,c){var a=0,b=1,g=0;c=Math.min(c||h.length,h.length);254==h[0]&&255==h[1]?(f=!0,a=2):255==h[0]&&254==h[1]&&(f=!1,a=2);f&&(b=0,g=1);f=[];for(var d=0;a<c;d++){var e=h[a+b],l=(e<<8)+h[a+g],a=a+2;if(0==l)break;else 216>e||224<=e?f[d]=String.fromCharCode(l): (e=(h[a+b]<<8)+h[a+g],a+=2,f[d]=String.fromCharCode(l,e))}h=new String(f.join(""));h.j=a;return h},K:function(h,f){var c=0;f=Math.min(f||h.length,h.length);239==h[0]&&187==h[1]&&191==h[2]&&(c=3);for(var a=[],b=0;c<f;b++){var g=h[c++];if(0==g)break;else if(128>g)a[b]=String.fromCharCode(g);else if(194<=g&&224>g){var d=h[c++];a[b]=String.fromCharCode(((g&31)<<6)+(d&63))}else if(224<=g&&240>g){var d=h[c++],e=h[c++];a[b]=String.fromCharCode(((g&255)<<12)+((d&63)<<6)+(e&63))}else if(240<=g&&245>g){var d= h[c++],e=h[c++],l=h[c++],g=((g&7)<<18)+((d&63)<<12)+((e&63)<<6)+(l&63)-65536;a[b]=String.fromCharCode((g>>10)+55296,(g&1023)+56320)}}a=new String(a.join(""));a.j=c;return a},I:function(g,f){var c=[];f=f||g.length;for(var a=0;a<f;){var b=g[a++];if(0==b)break;c[a-1]=String.fromCharCode(b)}c=new String(c.join(""));c.j=a;return c}}},{}]},{},[4])(4)});
Expand for more options Login