给mp3播放器增加音乐波形显示功能2008-04-02 16:18:18| 分类: 应用编程 | 标签: |字号大中小 订阅 用过winamp的人都知道,winamp有一个音乐波形显示功能,当播放音乐的时候,有一些音乐波形跟着上下跳动,翩翩起舞,又好看,又专业。那么如何给自己的播放器增加这样一个波形显示器呢。 本文给出了一个完整的代码例子,并一步一步的教你实现的过程。为了,推广as2.0和as3.0,本文的例子,采用外部纯 .as文件编写,编译测试时,完全脱离flash,采用FlashDevelop工具编译。代码见附录。 本文的运行效果,可以参考http://www./res/mywave.swf,本文可以随意转载,但请保证文章的完整性。 准确地说,这里实现地是一个伪波形显示功能。为什么叫做伪波形呢,真正的波形,应该来自实际的音频数据,对应时间对应频段的声音强度高时,就显示高的柱状,声音强度低时,就显示低的柱状。但是,对于大部分的用户来说,实际的音频数据对他们来说也没有什么概念,所以,用伪波形,几乎可以达到以假乱真的效果。 其实,要显示伪波形很容易,只要随机生成不同高度的柱状图,就可以了。但是,为了得到更逼真的效果,大家可以注意一下,很多播放器的波形图里,顶端都有一个小点,它们的反应往往迟钝一下,当一个柱状由高突然变低的时候,并不马上跟着变低,而是,慢慢的往下掉。如何实现这种效果呢,其实,分析一下他的原理,就很简单了。只要每次柱状高度变化的时候,记录一下这组高度,下次生成新的高度时,如果,新的高度比原高度高,那么,顶点跟着网往上走,就是,如果,新高度比原高度小,那么,就让顶点高度减掉一个常数,注意,这里只是减掉一个常数,而不是直接变成新高度。这样,实现出来的效果,就是顶点好像有些缓冲,别柱状顶上去后,是慢慢的往下掉。 本例子里的所有显示内容,都是通过BitmapData对象的画布直接画出来的。所以,也可以帮助读者复习一下BitmapData的用法,以及它如何与MovieClip关联。 在onEnterFrame事件中,调用updatePanel()函数,这个函数会重新生成新的波形,并刷新显示。其中的if (frameCount++>1) 是调整波形的刷新频率用的,不改变1这个数字,就可以实现让波形跳动的更快,或者更慢一些。 最后,因为这是一个继承自MovieClip的类。要想把这个类变成一个flash中的真正的MovieClip对象,必须通过 Object.registerClass()把它注册一下。然后,通过AttachMovie加入flash。这是as2.0里的做法,在as3.0 里,就方便很多了,直接new这个对象,然后通过addChild()加入flash即可。 附:代码 /** * Test class for testing mtasc swf building in FlashDevelop. * @mtasc -swf c:\Test.swf -header 500:400:12:EFEFEF -main -trust -trace org.flashdevelop.utils.FlashConnect.mtrace org/flashdevelop/utils/FlashConnect.as */ import flash.display.*; import flash.geom.Rectangle; class Wave extends MovieClip { static var symbolName:String = "__Packages.Wave"; static var symbolOwner:Function = Wave; // associate the symbol to the class when the class is defined static var symbolLinked = Object.registerClass(symbolName, symbolOwner); var LeftMargin, Bar_Width, Bar_Gap, Bar_Max_Height,BarCount,Client_Height: Number; var frameCount:Number = 0; var PolarBarHeight:Array; var img:BitmapData; var rect:Rectangle; var rectPolar: Rectangle; function Wave () { LeftMargin = 20; Bar_Width = 5; Bar_Gap = 3; Bar_Max_Height = 40; BarCount = 20; Client_Height = 200; rect = new Rectangle(0,0,100,100); rectPolar = new Rectangle(0,0,Bar_Width,1); img = new BitmapData( 256, 200, false, 0 ); PolarBarHeight = new Array(20); for (var i:Number = 0;i<BarCount;i++) PolarBarHeight[i] = 0; this.attachBitmap(img,1); } function updatePanel() { trace(PolarBarHeight); var i:Number =0; img.fillRect(img.rectangle,0x000000); for (i=0;i<BarCount;i++) { var WaveHeight:Number = random(Bar_Max_Height); rect.left = LeftMargin + i * (Bar_Width + Bar_Gap); rect.top = Client_Height - WaveHeight; rect.right = LeftMargin + i * (Bar_Width + Bar_Gap) + Bar_Width; rect.bottom = Client_Height; img.fillRect(rect,0x009900); if ((PolarBarHeight[i] == 0) || (PolarBarHeight[i] < WaveHeight + 5)) PolarBarHeight[i] = WaveHeight + 5; else PolarBarHeight[i] = PolarBarHeight[i] - 4; if (PolarBarHeight[i] < WaveHeight + 5) PolarBarHeight[i] = WaveHeight + 5; rectPolar.left = LeftMargin + i * (Bar_Width + Bar_Gap); rectPolar.top = Client_Height - PolarBarHeight[i]; rectPolar.width = Bar_Width; rectPolar.height = 1; img.fillRect(rectPolar,0xFF9900); } } function onEnterFrame() { if (frameCount++>1) { updatePanel(); frameCount = 0; } } // entry point static function main (mc) { //var wave:Wave = new Wave (); _root.attachMovie(Wave.symbolName, "wave", 1); } } |
|