Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web audio API get AudioBuffer of <audio> element

I have an audio element

var audioSrc = 'https://mfbx9da4.github.io/assets/audio/dope-drum-loop_C_major.wav'
var audio = document.createElement('audio')
audio.src = audioSrc

I need the AudioBuffer to do beat detection so I tried accessing the buffer when the audio is loaded as so:

audio.oncanplaythrough = () => {
  console.info('loaded');
  var source = context.createMediaElementSource(audio);
  source.connect(context.destination);
  console.info('source.buffer', source.buffer);
  source.start()
}

However, the above code snippet logs

> loaded
> source.buffer undefined
like image 533
david_adler Avatar asked Oct 20 '17 19:10

david_adler


1 Answers

It seems the best way to do this is to avoid <audio> tags and load the audio via XHR:

const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const audioSrc =
  "https://davidalbertoadler.com/assets/audio/dope-drum-loop_C_major.wav";

const audioData = await fetchAudio(audioSrc);
audioContext.decodeAudioData(audioData, onDecoded, onDecodeError);

function fetchAudio(url) {
  return new Promise((resolve, reject) => {
    const request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.responseType = "arraybuffer";
    request.onload = () => resolve(request.response);
    request.onerror = (e) => reject(e);
    request.send();
  });
}

function onDecoded(buffer) {
  // Play the song
  console.log("Got the decoded buffer now play the song", buffer);
  const source = audioContext.createBufferSource();
  source.buffer = buffer;
  source.connect(audioContext.destination);
  source.loop = true;
  source.start();
}

function onDecodeError(e) {
  console.log("Error decoding buffer: " + e.message);
  console.log(e);
}
like image 170
david_adler Avatar answered Nov 10 '22 20:11

david_adler