I have this visualizer, everthing is working well. The only problem is that when you clear canvas with clean function, then click changeSrc, you can always see a visualizer from last song for a second. Can I get rid of this?
You might need to run it on js fiddle.
https://jsfiddle.net/t87wyzgd/6/
var renderVizualitationID,
canvas, ctx, center_x, center_y, radius, bars,
x_end, y_end, bar_height, bar_width,
frequency_array,
wrap, source;
wrap = $('.w')
canvas = document.getElementById("renderer");
ctx = canvas.getContext("2d");
bars = 200;
bar_width = 2;
multiplier = 0.7;
audio = new Audio();
audio.crossOrigin = "anonymous";
context = new(window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio.src = "https://api.soundcloud.com/tracks/42328219/stream?client_id=b1495e39071bd7081a74093816f77ddb"; // the source path
audio.loop = true;
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequency_array = new Uint8Array(analyser.frequencyBinCount);
audio.play();
animationLooper();
function animationLooper() {
// set to the size of device
canvas.width = wrap.width();
canvas.height = wrap.height();
// find the center of the window
center_x = canvas.width / 2;
center_y = canvas.height / 2;
radius = canvas.height / 6;
//draw a circle
ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
ctx.stroke();
analyser.getByteFrequencyData(frequency_array);
var i;
for (i = 0; i < bars; i++) {
//divide a circle into equal parts
rads = Math.PI * 2 / bars;
bar_height = frequency_array[i] * multiplier;
// set coordinates
x = center_x + Math.cos(rads * i) * (radius);
y = center_y + Math.sin(rads * i) * (radius);
x_end = center_x + Math.cos(rads * i) * (radius + bar_height);
y_end = center_y + Math.sin(rads * i) * (radius + bar_height);
//draw a bar
var lineColor = "rgb(" + frequency_array[i] + ", " + frequency_array[i] + ", " + 205 + ")";
ctx.strokeStyle = lineColor;
ctx.lineWidth = bar_width;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x_end, y_end);
ctx.stroke();
}
renderVizualitationID = requestAnimationFrame(animationLooper);
}
$('#clean').on('click',function() {
if (renderVizualitationID) cancelAnimationFrame(renderVizualitationID);
audio.pause();
audio.src = '';
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
$('#changeSrc').on('click',function() {
audio.src = "https://api.soundcloud.com/tracks/693365626/stream?client_id=r4wruADPCq7iqJomagvYpdehvILa2bgE"; // the source path
audio.play();
animationLooper();
});
.w {
position: relative;
top: 0;
left: 0;
width: 400px;
height: 400px;
background: #ccc;
}
#renderer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #111;
background: #1D4350;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="w">
<canvas id="renderer"></canvas>
</div>
<a id="clean" href="#" >clean</a>
<a id="changeSrc" href="#" >changeSrc</a>
This happens because your AudioAnalyser works by buffering the data, it simply unshifts new data as time passes. So when you pause your audio, it will still contain some data.
To avoid this, you can simply create a new AudioAnalyser in the clean
function
var renderVizualitationID,
canvas, ctx, center_x, center_y, radius, bars,
x_end, y_end, bar_height, bar_width,
frequency_array,
wrap, source;
wrap = $('.w')
canvas = document.getElementById("renderer");
ctx = canvas.getContext("2d");
bars = 200;
bar_width = 2;
multiplier = 0.7;
audio = new Audio();
audio.crossOrigin = "anonymous";
context = new(window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio.src = "https://api.soundcloud.com/tracks/42328219/stream?client_id=b1495e39071bd7081a74093816f77ddb"; // the source path
audio.loop = true;
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequency_array = new Uint8Array(analyser.frequencyBinCount);
audio.play();
animationLooper();
// do not change the size of your canvas when you are drawing on it
// that will reset the whole canvas and require anew pixel buffer
// so do it only when really required
window.onresize = function() {
// set to the size of device
canvas.width = wrap.width();
canvas.height = wrap.height();
};
window.onresize();
function animationLooper() {
ctx.clearRect( 0, 0, canvas.width, canvas.height )
// find the center of the window
center_x = canvas.width / 2;
center_y = canvas.height / 2;
radius = canvas.height / 6;
//draw a circle
ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
ctx.stroke();
analyser.getByteFrequencyData(frequency_array);
var i;
for (i = 0; i < bars; i++) {
//divide a circle into equal parts
rads = Math.PI * 2 / bars;
bar_height = frequency_array[i] * multiplier;
// set coordinates
x = center_x + Math.cos(rads * i) * (radius);
y = center_y + Math.sin(rads * i) * (radius);
x_end = center_x + Math.cos(rads * i) * (radius + bar_height);
y_end = center_y + Math.sin(rads * i) * (radius + bar_height);
//draw a bar
var lineColor = "rgb(" + frequency_array[i] + ", " + frequency_array[i] + ", " + 205 + ")";
ctx.strokeStyle = lineColor;
ctx.lineWidth = bar_width;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x_end, y_end);
ctx.stroke();
}
renderVizualitationID = requestAnimationFrame(animationLooper);
}
$('#clean').on('click',function() {
if (renderVizualitationID) cancelAnimationFrame(renderVizualitationID);
audio.pause();
audio.src = '';
frequency_array.fill( 0 );
ctx.clearRect(0, 0, canvas.width, canvas.height);
// kill the previous one
analyser.disconnect();
// create a new analyser
analyser = context.createAnalyser();
source.connect( analyser );
analyser.connect(context.destination);
});
$('#changeSrc').on('click',function() {
audio.src = "https://api.soundcloud.com/tracks/693365626/stream?client_id=r4wruADPCq7iqJomagvYpdehvILa2bgE"; // the source path
audio.play();
animationLooper();
});
.w {
position: relative;
top: 0;
left: 0;
width: 400px;
height: 400px;
background: #ccc;
}
#renderer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #111;
background: #1D4350;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="w">
<canvas id="renderer"></canvas>
</div>
<a id="clean" href="#" >clean</a>
<a id="changeSrc" href="#" >changeSrc</a>