audio timedomain wave graph - somewhat reusable
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
archived:2017-03-10 19:54:15
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();
}
}