Flash - mp3编码器/ flash.media.Sound延迟

时间:2012-08-17 20:52:48

标签: flash loops mp3 delay

我正在尝试使用mp3文件播放无间隙循环。我已经阅读了一些教程,并了解到有类似编码器/解码延迟的东西,并且可以使用一些工具用适当的音乐数据填补这个空白。它甚至工作得很好,但是当我试图用闪光灯播放音乐时(实际上是haxe nme,但我认为它没有任何区别),我发现还有另一个延迟,我想,这是由flash制作的.media.Sound(好吧,实际上在互联网的代码中发现了这样的一些评论)。

Sooo,因为我有时需要更快或更慢地播放声音,这就是我的播放器的工作方式:

  • 引用字节存储在字节var
  • speed是一个浮点var,默认= 1
  • 有位置var表示以字节为单位的实际位置(字节由多个声音对象共享,所以我不能轻易使用bytes.position)
  • 当我播放声音时,在SampleDataEvent处理程序中,我设置bytes.position = position * 8,然后读取并播放两个浮点数并更新位置+ =速度

如果我已经做错了 - 请指出来。

为了摆脱这种延迟,我试图:

  • 添加DELAY var
  • 硬编码从大胆读取的声音长度(它看起来像flash.media.Sound object.length不准确,我不确定,但我猜是因为mp3解码器/编码器延迟)
  • 假设每个声音是128kbps,44.1kHz
  • 设置DELAY so flash.media.Sound对象bytesTotal - DELAY =硬编码长度* 128kbps

它起作用,但是:

    来自大胆的
  1. mp3仍然存在恼人的差距。
  2. 来自填充mp3间隙的工具(来自http://www.compuphase.com/mp3/mp3loops.htm)的mp3播放效果更好,但开头的声音不清楚。
  3. 停止声音后,我听到恼人的“咔哒”声。
  4. 你能帮助我理解为什么(1)发生以及如何解决所有3个问题?

1 个答案:

答案 0 :(得分:0)

使用Flash完成无缝循环很烦人,但这是可能的。

  • 尝试制作无间隙MP3很困难,所以完全避免这个问题!将循环导入为WAV文件,而不是MP3。 WAV没有任何编码器延迟,并且可以轻松地产生无缝循环。

  • 使用Sound.play()的loops参数循环播放声音。如果音频真的无间隙,这应该产生一个无缝循环。 不要尝试使用SOUND_COMPLETE事件来循环播放声音。此事件与帧速率相关,并在声音完成后不久发生,而不是在实际发生时触发,因此总会造成间隙。

  • 正如您所注意到的,Sound.length通常不准确。如果您确实需要准确的样本计数,请使用Sound.extract()提取完整的音频数据。它返回提取的样本数。

  • 如果由于某种原因您无法嵌入无间隙WAV文件,或者您必须从外部位置流式传输MP3,则可以执行以下操作:

    1. 使用Sound.extract()提取音频数据。
    2. 在数据的开头和结尾剪掉静音部分。你可以用一些硬编码的值来做到这一点,或者通过将样本与一些小的epsilon进行比较来实现智能和切断。
    3. 使用Sound.loadPCMFromByteArray()将裁剪后的数据重新加载到声音片段中。
    4. 现在可以使用Sound.play和loops参数循环裁剪剪辑。

以下是一些示例代码:

// load our original audio track and extract the samples
var music:Sound = new Music();
var data:ByteArray = new ByteArray();
music.extract(data,99999999);
data.position = 0;

// crop off silent samples from the beginning
// TODO: you should also do this for the end
var i:uint = 0;
const EPSILON:Number = 0.05;
var sample:Number = 0;
// step forward until the magnitude exceeds some threshold
while(data.bytesAvailable > 8 && sample < EPSILON) {
    sample = Math.abs(data.readFloat()) + Math.abs(data.readFloat());
}

// now, data.position is the location where the audio first kicks in
// let's crop it
var croppedData:ByteArray = new ByteArray();
croppedData.writeBytes(data, data.position);
croppedData.position = 0;

// load our newly cropped data and loop
music = new Sound();
music.loadPCMFromByteArray(croppedData, croppedData.length / 8);
music.play(0,99999);

与使用SampleDataEvent实时跳过差距相比,这更容易,处理器更少。如果你真的需要使用SampleDataEvent进行动态播放,那么这个方法仍然有助于为你提供一大堆音频数据而没有间隙。

请注意,以上内容仅适用于Flash 。由于您使用的是NME,因此会增加额外的皱纹层,因为NME可能会在打包过程中摆弄声音,并且上述功能并非在所有目标上都可用。但是,如果您只是为Flash目标发布,这些技术仍应有效。