I was playing around with ActionScript 3.0’s new SoundMixer.computeSpectrum() method last night, and managed to build this simple example:

var url:String = "";
var request:URLRequest = new URLRequest(url);
var s:Sound = new Sound();
s.addEventListener(Event.COMPLETE, completeHandler);
var song:SoundChannel =;
song.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
var ba:ByteArray = new ByteArray();

var gr:Sprite = new Sprite();
gr.x = 20;
gr.y = 200;

var time:Timer = new Timer(50);
time.addEventListener(TimerEvent.TIMER, timerHandler);

function completeHandler(event:Event):void {;
function soundCompleteHandler(event:Event):void {
function timerHandler(event:TimerEvent):void {
SoundMixer.computeSpectrum(ba, true);
var i:int;;, 0xFF0000);;, 0);
var w:uint = 2;
for (i=0; i<512; i+=w) {
var t:Number = ba.readFloat();
var n:Number = (t * 100);, 0, w, -n);

(** Sorry about the lack of formatting. I’m working on getting the blog restyled, and adding a bunch new AS2 and AS3 examples.)

UPDATE: Tom Green wrote a great article on the SoundMixer class over on Community MX, check it out: Sound Visualization in Flash CS3.

22 Responses to SoundMixer.computeSpectrum()

  1. peter says:

    Note: This example was built using the “Flash Professional 9 ActionScript 3.0 Preview” (’ll try and modify the example soon and port the code to an external ActionScript file so it can be used as an ActionScript Project in Flex Builder 2, or as a Document class in the Flash Preview.

  2. Lou Barber says:

    This is great. I took the code and loaded my own mp3. I’m trying to set the defaul volume. It seems like it has been moved to the SoundTransform class, but I can get it to work. Any ideas?

  3. Lou Barber says:

    I really like the above script. I’m really into Sound and excited about the possibilites with Flash Player 9. I revised to code and placed it into a package. I also added volume, (figured it out) and also added some other things.———package{import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import*;import;import;import;import;import;import flash.utils.Timer;import flash.geom.Matrix;import flash.utils.ByteArray;import flash.text.TextField;import flash.text.TextFieldAutoSize;import flash.text.TextFormat;public class SoundSpectrum extends Sprite{private var url:String = “elsewhere.mp3”;private var soundFactory:Sound;private var channel:SoundChannel;private var gr:Spriteprivate var time:Timer;private var ba:ByteArray = new ByteArray();private var positionTimer:Timer;private var myText:TextField;public function SoundSpectrum(){myText = new TextField();myText.autoSize = TextFieldAutoSize.LEFT;var format:TextFormat = new TextFormat();format.font = “Verdana”;format.color = 0xFF0000;format.size = 10;myText.defaultTextFormat = format;addChild(myText);stage.align = StageAlign.TOP_LEFT;stage.scaleMode = StageScaleMode.NO_SCALE;var request:URLRequest = new URLRequest(url);soundFactory = new Sound();soundFactory.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);soundFactory.load(request);channel =;stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);gr = new Sprite();gr.x = 20;gr.y = 400;addChild(gr);time = new Timer(50);time.addEventListener(TimerEvent.TIMER, timerHandler);time.start();}private function ioErrorHandler(event:Event):void {trace(“ioErrorHandler: ” + event);}private function setVolume(volume:Number):void {var transform:SoundTransform = channel.soundTransform;transform.volume = volume;channel.soundTransform = transform;}private function mouseMoveHandler(event:MouseEvent):void {var yPos:uint = event.stageY;var volume:Number = 1 – (yPos / stage.stageHeight);myText.text = “Volume: ” + Math.round(volume * 100);setVolume(volume);}private function timerHandler(event:TimerEvent):void {SoundMixer.computeSpectrum(ba,true);var fillType:String = “linear”;var colors:Array = [0xFF3300, 0xFFFF00,0x009900];var alphas:Array = [1, 1, 1];var ratios:Array = [0, 125, 255];var matr:Matrix = new Matrix();matr.createGradientBox(600, 600, 0, 0, 0);var spreadMethod:String = “PAD”;var i:int;;, 0x000000,1,false,”normal”,”round”,”miter”,8);, colors, alphas, ratios, matr, spreadMethod);, 0);var w:uint = 10;for (i=0; i

  4. Solomon says:

    Hey, thanks for this example! I used the code to get started and was able to have lots of fun with the sound spectrum!Lour Barber, I’m not sure about your code tho, I dont know anything about packages. is that for flash 9 alpha? o_O

  5. Alexandre Madurell says:

    COOOOOL!You should see it rendering Alanis Morissette’s 21 things I want in a lover :DThanks a lot, Peter ;)

  6. Matt Poole says:

    Lou,An alternative to your setVolume method.private function setVolume(volume:Number):void {var transform:SoundTransform = new SoundTransForm(volume)channel.soundTransform = transform;}dont need to get the sound trans form object from the channel first. You can pass the volume to the constructor of the soun transform object. (though thinking about it this does mean creating another object which has an overhead)

  7. Daniel Summers says:

    Typo in last for loop ?…

  8. Adam says:

    Hello,This might sound pretty stupid, but can anybody put here a sample on own to load the package into a Flash AS3 file?Thank you very much in advance and congrats for the excellent demo!Regards,Adam.

  9. Kevin says:

    Nice, can you tell me how I would get the bars to play downwards?

  10. Kevin says:

    Never mind :Pvar n:Number = (t * -200);

  11. Devaraj says:

    I have explored the ComputeSpectrum in the below link

  12. chiranjeevi says:

    WoW It is greatI am a beginnerI Understood so simplyThank You very much

  13. Peter says:

    Another great article by Tom Green can be found over at Community MX: great article and definitely worth the read.

  14. irfan says:

    This is awesome. I have one question though. I am really new to scripting. I used SoundMixer.computeSpectrum and it works fine. Question is this that If i create any graphics or Movie clip etc. It hides the sound spectrum(etc).What can we do to bring it forward and send all the rest, graphic anim etc in the back ?

  15. Dan Zen says:

    Thanks for the post!From what I surmise, the readFloat() method keeps an internal counter and just gets the next value in the byte array each time you call it.If your stretch factor (third parameter in the computeSpectrum) is 0 (the default) and your FFTMode is true to turn on the frequency analysis then you have 256 numbers in your bit array representing the frequency analysis for the left channel followed by 256 numbers representing the frequency analysis for the right channel.— asideI think that if your stretch factor is set to 1 then you only get 128 numbers for your left and 128 for your right – and then 56 for each channel if your factor is 2, etc. so watch that! I could be wrong though ;-) (If I am right, then this is a little counter-intuitive!)— /asideWhen you set w=2 for your loop, you are actually just getting the first 256 numbers in the byte array and thus really just getting the frequency for the left channel – which is probably adequate as most people will not notice.BUT… if you set w=10 thinking that you are just making fatter bars that average over the expected frequencies (like in that longer example) then you are only getting the first 51 or so (512/10) entries in the bitmap array which is really only the bass frequencies for the left channel. That is why your output looks too bass sloped and no longer has the same distribution!So a better solution would be to readFloat() for every iteration of the 512 bitmap array and average the first channel’s 256 elements with the second channel’s 256 elements. And if you want fatter bars then use a modulus to display the data only so often like below. Now you can safely use w to get fatter bars and keep the distribution. Just watch… if you use a stretch factor you will have to change the 256 in this loop (I think – see the aside above).var w:uint = 5;// array to store the first channel’s frequenciesvar temp:Array = [];for (var i=0; iAlso, the timer does not pick up all the beats with its 50 ms delay. You might want to just process it as fast as possible and that is the frame rate so use an onEnterFrame. (Timers and intervals can only fire at the nearest framerate anyway). The onEnterFrame worked better for me:In your constructor you could add this and get rid of your timer stuff:addEventListener(Event.ENTER_FRAME, processFrequency);Then adjust your old timer method to be called this – note the different dataType for the parameter of just Event:private function processFrequency(event:Event):void {

  16. Dan Zen says:

    Sorry… just realized that the code does not average over the w frequencies so here is a fix that will do that:var w:uint = 20;var t:Number = 0;var temp:Array = [];for (var i=0; i<256; i++) {t += baa.readFloat();if (i%w == 0) {temp[i] = t / w;t = 0;}}for (i=0; i<256; i++) {t += baa.readFloat();if (i%w == 0) {var n:Number = ((temp[i] + t/w) / 2 * 300);t = 0;, 0, w, -n);}}

  17. Peter says:

    Dan Zen,Thanks for the great comments/corrections/improvements. Yeah, I haven’t played too closely with the computeSpectrum() method, and I threw this example together [too] quickly, but it definitely looks like my example could use a bit of “improvement”.Peter

  18. Would you know how to use computespectrum to generate an image that represents the whole waveform of the mp3, like what you see if you open up a music file in an audio editor?

  19. I have been trying to create a visualization of an mp3, prior to playing the sound so that I can use the graphics in an editor. I have been attempting to pre-process the sample by repeatedly playing the sound from different positions and sampling the leftPeak with no success. Any ideas?

  20. Monkey says:

    Correct me if I’m wrong, but when I ran this code (as wonderful as it is), you made it play two different sounds (well, the same sound, but two different times). I noticed you started the channel playing (which is the one you really want it to play), and then had it in the COMPLETE event as well.Here’s the code I edited to stop the two from playing – it works perfectly:var url:String = “”;var request:URLRequest = new URLRequest(url);var s:Sound = new Sound();s.addEventListener(Event.COMPLETE, completeHandler);s.load(request);var song:SoundChannel;var ba:ByteArray = new ByteArray();var gr:Sprite = new Sprite();gr.x = 20;gr.y = 200;addChild(gr);var time:Timer = new Timer(50);time.addEventListener(TimerEvent.TIMER, timerHandler);time.start();function completeHandler(event:Event):void {song =;song.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);}function soundCompleteHandler(event:Event):void {time.stop();}function timerHandler(event:TimerEvent):void {SoundMixer.computeSpectrum(ba, true);var i:int;;, 0xFF0000);;, 0);var w:uint = 2;for (i=0; i

  21. Martin says:

    Hi, I just try to post the code examples on the first keyframe in a CS4 actionscript3 .FLA file.But when I run the code it plays the same file twice, sounding very bad.What should I do/change?

  22. Martin says:

    Hello,1) Does anyone know why all examples with ComputeSpectrum is not in sync? Music & graphic is never following each other! In some examples its just a little wrong, in others its impossible to see it should be synchronized!2) Does anyone know if its possible to listen and compute graphic on the sound being played in a WMP object within the browser? Flash should be listening to the mixer output right?Pls. mail me at “LoopStudio @ get2net .dk”