如何正确缓存 webaudio 对象?
Posted
技术标签:
【中文标题】如何正确缓存 webaudio 对象?【英文标题】:How to cache a webaudio object properly? 【发布时间】:2021-12-14 00:57:48 【问题描述】:我正在使用 javascript 和其他网络技术开发游戏。在其中,有一个基本上是塔防的游戏模式,其中多个对象可能需要同时使用同一个音频文件(.ogg)。加载一个文件并为每个文件创建一个新的 webaudio 太滞后了,即使我尝试流式传输它而不是简单的同步读取,并且如果我创建一个 webaudio 并将其保存在一个变量中以多次使用,每次它正在播放,并且有一个新的请求来播放所述音频,正在播放的音频将停止以允许新的音频播放(因此,如果有足够的音频,则根本不会播放任何内容)。
由于这些问题,我决定在每次播放时复制所述 webaudio 对象,但这样做不仅速度慢,而且还会造成轻微的内存泄漏(至少我这样做的方式是这样)。
如何正确缓存网络音频以供重复使用?考虑到我很确定我每次都需要一个新的,因为每个音频都有一个位置,因此每个音频的播放方式都会不同,具体取决于播放器相对于正在播放音频的对象的位置
【问题讨论】:
【参考方案1】:您使用 web-audio-api 标记了您的问题,但从这个问题的正文来看,您似乎使用的是 htmlMediaElement <audio>
而不是 Web Audio API。
所以我会邀请你转换到那个 Web Audio API。
从那里你将能够对你的音频文件进行一次解码,只将解码后的数据保存为 AudioBuffer,并创建 许多 阅读器,它们都将连接到那个唯一的 AudioBuffer,而无需吃掉更多的记忆。
const btn = document.querySelector("button")
const context = new AudioContext();
// a GainNode to control the output volume of our audio
const volumeNode = context.createGain();
volumeNode.gain.value = 0.5; // from 0 to 1
volumeNode.connect(context.destination);
fetch("https://dl.dropboxusercontent.com/s/agepbh2agnduknz/camera.mp3")
// get the resource as an ArrayBuffer
.then((resp) => resp.arrayBuffer())
// decode the Audio data from this resource
.then((buffer) => context.decodeAudioData(buffer))
// now we have our AudioBuffer object, ready to be played
.then((audioBuffer) =>
btn.onclick = (evt) =>
// allowing an AudioContext to make noise
// must be required from an user-gesture
if (context.status === "suspended")
context.resume();
// a very light player object
const source = context.createBufferSource();
// a simple pointer to the big AudioBuffer (no copy)
source.buffer = audioBuffer;
// connect to our volume node, itself connected to audio output
source.connect(volumeNode);
// start playing now
source.start(0);
;
// now you can spam the button!
btn.disabled = false;
)
.catch(console.error);
<button disabled>play</button>
【讨论】:
以上是关于如何正确缓存 webaudio 对象?的主要内容,如果未能解决你的问题,请参考以下文章
iOS“默认”UIWebView/WebKit 上的 WebAudio 支持
使用纯 JavaScript 和 Chromium WebAudio API 生成音调