Help needed with AS3 Sound.extract()
I'm trying to create a parametric equalizer in Flash. I've been looking for a way to read audio data and mess around with the samples before Flash plays them on the fly. Loading a sound in one Sound object and using Sound.extract() to read the data, processing it, then play a second second empty Sound object and writing the data to its samp开发者_开发技巧leData event seems to be the way to do it (please correct me if I am wrong or there is a better way).
Is there a way to use Sound.extract() while the Sound object is still loading a sound file? I don't want to have to wait for the entire sound file to load before it plays. Unfortunately, whenever I use Sound.extract() while the Sound object is still loading, it returns a zero-length byte array.
Is there a way to wait for enough samples to load first before playing? I imagine I'd have the same problem again when the Flash movie eats through all the loaded samples while the sound file is still loading.
Here's a simplified version of my code. It's working so far, but only when I wait for the Sound object to fire an Event.COMPLETE event.
var inputSound:Sound = new Sound();
inputSound.load("somefile.mp3");
inputSound.addEventListener(Event.COMPLETE, loadComplete);
var outputSound:Sound = new Sound();
outputSound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSamples);
var sc:SoundChannel;
/*if I called ouputSound.play() right now, it wouldn't work.*/
function loadComplete(e:Event) : void
{
sc = outputSound.play();
}
function processSamples(e:SampleDataEvent) : void
{
var samples:ByteArray = new ByteArray();
var len:int = snd.extract(samples, 8192);
var sample:Number;
var i:int = 0;
trace(len.toString());
samples.position = 0;
//TODO: Sound Processing here
//The following code plays a sine wave over the input sound as a test
while (samples.bytesAvailable)
{
i++;
sample = samples.readFloat();
sample += Math.sin(i * Math.PI / 256) * 0.5;
e.data.writeFloat(sample);
sample = samples.readFloat();
sample += Math.sin(i * Math.PI / 256) * 0.5;
e.data.writeFloat(sample);
}
}
EDIT: If I try using the PROGRESS event, I'm going to need to do a lot more low level stuff to implement buffering and whatnot (anything else I need to account for?). Could someone help me out with that? Also, is there a way to tell the position of a sample in milliseconds? Do I have to assume that all sound files are 44.1 kHz stereo (they may not be), or is there a better way?
check out the solution in this post here
How to compute viewport from scrollbar?
You don't need to extract the entire track into a bytearray. You only really need to get what you need when you need it.
If you really want to extract the track in one go you can use
sound.extract(yourbytearray,sound.lenght*44.1)
// lenght *44.1 gives you the number of samples if the mp3 is encoded at 44100
one you have all your pcm data, in your processsamples handler instead of calling sound extract you would do something like
if(yourbytearray.bytesAvailable==0)
{
yourbytearray.position==0
}
var left:Number = youbytearray.readFloat
var right:Number = youbytearray.readFloat
//process the left with eq
//process the right with eq
event.data.writeFloat(left);
event.data.writeFloat(right);
Extracting all the audio at once would probably be the easiest but you'll run into memory problem for mp3s longer than about 8 minutes.
On the whole samples milliseconds thing.....
bytearray.position / bytearray.lenght gives you where in the song you are.
Divide that by 44100 and it will give you the number of milliseconds.
Ask more questions if you need me to clear anything up
精彩评论