diff options
Diffstat (limited to 'libs/music/player.d/main.js')
-rw-r--r-- | libs/music/player.d/main.js | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/libs/music/player.d/main.js b/libs/music/player.d/main.js new file mode 100644 index 0000000..4795e5f --- /dev/null +++ b/libs/music/player.d/main.js @@ -0,0 +1,610 @@ +var audio; +var playlist; +var tracks; +var current; +var mbuttonstate=0; +var plistshown=true; +var shuffle=0,repeat=0; +var plistRect; +var dpiratio=window.devicePixelRatio?window.devicePixelRatio:1; + +var audioCtxt=null; +var CtxtSource=null; +var CtxtAnalyser=null; +var canvas; +var CSpectrum=1024,CSpectrumIF=128; +var SpecWidth=0.7,SpecGap=0.08125; +var caps=[]; +var visualselector=null; +var SpecRingRadius=225; +var spectrogrampos=0; +var inkimg=[]; +var f1=0,f2=0,penv=0,btrig=0,beatp=0,lastbp=0; +var lpbd=300,lpf=1./(2*Math.PI*lpbd),beatr=0.02; +var frms=0,lastfpsupd=null,fps=0; +var ic1=["#FF3333","#FF8800","#FFFF00","#CCFF00","#33CCFF","#0000FF","#9966FF"]; +var ic2=["rgba(204,51,51,0.6)","rgba(187,85,0,0.6)","rgba(255,204,0,0.6)","rgba(153,204,0,0.6)","rgba(51,153,255,0.6)","rgba(0,0,102,0.6)","rgba(153,51,204,0.6)"] +var Ink=function(_vx,_vy,_c) +{ + this.x=canvas.width/2;this.y=canvas.height/2; + this.vx=_vx;this.vy=_vy; + this.color=_c>6?6:_c;this.active=true; +}; +Ink.prototype.update=function() +{ + this.x+=this.vx;this.y+=this.vy; + this.vx*=0.995;this.vy*=0.995; + if(this.x<-10||this.x>canvas.width+10||this.y<-10||this.y>canvas.height+10) + this.active=false; +} +Ink.prototype.draw=function(cctx) +{ + cctx.drawImage(inkimg[this.color],this.x+5*window.devicePixelRatio,this.y+5*window.devicePixelRatio); +} +var inks=[]; +function inkPrepare() +{ + for(var i=0;i<7;++i) + { + inkimg[i]=document.createElement('canvas'); + inkimg[i].width=inkimg[i].height=10*window.devicePixelRatio; + var cctx=inkimg[i].getContext('2d'); + cctx.fillStyle=ic1[i]; + cctx.beginPath(); + cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,3*window.devicePixelRatio,0,2*Math.PI); + cctx.fill(); + cctx.fillStyle=ic2[i]; + cctx.beginPath(); + cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,5*window.devicePixelRatio,0,2*Math.PI); + cctx.fill(); + } +} +function createInk(_vx,_vy,_c1,_c2) +{ + var f=false; + for(var i=0;i<inks.length;++i) + { + if(!inks[i].active) + {inks[i]=new Ink(_vx,_vy,_c1,_c2);f=true;break;} + } + if(!f&&inks.length<512)inks.push(new Ink(_vx,_vy,_c1,_c2)); +} + +function gup(name,url) +{ + if(!url)url=location.href; + name=name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); + var regexS="[\\?&]"+name+"=([^&#]*)"; + var regex=new RegExp(regexS); + var results=regex.exec(url); + return results==null?null:results[1]; +} +function getcookie(key) +{return document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)"+key+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");} + +function initAPI() +{ + 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; + audioCtxt=new AudioContext; + CtxtSource=audioCtxt.createBufferSource(); + CtxtAnalyser=audioCtxt.createAnalyser(); + CtxtAnalyser.fftSize=2*CSpectrum; + for(var i=0;i<CSpectrum;++i)caps[i]=0; +} + +function init() +{ + if( navigator.userAgent.match(/Android/i) + || navigator.userAgent.match(/webOS/i) + || navigator.userAgent.match(/iPhone/i) + || navigator.userAgent.match(/iPad/i) + || navigator.userAgent.match(/iPod/i) + || navigator.userAgent.match(/BlackBerry/i) + || navigator.userAgent.match(/Windows Phone/i) + ) + { + visualselector=document.getElementById("playlist").style.width="90%"; + document.getElementById("help").style.maxWidth=window.innerWidth+"px"; + if(window.innerWidth<window.innerHeight) + document.getElementById("cvs").width=screen.width*0.98, + document.getElementById("cvs").height=(screen.width*0.98/16*9); + else + document.getElementById("cvs").width=(screen.height*0.98/9*16), + document.getElementById("cvs").height=screen.height*0.98; + } + if(!window.devicePixelRatio)window.devicePixelRatio=1; + document.getElementById("cvs").style.width=document.getElementById("cvs").width+"px"; + document.getElementById("cvs").style.height=document.getElementById("cvs").height+"px"; + document.getElementById("cvs").width=document.getElementById("cvs").width*window.devicePixelRatio; + document.getElementById("cvs").height=document.getElementById("cvs").height*window.devicePixelRatio; + current=0; + visualselector=document.getElementById("visualizationsel"); + canvas=document.getElementById("cvs"); + audio=document.getElementById("audio"); + playlist=$('#playlist'); + tracks=playlist.find('li a'); + len=tracks.length;SpecRingRadius=canvas.width/2; + audio.volume=.80;SpecWidth=canvas.width/CSpectrum;SpecGap=SpecWidth/10;SpecWidth*=0.9; + initAPI();inkPrepare();document.onmousemove=mm; + CtxtSource=audioCtxt.createMediaElementSource(audio); + CtxtSource.connect(CtxtAnalyser); + CtxtAnalyser.connect(audioCtxt.destination); + plistRect=document.getElementById("playlist").getBoundingClientRect(); + for(var i=0;i<playlist.find('a').length;++i) + { + if(playlist.find('a')[i].textContent==decodeURIComponent(gup('title'))) + {current=i;run($(playlist.find('a')[i]));break;} + } + playlist.find('a').click(function(e){ + e.preventDefault(); + link=$(this); + current=link.parent().index()-1; + run(link); + }); + visualselector.onchange=function(){ + if(this.value!="none"&&this.oldvalue=="none")requestAnimationFrame(updateVisualization); + else canvas.getContext('2d').clearRect(0,0,canvas.width,canvas.height); + document.cookie="playervisualization="+this.value; + this.oldvalue=this.value; + }; + window.onresize=windowresize; + audio.ontimeupdate=timeUpdate; + audio.addEventListener('ended',function(e){ + if(repeat==0) + { + current++; + if(current==len){ + current=0; + if(shuffle)shufflePlist(); + link=playlist.find('a')[0]; + }else{ + link=playlist.find('a')[current]; + } + run($(link)); + } + }); + document.getElementById("shufflesw").onclick=function(){ + shuffle=1-shuffle; + if(shuffle==0) + { + document.getElementById("shufflesw").innerHTML="Off"; + document.cookie="playershuffle=0"; + sortPlist(); + } + else + { + document.getElementById("shufflesw").innerHTML="On"; + document.cookie="playershuffle=1"; + shufflePlist(); + } + } + document.getElementById("repeatsw").onclick=function(){ + repeat=1-repeat; + if(repeat==0) + { + document.getElementById("repeatsw").innerHTML="Off"; + document.cookie="playerrepeat=0"; + audio.loop=false; + } + else + { + document.getElementById("repeatsw").innerHTML="On"; + document.cookie="playerrepeat=1"; + audio.loop=true; + } + } + document.getElementById("plistsw").onclick=togglePlist; + document.body.onmousedown=function(e){if(e.buttons==1)mbuttonstate=1;} + document.body.onmouseup=function(e){if(e.buttons!=1)mbuttonstate=0;} + document.getElementById("tsliderbase").onclick=function(e) + { + var sr=this.getBoundingClientRect(); + var p=(e.clientX-sr.left)/sr.width; + audio.currentTime=audio.duration*p; + } + document.getElementById("tsliderbase").onmousemove=function(e) + { + if(!mbuttonstate)return; + var sr=this.getBoundingClientRect(); + var p=(e.clientX-sr.left)/sr.width; + audio.currentTime=audio.duration*p; + } + document.getElementById("pbplaypause").onclick=function() + { + if(audio.src==""){run($(playlist.find('a')[0]));return;} + if(audio.paused) + { + audio.play(); + document.getElementById("imgplaypause").src="pause.svg"; + } + else + { + audio.pause(); + document.getElementById("imgplaypause").src="play.svg"; + } + } + document.getElementById("pbprev").onclick=function() + { + if(audio.currentTime>10)audio.currentTime=0; + else + { + current--; + if(current<0){ + current+=len; + if(shuffle)shufflePlist(); + link=playlist.find('a')[len-1]; + }else{ + link=playlist.find('a')[current]; + } + run($(link)); + } + } + document.getElementById("pbnext").onclick=function() + { + current++; + if(current==len){ + current=0; + if(shuffle)shufflePlist(); + link=playlist.find('a')[0]; + }else{ + link=playlist.find('a')[current]; + } + run($(link)); + } + switch(getcookie("playershuffle")) + { + case "1": + document.getElementById("shufflesw").innerHTML="On"; + document.cookie="playershuffle=1"; + shufflePlist(); + break; + default: + case "0": + document.getElementById("shufflesw").innerHTML="Off"; + document.cookie="playershuffle=0"; + sortPlist(); + break; + } + switch(getcookie("playerrepeat")) + { + case "1": + document.getElementById("repeatsw").innerHTML="On"; + document.cookie="playerrepeat=1"; + audio.loop=true; + break; + default: + case "0": + document.getElementById("repeatsw").innerHTML="Off"; + document.cookie="playerrepeat=0"; + audio.loop=false; + break; + } + if(getcookie("playervisualization").length!==0) + visualselector.value=getcookie("playervisualization"); + requestAnimationFrame(updateVisualization); +} +function shufflePlist() +{ + for(var i=0;i<playlist.find('a').length;++i) + $(playlist.find('a')[i]).attr("sord",Math.random()*playlist.find('a').length); + var plli=$(playlist).children('li'); + plli.sort( + function(a,b) + { + var as=Number($(a).children('a').attr("sord")); + var bs=Number($(b).children('a').attr("sord")); + return as>bs?1:as<bs?-1:0; + } + ); + plli.detach().appendTo($(playlist)); + var t=$("li.active").children().length?$("li.active").children()[0].textContent:""; + for(var i=0;i<playlist.find('a').length;++i) + { + if(playlist.find('a')[i].textContent==t) + {current=i;break;} + } +} +function sortPlist() +{ + var plli=$(playlist).children('li'); + plli.sort( + function(a,b) + { + var as=Number($(a).children('a').attr("ord")); + var bs=Number($(b).children('a').attr("ord")); + return as>bs?1:as<bs?-1:0; + } + ); + plli.detach().appendTo($(playlist)); + var t=$("li.active").children().length?$("li.active").children()[0].textContent:""; + for(var i=0;i<playlist.find('a').length;++i) + { + if(playlist.find('a')[i].textContent==t) + {current=i;break;} + } +} +function formatTime(t) +{ + var m=Math.floor(t/60),s=Math.round(t-Math.floor(t/60)*60); + if(s<10)return m+":0"+s; + else if(s==60)return (m+1)+":00"; + else return m+":"+s; +} +function bufferedUpdate() +{ + var r=0; + for(var i=0;i<audio.buffered.length;++i) + r=r<audio.buffered.end(i)?audio.buffered.end(i):r; + document.getElementById("cbuff").style.width=r/audio.duration*100+"%"; +} +function timeUpdate() +{ + document.getElementById("timenow").innerHTML=formatTime(audio.currentTime); + document.getElementById("timeleft").innerHTML="-"+formatTime(audio.duration-audio.currentTime); + document.getElementById("ctime").style.width=audio.currentTime/audio.duration*100+"%"; + bufferedUpdate(); +} +function mm(e) +{ + /*if(e.clientX<320&&e.clientY>(window.innerHeight-383)) + { + changeImage('../../../koishi_hovr.png'); + document.getElementById("aqt").style.opacity="0.5"; + } + else + { + changeImage('../../../koishi_norm.png'); + document.getElementById("aqt").style.opacity="1.0"; + }*/ +} +function windowresize() +{ + if(plistshown) + { + document.getElementById("playlist").style.left=(window.innerWidth-plistRect.width)/2+"px"; + plistRect=document.getElementById("playlist").getBoundingClientRect(); + } + else + { + } +} +function run(link) +{ + var trurl=""; + if(window.location.href.indexOf("&title=")==-1) + trurl=window.location.href; + else + trurl=window.location.href.substr(0,window.location.href.indexOf("&title=")); + trurl=trurl.concat("&title="); + trurl=trurl.concat(link.attr('tr')); + window.history.replaceState("","The Stupid Online Player",trurl); + document.getElementById("imgplaypause").src="pause.svg"; + audio.src=link.attr('href'); + document.getElementById("nowplaying").innerHTML="Now Playing: "+link.attr('tr'); + par=link.parent(); + par.addClass('active').siblings().removeClass('active'); + audio.load(); + audio.play(); +} + +function togglePlist() +{ + document.getElementById("plistsw").onclick=function(){}; + plistshown=!plistshown; + if(plistshown) + { + for(var i=0;i<playlist.find('a').length;++i) + $(playlist.find('a')[i]).css("transition","0.8s"); + document.getElementById("plistsw").innerHTML="[↓Hide Playlist]"; + setTimeout( + function(){ + document.getElementById("playlist").style.left=(window.innerWidth-plistRect.width)/2+"px"; + document.getElementById("playlist").style.top=document.getElementById("plistref").getBoundingClientRect().top+"px"; + document.getElementById("playlist").style.background="rgba(153,187,238,0.6)"; + for(var i=0;i<playlist.find('a').length;++i) + $(playlist.find('a')[i]).css("color",""); + } + ,40); + setTimeout( + function(){ + document.getElementById("playlist").style.position="static"; + document.getElementById("plistsw").onclick=togglePlist; + plistRect=document.getElementById("playlist").getBoundingClientRect(); + for(var i=0;i<playlist.find('a').length;++i) + $(playlist.find('a')[i]).css("transition","none"); + } + ,840); + } + else + { + var d=$(document).scrollTop(); + $('html,body').stop().animate({scrollTop:0},d); + setTimeout( + function(){ + plistRect=document.getElementById("playlist").getBoundingClientRect(); + document.getElementById("playlist").style.position="fixed"; + document.getElementById("playlist").style.top=plistRect.top+"px"; + document.getElementById("playlist").style.left=plistRect.left+"px"; + for(var i=0;i<playlist.find('a').length;++i) + $(playlist.find('a')[i]).css("transition","0.8s"); + }, + d+1); + setTimeout( + function(){ + document.getElementById("playlist").style.top="100%"; + document.getElementById("playlist").style.background="rgba(153,187,238,0)"; + document.getElementById("plistsw").onclick=togglePlist; + for(var i=0;i<playlist.find('a').length;++i) + $(playlist.find('a')[i]).css("color",$(playlist.find('a')[i]).hasClass("active")?"rgba(255,204,0,0);":"rgba(32,172,255,0)"); + }, + d+5); + document.getElementById("plistsw").innerHTML="[↑Show Playlist]"; + } +} + +function updateVisualization() +{ + if(visualselector.value=="spectrum") + { + var cctx=canvas.getContext('2d'); + cctx.clearRect(0,0,canvas.width,canvas.height); + try{ + var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount); + CtxtAnalyser.getByteFrequencyData(freqarr); + for(var i=0;i<CSpectrum;++i) + { + var color='hsl('+i*360.0/CSpectrum+',100%,50%)'; + cctx.fillStyle=color; + cctx.fillRect(i*(SpecWidth+SpecGap),canvas.height-(canvas.height*freqarr[i]/255.),SpecWidth,canvas.height*freqarr[i]/255.); + if(caps[i]<freqarr[i])caps[i]=freqarr[i];else if(caps[i]>0)--caps[i]; + color='hsl('+i*360.0/CSpectrum+',100%,25%)'; + cctx.fillStyle=color; + cctx.fillRect(i*(SpecWidth+SpecGap),canvas.height-(canvas.height*caps[i]/255.)-1,SpecWidth,1); + } + }catch(e){ + if(caps[i]>0)--caps[i]; + color='hsl('+i*360.0/CSpectrum+',100%,25%)'; + cctx.fillStyle=color; + cctx.fillRect(i*(SpecWidth+SpecGap),canvas.height-caps[i]-1,SpecWidth,1); + }; + } + if(visualselector.value=="spectrumring") + { + var cctx=canvas.getContext('2d'); + cctx.clearRect(0,0,canvas.width,canvas.height); + try{ + var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount); + CtxtAnalyser.getByteFrequencyData(freqarr); + for(var i=0;i<CSpectrum;++i) + { + var color='hsl('+i*360.0/CSpectrum+',100%,50%)'; + cctx.strokeStyle=color; + cctx.beginPath();cctx.moveTo(canvas.width/2.,canvas.height/2.); + cctx.lineTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*freqarr[i]/255., + canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*freqarr[i]/255.); + cctx.stroke(); + if(caps[i]<freqarr[i])caps[i]=freqarr[i];else if(caps[i]>0)--caps[i]; + color='hsl('+i*360.0/CSpectrum+',100%,25%)'; + cctx.strokeStyle=color; + cctx.beginPath(); + cctx.moveTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255., + canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255.); + cctx.lineTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255., + canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255.); + cctx.stroke(); + } + }catch(e){ + if(caps[i]>0)--caps[i]; + color='hsl('+i*360.0/CSpectrum+',100%,25%)'; + cctx.strokeStyle=color; + cctx.moveTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255., + canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255.); + cctx.lineTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255., + canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255.); + cctx.stroke(); + }; + } + if(visualselector.value=="scope") + { + var cctx=canvas.getContext('2d'); + cctx.clearRect(0,0,canvas.width,canvas.height); + try{ + var tdomainarr=new Uint8Array(CtxtAnalyser.frequencyBinCount); + CtxtAnalyser.getByteTimeDomainData(tdomainarr); + cctx.lineWidth=dpiratio; + cctx.strokeStyle="#000"; + cctx.beginPath(); + var x=0; + for(var i=0;i<CSpectrum;++i) + { + if(i==0)cctx.moveTo(x,tdomainarr[i]/128.*canvas.height/2); + else cctx.lineTo(x,tdomainarr[i]/128.*canvas.height/2); + x+=canvas.width*1./CSpectrum; + } + cctx.stroke(); + }catch(e){ + console.log(e.message); + }; + } + if(visualselector.value=="spectrogram") + { + var cctx=canvas.getContext('2d'); + try{ + var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount); + CtxtAnalyser.getByteFrequencyData(freqarr); + cctx.clearRect(spectrogrampos/1800*canvas.width,0,canvas.width/1800,canvas.height); + for(var i=0;i<CSpectrum;++i) + { + var color='rgba(0,0,0,'+freqarr[i]/256.+')'; + cctx.fillStyle=color; + cctx.fillRect(spectrogrampos/1800*canvas.width,(CSpectrum-i)/CSpectrum*canvas.height,canvas.width/1800.,canvas.height/CSpectrum); + } + ++spectrogrampos;if(spectrogrampos>=1800)spectrogrampos=0; + }catch(e){ + }; + } + if(visualselector.value=="inkfountain") + { + var cctx=canvas.getContext('2d'),ts=Date.now(),tu; + cctx.clearRect(0,0,canvas.width,canvas.height); + ++frms;if(Date.now()-lastfpsupd>500){if(lastfpsupd)fps=1000*frms/(Date.now()-lastfpsupd),frms=0;lastfpsupd=Date.now();} + try{ + var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount); + CtxtAnalyser.getByteFrequencyData(freqarr); + for(var i=0;i<CSpectrumIF;++i) + { + var r=0; + for(var j=0;j<8;++j)r+=freqarr[i*8+j]; + r/=8.; + if(r-caps[i]>7) + { + var color=Math.floor(i*8.0/CSpectrumIF),rad=Math.random()*Math.PI*2; + var ndrops=(128-i)/128.*3+1;ndrops*=(r/128.);ndrops=Math.floor(ndrops);if(ndrops<1)ndrops=1; + for(var k=0;k<ndrops;++k) + { + createInk(((r-caps[i]-7)/32*24+12)*Math.cos(rad),((r-caps[i]-7)/32*24+12)*Math.sin(rad),color); + rad=Math.random()*Math.PI*2; + } + } + if(r>caps[i])caps[i]=r;else caps[i]-=2; + } + }catch(e){ + console.log(e.message); + }; + tu=Date.now(); + var aa=0; + for(var i=0;i<inks.length;++i){ + if(inks[i].active){inks[i].update();inks[i].draw(cctx);++aa} + } + cctx.fillStyle="#000"; + cctx.font="1em Courier, monospace"; + cctx.fillText("Active droplets "+aa+", "+fps.toFixed(2)+" FPS",0,10); + cctx.fillText("Update time "+(tu-ts)+"ms, render time "+(Date.now()-tu)+"ms",0,24); + } + if(visualselector.value=="shakeurbody") + { + var cctx=canvas.getContext('2d'); + cctx.clearRect(0,0,canvas.width,canvas.height); + try{ + var tdomainarr=new Float32Array(CtxtAnalyser.frequencyBinCount); + CtxtAnalyser.getFloatTimeDomainData(tdomainarr); + for(var i=0;i<CSpectrum;++i) + { + var kbf=1/(audioCtxt.sampleRate*lpf),br=Math.exp(-1/(audioCtxt.sampleRate*beatr)); + f1+=(kbf*(tdomainarr[i]-f1)); + f2+=(kbf*(f1-f2)); + var env=Math.abs(f2); + if(env>penv)penv=env;else{penv*=br;penv+=(1-br)*env;} + if(!btrig){if(penv>0.20)btrig=1;}else{if(penv<0.125)btrig=0;} + beatp=0;if(btrig&&!lastbp)beatp=1;lastbp=beatp; + if(beatp)document.body.style.transform='translateY(100px)';else document.body.style.transform='translateY(0px)'; + } + }catch(e){ + document.body.style.transform='translateY(0px)'; + }; + }else document.body.style.transform='none'; + if(visualselector.value!="none") + af=requestAnimationFrame(updateVisualization); +} |