Load and Play .wav files at rumtime with AS 3.0 (source included)

This is a follow up to my previous post about mixing wav files with Actionscript. I couldn`t sleep tonight so I have hacked together some classes that make it easy to load and play wave files at runtime with Actionscript 3.0.
You know that it`s not natively possible to load and play wave files at runtime. The trick is to load the wave file as a ByteArray (e.g. with Loader, FileStream, URLStream…) and than construct a swf file in memory that has the wave bytes embedded. First i created a swf file in memory that has the wave sound embeded and played it back with a StartStream-Tag. I did not liked that method because it does not give you good control over the playback of your sound. So the solution was to create a SWF file that defines a sound that is linked to a class so you can access the Sound Object directly. For those interested in details here is how the SWF file that i create in memory looks like:

structure.jpg

Here is a overview of the classes you need if you want to load a wave at runtime:

classes.jpg

What the WaveMix class is for will be revealed in the next post :-)
In order to load a wave sound these are the basic steps:
// Create a new Wave Reader
waveReader = new WaveReader();
waveReader.read(bytes);

// Create a wave SWF
var waveSwf:WaveSWF = new WaveSWF(waveReader);
waveSwf.addEventListener(Event.COMPLETE, onWaveReady);

private function onWaveReady(evt:Event):void{
sound = WaveSWF(evt.target).sound;
channel = sound.play(0,0);
}

Now you can use all methods of the Sound Object to work with your sound.

All this is still a bit buggy (all hacked together this night :-). So use it at your own risk.

I`ve prepared a little example in AIR that let`s you load a wave sound. The Wave has to be a PCM encoded (uncompressed) wave file.
Download AIR Example
Download Flex Project (Source)
Let me know what you think 😉
This was a pretty long night :-) so in the next post i`ll add something to this (reading waveforms + mixing sounds)
Benz

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Pin on Pinterest

32 thoughts on “Load and Play .wav files at rumtime with AS 3.0 (source included)

  1. Hi Benz,

    I know you are busy coding and writing your next tutorial.

    I want to make a request for any additional information about your WaveSWF, WaveReader, Rect and Matrix classes. I’m looking at PlayWaveMix Project at the moment and although i get some parts… a lot are beyond my understanding (props to you!).

    I’m hoping all these classes and how they work are going to be covered in your Max session. So please keep me posted regarding the session and /or any updates to the Bits & Bytes pdf.

    Any other information/links will be greatly appreciated.

    Best wishes
    Doug

  2. Thanks! I’m interested in loading binary output from a SSScript. Flash’s URLRequest method for loading .mp3’s has no way to hide the .mp3’s server location.

    If you have any ideas, or contributions please let me know. Thanks!

  3. I’m hoping all these classes and how they work are going to be covered in your Max session. So please keep me posted regarding the session and /or any updates to the Bits & Bytes pdf.

  4. Hm. I can’t load wav file into ByteArray. Code I’m using is:

    var bytes:ByteArray=new ByteArray();
    var stream:URLStream=new URLStream();
    stream.load(new URLRequest(url));
    stream.readBytes(bytes);

    url I’m providing:
    http://localhost/stream/start.wav

    I can’t get bytes to fill. I always get length=0.

    Thank you in advance

    ps. I’m just a beginner.

  5. At the end I managed to play wav file with this code, but I have a problem cause when I try to play the file on the right side I only get loud aggresive noise, while I have no problems with the file on the left.

    What should I do if I wnated to play the file on the right side of the image???

    thanks in advance

  6. [URL=http://img137.imageshack.us/my.php?image=wavovigl4.png][IMG]http://img137.imageshack.us/img137/2774/wavovigl4.th.png[/IMG][/URL]

  7. Hi,
    How do I load the wav file into a bytearray?
    why doesn’t this work (Trying with a text file, for example):

    var request:URLRequest = new URLRequest(“./recorder/streams/instance1/txtfile.txt”);
    var myURLLoader:URLLoader = new URLLoader();
    URLLoaderDataFormat.TEXT;
    myURLLoader.load(request);
    trace(myURLLoader.bytesLoaded);
    trace(myURLLoader.data);

    the .data is “undefined”.
    and bytesLoaded=0

    thanks

  8. In reference to the post above, you have to add an event for when the file loads. The request is made and you’re immediately checking the size before the file has finished loading.

    Try something like this:

    var request:URLRequest = new URLRequest(”./recorder/streams/instance1/txtfile.txt”);
    var myURLLoader:URLLoader = new URLLoader();
    URLLoaderDataFormat.TEXT;
    request.addEventListener(Event.COMPLETE,dataLoaded);
    myURLLoader.load(request);

    private function dataLoaded(ev:Event):void
    {
    trace(myURLLoader.bytesLoaded);
    trace(myURLLoader.data);
    }

    You’d have to make the myURLLoader object global, but that’s the idea.

  9. There were some errors in the code posted above, so here’s a working version. I took the “SineWaveProvider” class from the flashbrighton library (http://www.flashcodersbrighton.org/wordpress/?p=9) and made it load an external .wav file.

    The audio processing loop still loads a sine wave because I haven’t had the time to implement loading the data from the external wav file. I’ll post that when it’s done; it’s going to involve skipping the header bytes to get to the raw sample data and looping the position of the ByteArray back to 0 when it reaches the end.

    package
    {
    import nu.mine.flashnet.sound.core.*;
    import flash.events.*;
    import flash.utils.ByteArray;
    import flash.net.URLRequest;
    import flash.net.URLStream;

    /**
    * An example class demonstrating how to make an AudioDataProvider.
    * Things to note:
    * extends AudioDataProvider
    * creates a PCMSoundFormat and passes it to super(fmt)
    * overrides fillBuffer
    * writes mono samples one at a time to buffer, with call buffer.writeMonoSample
    * @author spender
    *
    */
    public class SampleByteArrayStream extends AudioDataProvider
    {
    private var phase:Number;
    private var wavBytes:ByteArray;
    private var stream:URLStream;

    /**
    * creates a SineWaveProvider.
    * subclasses of AudioDataProvider must always call super(fmt) with a PCMSoundFormat object
    * @return
    *
    */
    public function SampleByteArrayStream()
    {
    var fmt:PCMSoundFormat=new PCMSoundFormat(44100,16,1); //define a format of 44100hZ sample rate, 16 bit audio, 1 channel
    super(fmt);
    phase=0.0;

    wavBytes = new ByteArray();
    stream = new URLStream();
    stream.addEventListener(Event.COMPLETE,dataLoaded);
    stream.load(new URLRequest(“http://feedbacker.us/wav/kick.wav”));

    }

    private function dataLoaded(ev:Event):void
    {
    trace( “HERE” );
    stream.readBytes( wavBytes );
    trace(wavBytes.length);
    }
    /**
    * this is where the audio is generated. Values should lie between -1 and +1 to avoid clipping.
    * every sample must be stored in the buffer with buffer.writeMonoSample(val)
    * this function should write numSamples*soundFormat.channels monophonic samples into the buffer
    * if soundFormat.channels is 2, then the channels are interleaved, so each consecutive call to buffer.writeMonoSample will store a samples for left then right channels etc…
    * @param numSamples The number of complete samples that must be written (for a stereo format, this means 2 monophonic samples per sample)
    *
    */
    protected override function fillBuffer(numSamples:int):void
    {

    for(var i:int=0;i(2*Math.PI))phase-=(2*Math.PI); //prevent phase from overflowing.
    }

    }

    }

    }

  10. hi all,
    please note a fllowing bug fix on class WaveSWF.as
    we used wav file with bitsPerSample = 8, and the playing it clipped the track by half.
    problem was the in samples count calculation.

    change lines 105 and 110 from:
    if(waveReader.sampleRate == 8)

    change to:
    if(waveReader.bitsPerSample == 8)

    Nice day,
    Amir.

  11. Can Anybody please email me this playing of Wav file through Flex at onlyprince@rediffmail.com. I am not able to download the zip file because website has just got hacked and none of the attachments are available for download.
    Thanks!

    Prince

  12. I am inveresting about the example. Can you send the source code to me? because above the uls can’t connect.
    Thanks.

  13. Hi,
    I was looking for something like this and your post describes the perfect solution for me. Unfortunately I am unable download any source from this file as I get a 404 error when I click on the zip file link. Not sure if the files have moved somewhere and post is yet to be updated. Anyway I will appreciate if you can email me the source or the correct link to download the source from.
    Thanks

  14. I am also looking for this class. Does it live somewhere else now? May I request it please? I would really appreciate the classes needed to play .wav files for runtime. Thank you very much.

  15. Hey Benz,

    i am working on a project for university and would be interested in your code for this audio player. is it still available somewhere? would be very kind.

    regards,

    Niklas

  16. I don’t know why you are saying that you have provided the source code as i have seen your both post and it is just time wasting nothing else.
    You have to provide valid link.

  17. Man you are doing great job can you please send me the source code.
    I want to load and play a wav file.

  18. Pingback: Pixel Expander Project » Interprétation du son

  19. For folks asking about how to encode the wav as a ByteArray. This worked for me (swiped from the gotoAndLearn forums)…

    var bytes:ByteArray = new ByteArray ();
    var ldr:URLLoader = new URLLoader();
    ldr.dataFormat=URLLoaderDataFormat.BINARY;
    var req:URLRequest=new URLRequest(“test.wav”);
    ldr.addEventListener(Event.COMPLETE, completeHandler);
    ldr.load(req);
    function completeHandler(e)
    {
    bytes=ldr.data;
    bytes.endian=Endian.LITTLE_ENDIAN;
    }

  20. Wow ! This is exactly what I am looking for … so surprised that you cannot play wave file with native API.

    But unfortunately, the links to download the sample
    are broken:

    Download AIR Example
    Download Flex Project (Source)

    How can I get a copy of the sources to play with it?

    Thanks for your nice work !

  21. Please, send me the source code for loading .wav file and playing. Thank you.

  22. Pingback: MIDI commands? » free icons download

Leave a Reply

Your email address will not be published. Required fields are marked *