Search code examples
audiohtml5-audioweb-audio-apiaudiocontextaudiobuffer

AudioBufferSourceNode not looping when duration is set


I've been playing around with js audio web api. The thing I'm trying to achieve is to play a piece of a track in loop.

No problem playing the whole track in loop, but if I define a duration then it doesn't loop anymore...I guess what I need is like a marker more than a duration...if there a way to do this?

const audioCtx = new AudioContext();
const srcUrl = 'https://freesound.org/data/previews/251/251248_1137749-lq.mp3';
let srcArrayBuffer;
let playingTrack;

async function loadSrcAudioFile(url) {
  const response = await fetch(url);
  const buffer = await response.arrayBuffer();

  return buffer;
}

function loop() {
  playingTrack = audioCtx.createBufferSource();

  playingTrack.connect(audioCtx.destination);

  playingTrack.buffer = srcArrayBuffer;
  
  playingTrack.loop = true;
  //playingTrack.loopStart = 0;
  //playingTrack.loopEnd = 1.5;
  
  playingTrack.start(audioCtx.currentTime, 0, 1.5);
}

function stop() {
  playingTrack.stop();
  playingTrack = null;
}

async function play() {
    if (!srcArrayBuffer) {
      const buffer = await loadSrcAudioFile(srcUrl);

      srcArrayBuffer = await audioCtx.decodeAudioData(buffer);
  }

  loop();
}

document.getElementById('playBtn').addEventListener('click', play);
document.getElementById('stopBtn').addEventListener('click', stop);

JSFIDDLE


Solution

  • You're almost there. Setting the duration means "play this for this long". It will stop after 1.5 seconds no matter what. It doesn't care if the buffer gets looped or not.

    Setting loopStart and loopEnd without specifying the duration will do the trick.

    https://jsfiddle.net/4yeavmp3/

    If you for example want to loop it 4 times you could set the duration to 6.