如何在没有SAMPLE_DATA的情况下从AS3中的AudioSprite播放无缝循环

时间:2015-04-08 20:49:47

标签: actionscript-3 flash audio mp3 howler.js

我使用此工具创建了一批声音:

AudioSprite

https://github.com/tonistiigi/audiosprite

输出通常用于JS库,例如Howler,Zynga Jukebox或SoundJS - 但我想看看它是否可以在AS3中实现。

我开始创建一个声音播放器,可以根据此工具生成的JSON和MP3文件加载,解析和播放声音。

到目前为止一切顺利! ......除了循环。

现在,大问题是 - 有一种方法可以无缝地播放声环,因为所有音乐和音乐都可以声音在同一个MP3文件中共存,它有一个 start&结束范围来玩和停止吗?

Example of how the sounds are placed in the file:

mygame_sounds.mp3 = [BUZZ + LASER + BOING ... + TRACKLOOP]

我正在寻找涉及使用SAMPLE_DATA事件的解决方案(因为它占用了大量CPU使用率)。如果没有办法,请解释原因。

到目前为止,我在使用给定的AudioSprite持续时间后触发的flash.utils.Timer对象取得了轻微的成功,但它并不一致。

要停止/处理非循环声音,我依靠主计时器(以非常短的间隔运行)并且似乎" cut& #34;适当的样本。但我已经尝试过使用这个主计时器来反复播放循环声音 - 同样的延迟问题。

是否有任何方法可以预测/测量声音完成一次传递所需的延迟时间?

3 个答案:

答案 0 :(得分:1)

在SoundJS中,我们找不到允许在AS3中平滑循环音频精灵的方法,并使用计时器。我们发现Web Audio是唯一允许平滑循环的api,因此建议远离audiosprites,以便在需要使用任何其他插件时能够顺利循环播放声音。

希望有所帮助。

答案 1 :(得分:1)

为什么无法从较大的音频文件中检索到的轨道的平滑循环的原因是您无法比每个SWF帧更快地检查声音位置,该长度取决于stage.frameRate和总处理时间您的申请并且通常是多种多样的。所以,如果你的循环声音持续5.123秒(我不关心有多少样本,只是它的长度不会产生完整数量的帧而不管stage.frameRate),你的声音会尝试播放5.125如果SWF会出现延迟,则秒数(205帧,40帧/秒,IMO最佳选择此特定声音),5.133秒(154帧,30帧/秒)或一些奇怪的帧数。由于AS3 / Flash引擎优化,无法通过任何方式完全控制多余的毫秒数。因此,请考虑不使用音频精灵并转换为音频包(SWF中的多个音频文件或MP3中的一个声音)。

答案 2 :(得分:0)

虽然我仍在努力寻找完美的解决方案,但这是我能想到的最好的解决方案:

  1. 加载JSON文件/ ByteArray。
  2. 解析JSON文件以获取每个sprite' ID,开始和结束时间。
  3. 将MP3文件/ ByteArray(需要loadCompressedDataFromByteArray())加载到主Sound对象中。
  4. 加载后,检查是否有任何精灵被标记为"循环"。
  5. 为上述循环创建单独的Sound对象,并通过loadPCMFromByteArray() master Sound中提取部分" magic-numbers & #34; (详情如下)。
  6. 要播放一次性声音,请拨打主音色play(sprite.start * 1000)(取决于格式,通常JSON' start值以秒为单位,需要以毫秒为单位。
  7. 要播放无缝循环声音,请调用单个声音对象(在步骤#5中创建)play(0, 9999)方法。
  8. 我没有详细说明如何停止声音(SoundChannel.stop(),bam!),但我会解释"魔术数字"上文提到的。请参阅以下代码段:

        var goldenOffset:UInt = (64 << 5);
        var goldenDuration:UInt = (64 << 2);
        var sampleRate:UInt = 44100;
    
        for (id in loops) {
            var sprite:AudioSpriteItem = _mapSprites.get(id);
            var loop:Sound = _mapLoops.get(id);
            var sampleBytes = new ByteArray();
            var samplesTotal:UInt = cast(sprite.duration * sampleRate + goldenDuration);
            var samplesStart:UInt = cast(sprite.start * sampleRate + goldenOffset);
    
            _sound.extract(sampleBytes, samplesTotal, samplesStart);
    
            sampleBytes.position = 0;
            loop.loadPCMFromByteArray(sampleBytes, samplesTotal, "float", true);
        }
    

    老实说,这些神奇的 goldenOffset goldenDuration 值只是通过Trial-and-Error找到的。只需用start计算durationsampleRate(默认情况下假定为44100),我就可以关闭到没有它们的无缝循环,但每个结局都有对它有点打嗝。

    经过多次调整后,这些情侣&#34; 64离开了位移&#34;值使循环听起来更顺畅。

    我在github上发布了Haxe项目(编译的SWC也可以在/bin文件夹中找到),如果您想尝试/阅读代码。

    FLAudioSprite

    Github页面:https://github.com/bigp/FLAudioSprite

    SWF演示(下载):bit.ly/FLAudioSpriteSWFDemo