summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2020-05-22 12:00:00 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2020-05-22 12:00:00 +0800
commit5e21f50d81e387b00a511afc711109bc846618ce (patch)
tree87e03040544f2ddc7297e9b20c21fa0a0a47ae19 /libs
parent53c0831cab3bc85621e10faa77a8895a641069f7 (diff)
downloadweb-5e21f50d81e387b00a511afc711109bc846618ce.tar.xz
Improved simulation for the spectrum visualization from ShadowPlayer.
Also re-indented the entire file so that it doesn't set the reader's eyes on fire.
Diffstat (limited to 'libs')
-rw-r--r--libs/music/player.d/main_static.js1374
1 files changed, 689 insertions, 685 deletions
diff --git a/libs/music/player.d/main_static.js b/libs/music/player.d/main_static.js
index f4077bb..fe30cca 100644
--- a/libs/music/player.d/main_static.js
+++ b/libs/music/player.d/main_static.js
@@ -8,499 +8,500 @@ let NSPlayer=null;
let NSUI=null;
const sh={
- elem:function(e)
- {return document.getElementById(e);},
- newelem:function(e)
- {return document.createElement(e);},
- getcookie:function(key)
- {return document.cookie.replace(new RegExp('(?:(?:^|.*;\\s*)'+key+'\\s*\\=\\s*([^;]*).*$)|^.*$'),'$1');},
- useFLAC:function()
- {return sh.elem('audio').canPlayType('audio/ogg')=='';}
+ elem:function(e)
+ {return document.getElementById(e);},
+ newelem:function(e)
+ {return document.createElement(e);},
+ getcookie:function(key)
+ {return document.cookie.replace(new RegExp('(?:(?:^|.*;\\s*)'+key+'\\s*\\=\\s*([^;]*).*$)|^.*$'),'$1');},
+ useFLAC:function()
+ {return sh.elem('audio').canPlayType('audio/ogg')=='';}
};
class Ink
{
- constructor(_vx,_vy,_c)
- {
- this.x=NSUI.canvas.width/2;this.y=NSUI.canvas.height/2;
- this.vx=_vx;this.vy=_vy;
- this.color=_c>6?6:_c;this.active=true;
- }
- update()
- {
- const canvas=NSUI.canvas;
- 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;
- }
- draw(cctx)
- {
- cctx.drawImage(NSInk.inkimg[this.color],this.x+5*window.devicePixelRatio,this.y+5*window.devicePixelRatio);
- }
+ constructor(_vx,_vy,_c)
+ {
+ this.x=NSUI.canvas.width/2;this.y=NSUI.canvas.height/2;
+ this.vx=_vx;this.vy=_vy;
+ this.color=_c>6?6:_c;this.active=true;
+ }
+ update()
+ {
+ const canvas=NSUI.canvas;
+ 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;
+ }
+ draw(cctx)
+ {
+ cctx.drawImage(NSInk.inkimg[this.color],this.x+5*window.devicePixelRatio,this.y+5*window.devicePixelRatio);
+ }
}
NSPlayer={
- plistname:null,
- tracks:null,
- current:null,
- shuffle:0,
- repeat:0,
- load_playlist:async function(pln,ord)
- {
- let r=null;
- try{
- const resp=await fetch(new Request(`/libs/music/player.d/playlists/${pln}.playlist?${new Date().getTime()}`));
- r=await resp.text();
- }catch(e){return;}
- let rarr=r.split('\n');
- let tarr=[];
- const fmt=sh.useFLAC()?'flac':'ogg';
- for(let i=1;i<rarr.length;++i)
- {
- let t=rarr[i].trim();
- if(!t.length)continue;
- let titem={};
- titem.title=t;
- titem.ord=i-1;
- titem.src=`//filestorage.chrisoft.org/music/${fmt}/${t}.${fmt}`;
- tarr.push(titem);
- }
- return ({plistname:pln,playlist:tarr,plistord:ord});
- },
- play:function(id)
- {
- if(!this.plistname)return;
- window.history.replaceState('','The Stupid Online Player',
- `#${encodeURIComponent(this.plistname)}/${encodeURIComponent(this.tracks[id].title)}`);
- NSUI.iplaypause.style.backgroundPosition=`${NSUI.bpauserect}`;
- this.current=id;
- NSUI.lbnowplaying.innerHTML=`Now Playing: ${this.tracks[id].title}`;
- if(navigator.mediaSession)
- navigator.mediaSession.metadata=new MediaMetadata({title:this.tracks[id].title,album:this.plistname});
- NSUI.set_highlighted(this.plistname,this.tracks[id].title);
- NSUI.audio.src=this.tracks[id].src;
- NSUI.audio.load();
- NSUI.audio.play();
- },
- next:function()
- {
- this.current=(this.current+1)%this.tracks.length;
- if(this.current==0&&this.shuffle)
- NSUI.switch_playlist(this.plistname);
- this.play(this.current);
- },
- prev:function()
- {
- this.current=(this.current-1+this.tracks.length)%this.tracks.length;
- this.play(this.current);
- },
- switch_playlist:function(plistname,plist)
- {
- this.plistname=plistname;
- this.tracks=plist;
- },
- sort_playlist:function(shuffle,plist)
- {
- const tarr=plist?plist:this.tracks;
- if(!tarr)return;
- if(shuffle)
- for(let i=0;i<tarr.length;++i)
- tarr[i].sord=Math.random()*tarr.length;
- tarr.sort(
- (a,b)=>{
- const ra=shuffle?a.sord:a.ord;
- const rb=shuffle?b.sord:b.ord;
- return ra<rb?-1:1;
- }
- );
- if(plist)plist=tarr;else this.tracks=tarr;
- }
+ plistname:null,
+ tracks:null,
+ current:null,
+ shuffle:0,
+ repeat:0,
+ load_playlist:async function(pln,ord)
+ {
+ let r=null;
+ try{
+ const resp=await fetch(new Request(`/libs/music/player.d/playlists/${pln}.playlist?${new Date().getTime()}`));
+ r=await resp.text();
+ }catch(e){return;}
+ let rarr=r.split('\n');
+ let tarr=[];
+ const fmt=sh.useFLAC()?'flac':'ogg';
+ for(let i=1;i<rarr.length;++i)
+ {
+ let t=rarr[i].trim();
+ if(!t.length)continue;
+ let titem={};
+ titem.title=t;
+ titem.ord=i-1;
+ titem.src=`//filestorage.chrisoft.org/music/${fmt}/${t}.${fmt}`;
+ tarr.push(titem);
+ }
+ return ({plistname:pln,playlist:tarr,plistord:ord});
+ },
+ play:function(id)
+ {
+ if(!this.plistname)return;
+ window.history.replaceState('','The Stupid Online Player',
+ `#${encodeURIComponent(this.plistname)}/${encodeURIComponent(this.tracks[id].title)}`);
+ NSUI.iplaypause.style.backgroundPosition=`${NSUI.bpauserect}`;
+ this.current=id;
+ NSUI.lbnowplaying.innerHTML=`Now Playing: ${this.tracks[id].title}`;
+ if(navigator.mediaSession)
+ navigator.mediaSession.metadata=new MediaMetadata({title:this.tracks[id].title,album:this.plistname});
+ NSUI.set_highlighted(this.plistname,this.tracks[id].title);
+ NSUI.audio.src=this.tracks[id].src;
+ NSUI.audio.load();
+ NSUI.audio.play();
+ },
+ next:function()
+ {
+ this.current=(this.current+1)%this.tracks.length;
+ if(this.current==0&&this.shuffle)
+ NSUI.switch_playlist(this.plistname);
+ this.play(this.current);
+ },
+ prev:function()
+ {
+ this.current=(this.current-1+this.tracks.length)%this.tracks.length;
+ this.play(this.current);
+ },
+ switch_playlist:function(plistname,plist)
+ {
+ this.plistname=plistname;
+ this.tracks=plist;
+ },
+ sort_playlist:function(shuffle,plist)
+ {
+ const tarr=plist?plist:this.tracks;
+ if(!tarr)return;
+ if(shuffle)
+ for(let i=0;i<tarr.length;++i)
+ tarr[i].sord=Math.random()*tarr.length;
+ tarr.sort(
+ (a,b)=>{
+ const ra=shuffle?a.sord:a.ord;
+ const rb=shuffle?b.sord:b.ord;
+ return ra<rb?-1:1;
+ }
+ );
+ if(plist)plist=tarr;else this.tracks=tarr;
+ }
};
NSUI={
- playlist:null,
- audio:null,
- canvas:null,
- iplaypause:null,
- irepeat:null,
- ishuffle:null,
- lbnowplaying:null,
- playlists:null,
- ulplaylists:null,
- swplaylist:null,
- selectedplist:null,
- vissel:null,
- pbnext:null,
- pbprev:null,
- ctrlcontainer:null,
- am3u8:null,
- bplayrect:"0 -48px",
- bpauserect:"-24px -48px",
- brallrect:"-24px -24px",
- brnonrect:"-48px -24px",
- bronerect:"0 0",
- bsoffrect:"-24px 0",
- bshonrect:"-48px 0",
- plistshown:true,
- setup_ui:function()
- {
- window.devicePixelRatio=window.devicePixelRatio?window.devicePixelRatio:1;
- window.onresize=function()
- {
- if(window.innerWidth<768)
- setupevents();
- else unsetevents();
- };
- window.onresize();
- this.playlist=sh.elem('playlist');
- this.swplaylist=sh.elem('plistsw');
- this.audio=sh.elem('audio');
- this.canvas=sh.elem('cvs');
- this.iplaypause=sh.elem('imgplaypause');
- this.irepeat=sh.elem('imgrepeat');
- this.ishuffle=sh.elem('imgshuffle');
- this.lbnowplaying=sh.elem('nowplaying');
- this.ulplaylists=sh.elem('plists');
- this.vissel=sh.elem('visualizationsel');
- this.pbnext=sh.elem('pbnext');
- this.pbprev=sh.elem('pbprev');
- this.ctrlcontainer=sh.elem('ctrlcontainer');
- this.am3u8=sh.elem('am3u8');
- NSUI.canvas.width=NSUI.canvas.clientWidth*window.devicePixelRatio;
- NSUI.canvas.height=NSUI.canvas.clientHeight*window.devicePixelRatio;
- NSUI.vissel.onchange=function(){
- if(this.value!='none'&&this.oldvalue=='none')requestAnimationFrame(NSVisualization.updateVisualization);
- else NSUI.canvas.getContext('2d').clearRect(0,0,NSUI.canvas.width,NSUI.canvas.height);
- document.cookie='playervisualization='+this.value;
- this.oldvalue=this.value;
- };
- document.getElementById('shufflesw').onclick=function(){
- NSUI.shuffle_switch(NSPlayer.shuffle=1-NSPlayer.shuffle);
- NSUI.ishuffle.style.backgroundPosition=`${NSPlayer.shuffle?NSUI.bshonrect:NSUI.bsoffrect}`;
- document.cookie=`playershuffle=${NSPlayer.shuffle}`;
- };
- document.getElementById('repeatsw').onclick=function(){
- NSPlayer.repeat=1-NSPlayer.repeat;
- NSUI.audio.loop=NSPlayer.repeat?true:false;
- NSUI.irepeat.style.backgroundPosition=`${NSPlayer.repeat?NSUI.bronerect:NSUI.brallrect}`;
- document.cookie=`playerrepeat=${NSPlayer.repeat}`;
- };
- document.getElementById('plistsw').onclick=NSUI.togglePlist;
- document.getElementById('tsliderbase').onclick=
- document.getElementById('tsliderbase').onmousemove=function(e)
- {
- if(e.type=='click'||(e.type=='mousemove'&&e.buttons==1))
- {
- const sr=this.getBoundingClientRect();
- const p=(e.clientX-sr.left)/sr.width;
- NSUI.audio.currentTime=NSUI.audio.duration*p;
- }
- };
- const playpausef=function()
- {
- if(NSUI.audio.src=='')
- {
- if(NSUI.selectedplist)
- {
- NSUI.switch_playlist(NSUI.selectedplist);
- NSUI.switch_track(0);
- }
- return;
- }
- if(NSUI.audio.paused)
- {
- NSUI.audio.play();
- NSUI.iplaypause.style.backgroundPosition=`${NSUI.bpauserect}`;
- }
- else
- {
- NSUI.audio.pause();
- NSUI.iplaypause.style.backgroundPosition=`${NSUI.bplayrect}`;
- }
- };
- NSUI.iplaypause.onclick=playpausef;
- NSUI.pbprev.onclick=function()
- {
- if(NSUI.audio.currentTime>10)NSUI.audio.currentTime=0;
- else NSPlayer.prev();
- };
- NSUI.pbnext.onclick=NSPlayer.next.bind(NSPlayer);
- if(navigator.mediaSession)
- {
- navigator.mediaSession.setActionHandler('previoustrack',NSUI.pbprev.onclick);
- navigator.mediaSession.setActionHandler('nexttrack',NSUI.pbnext.onclick);
- }
- window.onkeydown=function(e)
- {
- if(e.key==' ')
- {
- playpausef();
- return false;
- }
- if(e.key=='c')
- if(NSUI.audio.audioTracks.length==2)
- {
- const t=NSUI.audio.currentTime;
- NSUI.audio.audioTracks[0].enabled^=1;
- NSUI.audio.audioTracks[1].enabled^=1;
- NSUI.audio.currentTime=t;
- }
- return true;
- };
- },
- load_playlists:async function()
- {
- const moi=this;
- let r=null;
- try{
- const resp=await fetch(new Request(`/libs/music/player.d/playlists/playlists?${new Date().getTime()}`));
- r=await resp.text();
- }catch(e){return;}
- let rarr=r.split('\n');
- let tarr=[];
- let cnt=0;
- for(let i=0;i<rarr.length;++i)
- if(rarr[i].trim().length)++cnt;
- const p=new Promise((a,b)=>{
- for(let i=0;i<rarr.length;++i)
- {
- let t=rarr[i].trim();
- if(!t.length)continue;
- NSPlayer.load_playlist(t,i).then((rp)=>{
- tarr[rp.plistord]=rp;
- if(--cnt<=0)a(null);
- });
- }
- });
- await p;
- for(let i=0;i<tarr.length;++i)
- {
- const e=sh.newelem('li');
- const ea=sh.newelem('a');
- ea.innerHTML=tarr[i].plistname;
- ea.classList.add('listitem');
- ea.href='javascript:void(0);';
- ea.pid=i;
- ea.onclick=function(e){
- e.preventDefault();
- for(let i=0;i<NSUI.ulplaylists.childNodes.length;++i)
- {
- const ta=NSUI.ulplaylists.childNodes[i].firstChild;
- if(ta.pid==this.pid)
- {ta.classList.add('highlighted');ta.classList.add('active');}
- else{ta.classList.remove('highlighted');ta.classList.remove('active');}
- }
- NSUI.present_playlist.bind(NSUI,this.pid)();
- if(NSPlayer.current)
- NSUI.set_highlighted(NSPlayer.plistname,NSPlayer.tracks[NSPlayer.current].title);
- };
- e.appendChild(ea);
- NSUI.ulplaylists.appendChild(e);
- }
- moi.playlists=tarr;
- },
- present_playlist:function(id)
- {
- while(this.playlist.firstChild)
- this.playlist.removeChild(this.playlist.firstChild);
- const list=this.playlists[id].playlist;
- for(let i=0;i<list.length;++i)
- {
- const l=sh.newelem('li');
- const a=sh.newelem('a');
- a.innerHTML=list[i].title;
- a.href=list[i].src;
- a.ord=i;
- a.onclick=function(e){e.preventDefault();NSUI.switch_track.bind(NSUI,this.ord)();};
- l.appendChild(a);
- this.playlist.appendChild(l);
- }
- const d=sh.newelem('div');d.style.height=`${NSUI.ctrlcontainer.getBoundingClientRect().height+16}px`;
- this.playlist.appendChild(d);
- this.selectedplist=this.playlists[id].plistname;
- this.am3u8.href=`https://chrisoft.org/libs/music/player.d/cgi-bin/m3u8.cgi?plist=${this.playlists[id].plistname}`;
- },
- switch_playlist:function(pl,setactive)
- {
- let cid=0;
- for(;cid<this.playlists.length;++cid)
- if(this.playlists[cid].plistname==pl)break;
- if(cid>=this.playlists.length)return;
- if(setactive)
- {
- NSUI.ulplaylists.childNodes[cid].firstChild.classList.add('highlighted');
- NSUI.ulplaylists.childNodes[cid].firstChild.classList.add('active');
- }
- //VERY stupid design, but it _should_ work.
- NSPlayer.switch_playlist(pl,this.playlists[cid].playlist);
- NSPlayer.sort_playlist(NSPlayer.shuffle);
- this.playlists[cid].playlist=NSPlayer.tracks;
- this.present_playlist(cid);
- this.selectedplist=pl;
- },
- switch_track:function(id)
- {
- if(NSPlayer.plistname!=this.selectedplist)
- this.switch_playlist(this.selectedplist);
- NSPlayer.play(id);
- },
- set_highlighted:function(pl,t)
- {
- if(pl!=this.selectedplist)return;
- let cid=0;
- for(;cid<this.playlists.length;++cid)
- if(this.playlists[cid].plistname==pl)break;
- const clist=this.playlists[cid].playlist;
- for(let i=0;i<clist.length;++i)
- if(clist[i].title==t)
- this.playlist.childNodes[i].firstChild.classList.add('highlighted');
- else
- this.playlist.childNodes[i].firstChild.classList.remove('highlighted');
- },
- shuffle_switch:function(shuffle)
- {
- for(let i=0;i<this.playlists.length;++i)
- {
- NSPlayer.sort_playlist(shuffle,this.playlists[i].playlist);
- if(i==this.selectedplist)this.present_playlist(i);
- }
- NSPlayer.sort_playlist(shuffle);
- },
- togglePlist:function()
- {
- NSUI.plistshown=!NSUI.plistshown;
- NSUI.swplaylist.innerHTML=`[${NSUI.plistshown?'Hide':'Show'} Playlist]`;
- NSUI.playlist.style.opacity=NSUI.plistshown?'1':'0';
- NSUI.playlist.style.pointerEvents=NSUI.plistshown?'auto':'none';
- },
- formatTime:function(t)
- {
- if(isNaN(t))return '-:--';
- let 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}`;
- },
- bufferedUpdate:function()
- {
- let r=0;
- for(let i=0;i<NSUI.audio.buffered.length;++i)
- r=r<NSUI.audio.buffered.end(i)?NSUI.audio.buffered.end(i):r;
- document.getElementById('cbuff').style.width=r/NSUI.audio.duration*100+'%';
- },
- timeUpdate:function()
- {
- document.getElementById('timenow').innerHTML=NSUI.formatTime(NSUI.audio.currentTime);
- document.getElementById('timeleft').innerHTML=`-${NSUI.formatTime(NSUI.audio.duration-NSUI.audio.currentTime)}`;
- document.getElementById('ctime').style.width=NSUI.audio.currentTime/NSUI.audio.duration*100+'%';
- NSUI.bufferedUpdate();
- }
+ playlist:null,
+ audio:null,
+ canvas:null,
+ iplaypause:null,
+ irepeat:null,
+ ishuffle:null,
+ lbnowplaying:null,
+ playlists:null,
+ ulplaylists:null,
+ swplaylist:null,
+ selectedplist:null,
+ vissel:null,
+ pbnext:null,
+ pbprev:null,
+ ctrlcontainer:null,
+ am3u8:null,
+ bplayrect:"0 -48px",
+ bpauserect:"-24px -48px",
+ brallrect:"-24px -24px",
+ brnonrect:"-48px -24px",
+ bronerect:"0 0",
+ bsoffrect:"-24px 0",
+ bshonrect:"-48px 0",
+ plistshown:true,
+ setup_ui:function()
+ {
+ window.devicePixelRatio=window.devicePixelRatio?window.devicePixelRatio:1;
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ };
+ window.onresize();
+ this.playlist=sh.elem('playlist');
+ this.swplaylist=sh.elem('plistsw');
+ this.audio=sh.elem('audio');
+ this.canvas=sh.elem('cvs');
+ this.iplaypause=sh.elem('imgplaypause');
+ this.irepeat=sh.elem('imgrepeat');
+ this.ishuffle=sh.elem('imgshuffle');
+ this.lbnowplaying=sh.elem('nowplaying');
+ this.ulplaylists=sh.elem('plists');
+ this.vissel=sh.elem('visualizationsel');
+ this.pbnext=sh.elem('pbnext');
+ this.pbprev=sh.elem('pbprev');
+ this.ctrlcontainer=sh.elem('ctrlcontainer');
+ this.am3u8=sh.elem('am3u8');
+ NSUI.canvas.width=NSUI.canvas.clientWidth*window.devicePixelRatio;
+ NSUI.canvas.height=NSUI.canvas.clientHeight*window.devicePixelRatio;
+ NSUI.vissel.onchange=function(){
+ if(this.value!='none'&&this.oldvalue=='none')requestAnimationFrame(NSVisualization.updateVisualization);
+ else NSUI.canvas.getContext('2d').clearRect(0,0,NSUI.canvas.width,NSUI.canvas.height);
+ document.cookie='playervisualization='+this.value;
+ this.oldvalue=this.value;
+ };
+ document.getElementById('shufflesw').onclick=function(){
+ NSUI.shuffle_switch(NSPlayer.shuffle=1-NSPlayer.shuffle);
+ NSUI.ishuffle.style.backgroundPosition=`${NSPlayer.shuffle?NSUI.bshonrect:NSUI.bsoffrect}`;
+ document.cookie=`playershuffle=${NSPlayer.shuffle}`;
+ };
+ document.getElementById('repeatsw').onclick=function(){
+ NSPlayer.repeat=1-NSPlayer.repeat;
+ NSUI.audio.loop=NSPlayer.repeat?true:false;
+ NSUI.irepeat.style.backgroundPosition=`${NSPlayer.repeat?NSUI.bronerect:NSUI.brallrect}`;
+ document.cookie=`playerrepeat=${NSPlayer.repeat}`;
+ };
+ document.getElementById('plistsw').onclick=NSUI.togglePlist;
+ document.getElementById('tsliderbase').onclick=
+ document.getElementById('tsliderbase').onmousemove=function(e)
+ {
+ if(e.type=='click'||(e.type=='mousemove'&&e.buttons==1))
+ {
+ const sr=this.getBoundingClientRect();
+ const p=(e.clientX-sr.left)/sr.width;
+ NSUI.audio.currentTime=NSUI.audio.duration*p;
+ }
+ };
+ const playpausef=function()
+ {
+ if(NSUI.audio.src=='')
+ {
+ if(NSUI.selectedplist)
+ {
+ NSUI.switch_playlist(NSUI.selectedplist);
+ NSUI.switch_track(0);
+ }
+ return;
+ }
+ if(NSUI.audio.paused)
+ {
+ NSUI.audio.play();
+ NSUI.iplaypause.style.backgroundPosition=`${NSUI.bpauserect}`;
+ }
+ else
+ {
+ NSUI.audio.pause();
+ NSUI.iplaypause.style.backgroundPosition=`${NSUI.bplayrect}`;
+ }
+ };
+ NSUI.iplaypause.onclick=playpausef;
+ NSUI.pbprev.onclick=function()
+ {
+ if(NSUI.audio.currentTime>10)NSUI.audio.currentTime=0;
+ else NSPlayer.prev();
+ };
+ NSUI.pbnext.onclick=NSPlayer.next.bind(NSPlayer);
+ if(navigator.mediaSession)
+ {
+ navigator.mediaSession.setActionHandler('previoustrack',NSUI.pbprev.onclick);
+ navigator.mediaSession.setActionHandler('nexttrack',NSUI.pbnext.onclick);
+ }
+ window.onkeydown=function(e)
+ {
+ if(e.key==' ')
+ {
+ playpausef();
+ return false;
+ }
+ if(e.key=='c')
+ if(NSUI.audio.audioTracks.length==2)
+ {
+ const t=NSUI.audio.currentTime;
+ NSUI.audio.audioTracks[0].enabled^=1;
+ NSUI.audio.audioTracks[1].enabled^=1;
+ NSUI.audio.currentTime=t;
+ }
+ return true;
+ };
+ },
+ load_playlists:async function()
+ {
+ const moi=this;
+ let r=null;
+ try{
+ const resp=await fetch(new Request(`/libs/music/player.d/playlists/playlists?${new Date().getTime()}`));
+ r=await resp.text();
+ }catch(e){return;}
+ let rarr=r.split('\n');
+ let tarr=[];
+ let cnt=0;
+ for(let i=0;i<rarr.length;++i)
+ if(rarr[i].trim().length)++cnt;
+ const p=new Promise((a,b)=>{
+ for(let i=0;i<rarr.length;++i)
+ {
+ let t=rarr[i].trim();
+ if(!t.length)continue;
+ NSPlayer.load_playlist(t,i).then((rp)=>{
+ tarr[rp.plistord]=rp;
+ if(--cnt<=0)a(null);
+ });
+ }
+ });
+ await p;
+ for(let i=0;i<tarr.length;++i)
+ {
+ const e=sh.newelem('li');
+ const ea=sh.newelem('a');
+ ea.innerHTML=tarr[i].plistname;
+ ea.classList.add('listitem');
+ ea.href='javascript:void(0);';
+ ea.pid=i;
+ ea.onclick=function(e){
+ e.preventDefault();
+ for(let i=0;i<NSUI.ulplaylists.childNodes.length;++i)
+ {
+ const ta=NSUI.ulplaylists.childNodes[i].firstChild;
+ if(ta.pid==this.pid)
+ {ta.classList.add('highlighted');ta.classList.add('active');}
+ else{ta.classList.remove('highlighted');ta.classList.remove('active');}
+ }
+ NSUI.present_playlist.bind(NSUI,this.pid)();
+ if(NSPlayer.current)
+ NSUI.set_highlighted(NSPlayer.plistname,NSPlayer.tracks[NSPlayer.current].title);
+ };
+ e.appendChild(ea);
+ NSUI.ulplaylists.appendChild(e);
+ }
+ moi.playlists=tarr;
+ },
+ present_playlist:function(id)
+ {
+ while(this.playlist.firstChild)
+ this.playlist.removeChild(this.playlist.firstChild);
+ const list=this.playlists[id].playlist;
+ for(let i=0;i<list.length;++i)
+ {
+ const l=sh.newelem('li');
+ const a=sh.newelem('a');
+ a.innerHTML=list[i].title;
+ a.href=list[i].src;
+ a.ord=i;
+ a.onclick=function(e){e.preventDefault();NSUI.switch_track.bind(NSUI,this.ord)();};
+ l.appendChild(a);
+ this.playlist.appendChild(l);
+ }
+ const d=sh.newelem('div');d.style.height=`${NSUI.ctrlcontainer.getBoundingClientRect().height+16}px`;
+ this.playlist.appendChild(d);
+ this.selectedplist=this.playlists[id].plistname;
+ this.am3u8.href=`https://chrisoft.org/libs/music/player.d/cgi-bin/m3u8.cgi?plist=${this.playlists[id].plistname}`;
+ },
+ switch_playlist:function(pl,setactive)
+ {
+ let cid=0;
+ for(;cid<this.playlists.length;++cid)
+ if(this.playlists[cid].plistname==pl)break;
+ if(cid>=this.playlists.length)return;
+ if(setactive)
+ {
+ NSUI.ulplaylists.childNodes[cid].firstChild.classList.add('highlighted');
+ NSUI.ulplaylists.childNodes[cid].firstChild.classList.add('active');
+ }
+ //VERY stupid design, but it _should_ work.
+ NSPlayer.switch_playlist(pl,this.playlists[cid].playlist);
+ NSPlayer.sort_playlist(NSPlayer.shuffle);
+ this.playlists[cid].playlist=NSPlayer.tracks;
+ this.present_playlist(cid);
+ this.selectedplist=pl;
+ },
+ switch_track:function(id)
+ {
+ if(NSPlayer.plistname!=this.selectedplist)
+ this.switch_playlist(this.selectedplist);
+ NSPlayer.play(id);
+ },
+ set_highlighted:function(pl,t)
+ {
+ if(pl!=this.selectedplist)return;
+ let cid=0;
+ for(;cid<this.playlists.length;++cid)
+ if(this.playlists[cid].plistname==pl)break;
+ const clist=this.playlists[cid].playlist;
+ for(let i=0;i<clist.length;++i)
+ if(clist[i].title==t)
+ this.playlist.childNodes[i].firstChild.classList.add('highlighted');
+ else
+ this.playlist.childNodes[i].firstChild.classList.remove('highlighted');
+ },
+ shuffle_switch:function(shuffle)
+ {
+ for(let i=0;i<this.playlists.length;++i)
+ {
+ NSPlayer.sort_playlist(shuffle,this.playlists[i].playlist);
+ if(i==this.selectedplist)this.present_playlist(i);
+ }
+ NSPlayer.sort_playlist(shuffle);
+ },
+ togglePlist:function()
+ {
+ NSUI.plistshown=!NSUI.plistshown;
+ NSUI.swplaylist.innerHTML=`[${NSUI.plistshown?'Hide':'Show'} Playlist]`;
+ NSUI.playlist.style.opacity=NSUI.plistshown?'1':'0';
+ NSUI.playlist.style.pointerEvents=NSUI.plistshown?'auto':'none';
+ },
+ formatTime:function(t)
+ {
+ if(isNaN(t))return '-:--';
+ let 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}`;
+ },
+ bufferedUpdate:function()
+ {
+ let r=0;
+ for(let i=0;i<NSUI.audio.buffered.length;++i)
+ r=r<NSUI.audio.buffered.end(i)?NSUI.audio.buffered.end(i):r;
+ document.getElementById('cbuff').style.width=r/NSUI.audio.duration*100+'%';
+ },
+ timeUpdate:function()
+ {
+ document.getElementById('timenow').innerHTML=NSUI.formatTime(NSUI.audio.currentTime);
+ document.getElementById('timeleft').innerHTML=`-${NSUI.formatTime(NSUI.audio.duration-NSUI.audio.currentTime)}`;
+ document.getElementById('ctime').style.width=NSUI.audio.currentTime/NSUI.audio.duration*100+'%';
+ NSUI.bufferedUpdate();
+ }
};
NSAudio={
- audioctx:null,
- srcnode:null,
- anlznode:null,
- audioInit:function()
- {
- window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext||window.msAudioContext;
- if(!window.AudioContext)alert('This page requires Web Audio API to work...');
- this.audioctx=new AudioContext;
- this.anlznode=this.audioctx.createAnalyser();
- this.anlznode.fftSize=2*NSVisualization.nbins;
- NSUI.audio.volume=1;
- },
- connect:function()
- {
- this.srcnode=this.audioctx.createMediaElementSource(NSUI.audio);
- this.srcnode.connect(this.anlznode);
- this.anlznode.connect(this.audioctx.destination);
- },
+ audioctx:null,
+ srcnode:null,
+ anlznode:null,
+ audioInit:function()
+ {
+ window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext||window.msAudioContext;
+ if(!window.AudioContext)alert('This page requires Web Audio API to work...');
+ this.audioctx=new AudioContext;
+ this.anlznode=this.audioctx.createAnalyser();
+ this.anlznode.fftSize=2*NSVisualization.nbins;
+ NSUI.audio.volume=1;
+ },
+ connect:function()
+ {
+ this.srcnode=this.audioctx.createMediaElementSource(NSUI.audio);
+ this.srcnode.connect(this.anlznode);
+ this.anlznode.connect(this.audioctx.destination);
+ },
};
NSVisualization={
- nbinsp:10,
- nbins:Math.pow(2,10),
- spectgrmw:1200,
- spectrw:0.7,
- spectrm:0.08125,
- caps:[],
- cctx:null,
- spectgrmp:0,
- _61spbins:29,
- _61spfintv:Math.pow(1024,1./29),
- _61spbinw:9,
- _61spaccel:.35,
- _61spmaxvel:6.17274873,
- _61spgvel:.025,
- _61spelas:1.33*.617274873,
- _61spf:6.17274873,
- _61spelasth:.017274873,
- _61spcaps:new Float32Array(29),
- _61spcapsv:new Float32Array(29),
+ nbinsp:10,
+ nbins:Math.pow(2,10),
+ spectgrmw:1200,
+ spectrw:0.7,
+ spectrm:0.08125,
+ caps:[],
+ cctx:null,
+ spectgrmp:0,
+ _61spbins:29,
+ _61spfintv:Math.pow(1024,1./29),
+ _61spbinw:9,
+ _61spaccel:.617274873,
+ _61spdamp:Math.pow(.617274873,6.17274873),
+ _61spvelcap:2*6.17274873,
+ _61spgvel:.025,
+ _61spelas:.617274873,
+ _61spf:6.17274873*6.17274873,
+ _61spelasth:.017274873,
+ _61spcaps:new Float32Array(29),
+ _61spcapsv:new Float32Array(29),
_61spft:new Date(),
- init:function()
- {
- window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame;
- this.cctx=NSUI.canvas.getContext('2d');
- this.spectrw=NSUI.canvas.width/this.nbins;
- this.spectrm=this.spectrw/10;this.spectrw*=0.9;
- for(let i=0;i<this.nbins;++i)this.caps[i]=0;
- },
- update_spectrum:function()
- {
- const cctx=this.cctx,canvas=NSUI.canvas;
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- let freqdomv=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
- NSAudio.anlznode.getByteFrequencyData(freqdomv);
- for(let i=0;i<this.nbins;++i)
- {
- cctx.fillStyle='hsl('+i*360.0/this.nbins+',100%,50%)';
- cctx.fillRect(i*(this.spectrw+this.spectrm),canvas.height-(canvas.height*freqdomv[i]/255.),this.spectrw,canvas.height*freqdomv[i]/255.);
- if(this.caps[i]<freqdomv[i])this.caps[i]=freqdomv[i];else if(this.caps[i]>0)--this.caps[i];
- cctx.fillStyle='hsl('+i*360.0/this.nbins+',100%,25%)';
- cctx.fillRect(i*(this.spectrw+this.spectrm),canvas.height-(canvas.height*this.caps[i]/255.)-1,this.spectrw,1);
- }
- }catch(e){
- for(let i=0;i<this.nbins;++i)
- {
- if(this.caps[i]>0)--this.caps[i];
- cctx.fillStyle='hsl('+i*360.0/this.nbins+',100%,25%)';
- cctx.fillRect(i*(this.spectrw+this.spectrm),canvas.height-this.caps[i]-1,this.spectrw,1);
- }
- }
- },
- update_61_spectrum:function()
- {
- const cctx=this.cctx,canvas=NSUI.canvas;
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- let freqdomv=new Float32Array(NSAudio.anlznode.frequencyBinCount);
- NSAudio.anlznode.getFloatFrequencyData(freqdomv);
- let binl=Math.pow(2,(this._61spbinw-1)*this.nbinsp/(this._61spbins-1+this._61spbinw))-1;
- let _61spfdomv=new Float32Array(this._61spbins);
+ init:function()
+ {
+ window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame;
+ this.cctx=NSUI.canvas.getContext('2d');
+ this.spectrw=NSUI.canvas.width/this.nbins;
+ this.spectrm=this.spectrw/10;this.spectrw*=0.9;
+ for(let i=0;i<this.nbins;++i)this.caps[i]=0;
+ },
+ update_spectrum:function()
+ {
+ const cctx=this.cctx,canvas=NSUI.canvas;
+ cctx.clearRect(0,0,canvas.width,canvas.height);
+ try{
+ let freqdomv=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
+ NSAudio.anlznode.getByteFrequencyData(freqdomv);
+ for(let i=0;i<this.nbins;++i)
+ {
+ cctx.fillStyle='hsl('+i*360.0/this.nbins+',100%,50%)';
+ cctx.fillRect(i*(this.spectrw+this.spectrm),canvas.height-(canvas.height*freqdomv[i]/255.),this.spectrw,canvas.height*freqdomv[i]/255.);
+ if(this.caps[i]<freqdomv[i])this.caps[i]=freqdomv[i];else if(this.caps[i]>0)--this.caps[i];
+ cctx.fillStyle='hsl('+i*360.0/this.nbins+',100%,25%)';
+ cctx.fillRect(i*(this.spectrw+this.spectrm),canvas.height-(canvas.height*this.caps[i]/255.)-1,this.spectrw,1);
+ }
+ }catch(e){
+ for(let i=0;i<this.nbins;++i)
+ {
+ if(this.caps[i]>0)--this.caps[i];
+ cctx.fillStyle='hsl('+i*360.0/this.nbins+',100%,25%)';
+ cctx.fillRect(i*(this.spectrw+this.spectrm),canvas.height-this.caps[i]-1,this.spectrw,1);
+ }
+ }
+ },
+ update_61_spectrum:function()
+ {
+ const cctx=this.cctx,canvas=NSUI.canvas;
+ cctx.clearRect(0,0,canvas.width,canvas.height);
+ try{
+ let freqdomv=new Float32Array(NSAudio.anlznode.frequencyBinCount);
+ NSAudio.anlznode.getFloatFrequencyData(freqdomv);
+ let binl=Math.pow(2,(this._61spbinw-1)*this.nbinsp/(this._61spbins-1+this._61spbinw))-1;
+ let _61spfdomv=new Float32Array(this._61spbins);
const ft=new Date()-this._61spft;
this._61spft=new Date();
const rft=ft/1000*24;
- for(let i=0;i<this._61spbins;++i)
- {
- let binr=Math.pow(2,(i+this._61spbinw)*this.nbinsp/(this._61spbins-1+this._61spbinw))-1;
- if(Math.floor(binr)<=Math.floor(binl))binr=binl+1;
+ for(let i=0;i<this._61spbins;++i)
+ {
+ let binr=Math.pow(2,(i+this._61spbinw)*this.nbinsp/(this._61spbins-1+this._61spbinw))-1;
+ if(Math.floor(binr)<=Math.floor(binl))binr=binl+1;
let binli=Math.floor(binl);
let binri=Math.floor(binr);
const clamp=(x)=>Math.max(0,Math.min(1,x));
- _61spfdomv[i]=Math.pow(freqdomv.
- slice(binli,binri+1).
- reduce(
+ _61spfdomv[i]=Math.pow(freqdomv.
+ slice(binli,binri+1).
+ reduce(
(s,c)=>s+
clamp(
(c-NSAudio.anlznode.minDecibels)
/(NSAudio.anlznode.maxDecibels-NSAudio.anlznode.minDecibels)
)/(binri-binli+1)
,0),2);//iS tHiS dBv^2?
- binl=binr;
+ binl=binr;
if(ft>1000)
{
@@ -508,235 +509,238 @@ NSVisualization={
this._61spcapsv[i]=0;
continue;
}
- let vel=this._61spgvel*this._61spcapsv[i];
- if(this._61spcaps[i]-vel*rft<=_61spfdomv[i])
- {
- let elf=0;
- if(vel>rft*this._61spelasth)
- elf=this._61spcapsv[i]*this._61spelas;
- this._61spcapsv[i]=(this._61spcaps[i]-vel*rft-_61spfdomv[i])*this._61spf-elf;
- this._61spcaps[i]=_61spfdomv[i];
- }
- else
- {
- if(this._61spcapsv[i]+rft*this._61spaccel<=this._61spmaxvel)
- this._61spcapsv[i]+=rft*this._61spaccel;
- else this._61spcapsv[i]=this._61spmaxvel;
+ let vel=this._61spgvel*this._61spcapsv[i];
+ if(this._61spcaps[i]-vel*rft<=_61spfdomv[i])
+ {
+ let elf=0;
+ if(vel>this._61spgvel*this._61spvelcap)
+ {
+ vel=this._61spgvel*this._61spvelcap;//cap this so that Newton could rest in peace.
+ this._61spcapsv[i]=this._61spvelcap;
+ }
+ if(vel>rft*this._61spelasth)
+ elf=this._61spcapsv[i]*this._61spelas;
+ this._61spcapsv[i]=(this._61spcaps[i]-vel*rft-_61spfdomv[i])*this._61spf-elf;
+ this._61spcaps[i]=_61spfdomv[i];
+ }
+ else
+ {
+ this._61spcapsv[i]+=rft*(this._61spaccel-this._61spdamp*Math.sign(this._61spcapsv[i])*Math.pow(this._61spcapsv[i],2));
vel=this._61spgvel*this._61spcapsv[i];
- this._61spcaps[i]-=Math.min(rft*vel,this._61spcaps[i]);
- }
+ this._61spcaps[i]-=Math.min(rft*vel,this._61spcaps[i]);
+ }
- cctx.fillStyle=`rgba(70,130,180,${0.36+0.64*_61spfdomv[i]})`;
- cctx.fillRect(i*(canvas.width/this._61spbins),canvas.height-(canvas.height*_61spfdomv[i]),canvas.width/this._61spbins*0.96,canvas.height*_61spfdomv[i]);
+ cctx.fillStyle=`rgba(70,130,180,${0.36+0.64*_61spfdomv[i]})`;
+ cctx.fillRect(i*(canvas.width/this._61spbins),canvas.height-(0.617274873*canvas.height*_61spfdomv[i]),canvas.width/this._61spbins*0.96,0.617274873*canvas.height*_61spfdomv[i]);
- cctx.fillStyle='rgb(110,139,161)';
- cctx.fillRect(i*(canvas.width/this._61spbins),canvas.height-(canvas.height*this._61spcaps[i])-4,canvas.width/this._61spbins*0.96,4);
- }
- }catch(e){}
- },
- update_scope:function()
- {
- const cctx=this.cctx,canvas=NSUI.canvas;
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- let timedomv=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
- NSAudio.anlznode.getByteTimeDomainData(timedomv);
- cctx.lineWidth=window.devicePixelRatio;
- cctx.strokeStyle='#000';
- if(athm)cctx.strokeStyle='#FFF';
- cctx.beginPath();
- for(let i=0,x=0;i<this.nbins;++i)
- {
- if(i==0)cctx.moveTo(x,timedomv[i]/128.*canvas.height/2);
- else cctx.lineTo(x,timedomv[i]/128.*canvas.height/2);
- x+=canvas.width*1./this.nbins;
- }
- cctx.stroke();
- }catch(e){
- cctx.beginPath();
- cctx.moveTo(0,canvas.height/2);
- cctx.lineTo(canvas.width,canvas.height/2);
- cctx.stroke();
- }
- },
- update_spectrogram:function()
- {
- const cctx=this.cctx,canvas=NSUI.canvas;
- try{
- let freqdomv=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
- NSAudio.anlznode.getByteFrequencyData(freqdomv);
- cctx.clearRect(this.spectgrmp/this.spectgrmw*canvas.width,0,canvas.width/this.spectgrmw,canvas.height);
- for(let i=0;i<this.nbins;++i)
- {
- let color=(athm?'rgba(255,255,255,':'rgba(0,0,0,')+freqdomv[i]/256.+')';
- cctx.fillStyle=color;
- cctx.fillRect(this.spectgrmp/this.spectgrmw*canvas.width,(this.nbins-i)/this.nbins*canvas.height,canvas.width/this.spectgrmw,canvas.height/this.nbins);
- }
- if(!NSUI.audio.paused)++this.spectgrmp;
- if(this.spectgrmp>=this.spectgrmw)this.spectgrmp=0;
- }catch(e){
- this.spectgrmp=0;
- cctx.clearRect(0,0,canvas.width,canvas.height);
- }
- },
- updateVisualization:function()
- {
- switch(NSUI.vissel.value)
- {
- case 'spectrum':
- NSVisualization.update_spectrum();
- break;
- case 'spspectrum':
- NSVisualization.update_61_spectrum();
- break;
- case 'scope':
- NSVisualization.update_scope();
- break;
- case 'spectrogram':
- NSVisualization.update_spectrogram();
- break;
- case 'inkfountain':
- NSInk.update();
- break;
- }
- if(NSUI.vissel.value!='none')
- requestAnimationFrame(NSVisualization.updateVisualization);
- }
+ cctx.fillStyle='rgb(110,139,161)';
+ cctx.fillRect(i*(canvas.width/this._61spbins),canvas.height-(0.617274873*canvas.height*this._61spcaps[i])-4,canvas.width/this._61spbins*0.96,4);
+ }
+ }catch(e){}
+ },
+ update_scope:function()
+ {
+ const cctx=this.cctx,canvas=NSUI.canvas;
+ cctx.clearRect(0,0,canvas.width,canvas.height);
+ try{
+ let timedomv=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
+ NSAudio.anlznode.getByteTimeDomainData(timedomv);
+ cctx.lineWidth=window.devicePixelRatio;
+ cctx.strokeStyle='#000';
+ if(athm)cctx.strokeStyle='#FFF';
+ cctx.beginPath();
+ for(let i=0,x=0;i<this.nbins;++i)
+ {
+ if(i==0)cctx.moveTo(x,timedomv[i]/128.*canvas.height/2);
+ else cctx.lineTo(x,timedomv[i]/128.*canvas.height/2);
+ x+=canvas.width*1./this.nbins;
+ }
+ cctx.stroke();
+ }catch(e){
+ cctx.beginPath();
+ cctx.moveTo(0,canvas.height/2);
+ cctx.lineTo(canvas.width,canvas.height/2);
+ cctx.stroke();
+ }
+ },
+ update_spectrogram:function()
+ {
+ const cctx=this.cctx,canvas=NSUI.canvas;
+ try{
+ let freqdomv=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
+ NSAudio.anlznode.getByteFrequencyData(freqdomv);
+ cctx.clearRect(this.spectgrmp/this.spectgrmw*canvas.width,0,canvas.width/this.spectgrmw,canvas.height);
+ for(let i=0;i<this.nbins;++i)
+ {
+ let color=(athm?'rgba(255,255,255,':'rgba(0,0,0,')+freqdomv[i]/256.+')';
+ cctx.fillStyle=color;
+ cctx.fillRect(this.spectgrmp/this.spectgrmw*canvas.width,(this.nbins-i)/this.nbins*canvas.height,canvas.width/this.spectgrmw,canvas.height/this.nbins);
+ }
+ if(!NSUI.audio.paused)++this.spectgrmp;
+ if(this.spectgrmp>=this.spectgrmw)this.spectgrmp=0;
+ }catch(e){
+ this.spectgrmp=0;
+ cctx.clearRect(0,0,canvas.width,canvas.height);
+ }
+ },
+ updateVisualization:function()
+ {
+ switch(NSUI.vissel.value)
+ {
+ case 'spectrum':
+ NSVisualization.update_spectrum();
+ break;
+ case 'spspectrum':
+ NSVisualization.update_61_spectrum();
+ break;
+ case 'scope':
+ NSVisualization.update_scope();
+ break;
+ case 'spectrogram':
+ NSVisualization.update_spectrogram();
+ break;
+ case 'inkfountain':
+ NSInk.update();
+ break;
+ }
+ if(NSUI.vissel.value!='none')
+ requestAnimationFrame(NSVisualization.updateVisualization);
+ }
};
NSInk={
- ic1:['#FF3333','#FF8800','#FFFF00','#CCFF00','#33CCFF','#0000FF','#9966FF'],
- 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)'],
- inks:[],
- inkimg:[],
- ifcaps:[],
- nbinsif:128,
- inkPrepare:function()
- {
- for(let i=0;i<7;++i)
- {
- this.inkimg[i]=document.createElement('canvas');
- this.inkimg[i].width=this.inkimg[i].height=10*window.devicePixelRatio;
- const cctx=this.inkimg[i].getContext('2d');
- cctx.fillStyle=this.ic1[i];
- cctx.beginPath();
- cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,3*window.devicePixelRatio,0,2*Math.PI);
- cctx.fill();
- cctx.fillStyle=this.ic2[i];
- cctx.beginPath();
- cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,5*window.devicePixelRatio,0,2*Math.PI);
- cctx.fill();
- }
- for(let i=0;i<NSVisualization.nbins;++i)this.ifcaps[i]=0;
- this.nbinsif=NSVisualization.nbins/8;
- },
- createInk:function(_vx,_vy,_c1,_c2)
- {
- let f=false;
- for(let i=0;i<this.inks.length;++i)
- {
- if(!this.inks[i].active)
- {this.inks[i]=new Ink(_vx,_vy,_c1,_c2);f=true;break;}
- }
- if(!f&&this.inks.length<512)this.inks.push(new Ink(_vx,_vy,_c1,_c2));
- },
- frms:0,lastfpsupd:null,fps:0,
- update:function()
- {
- const canvas=NSUI.canvas;
- const cctx=canvas.getContext('2d'),ts=Date.now();
- cctx.clearRect(0,0,canvas.width,canvas.height);
- ++this.frms;if(Date.now()-this.lastfpsupd>500)
- {
- if(this.lastfpsupd)
- this.fps=1000*this.frms/(Date.now()-this.lastfpsupd),this.frms=0;
- this.lastfpsupd=Date.now();
- }
- try{
- let freqarr=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
- NSAudio.anlznode.getByteFrequencyData(freqarr);
- for(let i=0;i<this.nbinsif;++i)
- {
- let r=0;
- for(let j=0;j<8;++j)r+=freqarr[i*8+j];
- r/=8.;
- if(r-this.ifcaps[i]>7)
- {
- let color=Math.floor(i*8.0/this.nbinsif),rad=Math.random()*Math.PI*2;
- let ndrops=(128-i)/128.*3+1;ndrops*=(r/128.);ndrops=Math.floor(ndrops);if(ndrops<1)ndrops=1;
- for(let k=0;k<ndrops;++k)
- {
- this.createInk(((r-this.ifcaps[i]-7)/32*24+12)*Math.cos(rad),((r-this.ifcaps[i]-7)/32*24+12)*Math.sin(rad),color);
- rad=Math.random()*Math.PI*2;
- }
- }
- if(r>this.ifcaps[i])this.ifcaps[i]=r;else this.ifcaps[i]-=2;
- }
- }catch(e){
- cctx.clearRect(0,0,canvas.width,canvas.height);
- }
- const tu=Date.now();
- let aa=0;
- for(let i=0;i<this.inks.length;++i)
- if(this.inks[i].active){this.inks[i].update();this.inks[i].draw(cctx);++aa;}
- cctx.fillStyle='#000';
- cctx.font="1em 'CMU Typewriter Text w', 'CMU Typewriter Text', 'TeX Gyre Cursor', 'FreeMono', 'Courier New', Courier, monospace";
- cctx.fillText('Active droplets '+aa+', '+this.fps.toFixed(2)+' FPS',0,10);
- cctx.fillText('Update time '+(tu-ts)+'ms, render time '+(Date.now()-tu)+'ms',0,24);
- }
+ ic1:['#FF3333','#FF8800','#FFFF00','#CCFF00','#33CCFF','#0000FF','#9966FF'],
+ 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)'],
+ inks:[],
+ inkimg:[],
+ ifcaps:[],
+ nbinsif:128,
+ inkPrepare:function()
+ {
+ for(let i=0;i<7;++i)
+ {
+ this.inkimg[i]=document.createElement('canvas');
+ this.inkimg[i].width=this.inkimg[i].height=10*window.devicePixelRatio;
+ const cctx=this.inkimg[i].getContext('2d');
+ cctx.fillStyle=this.ic1[i];
+ cctx.beginPath();
+ cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,3*window.devicePixelRatio,0,2*Math.PI);
+ cctx.fill();
+ cctx.fillStyle=this.ic2[i];
+ cctx.beginPath();
+ cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,5*window.devicePixelRatio,0,2*Math.PI);
+ cctx.fill();
+ }
+ for(let i=0;i<NSVisualization.nbins;++i)this.ifcaps[i]=0;
+ this.nbinsif=NSVisualization.nbins/8;
+ },
+ createInk:function(_vx,_vy,_c1,_c2)
+ {
+ let f=false;
+ for(let i=0;i<this.inks.length;++i)
+ {
+ if(!this.inks[i].active)
+ {this.inks[i]=new Ink(_vx,_vy,_c1,_c2);f=true;break;}
+ }
+ if(!f&&this.inks.length<512)this.inks.push(new Ink(_vx,_vy,_c1,_c2));
+ },
+ frms:0,lastfpsupd:null,fps:0,
+ update:function()
+ {
+ const canvas=NSUI.canvas;
+ const cctx=canvas.getContext('2d'),ts=Date.now();
+ cctx.clearRect(0,0,canvas.width,canvas.height);
+ ++this.frms;if(Date.now()-this.lastfpsupd>500)
+ {
+ if(this.lastfpsupd)
+ this.fps=1000*this.frms/(Date.now()-this.lastfpsupd),this.frms=0;
+ this.lastfpsupd=Date.now();
+ }
+ try{
+ let freqarr=new Uint8Array(NSAudio.anlznode.frequencyBinCount);
+ NSAudio.anlznode.getByteFrequencyData(freqarr);
+ for(let i=0;i<this.nbinsif;++i)
+ {
+ let r=0;
+ for(let j=0;j<8;++j)r+=freqarr[i*8+j];
+ r/=8.;
+ if(r-this.ifcaps[i]>7)
+ {
+ let color=Math.floor(i*8.0/this.nbinsif),rad=Math.random()*Math.PI*2;
+ let ndrops=(128-i)/128.*3+1;ndrops*=(r/128.);ndrops=Math.floor(ndrops);if(ndrops<1)ndrops=1;
+ for(let k=0;k<ndrops;++k)
+ {
+ this.createInk(((r-this.ifcaps[i]-7)/32*24+12)*Math.cos(rad),((r-this.ifcaps[i]-7)/32*24+12)*Math.sin(rad),color);
+ rad=Math.random()*Math.PI*2;
+ }
+ }
+ if(r>this.ifcaps[i])this.ifcaps[i]=r;else this.ifcaps[i]-=2;
+ }
+ }catch(e){
+ cctx.clearRect(0,0,canvas.width,canvas.height);
+ }
+ const tu=Date.now();
+ let aa=0;
+ for(let i=0;i<this.inks.length;++i)
+ if(this.inks[i].active){this.inks[i].update();this.inks[i].draw(cctx);++aa;}
+ cctx.fillStyle='#000';
+ cctx.font="1em 'CMU Typewriter Text w', 'CMU Typewriter Text', 'TeX Gyre Cursor', 'FreeMono', 'Courier New', Courier, monospace";
+ cctx.fillText('Active droplets '+aa+', '+this.fps.toFixed(2)+' FPS',0,10);
+ cctx.fillText('Update time '+(tu-ts)+'ms, render time '+(Date.now()-tu)+'ms',0,24);
+ }
};
function init()
{
- if(!window.devicePixelRatio)window.devicePixelRatio=1;
- NSUI.setup_ui();
- NSUI.load_playlists()
- .then(()=>{
- sh.elem('overlaytext').innerHTML+="Done!<br>Click or tap anywhere to start."
- sh.elem('overlay').onclick=function(){
- NSAudio.audioInit();NSAudio.connect();
- if(window.location.hash.length)
- {
- let p=window.location.hash.substr(1).split('/');
- for(let i=0;i<p.length;++i)p[i]=decodeURIComponent(p[i]);
- NSUI.switch_playlist(p[0],true);
- let id=0;
- for(;id<NSPlayer.tracks.length&&NSPlayer.tracks[id].title!=p[1];++id);
- if(id<NSPlayer.tracks.length)NSUI.switch_track(id);
- }
- sh.elem('overlay').style.display='none';
- }
- });
- NSVisualization.init();NSInk.inkPrepare();
- NSUI.audio.ontimeupdate=NSUI.timeUpdate;
- NSUI.audio.onended=NSPlayer.next.bind(NSPlayer);
- NSUI.audio.onplay=NSUI.audio.ondurationchange=function(){
- if(NSUI.audio.audioTracks.length==2)
- sh.elem('mt').style.display='inline';
- else
- sh.elem('mt').style.display='none';
- };
- switch(sh.getcookie('playershuffle'))
- {
- case '1':NSPlayer.shuffle=1;break;
- default:
- case '0':NSPlayer.shuffle=0;break;
- }
- switch(sh.getcookie('playerrepeat'))
- {
- case '1':
- NSPlayer.repeat=1;
- NSUI.audio.loop=true;
- break;
- default:
- case '0':
- NSPlayer.repeat=0;
- NSUI.audio.loop=false;
- break;
- }
- NSUI.ishuffle.style.backgroundPosition=`${NSPlayer.shuffle?NSUI.bshonrect:NSUI.bsoffrect}`;
- NSUI.irepeat.style.backgroundPosition=`${NSPlayer.repeat?NSUI.bronerect:NSUI.brallrect}`;
- if(sh.getcookie('playervisualization').length!==0)
- NSUI.vissel.value=sh.getcookie('playervisualization');
- requestAnimationFrame(NSVisualization.updateVisualization);
+ if(!window.devicePixelRatio)window.devicePixelRatio=1;
+ NSUI.setup_ui();
+ NSUI.load_playlists()
+ .then(()=>{
+ sh.elem('overlaytext').innerHTML+="Done!<br>Click or tap anywhere to start."
+ sh.elem('overlay').onclick=function(){
+ NSAudio.audioInit();NSAudio.connect();
+ if(window.location.hash.length)
+ {
+ let p=window.location.hash.substr(1).split('/');
+ for(let i=0;i<p.length;++i)p[i]=decodeURIComponent(p[i]);
+ NSUI.switch_playlist(p[0],true);
+ let id=0;
+ for(;id<NSPlayer.tracks.length&&NSPlayer.tracks[id].title!=p[1];++id);
+ if(id<NSPlayer.tracks.length)NSUI.switch_track(id);
+ }
+ sh.elem('overlay').style.display='none';
+ }
+ });
+ NSVisualization.init();NSInk.inkPrepare();
+ NSUI.audio.ontimeupdate=NSUI.timeUpdate;
+ NSUI.audio.onended=NSPlayer.next.bind(NSPlayer);
+ NSUI.audio.onplay=NSUI.audio.ondurationchange=function(){
+ if(NSUI.audio.audioTracks.length==2)
+ sh.elem('mt').style.display='inline';
+ else
+ sh.elem('mt').style.display='none';
+ };
+ switch(sh.getcookie('playershuffle'))
+ {
+ case '1':NSPlayer.shuffle=1;break;
+ default:
+ case '0':NSPlayer.shuffle=0;break;
+ }
+ switch(sh.getcookie('playerrepeat'))
+ {
+ case '1':
+ NSPlayer.repeat=1;
+ NSUI.audio.loop=true;
+ break;
+ default:
+ case '0':
+ NSPlayer.repeat=0;
+ NSUI.audio.loop=false;
+ break;
+ }
+ NSUI.ishuffle.style.backgroundPosition=`${NSPlayer.shuffle?NSUI.bshonrect:NSUI.bsoffrect}`;
+ NSUI.irepeat.style.backgroundPosition=`${NSPlayer.repeat?NSUI.bronerect:NSUI.brallrect}`;
+ if(sh.getcookie('playervisualization').length!==0)
+ NSUI.vissel.value=sh.getcookie('playervisualization');
+ requestAnimationFrame(NSVisualization.updateVisualization);
}