我知道这不是您想听到的答案,但是无论您是否编写了自己的 Flash 库来播放声音,都无法阻止这种情况。
对于每个说“它对我来说很好!”的人。尝试在海报的演示播放时调整浏览器窗口的大小或移动浏览器窗口。您将听到的不仅仅是细微的延迟。这在 Firefox 和 IE 中最为明显,但即使是 Chrome 也会体验到它。
更糟糕的是,如果您在浏览器窗口的关闭框上单击并按住鼠标,声音会完全停止,直到您松开鼠标(您可以在关闭框之外释放它而不是实际关闭窗口,仅供参考)。
这里发生了什么?
事实证明,当您开始调整浏览器窗口大小或在浏览器窗口中移动时,浏览器会尝试将更改窗口属性的行为与跟上窗口中正在进行的 javascript 的行为进行多任务处理。它会在需要时缩短窗口。
当您在浏览器窗口中的关闭框上按住鼠标时,时间会完全停止。当您重新调整窗口大小或移动窗口时,这就是以较小的增量发生的情况:时间在 JavaScript 世界中以小的、零星的块(或大块,取决于您的机器有多慢)静止不动。
现在,您可能会说“当然,调整浏览器大小或按住关闭按钮会使浏览器暂停,但通常不会发生这种情况”。不幸的是,你会错的。
实际上,它一直在发生。我已经进行了测试,结果发现即使浏览器窗口完全静止,不触摸鼠标,也不触摸键盘,计算机上的后台进程仍然会导致“打嗝”,这意味着在短时间内(也许小到几毫秒)时间在浏览器中“静止不动”,完全随机的时间间隔在您的控制之外。
“静止不动”是什么意思?假设您有一个 setInterval() 调用(这也适用于 setTimeout)每 33 毫秒(大约每秒 30 帧)运行一次。现在,您会期望在每 33 个“真实世界”毫秒后调用您的函数。大多数时候,这是真的。
但是当“打嗝”开始发生时,您的 setInterval 调用可能会在 43 毫秒内发生。在这 10 毫秒内发生了什么?没有什么。时间暂停。浏览器上没有任何更新。如果您有声音播放,它将继续播放,但不会开始播放新的声音调用,因为根本没有执行任何 javascript。如果您有 5 个 setInterval() 函数正在运行,它们将在某个时间点全部暂停 10 毫秒。
告诉“时间静止”的唯一方法是在 setInterval 函数回调中轮询实际时间。您将能够看到浏览器大部分时间都在尝试跟上,但是当您开始调整窗口大小或做一些有压力的事情时,间隔会比平时长,但您的所有代码将保持同步(我正在使用这种技术制作游戏,所以你会看到你所有的游戏更新都是同步发生的,但只是有点卡顿)。
通常,我应该指出,这些口吃是完全不引人注意的,除非您编写一个函数来记录 setInterval 时间期间的实际时间(正如我在自己的测试中所做的那样),您甚至不会知道它。但是,如果您尝试使用重复的 play() 调用来创建某种类型的重复声音(例如 Asteriods 背景中的哔哔声),就会出现问题。
我的建议?如果你有一个你知道会循环播放的声音,给它一个较长的持续时间,也许 10 秒,你就不太可能注意到打嗝了(现在,屏幕上的图形可能仍然打嗝,但你搞砸了)。
如果您正在编写游戏并让主角用机关枪开火,请不要对 playSound('singleShot') 进行 10 次快速连续调用,对 playSound('machineGunFire10Rounds') 进行一次调用或类似的操作.
你必须做一些诡计才能绕过它,但在大多数情况下你会没事的。
似乎 Flash 小程序运行在一个进程中,该进程对常规浏览器/javascript 环境中发生的整个“时间冻结”事件的影响较小,但我仍然可以让它发生,即使在您指向 ToneMatrix 示例的链接上,通过调整或移动浏览器窗口。
但 Flash 似乎仍然比 javascript 好得多。当我不理会浏览器时,我愿意打赌 Flash 在任何时间都不会冻结,并且间隔总是按时运行。
tl;博士:
- 你被你希望达到的目标搞砸了
- 尝试使用一些解决方法来处理它
- 用纯闪存重写您的项目(无 javascript)
- 等待浏览器变得更好(Firefox 4 正在获得一个名为JaegerMonkey的新 javascript 引擎,这将很有趣)
- 我怎么知道这一切?我已经使用 javascript、setInterval 和 soundManager/html5 音频调用进行了大量测试和记录