Originally written by NME a.k.a Anthony R Pace
You have to have the initial straight/zero line for when the mic isn't active, so I added a function that does that
/**
* Copyright NME ( http://wonderfl.net/user/NME )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/lUMJ
*/
//Originally written by NME a.k.a Anthony R Pace
package {
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import flash.events.SampleDataEvent;
import flash.media.Microphone;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
public class BMPAudioGraph extends Sprite {
//I shouldn't be initializing things here...,
//and I am not modifying or utilizing bmpHeight, smplHeight, clrs, and the smpleBMD consistently,
//(although I probably will do something with them later) so I could just get rid of them...
public var bmpHeight:int = stage.stageHeight,//The height of the graph
smplHeight:int = 60,//The height of the Rect that will visually represent the position and height of the sample
bmp:Bitmap = new Bitmap(new BitmapData(512,bmpHeight,false,0x333333)), //the bitmap that will be used to represent the time domain
mic:Microphone = Microphone.getMicrophone(), //the default microphone if available
n:int, // the sample number
sn:Number, //sample value at n, or s[n]
A:Number = ((bmpHeight-smplHeight)/2),//'A' for amplitude factor. It is also the remainder of space that you will be able to lift/drop the sampleBMP
sampleBMD:BitmapData = new BitmapData(1,smplHeight,false,0x000000),
pt:Point = new Point(0,0),
b:BitmapData,//at first it's the sample image bmd, and then it'll be a reference to the main bmd
zbdDrawn:Boolean = true,
zbd:BitmapData,
//ba:ByteArray,//as I plan to have it store the
clrs:Array = [0xE52019,0xFF6600,0xFFA500,0xD4FF00,0x00FFA1,0x2644D8];// colours to make the sample image
public function drawWave(ba:ByteArray):void{ //sample data event handler
ba.position = 0;
b = bmp.bitmapData;
b.lock();
b.fillRect(b.rect,0x333333);
for (n = 0;n<512;++n){
sn = ba.readFloat();//reads 4 bytes = 32 bit floating point sample value
pt.x=n;
pt.y = A-sn*A;//in this case I am using the Amplitude as not only a factor, but also the offset for the zero line.
b.copyPixels(sampleBMD,sampleBMD.rect,pt);
}
b.unlock();
}
public function makeZeroLine():void{
var ba:ByteArray = new ByteArray();
for(var i:uint = 0 ;i!=2048;++i){
ba.writeByte(0);
}
drawWave(ba);
zbd = new BitmapData(512,smplHeight,false,0x000000);
zbd.copyPixels(bmp.bitmapData, new Rectangle(0,A,512,smplHeight), new Point(0,0));
}
public function drawZeroLine():void{
b = bmp.bitmapData;
b.lock();
b.fillRect(b.rect,0x333333);
pt.x = 0;
pt.y = A;
b.copyPixels(zbd,zbd.rect,pt);
b.unlock();
}
public function makeSampleSlice(clrs:Array):BitmapData{
//putting this here as later I will want to repeatedly modify the sample slice based on timing
var b:BitmapData = new BitmapData(1,smplHeight,false,0x000000);
var lc:uint = clrs.length;
var rdiv:uint =(smplHeight-lc)/(lc + 0.5); //rainbow division
var lastY:uint=0;
for(var i:uint =0; i!= lc; ++i){
//start this at 1, because we want to leave a bit of black at the top
b.fillRect(new Rectangle(0,lastY+=1,1,rdiv),clrs[i]);
b.setPixel(0,lastY+=rdiv,0x000000);
}
return b;
}
public function sdeh(e:SampleDataEvent):void{
if (mic.activityLevel <5){
if(!zbdDrawn){
zbdDrawn = true;
drawZeroLine();
}
}else{
zbdDrawn = false;
drawWave(e.data);
}
}
public function BMPAudioGraph():void {
sampleBMD = makeSampleSlice(clrs);
stage.addChild(bmp);//place the main bitmap on the display list to make it visible
makeZeroLine();
mic.rate = 11;// sets the sample frequency to 11025hz
mic.setSilenceLevel(0);//setting this to 0 makes it so you hear all activity... you should notice noise in the line.
mic.addEventListener(SampleDataEvent.SAMPLE_DATA,sdeh); // call the sdeh function if the mic hears audio
}}}