好的,这是您想要的函数代码。该代码可以使用本地文件进行测试,以排除所有类型的安全问题(包括 xhr 代码)。它使用纯 JS ES5,并已在不同操作系统上使用 firefox 和 chrome 进行了测试。请将其放入audio_test.html中以验证该功能。警告一句,不要混合 html 标签和 java 脚本函数调用,使用事件监听器,就像我在代码中演示的那样。停止按钮功能只是一个开始,在播放后重新锁定需要额外的代码,我没有打扰来写。
不要尝试持续创建缓冲区,因为这会填满内存并使浏览器/操作系统崩溃。如果你想要重叠的声音,这意味着使用缓冲区数组,但这将是另一个问题。
<!DOCTYPE html>
<!-- Author: codebreaker007 @ stackoverflow -->
<html class="h-100" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Web Audio API: load + play</title>
</head>
<body>
<p>Example of using the Web Audio API to load a sound file and </br>play once, play continous on mousedown or stop play
and start playing on user-click.</p>
Tested in Firefox and Chrome</p>
<input type="file" accept="audio/*" value="">
<button id="playonce" disabled=disabled>Play once</button>
<button id="playstop" disabled=disabled>Stop play</button>
<button id="playcont" disabled=disabled>Play cont</button>
<script>
/* global AudioContext:true,
*/
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var source = null;
var clickingBuffer = null;
var mouseIsDown = false;
var buttonPo = document.getElementById("playonce");
var buttonPs = document.getElementById("playstop");
var buttonPc = document.getElementById("playcont");
if (document.readyState!="loading") docReady();
/* Modern browsers */
else document.addEventListener("DOMContentLoaded", docReady);
function docReady() {
buttonPo.addEventListener("click", function(e){
playSound(clickingBuffer, 0, 0, 0.8);
buttonPs.disabled = false;
});
buttonPs.addEventListener("click", function(e){
if (source) {
source.stop(0);
}
buttonPs.disabled = true;
});
buttonPc.addEventListener("mousedown", function(e){
playSound(clickingBuffer, 1, 0, 1);
// while(mouseIsDown) playSound(clickingBuffer, 0, 1);
});
buttonPc.addEventListener("mouseup", function(e){
if (source) {
source.stop(0);
}
});
}
function playSound(buffer2play, isLoop, time, volume) {
console.log("playsound called");
source = context.createBufferSource(); // creates a sound source
source.buffer = buffer2play; // tell the source which sound to play
if (isLoop) source.loop = true;
else source.loop = false;
source.connect(context.destination); // connect the source to the context's destination (the speakers)
var gainNode = context.createGain(); // Create a gain node
source.connect(gainNode); // Connect the source to the gain node
gainNode.connect(context.destination); // Connect the gain node to the destination
gainNode.gain.value = volume; // Set the volume
source.start(time); // play the source at the deisred time 0=now
console.log("playSound");
}
function initSound(arrayBuffer) {
context.decodeAudioData(arrayBuffer, function(buffer) {
// clickingBuffer is global to reuse the decoded audio later.
clickingBuffer = buffer;
// Test routine activate buttons
buttonPo.disabled = false;
buttonPc.disabled = false;
}, function(e) {
console.log('Error decoding file', e);
});
}
// User selects file, read it as an ArrayBuffer and pass to the API.
var fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', function(e) {
var reader = new FileReader();
reader.onload = function(e) {
initSound(this.result);
};
reader.readAsArrayBuffer(this.files[0]);
}, false);
// Load file from a URL as an ArrayBuffer.
// Example: loading via xhr2: loadSoundFile('sounds/test.mp3');
function loadClickSound(url) {
console.log("loading sound");
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
// Decode asynchronously
initSound(this.response); // this.response is an ArrayBuffer.
};
xhr.send();
}
</script>
</body>
</html>