2010-03-16 25 views
4

我正在定期播放一些音符。每一个都被延迟了一个毫秒的随机数,产生了一个不规则的效果。我如何解决它?SoundManager2有不规则的延迟

注意:只要一致,我还是有一些延迟。

类型“实现您自己的小SoundManager2替换,优化定时敏感回放”的答案是确定的,如果你知道如何做到这一点:)但我试图避免重写我的整个应用程序在Flash中现在。

有关可听延迟为零的应用的示例,请参阅基于闪存的应用ToneMatrix

测试用例 (see it here liveget it in an zip):

<head> 
<title></title> 
<script type="text/javascript" 
src="http://www.schillmania.com/projects/soundmanager2/script/soundmanager2.js"> 
</script> 
<script type="text/javascript"> 
soundManager.url = '.' 
soundManager.flashVersion = 9 
soundManager.useHighPerformance = true 
soundManager.useFastPolling = true 
soundManager.autoLoad = true 

function recur(func, delay) { 
    window.setTimeout(function() { recur(func, delay); func(); }, delay) 
} 

soundManager.onload = function() { 
    var sound = soundManager.createSound("test", "test.mp3") 
    recur(function() { sound.play() }, 300) 
} 
</script> 
</head> 
<body> 
</body> 
</html> 
+0

当我运行你的测试用例时,这些音符与我听起来像节奏规律一样播放。这是否意味着我在快速机器上获得了更好的浏览器,而只有很少或没有其他后台进程?或者我对你听到的违规行为不敏感?您能否详细介绍一下您遇到的不规则情况 - 您提到了“毫秒的随机数”,但我敢肯定我无法检测到5毫秒和15毫秒之间的差异。换句话说,如果我们听不到有什么问题,我们不能提出解决方案。 – brainjam 2010-03-24 21:36:25

回答

0

您正在使用的JavaScript间隔,这是不能被保证开火的准确时间。我相信内部闪存时序更可靠。

但是,这可能会有所帮助,在您触发播放声音之后发生火灾。

window.setTimeout(function() { func(); recur(func, delay); }, delay); 
+0

谢谢。你所建议的改变没有帮助。另外,我刚刚意识到我的'复发'功能已经存在于JavaScript中,它被称为window.setInterval(但这也不能解决问题)。 – 2010-03-23 17:56:03

1

在我对你的问题的评论我说过,我没有听到不规则当我玩你的样品。这意味着我要么是“节奏失聪”,要么是您的设置中可能存在干扰良好实时性能的事情。您没有提及您的环境的任何细节,但是您的计算机上可能还有其他进程正在吸取CPU周期,或者Flash版本较旧,但可能无法很好地处理声音延迟。我自己正在使用最新版本的Flash(10.something),而您的参数需要Flash 9.但是,也许我应该假设,如果您足够聪明,可以使用SoundManager2和StackOverflow,那么您将消除这些问题。

因此,这里有一些可能存在的故障和评论浮现在脑海:

1)SoundManager类网站有一些演示,包括JS-DOM "painting" + Sound, V2。你是否听到过不规则的延迟和延迟?如果没有,也许你可以比较他们在那里做什么和你正在做什么。如果你是,那么也许看看你的机器环境。当我运行该演示时,它非常灵敏。 (编辑:然而,仔细观察一下,您可以观察笔画大小在笔画中的变化情况,因为它随鼠标事件之间的时间间隔而变化(假设您保持鼠标速度不变),您可以在视觉上看到鼠标事件模式中的任何不规则情况,我可以看到邮票大小的偶尔变化,这表明鼠标事件不会在常规时间进入,这会使我们看到Javascript事件。)

2)Javascript当谈到计时时,setTimeout()setInterval()不是很可靠。大多数情况下,他们会按照您要求的时间间隔返回一些球场,但可能会有很大的变化,通常是延迟,这使得他们不可靠。我发现在Flash中使用ActionScript时也是如此。您可能需要打印正在进行sound.play()调用的时间,以查看这些违规行为是否由于setTimeout/setInterval()中的违规行为所致。如果是这样的话,你可以尝试缩短间隔时间,然后轮询系统时间以更接近你想要的300ms间隔。你可以使用new Date().getTime()查询系统时间,这似乎有ms精度。轮询当然是一个可怕的骇客,当它们可以用于其他事情时会吸收周期,我不推荐它,但是您可以尝试查看它是否有帮助。 编辑:这是a writeup by John Resig on the handling of input and timer events in js

3)当闪光灯播放声音时,通常会有一个延迟,这样玩家就可以“建立一个头脑”并确保在下一个缓冲区请求之前缓冲区中有足够的东西被播放填充。这种延迟与不间断播放的可靠性之间存在折衷。这可能是一个限制,你不能做任何事情,缺少“实现你自己的小SoundManager2替换”,我知道你不想这样做。

希望这会有所帮助。我最近编写了一个AS3声音实验,让我了解了一些基础知识,并将观察这个空间,看看人们提出了哪些其他建议。

10

我知道这不是您想要听到的答案,但无法停止此操作,无论您是否编写自己的闪存库来播放声音。

对于所有说“这对我来说工作正常!尝试调整大小或移动浏览器窗口,因为海报的演示播放完毕。你会听到的不仅仅是微妙的延迟。这在Firefox和IE中最为引人注目,但即使Chrome也能体验它。

更糟糕的是,如果您在浏览器窗口的关闭框上单击并按住鼠标,声音将完全停止,直到您释放鼠标(您可以将它释放到关闭框外而不是实际关闭窗口, FYI)。

这是怎么回事?

事实证明,当您开始调整大小或在浏览器窗口周围移动时,浏览器会尝试多任务更改窗口属性的动作,以便跟上窗口中正在进行的JavaScript操作。它在需要时缩短窗口的大小。

当您将鼠标按住浏览器窗口中的关闭框时,时间会完全停止。当您调整窗口大小或移动窗口时,这就是以较小的增量发生的事情:时间在JavaScript世界中停留在小型零星块(或大块,取决于您的机器速度有多慢)。

现在,您可以说“确定,调整浏览器大小或按住关闭按钮会使浏览器暂停,但通常情况下不会发生这种情况。不幸的是你会错的。

它实际上一直在发生。我已经运行了测试,事实证明,即使通过完全静止浏览器窗口,不触摸鼠标,也不触摸键盘,计算机上的背景进程仍然会导致“打嗝”,这意味着在短时间内(可能小至几毫秒)时间在浏览器中“静止不动”,在您的控制之外完全随机的时间间隔。

“静止不动”是什么意思?假设你有一个setInterval()调用(这也适用于setTimeout),每33毫秒(约30帧/秒)运行一次。现在,你会期望在每33个“真实世界”毫秒之后,你的函数就会被调用。大多数情况下,这是真的。

但是,当“打嗝”开始发生时,您的setInterval调用可能发生在43毫秒。在10毫秒内发生了什么?没有。时间暂停。浏览器上没有任何内容正在更新。如果您有声音播放,则会继续播放,但不会开始播放新的声音通话,因为根本没有执行任何JavaScript。如果你有5个setInterval()函数正在运行,那么它们在某个时刻会被暂停10ms。

要告诉“时间停滞不前”的唯一方法是在您的setInterval函数回调中轮询实际时间。您将能够看到浏览器试图保持大部分时间,但是当您开始调整窗口大小或进行一些紧张的工作时,间隔时间会比平常长,但是您的所有代码都将保持同步(我正在使用这种技术制作游戏,所以你会看到所有的游戏更新都是同步发生的,但只是稍微结束了)。

通常,我应该指出,这些口吃是完全不明显的,除非您在setInterval时间内编写函数来记录真实世界的时间(正如我自己测试中所做的那样),否则您甚至不会知道它。但如果您尝试使用重复性play()调用创建某种类型的重复声音(如Asteriods背景中的哔声),则会成为问题。

我的建议?如果你有一个声音,你知道会循环,给它一个很长的时间,也许10秒,你不会注意到打嗝(现在,屏幕上的图形仍然可能打嗝,但你拧在那里)。

如果您正在编写游戏并让主角从机关枪发射,请不要对playSound('singleShot')执行10次快速连续呼叫,只需要对playSound('machineGunFire10Rounds')执行一次呼叫,或者沿着这些线路。

你必须做一些欺骗才能避开它,但在大多数情况下,你会没事的。

看来,Flash小程序运行在一个过程中,在某种程度上影响了整个在定时浏览器/ JavaScript环境中发生的“时间冻结”事件,但我仍然可以实现这一点,即使在您链接到ToneMatrix示例,通过调整大小或移动浏览器窗口。

但Flash仍然看起来比JavaScript好多了。当我独自离开浏览器时,我愿意打赌,闪存不会在任何时间内冻结,并且间隔始终按时运行。

TL;博士:

  • 你在你希望实现
  • 尝试使用一些解决方法
  • 重新写在纯闪存项目来对付它什么就完蛋了(无javascript)
  • 等待浏览器变得更好(Firefox 4正在获得一个名为JaegerMonkey的新的JavaScript引擎,这将是有趣的观看)
  • 我怎么知道这一切?我已经做了很多的测试&记录的使用JavaScript,setInterval的,和SoundManager类/ HTML5音频呼叫
+0

非常有用的答案,谢谢! – Sean 2012-11-28 15:16:10

0

正如另一个答案解释的,有没有办法可以避开这一点。但是......

我已经done some experiments缓解这一问题,并在最后,我使出使用:

在上演示的prototype源采取偷看,并(如果可能的话)给lowLag一枪。它对我很好。

祝你好运!