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:
Here is a overview of the classes you need if you want to load a wave at runtime:
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
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
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!
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.
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.
I’m trying to play a file, that is a womens voice. I used your flex project source, and all that I get is a mans voice. How do I get file to sound exactly as it should?
Darren Moore
Software Developer
dmoore@getabby.com
http://www.getabby.com
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
[URL=http://img137.imageshack.us/my.php?image=wavovigl4.png][IMG]http://img137.imageshack.us/img137/2774/wavovigl4.th.png[/IMG][/URL]
I wanted to post a picture inside my comment. Please delete the last post.
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
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.
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.
}
}
}
}
Hey Ben, is this possible with ActionScript 2.0?
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.
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
I am inveresting about the example. Can you send the source code to me? because above the uls can’t connect.
Thanks.
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
You can get sources of my player here:
http://etcs.ru/pre/WAVPlayer/
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.
Thank you etc! your player is awesome!
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
I have made wav player, that able to playback stream, seek in it (after it have loaded and parsed file headers, of course).
It directly decodes file (file can be coded as PCM, GSM or G711), resample it (from any source bitrate to 44100) and play thru audiosink.
Support as mono as stereo
Here you can grab a copy with source code:
http://blog.datacompboy.ru/2009/11/29/asterisk-records-flash-player-wavplayer-1-6-1/
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.
Man you are doing great job can you please send me the source code.
I want to load and play a wav file.
Can anyone send me player like http://etcs.ru/pre/WAVPlayer/?url=sound3.wav in flex 3
Please send me the source in flex 3 of playing .wav file
Pingback: Pixel Expander Project » Interprétation du son
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;
}
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 !
Please, send me the source code for loading .wav file and playing. Thank you.
Can you send me the source code? The link is broken.
tnx!
I’ve uploaded a new copy of source code. Enjoy 😉
http://www.4shared.com/rar/i1iBwfcg/WaveFlex.html
Pingback: MIDI commands? » free icons download