I create sounds using oscillator nodes and want to draw a frequency visualization on a canvas. When the oscillator is playing, the visualization looks like this (standard oscillator settings, see code below). http://i58.tinypic.com/wtvwgz.png
After the oscillator stopped playing (complete silence!), this is what I get. The exact result changes from run to run, sometimes the values even keep slightly changing after the stop. http://i62.tinypic.com/2duji81.png
I don't understand why the frequency data is not zero for all bins, when the sound is not playing.
Tested on Firefox 30.0 and Iron 34.0.1850.0 (Chrome)
Here's my sample code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
window.onload = function () {
var ctx = document.getElementById("canvas").getContext("2d");
var audioContext = new (window.AudioContext
|| window.webkitAudioContext || window.mozAudioContext)();
var analyser = audioContext.createAnalyser();
analyser.fftSize = 512;
analyser.connect(audioContext.destination);
var frequencyBins = new Uint8Array(analyser.frequencyBinCount);
var osc = audioContext.createOscillator();
osc.connect(analyser);
osc.start(audioContext.currentTime + 2);
osc.stop(audioContext.currentTime + 4);
var WIDTH = 512;
var HEIGHT = 100;
var value, h, w;
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < frequencyBins.length; i++) {
value = frequencyBins[i];
h = HEIGHT * (value / 255);
w = WIDTH / frequencyBins.length;
ctx.fillRect(i * w, HEIGHT - 1, w, -h);
}
};
function animate() {
analyser.getByteFrequencyData(frequencyBins);
draw();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
};
</script>
</head>
<body>
<canvas id="canvas" width="512" height="100"></canvas>
</body>
</html>
I found a solution that works for me.
Instead of connecting the oscillator directly to the analyser, I pass the frequencies through a high-pass filter first. It seems that the value for the cutoff frequency can be set arbitrarily low, as long as it is not 0. Even with a cutoff of 0.00000001 the visualisation will be blank during silence.
http://jsfiddle.net/a2ZL9/3/
var analyser = audioContext.createAnalyser();
analyser.fftSize = 512;
analyser.connect(audioContext.destination);
var frequencyBins = new Uint8Array(analyser.frequencyBinCount);
var filter = audioContext.createBiquadFilter();
filter.type = "highpass";
filter.frequency.value = 0.0001;
filter.connect(analyser);
var osc = audioContext.createOscillator();
osc.connect(filter);
osc.start(audioContext.currentTime + 2);
osc.stop(audioContext.currentTime + 4);
It's not a noise floor. It happens with audio buffers too. It's a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With