我怎样才能通过网络声音 API 播放一段声音样本?

how can i play piece of sound sample by web sound API?

我有一个总持续时间为 3 秒的 "asd.wav" 样本并播放它:

let source = audioCtx.createBufferSource();
source.buffer = buffer; // recieved buffer of asd.wav
source.connect(audioCtx.destination);
source.start(0);

它从 0.00 到 3.00 秒播放完美,但我怎么只能从 1.00 到 2.00 秒播放这个样本?

这应该可以解决问题。也许可以用更简单的方式完成,但这是我能想到的。

var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();

var getSound = new XMLHttpRequest();
getSound.open("GET", "./asd.wav", true);
getSound.responseType = "arraybuffer";
getSound.onload = function() {
  audioCtx.decodeAudioData(getSound.response, function(buffer) {
    let start_time = 1, end_time = 2, sample_rate = buffer.sampleRate,
        channel_number = 0; // assuming a mono (one channel) audio
    let source = audioCtx.createBufferSource();
    let data = buffer.getChannelData(channel_number);
    data = data.slice(start_time * sample_rate, end_time * sample_rate)
    let new_buffer = audioCtx.createBuffer(1 /*number of channels =1*/ , data.length, sample_rate);
    new_buffer.copyToChannel(data, 0);
    source.buffer = new_buffer
    source.connect(audioCtx.destination);
    source.start(0);
  });
};

getSound.send();

如果是多声道音频,您需要重复上述步骤将数据复制到每个声道。

除了明确请求要播放的资源并切出一部分资源之外,您还可以利用 audio 元素。根据 docs,通过将 #t=[starttime][,endtime] 附加到 URL,您可以指定感兴趣的部分。

从那里开始,从媒体元素创建源并播放它是一件微不足道的事情,而不是从头开始。

与 AJAX 请求一样,您仍然受到 Cross-Origin 限制。

这是一个示例 - 只需将 URL 替换为同一域中的一个,一个引用具有 CORS header 的资源,或者一个使用您自己的服务器作为代理的资源CORS header.

不附带的兼容资源

如您所见,与 AJAX 方法相比,此方法及其附带的 HTML 所需的代码要少得多。您还可以动态创建和加载 audio 元素,如按钮单击处理程序中所示。

<!doctype html>
<html>
<head>
<script>
"use strict";
function byId(id){return document.getElementById(id)}
///////////////////////////////////
window.addEventListener('load', onDocLoaded, false);

function onDocLoaded(evt)
{
    //loadAndPlayPortion("3 seconds.wav", 0.0, 1.0);
    playAudioElement( byId('myAudioElem') );
};

function onBtnClicked(evt)
{
    var audio = document.createElement('audio');
    audio.onloadeddata = function(){ playAudioElement(this); };
    audio.src = '3 seconds.wav#t=2,3';  // could build this URL from user input
}


function playAudioElement(audioElem)
{
    var AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioCtx = new AudioContext();
    var source = audioCtx.createMediaElementSource(audioElem);
    source.connect(audioCtx.destination);
    audioElem.play();
}


function loadAndPlayPortion(soundUrl, startTimeSecs, endTimeSecs)
{
    var AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioCtx = new AudioContext();

    var ajax = new XMLHttpRequest();
    ajax.open("GET", soundUrl, true);
    ajax.responseType = "arraybuffer";
    ajax.onload = onFileLoaded;
    ajax.send();

    function onFileLoaded()
    {
        audioCtx.decodeAudioData(this.response, onDataDecoded);
    }

    function onDataDecoded(sampleBuffer)
    {
        let source = audioCtx.createBufferSource(), numChannels=sampleBuffer.numberOfChannels,
            sampleRate = sampleBuffer.sampleRate,
            nRequiredSamples = (endTimeSecs-startTimeSecs)*sampleRate,
            newBuffer = audioCtx.createBuffer( numChannels, nRequiredSamples, sampleRate);
        for (var curChannel=0; curChannel<numChannels; curChannel++)
        {
            var channelData = sampleBuffer.getChannelData(curChannel);
            channelData = channelData.slice(startTimeSecs*sampleRate, endTimeSecs*sampleRate);
            newBuffer.copyToChannel(channelData, curChannel, 0);
        }
        source.buffer = newBuffer;              // chosen portion of received buffer of sound-file
        source.connect(audioCtx.destination);
        source.start(0);
    }
}
</script>
<style>
</style>
</head>
<body>
    <button onclick='onBtnClicked()'>Create Audio element</button>
    <audio id='myAudioElem' src='3 seconds.wav#t=1,2'></audio>
</body>
</html>