在播放整个声音时,很少有将两个音轨与 sampleDataEvent 监听器混合的答案。有什么办法可以尽快混音吗? (轨道的时长相等,采用 ByteArray 的形式)
在下面的帖子中
Programatically Mixdown of audio tracks (no playback)
作者建议使用 Event.EnterFrame。但是,我对 AS3 的 API 不是很熟悉。谁能给出一些示例代码?谢谢!
最佳答案
如果您不需要以二进制格式输出混音,只需进行双重播放。
track1.play();
track2.play();
是的,因为您的轨道在 ByteArrays 中,所以首先制作两个
Sound
对象并通过 loadPCMDataFromByteArray()
从字节数组中获取数据.更新:由于您根本不想播放,混合两个轨道的最简单方法是从每个 ByteArray 中读取一个浮点数,然后将它们的平均值写入结果 ByteArray。使用
ENTER_FRAME
如果您不想在转换时让 SWF 停顿,那么 listener 是值得的。您已经说过您的数组长度相等,如果是这样,下面的代码片段应该对这些 wav 进行“简单混合”:var f1:Number;
var f2:Number;
b1.position=0;
b2.position=0;
var result:ByteArray=new ByteArray();
var l:int=b1.length; // cache property
var i:int=0;
while (i<l) {
i=i+4; // size of float
f1=b1.readFloat();
f2=b2.readFloat();
result.writeFloat(0.5*f1+0.5*f2);
}
执行企业级方法需要您的
result
在监听器调用之间可用,并且位置不变,在循环中运行一个临时计数器,它将控制“在此帧中进行足够的转换”。像这样:var result:ByteArray;
var tracks:Vector.<ByteArray>=[];
var mixFinished:Function; // a callback
function startMixing():void {
// just make it start mixing
for (var i:int=tracks.length;i>=0;i--) tracks[i].position=0;
addEventListener(Event.ENTER_FRAME,doMixing);
result=new ByteArray();
}
function doMixing(e:Event):void {
if (tracks.length==0) {
removeEventListener(Event.ENTER_FRAME,doMixing);
return;
} // sanity check
var mixrate:Number=1.0/tracks.length;
for (var i:int=0;i<2048;i++) { // adjust number accordingly
var tm:int=0; // how many tracks mixed
var f:int=0;
for (var j:int=tracks.length-1;j>=0;j--) {
if (tracks[j].position<tracks[j].length) {
// this track isn't finished
tm++;
f+=tracks[j].readFloat();
}
}
if (tm==0) { // all tracks reached end, stop mixing
removeEventListener(Event.ENTER_FRAME,doMixing);
if (mixFinished!=null) mixFinished(); // do a callback
return;
}
result.writeFloat(f*mixrate);
}
}
有了这个,你填写
tracks
, 设置mixFinished
并调用startMixing
,然后等到 mixFinished
会被调用,到那时你的声音应该被正确混合。如果您觉得混音过程应该更快,请适当增加代码中的 2048 值。
关于actionscript-3 - [AS3]如何快速混合两个音轨,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24820178/