audio timedomain wave graph - somewhat reusable

by NME
Originally written by NME a.k.a Anthony R Pace 

Overall I wanted this to be an example of how to:
-grab data from a microphone
-represent that data in a time domain graph
-easily extend the bitmap class
-make my previous bitmap graph code somewhat reusable
-change the water effect to a wave line

As usual, the whole thing was hacked up pretty quickly, and really just meant to be a tutorial/study of sorts; therefore, there may be more than a few things you may want to add or modify before using this/something like this in a real project.

It was my hope that this would be easy to read, but it may not be; thus, if you have questions, just ask.

BTW... I do know drawing one graph, and duplicating the BitmapData to get the same effect would be a great deal faster; however, as stated, this was meant to be an example of how to reuse my previous code.
♥2 | Line 83 | Modified 2012-05-16 06:09:41 | MIT License
play

ActionScript3 source code

/**
 * Copyright NME ( http://wonderfl.net/user/NME )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/heMs
 */

// forked from NME's somewhat reusable basic bmp audio wave graph
//Originally written by NME a.k.a Anthony R Pace
package {
import flash.events.Event;
    import flash.events.SampleDataEvent;
    import flash.media.Sound;
    import flash.utils.ByteArray;
    import flash.media.Microphone;
    import flash.display.Sprite;
    //import BMPWaveGraph; //in a project, where the files would be seperate, you would want to import this
    public class FlashTest extends Sprite {
        public var  mic:Microphone,
                    bmpwgVec:Vector.<BMPWaveGraph> = new Vector.<BMPWaveGraph>;    
        public function FlashTest():void {
            stage.addEventListener(Event.ADDED_TO_STAGE, init, true);
        }
        public function distrubuteData(e:SampleDataEvent):void {
            for(var i:int = 0;i!=9;++i){
                bmpwgVec[i].drawGraph(e.data);
            }
        }
        private function init(e:Event):void {
            var sh_9:int= stage.stageHeight/9;
            var i:int = 0;
            stage.removeEventListener(Event.ADDED_TO_STAGE, init, true);
            for (; i!=9; ++i){
                bmpwgVec[i] = new BMPWaveGraph(stage.stageWidth,sh_9);
                stage.addChild(bmpwgVec[i]);
                bmpwgVec[i].y = bmpwgVec[i].height*i;
            }
            mic = Microphone.getMicrophone();
            mic.rate = 11;
            mic.setSilenceLevel(0);
            mic.addEventListener(SampleDataEvent.SAMPLE_DATA, distrubuteData, false);
        }
    }
}
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import flash.events.SampleDataEvent;
internal class BMPWaveGraph extends Bitmap{
        private var _w:uint,//width  with a rate of 11 this should be 512
                    _h:uint,//should be an odd number.
                    _a:uint,//amplitude factor
                    _ww:uint,//wave width
                    _wc:uint,//wave colour
                    _bgc:uint,//background colour
                    _offset:uint,//offset... just think of a DCOffset to get the idea
                    _sampleRect:Rectangle,//this is the line that we will draw per x
                    _N:int, //the max number of samples to draw
                    _sn:Number,//the current value of the sample at n  or s[n]
                    _n:int;
        public function BMPWaveGraph(width:uint = 512, height:uint = 211, waveWidthPercent:uint = 20, waveColour:uint = 0xd7f7ff, backgroundColour:uint = 0x3CD8FF):void{
            _w = width;
            //the height should be odd, or you will over flow... this isn't a concern in as3, as the player handles this automatically, so you won't get errors if you remove it.
            //I just wanted to keep it there for myself...
            if (height & 1) {
                //if odd do something
            }else {
                height += 1; //I know I should't have written it like this, but w/e  I it as it's better/faster than if(height%2==0){height+=1}
            }
            _h = height;
            _ww = (_h/100)*waveWidthPercent;
            _a = (_h - _ww) / 2;
            _offset = _a;
            _wc = waveColour;
            _bgc = backgroundColour;
            _sampleRect = new Rectangle(0, 0, 1, _ww);
            super(new BitmapData(_w, _h, false, _bgc));
        }
        public function drawGraph(ba:ByteArray):void {
            _N = ba.length / 4;
            if (_N>_w){
                _N = _w;
            }
            ba.position = 0;
            super.bitmapData.lock();
            super.bitmapData.fillRect(super.bitmapData.rect,_bgc);
            for (_n = 0; _n != _N; ++_n) {
                _sn = ba.readFloat();//reads 4 bytes = 32 bit floating point sample value
                _sampleRect.x = _n;// as the width of the sample rect is 4, and we want 2 on each side.  We could constraine this within bounds but I'm not going to.
                _sampleRect.y = _offset - _a * _sn;
                super.bitmapData.fillRect(_sampleRect,_wc);
            }//I should probably also add a bit of code to draw the rest of the wave if _n is less than _w
            super.bitmapData.unlock();
        }
    }