论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > Flash AS教程
Tag:2.0,3.0菜鸟,游戏,,cs,技巧,源码,,文本,文字,函数,音乐,随机,拖拽,asp,access,xml,mc,视频教程

使用Flash as3实现音频波形与条形EQ显示的方法

文章类别:Flash AS | 发表日期:2009-8-2 17:25:56

使用Flash  as3实现音频波形与条形EQ显示的方法


为了能更好的学习Flash  as3,所以平时的时候整理了一些关于使用Flash as3实现音频波形与条形EQ显示的方法,希望对大家有所帮助。

FFTMode代表是否进行离散形式的快速傅立叶变换.

stretchFactor参数有2个,
为0时,采样率为44.1Khz,
为1时采样率22.05Khz,
为2时,11.025Khz.
因此一般我们使用参数0,也就是44.1Khz

下面再来看傅立叶变化,首先撇开原理不谈.实验证明,进行变换之后的数据试用于画条形和环形图,变换之前的数据适合作波形图.
why?
波形图是函数随着自变量的变化而在平衡位置附近上下运动的结果,
那么需要画波形图的时候,我们需要在0附近左右振荡的波形数据,而画条形和环形时,我们只需要在0+方向的波形数据.
因此如果你需要做波形图,请将FFTMode置0,否则置1.

现在我们已经知道我们需要的波形数据,已经以二进制串的形式保存在了ByteArray这个数组中
假设我们用Barray这个数组来存储,
那么快照后保存的数据以一维方式从Barray[0]开始存,一直存到Barray[2047]
这样一共是2048bit(我是如此理解的)
每一位对应一个数据元素,你可以想象在每一秒中声卡将对波形数据进行还原,每秒取样频率达到4万多次,每次的数据流量如果按照这里的Barray的2048bit来计算,......我也懒得算了,反正1Kb=1024bit,1Mb=1024Kb.......

这里其实默认的是双声道立体声,大多数mp3都是如此的,如果是单声道可能会有些出入,也许只需要1024bit
那么从第一个bit到1024个bit这里放的是左声道的数据,从1025到2048放的是右声道数据.
也许你说要是能把这些数据进行混合与处理,是不是可以做均衡器了,so 遗憾,这只是个method,我们只有读的份.

好了到这里你应该迫不及待了,我只需要搞清楚Barray如何来用就OK了
不错,实事就是如此.
这里有两种方法:
1.将这个二进制串转换为浮点数
2.逐个读取这个二进制串中的每一个数据

这两种方法有利有弊
先说第一个,最大的好处就是省资源,不用遍历整个二进制串你就可以使用宝贵的数据了,在这个将就资源环保的今天,你还犹豫什么呢.缺点呢,缺点就是,我觉得不太准确,因为似乎并不是每一个数据都派上了用场,有相当一部分被抛弃了,在资源匮乏的今天......

第二个,是我自己独立想出来的 表扔鸡蛋,我觉得第二个对于提高EQ显示的精确度有些许帮助,当然,我也在考虑将所有的音频数据重新分频,有点不现实,毕竟flash无法调用声卡,也没有相应的API.第二个方法最大的好处就是不管你的条形是宽是窄是胖是瘦,我都能让你吃饱.

什么意思?就是说我让所有数据都能显示到你的条形上面去,如果你的条形宽,数量少,那么我将每十个单位的数据整理成一个,也就是压缩之后,再传给条形显示函数,要是你条形窄,数量多,那么我可以5合1甚至不合,这恐怕不太现实,有谁愿意让2048个进度条在屏幕上跳.而且还是每秒钟跳动几十下.非卡死你不可.

差点忘了关键的一点
soundmixer类对policy安全设置要求严格
只能在samedomain同域名下可用
如果是crossdomain不同域名下,读取将会报错
下面的代码没有加入查错处理,所以,attention

此处为代码区域,或许你看到这里已经不需要代码
但我还是贴出来一部分
这是我的彩色条形代码
复制内容到剪贴板
代码:

var myurl=new URLRequest;
var mytimer:uint;
var bit:Array = new Array(36);//采样数组
var prebit:Array = new Array(36);//预采样数组
var vt:Array = new Array(36);//下落速度数组
var peak:Array = new Array(36);//峰值位置数组
var ratios:Array = new Array(255,255)
var alphas:Array = new Array(100,100)
var matrix:Matrix = new Matrix(50,50,0,100,200,0);
var color = createRainbowGradientArray();
for(var i=0;i<36;i++) {
    bit[i]=0;prebit[i]=0;vt[i]=0;peak[i]=0;
}
var bArray:ByteArray = new ByteArray();
myurl.url="song.mp3";//此处替换为您自己的mp3地址
var mysound=new Sound(myurl);
mysound.play();
setInterval(showBar,20);
mytimer=setInterval(caiyang,80);
//clik.addEventListener(MouseEvent.CLICK,clikme);
function clikme(Event:MouseEvent) {
   
}
function showBar() {
    this.graphics.clear()
    for(i=0;i<18;i++) {
        if(bit[i]<prebit[i]) {
            bit[i]=prebit[i];
        }
        if(peak[i]<bit[i]) {
            peak[i]=bit[i];
            vt[i]=0;
        }
        if(bit[i+18]<prebit[i+18]) {
            bit[i+18]=prebit[i+18];
        }
        if(peak[i+18]<bit[i+18]) {
            peak[i+18]=bit[i+18];
            vt[i+18]=0;
        }
        this.graphics.lineStyle(10,0xFFF001,20,false,"noSacle","none");
        this.graphics.lineGradientStyle("linear",new Array(color[i*14+14],color[i*14+14]),alphas,ratios,matrix,"reflect","LinearRGB",1)   
        this.graphics.moveTo(50+i*15,200);
        this.graphics.lineTo(50+i*15,200-bit[i]/2)
        this.graphics.lineGradientStyle("linear",new Array(color[i*14+14],color[i*14+14]),alphas,ratios,matrix,"reflect","LinearRGB",1)
        this.graphics.moveTo(600-i*15,200);
        this.graphics.lineTo(600-i*15,200-bit[i+18]/2)
        bit[i]-=4;
        bit[i+18]-=4;
        vt[i]+=0.1;
        vt[i+18]+=0.1;
        if(peak[i]>0) {
            peak[i]-=vt[i];
            this.graphics.lineStyle(2,0xCCCCCC,100,false,"noScale","none")
            this.graphics.moveTo(45+i*15,200-peak[i]/2);
            this.graphics.lineTo(55+i*15,200-peak[i]/2);
        }
        if(peak[i+18]>0) {
            peak[i+18]-=vt[i+18];
            this.graphics.lineStyle(2,0xCCCCCC,100,false,"noScale","none")
            this.graphics.moveTo(595-i*15,200-peak[i+18]/2);
            this.graphics.lineTo(605-i*15,200-peak[i+18]/2);
        }
    }
}
function caiyang() {
    SoundMixer.computeSpectrum(bArray,true,0);
    for(var i=0;i<18;i++) {
        for(var j=0;j<30;j++) {
            prebit[i]+=bArray[i*50+j+1]*2^j
            prebit[i+18]+=bArray[1024+i*50+j]*2^j
        }
        prebit[i]/=50
        prebit[i+18]/=50
    }
}
function createRainbowGradientArray(): Array
        {
            var gradient: Array = new Array();
           
            var shape: Shape = new Shape();
            var bmp: BitmapData = new BitmapData( 256, 1, false, 0 );
           
            var colors: Array = [ 0, 0xff0000, 0xffff00, 0x00ff00, 0x00ffff ];
            var alphas: Array = [ 100, 100, 100, 100, 100 ];
            var ratios: Array = [ 0, 16, 128, 192, 255 ];
           
            var matrix: Matrix = new Matrix();
           
            matrix.createGradientBox( 256, 1, 0, 0, 0 );
           
            shape.graphics.beginGradientFill( 'linear', colors, alphas, ratios, matrix );
            shape.graphics.drawRect( 0, 0, 256, 1 );
            shape.graphics.endFill();
           
            bmp.draw( shape );
           
            for( var i: int = 0 ; i < 256 ; i++ )
            {
                gradient[i] = bmp.getPixel( i, 0 );
            }
           
            return gradient;
        }
这是小东的波形代码
复制内容到剪贴板
代码:
package {
    //导入类
    //Sprite是一个只有一帧的MovieClip,相对于MovieClip少了帧和场景...
    import flash.display.Sprite;
    //混合模式类
    import flash.display.BlendMode;
    //事件类
    import flash.events.*;
    //声音类
    import flash.media.Sound;
    //混音器类
    import flash.media.SoundMixer;
    //声道类
    import flash.media.SoundChannel;
    //URLRequest类
    import flash.net.URLRequest;
    //ByteArray类
    import flash.utils.ByteArray;
    //位图类
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    //滤镜类
    import flash.filters.BlurFilter;
    import flash.filters.ColorMatrixFilter;
    //滤镜品质类
    import flash.filters.BitmapFilterQuality;
    //矩形类
    import flash.geom.Rectangle;
    //Point类(点)
    import flash.geom.Point;
    //定义类
    public class SwfdongSound extends Sprite {
        //声明用来包含line和bg的Sprite
        private var Main:Sprite=new Sprite();
        //声明用来画线的Sprite
        private var line:Sprite=new Sprite();
        //声明用来放位图数据的BitmapData
        private var bmpData:BitmapData=new BitmapData(350,200,true,0xFF0);
        //声明用来显示效果的Bitmap
        private var bmp:Bitmap=new Bitmap(bmpData);
        //声明MP3路径
        private var url:String = "MySound.mp3";
        //声明一个Sound对象
        private var DongSound:Sound = new Sound();
        //声明一个SoundChannel对象
        private var sChannel:SoundChannel;
        //声明一个ByteArray对象
        private var bArray:ByteArray = new ByteArray();
        //声明一个数组对象
        private var Ary:Array;
        //声明两个数字对象
        private var n:Number = 0;
        private var c:Number = 0;
        //声明一个ColorMatrix滤镜
        private var colorM:ColorMatrixFilter=new ColorMatrixFilter([
            0.98,0,0,0,0,
            0,0.98,0,0,0,
            0,0,0.98,0,0,
            0,0,0,0.90,0,
        ]);;
        //声明一个BlurFilter滤镜
        private var blur:BlurFilter = new BlurFilter(7,7,BitmapFilterQuality.LOW);
        //声明一个矩形
        private var r:Rectangle=new Rectangle(0,0,350,200);
        //声明一个点
        private var p:Point=new Point(0,0);
        //类构造函数
        public function SwfdongSound() {
           
            //Main的混合模式为"添加"
            Main.blendMode=BlendMode.ADD;
            //在舞台上显示各个部分
            Main.addChild(bmp);
            Main.addChild(line);
            addChild(Main);
            //将字符串转化为URLRequest
            var req:URLRequest = new URLRequest(url);
            //加载歌曲
            DongSound.load(req);
            //播放
            DongSound.play();
            //添加一个EnterFrame的侦听器,同以前的this.onEnterFrame=showBar();
            this.addEventListener(Event.ENTER_FRAME,showBar);
    }
private function showBar(event:Event){
        n = 0;
        //这里是为了每2次才执行一次滤镜而做的if,如果需要让原来的波形图消失的更慢就把2改成更大的数字
        if(c%2==0){
        //将Main的内容绘制到bmpData
        bmpData.draw(Main);
        //应用滤镜
        bmpData.applyFilter(bmpData,r,p,colorM);
        bmpData.applyFilter(bmpData,r,p,blur);
        }
        c++;
        //清除绘图
        line.graphics.clear();
        //设置线条样式,颜色湖蓝,宽度1,透明度100
        line.graphics.lineStyle(1,0x2AEAEB,100);
        //将当前声音输出为ByteArray,注意哦,这次用的是false,上次是true
        SoundMixer.computeSpectrum(bArray,false,0);
        for(var i=0; i < 256; i+=2){
                //在ByteArray中读取一个32位的单精度浮点数(这个是livedoc上写的,实际就是把数据流读取成浮点数)
                n = bArray.readFloat();
                //这个实际作用是把n扩大一下
                n = n*360;
                //如果i不为0
                if(i!=0){
                //画波形图
                line.graphics.lineTo(50+i,100-n/5);
                }else{
                //移动   
                line.graphics.moveTo(50,100-n/5);
                }
        }
     } 
   }
}
如果你还有很多想法,可以访问这里
http://theflashblog.com/?p=197
还有这里
http://blog.andre-michelle.com/upload/as3/compute.spectrum/
PS:相信大家一定会所收获!呵


AS3中提供了一个新的类SoundMixer
我们需要用的是其中的
computeSpectrum(outputArray:ByteArray, FFTMode:Boolean = false, stretchFactor:int = 0):void
将当前播放的声音的波形数据进行一次快照,所得的数据存入ByteArray类型的二进制数组中,
视频教程列表
文章教程搜索
 
Flash AS推荐教程
Flash AS热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058