There are few answers which mix two audio tracks with sampleDataEvent listener while playing the entire sound. Is there any way to mix the tracks as fast as possible? (The tracks are of equal duration and is in the form of ByteArray)
In the post below
Programatically Mixdown of audio tracks (no playback)
the author suggests using Event.EnterFrame. However, I'm not quite familar with AS3's API. Can anyone give some example code? Thanks!
1 Answers
If you don't need to output the mix in binary format, just do double play.
track1.play();
track2.play();
Yep, as your tracks are in ByteArrays, first make two Sound
object and get the data from bytearrays by loadPCMDataFromByteArray()
.
UPDATE: Since you don't want playback at all, the most simple way to mix the two tracks will be reading one float out of each ByteArray, then write their average into the resultant ByteArray. Using the ENTER_FRAME
listener is worth it if you don't want to have your SWF stall while doing the conversion. You've said your arrays are of equal length, if so, the following code snippet should do your "simple mix" of those wavs:
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);
}
Doing an enterframe approach requires your result
be available between listener calls, and positions unaltered, with a temporary counter running in the loop which will control "enough converting in this frame". Like this:
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);
}
}
With this, you fill tracks
, set up mixFinished
and call startMixing
, then wait until mixFinished
would get called, by that time your sound should be mixed properly. If you feel your mixing process should go faster, increase the 2048 value in code appropriately.

- 18,599
- 6
- 39
- 61
-
Thanks for answering, but I want to generate a wav file without any playbacks. – DQLin Jul 18 '14 at 11:47