diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e9b47a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.php \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..a07a88c --- /dev/null +++ b/app.js @@ -0,0 +1,386 @@ +window.onload = linkAudio; +var mouseDownEvent; +var vibranceMode = false; +var strobeMode = true; +var inverseMode = false; +var colourShift = true; +var increment = true; +var pulseSpacing = 20; +var pulse = 1; +var pulseMode = false; +var visualizerElement; +var foregroundElement; +var settingsFXElement; +var audioTag; +var sredHex = "05"; +var sgrnHex = "10"; +var sbluHex = "15"; +var oredHex = "33"; +var ogrnHex = "aa"; +var obluHex = "ff"; +var audioData; +var audioDataBackup; +var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); +var source1; +var source2; +var gainNode; +var analyser = audioCtx.createAnalyser(); +analyser.fftSize = 2048; +var bufferLength = analyser.frequencyBinCount; +var dataArray = new Uint8Array(bufferLength); +var HEIGHT; +var WIDTH; +var barHeight = 2; +var barWidth = 5; +var barSpacing = 1; +var bleed = 10; +var fgColour = "33aaff"; +var bgColour = "051015"; +var barSize = 55; +var activeBufferLength = bufferLength / 0.666; +var radio = getUrlVars()["src"]; +analyser.getByteTimeDomainData(dataArray); +var fps; +var lastFrame = new Date(); +var lastFrameFrame = lastFrame; +var title; + +function getUrlVars() { + var vars = {}; + var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { + vars[key] = value; + }); + return vars; + // From http://papermashup.com/read-url-get-variables-withjavascript/ +} + +function checkUrl(){ + if(radio){ + document.querySelector("source").setAttribute("src",radio); + document.getElementById("Stream").load(); + document.getElementById("Stream").play(); + var split = radio.split(".com")[0].split("."); + radioName = split[split.length-1]; + radioName = radioName[0].toUpperCase() + radioName.slice(1); + } +} + +function init(){ + checkUrl(); + HEIGHT = window.innerHeight; + WIDTH = window.innerWidth; + canvas.height = HEIGHT; + canvas.width = WIDTH; + for(var i = 0; i < WIDTH / 55; i++){ + $("#bars").append("
"); + $("#bars-blur").append("
"); + } + visualizerElement = document.getElementById("visualizer"); + foregroundElement = document.getElementById("foreground"); + settingsFXElement = document.getElementById("settings-fx-wrapper"); + visualizerElement.setAttribute("style","background:#"+bgColour); + sredHex = parseInt(bgColour[0]+bgColour[1], 16); + sgrnHex = parseInt(bgColour[2]+bgColour[3], 16); + sbluHex = parseInt(bgColour[4]+bgColour[5], 16); + oredHex = parseInt(fgColour[0]+fgColour[1], 16); + ogrnHex = parseInt(fgColour[2]+fgColour[3], 16); + obluHex = parseInt(fgColour[4]+fgColour[5], 16); + setVol(0.5); + anim(); +} + +function GetInfo(){ + var element = document.getElementById("Stream"); +} + +$(window).resize(function(){ + HEIGHT = window.innerHeight; + WIDTH = window.innerWidth; + canvas.height = HEIGHT; + canvas.width = WIDTH; +}); + +function SettingsToggle(){ + if(document.getElementById("settings").style.left === "-230px" || !document.getElementById("settings").style.left){ + document.getElementById("settings").style.left = "0px"; + document.getElementById("settings-toggle").style.margin = "0px"; + document.getElementById("settings-toggle").innerHTML = "<"; + }else{ + document.getElementById("settings").style.left = "-230px"; + document.getElementById("settings-toggle").style.margin = "0px -60px 0px 0px"; + document.getElementById("settings-toggle").innerHTML = ">"; + } +} + +function NewSource(){ + radio = document.getElementById("srInput").value; + document.querySelector("source").setAttribute("src",radio); + document.getElementById("Stream").load(); + document.getElementById("Stream").play(); + window.history.pushState("Radio Visualizer","Canvas Web Audio API Music Visualizer",window.location.href.split("?")[0] + "?src=" + radio); + var split = radio.split(".com")[0].split("."); + radioName = split[split.length-1]; + radioName = radioName[0].toUpperCase() + radioName.slice(1); +} + +function NewBGColour(){ + var input = document.getElementById("bgInput").value; + input = input.replace("#",""); + if(input.length === 6){ + bgColour = input; + $("svg").css({"fill":"#" + bgColour, "stroke":"#"+fgColour}); + visualizerElement.setAttribute("style","background:#"+bgColour); + } + else if(parseInt(input) !== "NaN" && input.legnth < 4){ + bgColour = parseInt(input,16).toString(16); + $("svg").css({"fill":"#" + bgColour, "stroke":"#"+fgColour}); + visualizerElement.setAttribute("style","background:#"+bgColour); + } + else{ + alert("Please enter decimal or hex code"); + } + oredHex = parseInt(fgColour[0]+fgColour[1], 16); + ogrnHex = parseInt(fgColour[2]+fgColour[3], 16); + obluHex = parseInt(fgColour[4]+fgColour[5], 16); +} + +function NewFGColour(){ + var input = document.getElementById("fgInput").value; + input = input.replace("#",""); + if(input.length === 6){ + fgColour = input; + if(parseInt(fgColour[0]) < 1 && parseInt(fgColour[2]) < 1 && parseInt(fgColour[4]) < 1){ + document.body.style.color = "#ffffff"; + $('input').css('color','#ffffff'); + }else{ + document.body.style.color = "#"+fgColour; + $('input').css('color','#'+fgColour); + $("#current-volume").css({"fill":"#" + bgColour}); + } + } + else if(parseInt(input) !== "NaN" && input.legnth < 4){ + fgColour = parseInt(input,16).toString(16); + document.body.style.color = "#"+fgColour; + $('input').css('color','#'+fgColour); + } + else{ + alert("Please enter decimal or hex code"); + } + sredHex = parseInt(bgColour[0]+bgColour[1], 16); + sgrnHex = parseInt(bgColour[2]+bgColour[3], 16); + sbluHex = parseInt(bgColour[4]+bgColour[5], 16); +} + +function NewBleedQuality(){ + bleed = parseInt(document.getElementById("bqInput").value); +} + +function NewBarHeight(){ + barHeight = 2 - document.getElementById("bhInput").value; +} + +function NewBarWidth(){ + barWidth = parseInt(document.getElementById("bwInput").value); +} + +function NewBarSpacing(){ + barSpacing = parseInt(document.getElementById("bsInput").value); +} + +function anim(){ + pulse = 1; + drawVisual = requestAnimationFrame(anim); + analyser.getByteFrequencyData(dataArray); + var mean = 0; + canvasCtx.fillStyle = "#3af"; + canvasCtx.clearRect( 0 , 0 , WIDTH, HEIGHT ); + for(var i = 0; i < bufferLength * 0.666; i++) { + var v = dataArray[i] / 128.0; + var h = v * HEIGHT/2; + mean += h; + var sred = sredHex; + var sgrn = sgrnHex; + var sblu = sbluHex; + var ored = oredHex; + var ogrn = ogrnHex; + var oblu = obluHex; + var tred = ored / 2; + var tgrn = ogrn / 2; + var tblu = oblu / 2; + var amp = 0; + var loud = Math.abs(dataArray[i]); + var cred = sred; + var cgrn = sgrn; + var cblu = sblu; + if(pulseMode === true){ + opacity = (1 / pulseSpacing) * pulse; + }else{ + opacity = 1; + } + + if(loud > amp) { + amp = loud; + } + if(vibranceMode === true){ + document.body.setAttribute("style","-webkit-filter:brightness(" + (amp/256 + 1) + ")"); + }else{ + document.body.removeAttribute("style"); + } + var redinc = Math.floor((tred - sred) / bleed); + var grninc = Math.floor((tgrn - sgrn) / bleed); + var bluinc = Math.floor((tblu - sblu) / bleed); + + for(var o = 0; o < bleed;o++){ + if(o < bleed - 1){ + //--TODO-- Check for outerbars mode + cred += redinc; + cgrn += grninc; + cblu += bluinc; + + red = cred; + green = cgrn; + blue = cblu; + canvasCtx.fillStyle = "rgba(" + red + "," + green + "," + blue + "," + opacity + ")"; + canvasCtx.fillRect(i * (barWidth + barSpacing), HEIGHT/2 - ((2-(o/bleed))*h/(2*barHeight)), barWidth, (((2-(o/bleed))*h)/barHeight)); + }else{ + red = ored; + green = ogrn; + blue = oblu; + canvasCtx.fillStyle = "rgba(" + red + "," + green + "," + blue + "," + opacity + ")"; + canvasCtx.fillRect(i * (barWidth + barSpacing), HEIGHT/2 - h/(barHeight * 2), barWidth, h/barHeight); + } + } + if(increment === true){ + pulse++; + } + else{ + pulse--; + } + if(pulse > pulseSpacing -1){ + increment = false; + }else if(pulse < 1){ + increment = true; + } + mean = 0; + } + var total = Math.floor(audioTag.currentTime); + var seconds = Math.floor(total % 60).toString(); + var minutes = Math.floor(total/60 % 60).toString(); + var hours = Math.floor(total/3600).toString(); + var ouput; + if(hours.length === 1){ + hours = "0" + hours; + } + if(minutes.length === 1){ + minutes = "0" + minutes; + } + if(seconds.length === 1){ + seconds = "0" + seconds; + } + canvasCtx.strokeStyle = "#"+fgColour; + canvasCtx.lineWidth = 3; + canvasCtx.font = "30px Play"; + canvasCtx.strokeText(hours + ":" + minutes + ":" + seconds,10,HEIGHT/2+30); + canvasCtx.font = "60px Play"; + canvasCtx.strokeText(radioName,10,HEIGHT/2); + canvasCtx.fillStyle = "#"+bgColour; + canvasCtx.font = "30px Play"; + canvasCtx.fillText(hours + ":" + minutes + ":" + seconds,10,HEIGHT/2+30); + canvasCtx.font = "60px Play"; + canvasCtx.fillText(radioName,10,HEIGHT/2); + + var now = new Date(); + if(now - lastFrameFrame > 100){ + fps = Math.floor(1000 / (now - lastFrame)); + lastFrameFrame = now; + } + canvasCtx.font = "30px Play"; + canvasCtx.strokeStyle = "#"+fgColour; + canvasCtx.strokeText(title,WIDTH/2 - 100,HEIGHT/2 + 10); + canvasCtx.fillText(title,WIDTH/2 - 100,HEIGHT/2 + 10); + lastFrame = now; +} + +function linkAudio(){ + gainNode = audioCtx.createGain(); + analyser.connect(gainNode); + gainNode.connect(audioCtx.destination); + canvas = document.getElementById("visualizer"); + audioTag = document.querySelector('audio'); + canvasCtx = canvas.getContext("2d"); + source1 = audioCtx.createMediaElementSource(audioTag); + source1.connect(analyser); + init(); +} + +function start(){ + document.getElementById("Stream").play(); +} + +function pause(){ + document.getElementById("Stream").pause(); +} + +$('#volume-bar').mousedown(function () { + setVol($('#volume-bar').val()); + mouseDownEvent = setInterval(function () { + setVol($('#volume-bar').val()); + }, 100); +}); +$('#volume-bar').mouseup(function () { + clearInterval(mouseDownEvent); +}); +$('#volume-bar').mouseout(function () { + clearInterval(mouseDownEvent); +}); + +function setVol(value){ + gainNode.gain.value = value; + document.getElementById("current-volume").style.width = (119 * value) + "px"; +} + +$(".filter-toggle").click(function(){ + firstChild = this.children[0]; + secondChild = this.children[1]; + + if(firstChild.hasAttribute("style")){ + firstChild.removeAttribute("style"); + secondChild.setAttribute("style","opacity:0.2;"); + }else{ + firstChild.setAttribute("style","opacity:0.2;"); + secondChild.removeAttribute("style"); + } +}); + +function toggleFX(string){ + if(string === "vibrance"){ + vibranceMode = !vibranceMode; + }else if(string === "strobe"){ + strobeMode = !strobeMode; + }else if(string === "inverse"){ + inverseMode = !inverseMode; + }else if(string === "colourShift"){ + if(!colourShift){ + colourShift = setInterval(function(){$("#body-fx-wrapper").css("-webkit-filter", "hue-rotate("+(Math.random() * 360)+"deg)");},1000); + }else{ + clearInterval(colourShift); + colourShift = false; + } + }else if(string === "pulse"){ + pulseMode = !pulseMode; + } +} + +(function worker() { + $.ajax({ + url: 'fetcher.php?host='+host, + success: function(data) { + title = data; + document.title = data; + }, + complete: function() { + // Schedule the next request when the current one's complete + setTimeout(worker, 3000); + } + }); +})(); \ No newline at end of file diff --git a/config-example.php b/config-example.php new file mode 100644 index 0000000..695b3c3 --- /dev/null +++ b/config-example.php @@ -0,0 +1,16 @@ + 'My Radio', + 'description' => 'Just click play and enjoy.', + 'author' => 'Mydnic', + 'keywords' => 'radio, music, free, genre, webradio, free music, free radio', + 'url' => 'http://my.radio.stream.domain', + 'image' => 'http://my.radio.stream.domain/cover.png', + + 'stream_url' => 'http://icecast.host:8000/radio.ogg', + 'icecast_url' => 'http://icecast.host:8000/', + + 'analytics' => 'UA-XXXXXXXX-X', + + 'customizable' => false, // Set this to true if you want to allow users to change the visualizer settings like in the demo page. +]; diff --git a/fetcher.php b/fetcher.php new file mode 100644 index 0000000..c48a33a --- /dev/null +++ b/fetcher.php @@ -0,0 +1,4 @@ +(.*)$s',$html,$match); +echo preg_replace('/\s+/', ' ',$match[1]); \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..22bfa2f --- /dev/null +++ b/index.php @@ -0,0 +1,83 @@ + + + + <?php echo $config['name'] ?> + + + + + + + + + + + + + +
+ + + + + + + +
+ + + + + + +
+
+ +
+
+
+ Settings +
+
+ + + + + + + +
Source:
Save
Foreground:
Save
Background:
Save
Bleed Quality:
Save
Bar Height:
Save
Bar Width:
Save
Bar Spacing:
Save
+ +
+
FX
+ + + + + + + +
Vibrance:
On
Off
Color Shift:
On
Off
Pulse:
On
Off
Strobe:
On
Off
Inverse:
On
Off
+
+
+ +
+ > +
+
+
+ +
+ + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..57f6b64 --- /dev/null +++ b/readme.md @@ -0,0 +1,4 @@ +All credits goes to this codepen : http://codepen.io/AfroDev/pen/MYOrvP + +Create a file "config.php" and copy the content of config-example-php in it. +Adapt the informations and you should be running :) \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..1d910f8 --- /dev/null +++ b/style.css @@ -0,0 +1,200 @@ +@import url(http://fonts.googleapis.com/css?family=Play); + +body{ + margin:0px; + height:100%; + width:100%; + overflow:hidden; + user-select:none; + -webkit-user-select:none; + color:#3af; + font-family:"Play"; + background:#111; +} + +audio{ + display:none; +} + +#visualizer{ + position:absolute; + left:0px; + top:0px; + width:100%; + height:100%; +} + +#foreground{ + position:absolute; + top:50%; +} + +#foreground input[type="range"]{ + position:relative; + outline:none; + -webkit-appearance:none; + height:8px; + width:119px; + background:rgba(0,0,0,0.8); + left:4px; + top:30px; + display:inline-block; + vertical-align:top; + cursor:pointer; +} + +#foreground input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + height:10px; + width:10px; +} + +#current-volume{ + display:inline-block; + position:absolute; + background:#3af; + height:4px; + width:119px; + left:6px; + top:34px; + pointer-events:none; + transition:all .2s ease; +} + +#foreground .btn{ + position:relative; + top:8px; +} + +#foreground svg{ + position:relative; + width:30px; + height:30px; + top:3px; + margin:5px; + fill:#051015; + stroke-width:3; + stroke:#3af; + cursor:pointer; +} + +#settings{ + position:absolute; + left:-230px; + top:0px; + width:220px; + padding:5px; + height:100%; + background:rgba(0,0,0,0.9); + transition:all 0.5s ease; + cursor:default; + /*overflow-y:scroll; + overflow-x:visible;*/ +} + +#settings-wrapper{ + margin:80px 0px 0px 0px; + height:300px; + with:100%; + text-align:center; +} + +#settings-title{ + position:absolute; + width:220px; + left:0px; + top:0px; + font-size:40px; + padding-bottom:5px; + margin:5px; + border-bottom:3px solid; +} + +#settings table{ + text-align:left; +} + +#settings-toggle{ + position:absolute; + right:10px; + top:10px; + background: rgba(0,0,0,0.8); + width:38px; + height:38px; + border-radius:20px; + margin:0px -60px 0px 0px; + text-align:center; + font-size:30px; + cursor:pointer; + transition:all 0.2s ease; +} + +#settings input{ + background:rgba(0,0,0,0.5); + border:0px; + outline: none; + color:#3af; + padding:5px; + width:50px; + vertical-align:bottom; +} + +#settings input[type='range']{ + -webkit-appearance:none; + width:55px; + padding:0px; +} + +#settings input[type='range']::-webkit-slider-runnable-track{ + -webkit-appearance:none; + background:rgba(0,0,0,0.5); + height:5px; + margin:-20px 0px 0px; +} + +#settings input[type='range']::-webkit-slider-thumb{ + -webkit-appearance:none; + height:10px; + width:10px; + margin:-2px 0px 0px; + background:#3af; +} + +#settings .btn{ + +} + +#filters{ + border-bottom:1px #3af solid; + text-align:left; + background:rgba(0,0,0,0.5); + padding:5px 5px 0px; +} + +#filters-title{ + font-size:20px; +} + +.filter-toggle{ + display:inline-block; +} + +.filter-toggle div{ + display:inline-block; + padding:5px; + cursor:pointer; +} + +.btn{ + display:inline-block; + background:#fff; + padding:3px; + margin:0px 5px; + background:rgba(0,0,0,0.5); + cursor:pointer; +} + + + + +