Question

I'm creating an audio visualizer with webgl, and have been integrating soundcloud tracks into it. I want to no be able to switch tracks, but I can either get my visualizer to work and the audio to break, or I can get the audio to work and the visualizer to break.

The two ways that I've been able to make it work are

Audio working

  1. delete audio element
  2. append new audio element to body
  3. trigger play

Visualizer working

  1. stop audio
  2. change source
  3. trigger play

When I have the visualizer working, the audio is totally messed up. The buffers just sound wrong, and the audio has artifacts in it (noise, beeps and bloops).

When I have the audio working, when I call analyser.getByteFrequencyData, I get an array of 0's. I presume this is because the analyser is not hooked up correctly.

The code for the audio working looks like

$('#music').trigger("pause");
currentTrackNum = currentTrackNum + 1;
var tracks = $("#tracks").data("tracks")
var currentTrack = tracks[parseInt(currentTrackNum)%tracks.length];
// Begin audio switching
analyser.disconnect();
$('#music').remove();
$('body').append('<audio id="music" preload="auto" src="'+ currentTrack["download"].toString() + '?client_id=4c6187aeda01c8ad86e556555621074f"></audio>');
startWebAudio(),

(I don't think I need the pause call. Do I?)

when I want the visualizer to work, I use this code

currentTrackNum = currentTrackNum + 1;
var tracks = $("#tracks").data("tracks")
var currentTrack = tracks[parseInt(currentTrackNum)%tracks.length];
// Begin audio switching
$("#music").attr("src", currentTrack["download"].toString() + "?client_id=4c6187aeda01c8ad86e556555621074f");
$("#songTitle").text(currentTrack["title"]);
$('#music').trigger("play");

The startWebAudio function looks like this.

function startWebAudio() {
  // Get our <audio> element
  var audio = document.getElementById('music');
  // Create a new audio context (that allows us to do all the Web Audio stuff)
  var audioContext = new webkitAudioContext();
  // Create a new analyser
  analyser = audioContext.createAnalyser();
  // Create a new audio source from the <audio> element
  var source = audioContext.createMediaElementSource(audio);
  // Connect up the output from the audio source to the input of the analyser
  source.connect(analyser);
  // Connect up the audio output of the analyser to the audioContext destination i.e. the speakers (The analyser takes the output of the <audio> element and swallows it. If we want to hear the sound of the <audio> element then we need to re-route the analyser's output to the speakers)
  analyser.connect(audioContext.destination);

  // Get the <audio> element started  
  audio.play();
  var freqByteData = new Uint8Array(analyser.frequencyBinCount);
}

My suspicion is that the analyzer isn't hooked up correctly, but I can't figure out what to look at to figure it out. I have looked at the frequencyByteData output, and that seems to be indicative of something not being hooked up right. The analyser variable is global. If you would like more reference to the code, here's where it is on github

Was it helpful?

Solution

You can only create a single AudioContext per window. You should also be disconnecting the MediaElementSource when you're finished using it.

Here's an example that I used to answer a similar question: http://jsbin.com/acolet/1/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top