【问题标题】:AS3 using Sound.extract in a loop to analyse a soundfileAS3 在循环中使用 Sound.extract 来分析声音文件
【发布时间】:2011-08-27 00:05:28
【问题描述】:

从这个 AS3 代码中,我预计 500 行包含“2048”的跟踪输出。但相反,我只得到一些包含“2048”的行。其余的痕迹打印一个“0”,这表明 extract() 方法没有返回任何数据。

为什么会这样?我想用特定数量的步骤遍历声音文件,以在相应位置提取 2048 个字节的声音。一次提取整个声音文件会使 flashplayer 冻结几秒钟,因此对我来说不是一个好的解决方案

只要 steps 小于 samplesInSound/2048,就会发现这种行为。越接近该值,与包含 2048 的行相比,打印的“0”行就越多。

var sound:Sound = new Sound();
sound.load(new URLRequest("soundfile.mp3"));
sound.addEventListener(Event.COMPLETE, soundLoaded);

function soundLoaded(e:Event){
    var samplesInSound:Number = sound.length*44.1;
    var steps:int = 500;
    var byteArray:ByteArray = new ByteArray();
    for(var i=0; i<samplesInSound; i += Math.floor(samplesInSound/steps)){
        var extracted = sound.extract(byteArray, 2048, i);
        trace(i + ": " + extracted);
    }
}

我的想法是,提取后的声音文件的提取部分会从声音文件的其余部分中删除(如Actionscript 3 - Sound.extract method empties sound object data),所以我尝试了另一个 for 循环:

for(var i=0; i<samplesInSound - steps * 2048; i += Math.floor(samplesInSound/steps) - 2048)

但这也没有成功。

谁能帮我解决这个问题?

【问题讨论】:

    标签: flash actionscript-3 audio bytearray extract


    【解决方案1】:

    我没有足够的声誉来评论你的问题,所以我会写这个答案并附上免责声明,如果它不能解决你的问题,请告诉我。

    对 sound.extract 的每次调用只会从上一次对 sound.extract 的调用完成的位置提取,因此您不需要每次都使用 startPosition 参数。这就是为什么你得到奇怪的结果,对 sound.extract 的调用已经在声音中前进了:

    sound.extract(byteArray, 2048) // advances 2048 samples into the sound
    sound.extract(byteArray, 2048) // we are 2048 samples in, grab another 2048
    sound.extract(byteArray, 2048) // we are 4096 samples in, grab another 2048, etc.
    

    更重要的是,您现在的方式实际上并不能阻止 Flash 播放器在长音上停止,因为无论如何您都是在一个循环中完成所有操作。在一个循环中抓取 500 * 2048 (1,024,000) 步并不比使用 sound.extract(byteArray, 1024000) 一次抓取它们更好。如果有的话,它会更慢。您需要在对 sound.extract 的调用之间给 Flash 时间来“呼吸”。

    这是一个可能的解决方案:

    class SoundLoader
    {
        public var sound:Sound;
        public var byteArray:ByteArray;
        public var samplesInSound:int;
    
        public function SoundLoader(sound:Sound)
        {
            this.sound = sound;
            samplesInSound = sound.length * 44.1;
            byteArray = new ByteArray();
        }
    
        // Returns "true" if the sound has finished extracting.
        public function extract(samplesToExtract:int):Boolean
        {
            var extracted:int = sound.extract(byteArray, samplesToExtract);
    
            return extracted < samplesToExtract;
        }
    }
    
    function soundLoaded(e:Event)
    {
        soundLoader = new SoundLoader(sound);
    
        // 2048 is very low, you'll need to experiment with how much you can load at once without Flash hiccupping.
    
        if (soundLoader.extract(2048))
        {
            // A very short sound! soundLoader.byteArray contains the extracted sound, ready to use.
        }
        else
        {
            // add a timer that calls soundLoader.extract(2048) again.
            // keep repeating the timer until soundLoader.extract returns 'true' - then you can use soundLoader.byteArray.
            // the timer allows Flash to do other things inbetween, which avoids it freezing up.
        }
    }
    

    【讨论】:

    • 感谢您的回答。不幸的是,我的计划是以比我在每个循环中提取的数据更大的步骤循环声音。例如,我想要实现的是:sound.extract(byteArray, 2048, 0) // advances 2048 samples into the sound sound.extract(byteArray, 2048, 10000) // we are 10000 samples in, grab another 2048 sound.extract(byteArray, 2048, 20000) // we are 20000 samples in, grab another 2048, etc. 我知道你提到的冻结问题。在最后的代码中,我将在帧上连接循环,或者像您的示例一样,在计时器上连接循环。
    猜你喜欢
    • 2017-01-02
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 2012-01-13
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多