问题描述
我正在用html + js构建一个命运之轮,它很快就旋转了.每次有新颜色飞过该标记时,转轮都应发出喀哒声.以最快的速度听起来像是机关枪,因此在旧文件基本完成之前就开始播放新文件.文件本身总是相同的:click.wav
I'm building a wheel of fortune in html+js that spins rather quickly. Every time a new color flies by the mark, the wheel should play a click-sound. At top speed this sounds almost like a machine gun, so a new file starts playing before the old one is finished basically. The file itself is always the same: click.wav
它只能在Chrome中在Chrome中正常运行. Firefox有一个怪异的错误,只有在其他音频源处于活动状态时才播放声音,例如在其他选项卡中播放的youtube视频. Edge和Safari可以将点击安全地保留到最后,然后同时播放所有这些点击.一团糟...我使用的是此处描述的方法使用克隆<audio>
标签
It works fine in Chrome, only in chrome. Firefox has a weird bug, where it only plays the sound, if there is any other audio source active, such as a youtube video playing in a different tab. Edge and Safari kinda safe up the clicks to the end and then play them all simultaniously. It's a mess...I use the method described here which uses cloning an <audio>
tag
我想这是问题所在:
var sound = new Audio("sounds/click.wav");
sound.preload = 'auto';
sound.load();
function playsound(){
var click=sound.cloneNode();
click.volume=1;
click.play();
}
这是我的自旋函数的简化版本,它每秒仅几次调用playsound()函数:
Here is a simplified version of my spinning function that just calls the playsound() function several times per second:
function rotateWheel(){
angle = angle + acceleration
while (angle >= 360) {
angle = angle - 360
}
var wheel = document.getElementById("wheel")
wheel.style.transform = "rotate("+angle +"deg)"
// play the click when a new segment rotates by
if(Math.floor(angle/21) != previousSegment){
playsound()
previousSegment = Math.floor(angle/21)
}
推荐答案
您使用了此方法有时会导致浏览器进程崩溃,因为您要么创建了内存问题,要么用浏览器必须处理的元素填充了DOM -因此,您应该重新考虑您的方法,因为您发现它无法在大多数浏览器(例如Safari或FireFox)中大量使用
深入研究<audio>
标签规范,很显然,有很多事情根本无法使用它完成,这不足为奇,因为它是为媒体播放而设计的.限制之一包括->没有精确的声音计时.
You used an answer from here this methods cause at some point to crash the browser process because you either create a memory issue or you fill up the DOM with elements the browser has to handle - so you should re-think your approach AND as you found out it will not work for heavy use in most browsers like safari or FireFox
Looking deeper into the <audio>
tag specification, it becomes clear that there are many things that simply can't be done with it, which isn't surprising, since it was designed for media playback.One of the limitations includes -> No fine-grained timing of sound.
因此,您必须找到所需的另一种方法,我们使用为在线视频游戏设计的Web Audio API.
网络音频API
AudioContext用于管理和播放所有声音.要使用Web Audio API产生声音,请创建一个或多个声音源,并将它们连接到AudioContext实例(通常是扬声器)提供的声音目标. AudioBuffer
使用Web Audio API,只有将音频文件加载到缓冲区后才能播放音频文件.加载声音需要花费时间,因此在动画/游戏中使用的资产应在页面加载时,游戏或关卡开始时加载,或者在玩家玩游戏时逐步加载.
基本步骤
So you have to find another method for what you want we use Web Audio API designed for online video games.
Web Audio API
An AudioContext is for managing and playing all sounds. To produce a sound using the Web Audio API, create one or more sound sources and connect them to the sound destination provided by the AudioContext instance (usually the speaker).The AudioBuffer
With the Web Audio API, audio files can be played only after they’ve been loaded into a buffer. Loading sounds takes time, so assets that are used in the animation/game should be loaded on page load, at the start of the game or level, or incrementally while the player is playing.
The basic steps
- 我们使用XMLHttpRequest将数据从音频文件加载到缓冲区中.
- 接下来,我们进行异步回调并发送实际请求以进行加载.
- 一旦声音被缓冲和解码,就可以立即触发.
- 每次触发时,都会创建一个不同的缓冲声音实例.
游戏中音效的关键特征是可以同时存在许多音效.因此,以机枪"为例:假设您正处于射击机枪的交战中.机关枪每秒发射多次,导致同时播放数十种声音效果.这是Web Audio API真正发挥作用的地方.您的应用程序的简单示例:
A key feature of sound effects in games is that there can be many of them simultaneously.So to take your example of the "machine gun": Imagine you're in the middle of a gunfight a shooting machine gun.The machine gun fires many times per second, causing tens of sound effects to be played at the same time. This is where Web Audio API really shines.A simple example for your application:
/* global AudioContext:true,
*/
var clickingBuffer = null;
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
function loadClickSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
if (!buffer) {
console.log('Error decoding file data: ' + url);
return;
}
clickingBuffer = buffer;
});
request.onerror = function() {
console.log('BufferLoader: XHR error');
};
request.send();
};
}
function playSound(buffer, time, volume) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
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
}
// You call with in your document ready
loadClickSound('sounds/click.wav');
//and this plays the sound
playSound(clickingBuffer, 0, 1);
现在,您可以通过引入随机因素来应对不同的时机和音量变化如果您需要一个更复杂的解决方案,该解决方案具有不同的点击声音(存储在缓冲区阵列中)和音量/距离变化,那么这将是一段较长的代码.
Now you can play around with different timings and volume variations for example by intoducing a random factorIf you need a more complex solution with different clicking sounds (stored in a buffer array) and volume/ distance variations this would be a longer piece of code.
这篇关于如何在javascript中快速播放声音文件的多个副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!