从这个AS3代码我期望500行跟踪输出包含“2048”。但相反,我只得到一些包含“2048”的行。其余的跟踪打印“0”,这表明extract()方法没有返回任何数据。
为什么会这样?我想用特定的步骤迭代声音文件,以在相应的位置提取2048字节的声音。一次提取整个声音文件会冻结flashplayer几秒钟,因此对我来说不是一个好的解决方案
当步骤小于 samplesInSound / 2048 时,可以找到此行为。它越接近该值,打印的“0”行就越多,而打印量为2048的行。
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)
但这也没有用。
任何人都可以帮我解决这个问题吗?
答案 0 :(得分: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.
}
}