0

I am attempting to make an audio bar visualizer.

Reading up on Web Audio API, I have the following code:

HTML:

<audio controls>  
      <source src="video/DownToEarth.mp3" type="audio/mp3">
</audio>
<canvas id="analyser_render"></canvas>

JAVASCRIPT:

var audioCtx, myAudio, canvas, ctx, source, analyser, bufferLength, dataArray, bars, bar_x, bar_width, bar_height;

window.addEventListener("load", initMp3Player, false);

function initMp3Player(){
    var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    var myAudio = document.querySelector('audio');
    var source = audioCtx.createMediaElementSource(myAudio);

    var analyser = audioCtx.createAnalyser();
    var bufferLength = analyser.frequencyBinCount;
    var dataArray = new Uint8Array(bufferLength);
    analyser.minDecibels = -90;
    analyser.maxDecibels = -10;

    var canvas = document.getElementById('analyser_render');
    ctx = canvas.getContext('2d');

    source.connect(analyser);
    analyser.connect(audioCtx.destination);
    frameLooper();
}

function frameLooper(){
    window.requestAnimationFrame(frameLooper);

    analyser.getByteFrequencyData(dataArray);

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#00CCFF';
    bars = 100;
    for (var i = 0; i < bars; i++) {
        bar_x = i * 3;
        bar_width = 2;
        bar_height = -(dataArray[i] / 2);
        ctx.fillRect(bar_x, canvas.height, bar_width, bar_height);
    }
}

Now everything looks to be in order, but every time I try to run it I continue to get an error: Uncaught TypeError: Cannot read property 'getByteFrequencyData' of undefined I have data going INTO dataArray, but the getByteFrequencyData doesn't seem to be getting anything out of it.

I read from THIS POST that I might want to include some lines about the min and max decibel range, but that didn't make an ounce of difference, I am still receiving this error.

Community
  • 1
  • 1
Murphy1976
  • 1,415
  • 8
  • 40
  • 88

1 Answers1

1

The variable analyser does not exist in the scope you are trying to use it, as it is local to function initMp3Player.

You need to change the signature of frameLooper:

function frameLooper(analyser){...

and when you call it, pass analyser, which is in scope at the place that you call it from.

frameLooper(analyser);

so that it is available in your frameLooper function.

Alternatively, you could declare analyser in a higher scope... but it's probably a good idea to avoid globals.

spender
  • 117,338
  • 33
  • 229
  • 351
  • Well... that got rid of the Cannot read property error, but now I have another one in tow: for the line of code `analyser.getByteFrequencyData(dataArray)` it is calling a **Uncaught TypeError: undefined is not a function** I have added the analyser, as you have suggested, to the signature of frameLooper and made sure it was part of the scope, but still.. no dice. – Murphy1976 Dec 04 '14 at 13:41
  • also, when I posted this, I noticed that I was using a mix of old variables and new variables, and was getting an error on **cannot find width** and saw that my old variable fbc_array was still in the code, instead of dataArray - I have updated my original question to reflect that change. – Murphy1976 Dec 04 '14 at 13:44
  • HOLY S@^#$! by declaring analyser as a global and removing it from the signature of frameLooper and the scope of frameLooper, the issue was solved. @spender, even though your solution didn't initially solve my problem, it still sparked my brain to fix my issue. So you get the points, thank you. – Murphy1976 Dec 04 '14 at 13:47