通过JS与重叠播放音频
Play Audio through JS with Overlapping
我为一款基于画布的游戏编写了以下JS代码。
var EXPLOSION = "sounds/explosion.wav";
function playSound(str, vol) {
var snd = new Audio();
snd.src = str;
snd.volume = vol;
snd.play();
}
function createExplosion() {
playSound(EXPLOSION, 0.5);
}
这个可以工作,但是每次调用它时,它都会发送一个服务器请求来下载声音文件。或者,如果我事先声明Audio对象:
var snd = new Audio();
snd.src = EXPLOSION;
snd.volume = 0.5;
function createExplosion() {
snd.play();
}
这是有效的,但是如果createExplosion函数在声音完成播放之前被调用,它根本不播放声音。这意味着一次只允许播放一个声音文件——在多个爆炸发生的场景中,它根本不起作用。
是否有办法正确播放音频文件多次重叠与自己?
我在一款俄罗斯方块游戏中寻找了很长时间,我认为这个解决方案是最好的。
function playSoundMove() {
var sound = document.getElementById("move");
sound.load();
sound.play();
}
只要把它加载好就可以了
您可以使用复制节点的cloneNode()
和play()
来复制节点。
我的audio元素看起来像这样:
<audio id="knight-audio" src="knight.ogg" preload="auto"></audio>
,我有一个onClick
监听器,它就是这样做的:
function click() {
const origAudio = document.getElementById("knight-audio");
const newAudio = origAudio.cloneNode()
newAudio.play()
}
由于不显示audio
元素,因此实际上不必将节点附加到任何东西上。
我验证了客户端和服务器端Chrome只尝试下载一次音频文件。
警告:我不确定对性能的影响,因为在我的网站上,这个剪辑的播放次数最多不超过40倍。如果你做的事情比这个大得多,你可能需要清理音频节点?
试试这个:
(function() {
var snds = {};
window.playSound(str,vol) {
if( !snds[str]) (snds[str] = new Audio()).src = str;
snds[str].volume = vol;
snds[str].play();
}
})();
那么你第一次调用它时,它将获取声音,但之后每次它都会重复使用相同的声音对象。
编辑:你也可以预加载重复,让声音播放不止一次:
(function() {
var snds = {}
window.playSound = function(str,vol) {
if( !snds[str]) {
snds[str] = [new Audio()];
snds[str][0].src = str;
}
var snd = snds[str], pointer = 0;
while( snd[pointer].playing) {
pointer++;
if( pointer >= snd.length) {
snd.push(new Audio());
snd[pointer].src = str;
}
}
snd[pointer].volume = vol;
snd[pointer].play();
};
})();
请注意,如果你播放的声音重叠太多,它会发送多个请求,但它应该很快返回未修改,只有当你播放的次数比以前多时才会这样做。
在我的游戏中,我使用预加载,但在声音启动后(不预加载或在页面加载时预加载所有内容并不明智,有些声音根本没有在某些游戏玩法中播放,为什么要加载它们)
const audio {};
audio.dataload = {'entity':false,'entityes':[],'n':0};
audio.dataload.ordernum = function() {
audio.dataload.n = (audio.dataload.n + 1)%10;
return audio.dataload.n;
}
audio.dataload.play = function() {
audio.dataload.entity = new Audio('/some.mp3');
for (let i = 0; i<10;i++) {
audio.dataload.entityes.push(audio.dataload.entity.cloneNode());
}
audio.dataload.entityes[audio.dataload.ordernum()].play();
}
audio.dataload.play() // plays sound and preload sounds to memory when it isn't
我创建了一个允许分层音频的类。这与其他答案非常相似,它使用相同的src创建另一个节点,但该类只在必要时才会执行。如果它已经创建了一个已经完成的节点,它将重播该现有节点。
另一个调整是最初获取音频并使用blob的URL。我这样做是为了效率;因此,SRC不必在每次创建新节点时都从外部获取。
class LayeredAudio {
url;
samples = [];
constructor(src){
fetch(src)
.then(response => response.blob())
.then((blob) => {
this.url = URL.createObjectURL(blob);
this.samples[0] = new Audio(this.url);
});
}
play(){
if(!this.samples.find(e => e.paused)?.play()){
this.samples.push(new Audio(this.url))
this.samples[this.samples.length - 1].play()
}
}
}
const aud = new LayeredAudio("URL");
aud.play()
更多地依赖于内存而不是处理时间,我们可以制作多个音频克隆的数组,然后按顺序播放它们:
function gameSnd() {
tick_wav = new Audio('sounds/tick.wav');
victory_wav = new Audio('sounds/victory.wav');
counter = 0;
ticks = [];
for (var i = 0; i<10;i++)
ticks.push(tick_wav.cloneNode());
tick = function(){
counter = (counter + 1)%10;
ticks[counter].play();
}
victory = function(){
victory_wav.play();
}
}
当我尝试其他一些解决方案时,出现了一些延迟,但我可能已经找到了更好的替代方案。如果您将音频数组的长度设置得很高,这将消耗大量内存。我怀疑你是否需要在同一时间播放相同的音频超过10次,但如果你只是把数组长度变长。
var audio = new Array(10);
// The length of the audio array is how many times
// the audio can overlap
for (var i = 0; i < audio.length; i++) {
audio[i] = new Audio("your audio");
}
function PlayAudio() {
// Whenever you want to play it call this function
audio[audioIndex].play();
audioIndex++;
if(audioIndex > audio.length - 1) {
audioIndex = 0;
}
}
我发现这是一个简单的方法来重叠相同的音频本身
<button id="btn" onclick="clickMe()">ding</button>
<script>
function clickMe() {
const newAudio = new Audio("./ding.mp3")
newAudio.play()
}
- 使用HTMLMediaElement向后播放音频
- 播放音频时创建一个跳动的圆圈
- Javascript播放音频后其他没有音频崩溃
- 在播放完成之前再次单击播放音频文件
- 延迟后播放音频标签
- 如何使用Flash CC画布项目在iPad上播放音频
- 使用javascript播放音频(没有HTML5或可见播放器)
- 如何使用Bootstrap和Heroku为Rails应用程序添加隐藏的播放音频
- 检测iOS移动设备的JavaScript比自动播放音频
- 在手机和平板电脑浏览器上播放音频片段
- 需要帮助修复我的javascript"对于循环“;播放音频播放列表
- 自动播放音频播放列表SoundManager2 bar ui
- 单击链接时播放音频剪辑
- 使用 Redux 播放音频文件
- 在 iPad 上延迟后正在播放音频
- 关闭后,引导模式弹出窗口上的视频继续播放音频
- 无法更改用于播放音频的变量
- 我在 html5 音频标签中播放音频时收到 [对象媒体错误]
- 无法使用谷歌应用引擎播放音频.它在本地工作
- 在 javascript 数组中播放音频文件时遇到问题