Reputation: 27
I wanted a suggestion from you guys regarding drawing and scrolling performance. The requirement is - I have to draw a graph with sound volume's values updated at 30 fps. And I need to draw this graph and simultaneously scroll to fit in the new values. So the length(width) of the graph is unlimited. So please suggest the best way of accomplishing this
Upvotes: 0
Views: 192
Reputation: 8033
BitmapData has a scroll()
method that you can use - http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html#scroll()
Basically every frame, you only draw one column of pixel's worth of data (your BitmapData will be the view of your sound, and each column of pixels one capture's worth of data) - for the most part, you're probably only going to be using setPixel()
to set the volume value.
Keep moving along, one column of pixels for one frame of data, then when you get to your threshold (the very right-hand side of the BitmapData), use scroll()
to move the data one pixel left (you'll lose the left-most column of pixels), then continue drawing in the last column (right) of pixels. You'll create a constantly updating volume display.
Finally use lock()
and unlock()
before and after drawing to stop Flash from updating the screen in the meantime.
I'd advise having some sort of limit however - items that grow infinitely = big problems later
Edit
Here's some code. This is taking me 0ms (using getTimer()
on the debug player) to render. You will eventually run into problems, as the volume Vector is growing unbounded, which is never a good thing. If you only need to hold the last x number of frames, then this code is even easier.
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.getTimer;
public class Main extends Sprite
{
private var m_bmd:BitmapData = null;
private var m_vol:Vector.<int> = null;
private var m_currVol:int = 0;
public function Main():void
{
// create our bmd
this.m_bmd = new BitmapData( 400.0, 200.0, false, 0 );
// add it to the stage
var b:Bitmap = new Bitmap( this.m_bmd );
this.addChild( b );
// create our volume array
this.m_vol = new Vector.<int>();
// set our current volume
this.m_currVol = this.m_bmd.height / 2;
// start our volume listener
this.addEventListener( Event.ENTER_FRAME, this._onEnterFrame );
}
private function _onEnterFrame( e:Event ):void
{
var start:int = getTimer();
// update our volume and add it to our array
this.m_currVol += int( ( Math.random() * 10.0 ) - 5.0 ); // adds a random int between -5 and 5
this.m_currVol = ( this.m_currVol < 0 ) ? 0 : ( this.m_currVol > this.m_bmd.height ) ? this.m_bmd.height : this.m_currVol; // clamp it to the bitmap data height
this.m_vol[this.m_vol.length] = this.m_currVol;
// lock our bitmap
this.m_bmd.lock();
// clear the bitmap
this.m_bmd.fillRect( this.m_bmd.rect, 0 );
// go through and draw our volumes (for max the size of the bmd)
var len:int = ( this.m_vol.length < this.m_bmd.width ) ? this.m_vol.length : this.m_bmd.width;
var startX:int = ( this.m_vol.length < this.m_bmd.width ) ? 0 : this.m_vol.length - this.m_bmd.width;
for ( var i:int = 0; i < len; i++ )
this.m_bmd.setPixel( i, this.m_vol[startX + i], 0xffff00 );
// unlock our bitmap
this.m_bmd.unlock();
trace( "This took " + ( getTimer() - start ) + "ms to render" );
}
}
}
Add in a scrollbar to change the startX
variable (by default, it will always show the last amount of data), and you're there
Upvotes: 1