May 192008
 

I have had reason to play around with some of the new functionality of Flash Player 10 and the vectors is just awesome.
On top of the benefits of the strict typing they are about 50% faster than Arrays according to my tests.

Being completely new to the concept, how to create multidimensional vectors was not completely obvious since you need to type every dimension when declaring the bottom level dimension:

var v1:Vector.>>= new Vector.>>();
var v2:Vector.> ;
var v3:Vector.;
for (var i:int = 0; i < 10; i++) {
v2 = new Vector.>();
for (var ii:int = 0; ii < 10; ii++) {
v3 = new Vector.();
for (var iii:int = 0; iii < 10; iii++){
v3[iii] = iii;
}
v2[ii]=v3;
}
v1[i]=v2;
}

 

So far I have mostly been experimenting with the new samplesCallbackData to create a little mixer.
It seems like one needs to bypass the mixer in the Flash Player if one want to write to the output buffer because creating several sounds and then doing samplesCallbackData.writeFloat() on them will not work.
Of course each channel doesn’t have its own output buffer, so you can only write to the master output.
The problem I’m having with this is that if one would like to have a level meter for each individal track I cannot figure out a way to determine what sample is currently being output.
Here is a simplified version of how I implemented the mixing in the SamplesCallbackEvent handler:

var i:int = 0, l:int = _sounds_vect.lengt;
while (i < l) {
samples = new ByteArray();
samples.position = 0;
snd = _sounds_vect[i];
snd.extract(samples, _bufferSize);
_samples_vect[i] = samples;
_samples_vect[i].position = 0;
i++;
}
while (c < _bufferSize) {
left = 0;
right = 0;
i = 0;
while (i < l) {
valL = _samples_vect[i].readFloat();
valR = _samples_vect[i].readFloat();
left += valL;
right += valR;
i++;
}
valL = left;
valR = right;
_out_snd.samplesCallbackData.writeFloat(valL);
_out_snd.samplesCallbackData.writeFloat(valR);
c++;
}

So the audio is mixed in chunks the size of the buffer and then written to the buffer using samplesCallbackData.writeFloat().

 

For the main output I can create a level meter using:

_out_chn = new SoundChannel();
_out_chn = _out_snd.play();
function onEnterFrame(e:Event):void {
_masterSlider.drawLevel(_out_chn.leftPeak, _out_chn.rightPeak);
}

 

But for the individal channels I will never issue a play() and hence cannot find a way to get a really consistently behaving level meter or spectrum.
I’m sure there is some clever way to do it that is escaping me.

 

What I currently do is to get the value in the mixing loop like so:

while (i < l) {
valL = _samples_vect[i].readFloat();
valR = _samples_vect[i].readFloat();
left += valL;
right += valR;
if (c == 0){ // tried with (c == _bufferSize - 1) and (c == _bufferSize/2) as well
_levelR_vect[i] = valL;
_levelL_vect[i] = valR;
}
i++;
}

I then use the _levelL_vect and levelR_vect values in my onEnterFrame handler to draw the bars, but the result is a lot less accurate than what is possible using my_chn.leftPeak and far from satisfactory.
I guess what I would need is a way to be able to tell what sample from the output buffer that is playing a certain moment in time.

 

Apart from that small issue it’s great to have the functionality to generate and process audio and I think we will see some very cool applications appearing eventually.

Share/Bookmark

Switch to our mobile site