如何在网络音频中循环播放wav一定次数?

问题描述 投票:1回答:3

我知道AudioBufferSourceNode上有一个选项loop=true。但是我只想重复几次wav。例如,如何重复两次?

var url  = 'main.wav';

var context = new AudioContext();
var source = context.createBufferSource();

source.connect(context.destination);

var request = new XMLHttpRequest();
request.open('GET', url, true); 
request.responseType = 'arraybuffer';
request.onload = function() {
    context.decodeAudioData(request.response, function(response) {

        source.buffer = response;

        source.start(0);
        source.start(source.buffer.duration); // doesn't work "cannot call start more than once."
        //source.loop = true; // this is infinite amount of times, not good

    }, function () { console.error('The request failed.'); } );
}
request.send();

我也尝试创建第二个缓冲区:

var source2 = context.createBufferSource();

// inside callback
source2.buffer = response; // same response so I don't need to load this separately
source2.start(source.buffer.duration); // doesn't work

但是那也不起作用。有什么想法吗?

javascript web-audio-api
3个回答
1
投票

一种解决方案是使用在ended节点上可用的ended事件来确定声音何时完成了完整的播放,此时可以计算播放的数量以确定播放是继续还是停止:

source

1
投票

您可以将AudioBufferSource的source设置为true并调用

const url = 'main.wav';
const context = new AudioContext();
const source = context.createBufferSource();

// Tracks the number to playback cycles remaining
let playbackCount = 5;

source.connect(context.destination);

const request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = () => {

  context.decodeAudioData(request.response, (response) => {

    source.buffer = response;
    source.start(0);
    // Enable loop behavior
    source.loop = true;
    // Add event listener that fires after full playthrough
    source.addEventListener("ended", () => {

        // Decrement playback count
        playbackCount --;
        if(playbackCount <= 0) {
          // Stop playback source if count reaches zero
          source.stop();
        }
    });
  }, () => {
    console.error('The request failed.');
  });
}
request.send();

loop
source.stop( ctx.currentTime + audioBuffer.duration * repeatTime )

0
投票

您使用第二个缓冲区的方法是正确的,您只需要通过将音频上下文时间和声音持续时间相加来使用绝对开始时间:

(async () => {  
  const url = 'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3';
  const buf = await fetch( url ).then( (r) => r.arrayBuffer() );
  const ctx = new AudioContext();
  const audioBuffer = await ctx.decodeAudioData( buf );
  
  btn.onclick = (e) => {
    const source = ctx.createBufferSource();
    source.buffer = audioBuffer;
    source.loop = true;
    source.connect( ctx.destination );
    source.start( 0 );
    source.stop( ctx.currentTime + audioBuffer.duration * inp.valueAsNumber );
  };
  btn.disabled = false;
})().catch( console.error );

此方法可提供无缝播放(如果文件无间隙)。

您可以将其包装为一个简单的函数:

<label> repeat<input id="inp" type="number" min="1" max="20" value="5"></label>
<button id="btn" disabled>start</button>
© www.soinside.com 2019 - 2024. All rights reserved.