Web Audio API - multiple synchronized tracks - stopping previous track when new track starts

前端 未结 2 2000
闹比i
闹比i 2021-01-21 22:33

I\'m trying to mimic the Web Audio API multitrack demo from the \'Mozilla Web Audio API for games\' Web doc.

https://developer.mozilla.org/en-US/docs/Games/Techniques/Au

2条回答
  •  傲寒
    傲寒 (楼主)
    2021-01-21 22:55

    Figured it out with help from @Kaiido

    Example with both synchronization and starting a new track where a previous track stops:

    
    
    let active_source = null;
    let buffers = {};
    const context = new(window.AudioContext || window.webkitAudioContext)();
    let offset = 0;
    const tempo = 3.074074076;
    const tracks = document.getElementsByClassName('track');
    
    function playTrack(url) {
      let buffer = buffers[url];
      let source = context.createBufferSource();
    
      source.buffer = buffer;
      source.connect(context.destination);
      source.loop = true;
    
      if (offset == 0) {
        source.start();
        offset = context.currentTime;
        active_source = source;
      } else {
        let relativeTime = context.currentTime - offset;
        let beats = relativeTime / tempo;
        let remainder = beats - Math.floor(beats);
        let delay = tempo - (remainder*tempo);
        let when = context.currentTime+delay;
    
        stopActiveSource(when);
        source.start(context.currentTime+delay,relativeTime+delay);
        active_source = source;
        source.onended = function() {
          active_source = null;
        };
      }
    }
    
    for (var i = 0, len = tracks.length; i < len; i++) {
      tracks[i].addEventListener('click', function(e) {
        playTrack(this.href);
        e.preventDefault();
      });
      getBuffer(tracks[i].href);
    }
    
    function getBuffer(url) {
      const request = new XMLHttpRequest();
      request.open('GET', url, true);
      request.responseType = 'arraybuffer';
      request.onload = function(evt) {
        context.decodeAudioData(request.response, store);
      };
      request.send();
    
      function store(buffer) {
        buffers[url] = buffer;
      }
    }
    
    function stopActiveSource(when) {
      if (active_source) {
        active_source.onended = null;
        active_source.stop(when);
      }
    }
    

    http://jsfiddle.net/mdq2c1wv/1/

提交回复
热议问题