我怎样才能通过网络声音 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>
我有一个总持续时间为 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>