用户名: 密码: 验证码: QQ--程序群:31736530 动画群:38836599
闪无忧
 
首 页 业界新闻 业界杂谈 Flash教程 Flash源码 Flash图书 Flash酷站 Flex & AIR 供求信息
   本栏目通告:   有意向写收费精品教程的朋友,请联系本站合作
当前位置 :首页>flash教程>Flash as3.0教程>列表

我对as3声音架构的理解

[来源:as3天地会 | 作者:xin | 时间:2008-05-15 | 点击:  | 收藏本文  【 】]
一直都对as3的声音架构设计感到困惑,as3为什么要把播放和停止方法分开呢?为什么不能用一个Sound更换载入的声音呢?这几天有空专门专研了一下。原来as3对声音的设计也是深思熟虑的。目的不是为了把问题搞得复杂,而是为了在功能强化的同时做到精简。并尽可能方便我们使用。现在把我这两天的理解拿出来共享,有什么不到位的地方请多多建议。


架构图:


架构图.jpg



可以看出,as3中的声音处理是独立的,不再依赖影片剪辑作为声道。as3使用多个类合作处理声音,功能被细化到对应的类中,使得逻辑更加清晰。下面对着架构图由下往上详细阐述各个类所但当的任务。


Sound负责创建、加载、播放声音。Sound类更像BitmapData扮演的角色,用于描述数据。而不是控制声音。使用Sound创建声音有两种创建方式:
1.通过库中元件创建和载入
库中声音是Sound的子类。要播放必须创建它们的实例。


2.通过外部加载的声音
外部加载声音创建类型是Sound类本身。为强调一个类描述一个声音数据这种模式,Sound禁止第二次加载外部声音。加载控制符合open—progress—complete的标准。
Sound的构造函数为Sound(stream:URLRequest = null, context:SoundLoaderContext = null),创建外部声音时与load方法参数相同。如果创建库中的声音则不需要任何参数。

方法:
load(stream:URLRequest = null, context:SoundLoaderContext = null):void
加载声音。不能使用一个Sound对象加载多个声音。当有多声音播放时,必须为每个声音创建不同的Sound对象。

play(startTime:Number = 0, loops:int = 0, sndTransform:SoundTransform = null):SoundChannel
播放声音。startTimer为开始播放事件,单位为毫秒。loops为循环次数,01都表示播放一次,如同flash属性面板中的次数设置。sndTransform是分配给每个通道的初始对象,如果有必要还可以在soundChannel中修改这个对象。每次播放都会选择不通的声道,对应方法返回值。多次执行会导致重叠播放。

close():void
关闭声音流。对于流式播放声音,close很重要,因为soundChannelstop方法不足以停止流式下载的声音。可能产生继续播放的现象。


事件:
open:
类型为Event.OPEN。开始下载时触发。

progress:
类型为PrograssEvent.PROGRESS。下载时触发。

complete:
类型为Event.COMPLETE。下载完毕时触发。

ioError:
类型为Event.IO_ERROR。发生IO错误时触发。

id3:
类型为Event.ID3。可以访问id3数据时触发。


属性:
所有属性都是只读的,用来访问加载信息。

url:String
加载声音的url值。

bytesLoaded:uint
加载字节数。

bytesTotal:int
总字节数。

length:Number
当前声音长度,如果加载中只反应加载的长度。

id3:ID3Info
id3属性包含唱片信息。


加载播放外部声音的顺序:
加载播放外部声音的顺序如下:


ID3Info
ID3Info类用于描述声音信息。对应Sound类的id3属性。

属性:
songName:String
歌曲名称。

track:String
曲目编号。

artist:String
歌手名称。

album:String
专辑名称。

yesr:String
录制年份。

genre:String
歌曲流派。

comment:String
相关注释。


获取唱片信息顺序:



获取唱片信息.jpg








SoundChannel

SoundChannel继承EventDispatcher,使用import flash.media.SoundChannel声明。SoundChannel用于描述声音通道。有了这个类,声音通道再不用依赖MovieClip了。多个声道可以播放一个声音,一个声道可以播放多个声音(同一时刻只能播放一个)。对声音的操控和状态描述从描述声音数据的Sound类中分离出来。声道与声音之间的关系类似BitmapBitmapData的关系。这种逻辑描述更加精确。但与位图不同的是声音通道不是由用户创建的而是系统生成的。这个纽带是Soundplay方法。采用这种处理方式是为了降低复杂性,因为系统自动管理声道免去我们因声道分配分散注意力。系统每次选择空余声道进行回放。当停止了一个声道的播放后,声道自动被as回收。这样一来,我们完全不必去管声道如何分配的,就如显示对象的深度管理一样。

方法:
stop()
停止播放声音。但不能停止流式下载时播放的声音。


属性:
position:Number
播放头位置,单位毫秒。只读属性。这表示position并不能设置播放进度。要设置播放进度只能使用play的参数。

leftPear:Number
左声道音量。范围为0-1。这个属性并不用来控制平移而是用来读取左声道峰值波幅。可以用这个属性检查是否是单声道。

rightPear:Number
右声道音量。范围为0-1。这个属性并不用来控制平移而是用来读取右声道峰值波幅。可以用这个属性检查是否是单声道。


soundTransform:SoundTransform
分配给声道的soundTransform对象。


事件:
soundComplete
类型为Event.SoundComplete。声音播放完毕后触发。


监视和设置声音播放进度:
监视播放进度:
对于下载完毕的声音可以使用position监视播放进度。但对于正在下载中的声音虽然position可以正常访问,但length属性只能在下载完毕后才能获取,这给监视播放进度造成了困难。这时可以通过bytesLoadedbytesTotal的比值估算出长度。公式为:position*bytesTotal/bytesLoaded

设置播放进度:
由于position属性是只读的。因此不能通过它设置播放进度。设置播放进度只能通过play方法的startTime参数。这是因为考虑到功能重复。采取这种逻辑还有个长处是不必管播放的状态。方法也只有播放和停止而没有暂停方法。少了一个状态和方法后,播放进度不必管是否播放或暂停。所以免去了playState属性。position的只读特性也避免设置进度时是否要保持播放或暂停状态。现在一切都被简化成播放和停止两个方法了。逻辑大大简化。而暂停和设置进度都由播放和停止两个方法衍生出来。方法如下:
设置进度=stop+play(startTime)
暂停播放=记录position+stop
恢复播放=play(记录position)
SoundTansform
SoundTransform
SoundMixer类继承Object。使用import flash.media.SoundMixer声明。由于不使用MovieClip绑定声音通道。所以描述全局声音通道的不是主时间轴而是SoundMixer类。由于与任何声道无关,所以SoundMixer是个静态类。

属性:
SoundMixer.bufferTime:int
全局缓冲时间。如果在Sound类的play方法中未指定缓冲则由这里决定。

SoundMixer.soundTransform:SoundTransform
全局SoundTransform对象。控制总体声音效果。当应用了单个soundsoundTransform属性后再应用总声音特效。比如对于音量控制而言,这里是总音量控制。


方法:
SoundMixer.stopAll():void
停止所有通道播放声音。

SoundMixer.areSoundsInaccessible():Boolean
如果声音因为安全模型不能访问则返回true.

SoundMixer.computeSpectrum(outputArray:ByteArray, FFTMode:Boolean = false, stretchFactor:int = 0):void
返回当前组合音频快照。波形被分为256级,分为左声道和右声道。被记录在outputArray中。outputArray是个二进制数组,拥有512个元素,类型为Numer。使用readFloat方法访问。前256个浮点数描述左声道的波形,后256个浮点数描述右声道的波形。浮点数也分为两种描述类型,FFTMode参数为true时使用频谱形式描述。范围为0~2的平方根。为false时采用波形描述,范围为-1~1strechFactor是采样率。044HZ122.HZ,以此类推。不管采样率为多少,始终都是256级别。采样率只会影响波形是否平滑。

生成播放特效:
很多时候我们很羡慕media player的视觉特效吧。也很想知道是怎么做出来的。答案就是两个字——算法。现在利用as3提供的computeSpectrum可以实现我们的梦想,这是在as2中做不到的。下面我们来看看实现的原理。
不管使用什么算法,数据都是相同的。我们可以写一段小代码,输出某个音乐播放中的浮点状态。
导入一首歌曲,库中类名改为Song。在帧上输入如下代码:
var s:Song=new Song();
s.play();

var ba:ByteArray=new ByteArray();

stage.addEventListener(MouseEvent.CLICK,onClick);

function onClick(event:MouseEvent):void
{

SoundMixer.computeSpectrum(ba);


ba.position=0;


for(var i:int=0;i<512;i++)


{


var num:Number=ba.readFloat();


trace(num);


}

}
看到数据的组织结构后,下一步就可以发挥你编程与艺术的完美结合,而media player中的特效就是完美最好的榜样。在这么多另人眼花缭乱的效果中,条形与波形是最直接最简单的可视效果,它是数组的直接透视。现在我们来看看FFTModetruefalse时的波形区别。
用于控制声音的音量和平移。它跟多个类有联系,如:MicrophoneNetStreamSoundChannelSoundMixer都通过它调节声音效果。再次显示了声音架构的标准统一。更可贵的的是在SimpleButtonSprite中也有这个属性。这代表着可以通过as调整flash 工具创作的按钮和影片剪辑中嵌入的声音。这种操控能力使得我们不必因为嵌入的声音对应调整音量上的干扰。但这并不代表我们能控制帧中声音的播放和停止。SoundTransform的构造函数为new SoundTransform(vol:Number=1,panning:Number=0)。构造函数的参数是它的属性。

属性:
volume:Number
音量,范围为0~1

pan:Number
声道平移,范围为-1~1

leftToLeft:Number
左输入在左声道中的音量。

leftToRight:Number
左输入在右声道中的音量。

rightToLeft:Number
右输入在左声道中的音量。

rightToRight:Number
右输入在右声道中的音量。




SoundMixer


快速傅立叶变换:
快速傅氏变换,是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。

x(n)N项的复数序列,由DFT变换,任一Xm)的计算都需要N次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次运算(四次实数乘法和四次实数加法),那么求出N项复数序列的Xm, NDFT变换大约就需要N2次运算。当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT中,利用WN的周期性和对称性,把一个N项序列(设N=2k,k为正整数),分为两个N/2项的子序列,每个N/2DFT变换需要(N/22次运算,再用N次运算把两个N/2点的DFT 变换组合成一个N点的DFT变换。这样变换以后,总的运算次数就变成N+2N/22=N+N2/2。继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。而如果我们将这种一分为二的思想不断进行下去,直到分成两两一组的DFT运算单元,那么N点的 DFT变换就只需要Nlog2N次的运算,N1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是 FFT的优越性.


这就是快速傅立叶转换的原理,但若频繁的把波形转化成频谱,除了算法上的处理,还会会消耗一定的cpu资源,这就是as3直接提供了波形和频谱两种浮点模式的原因。


创建自定义播放效果:
下面一个是我用矢量生成的一个特效。实际上还可以使用位图,甚至结合flash工具创建的动画来制作特效。可以说这方面的发挥空间是无穷无尽的。这里我使用256条线段来描述声道的波幅,使用25层来描述场密度。效果如下:




点击下载此效果。


image007.jpg

 

水纹效果.rar
(2008-05-12 18:15:40, Size: 24.8 KB, Downloads: 6)



说明:由于嵌入声音造成文档太大,所以载入百度中的歌曲。歌曲地址放在界面文本框中又会影响美观,所以我在路径下放了一个songURL.txt的文本。大家可以更改网址。但同时访问本地和网络又会造成安全问题。于是找来我的flashBox。flashBox可不管什么沙箱,本地网络通吃。而且全屏播放又能加快执行速度。可以当作屏保一样。真是很适合呢。

另外由于是矢量制作的因而不可能使得密度到达media player中水纹那样的效果,我们可以使用BitmapData来达到。但以像素级来描述波形将会更慢。因为flash player是不能象c++那样调用系统API的。也不能直接使用显卡支持的driectXopenGL。无法直接操作显存。即便如此,我还是要说说使用BitmapData代替矢量呈现的方法。原理并不是很困难。使用矢量只不过是绘制线条。我们可以写一个使用位图创建线条的函数。原理如下:想象线段是一条路径,一个爬虫从一段爬到另一端,走过的路径使用像素填充。这样一来就非常简单了。结合Tween来进行像素填充,为位图创建一个lineTo函数,代码改动基本上不大。详细代码我就不写了。请大家自己尝试。

以上是我对as3架构的理解,不到之处还请见谅。谢谢!

文章如果有错误或者缺少文件,请发邮件提交给我们
上一篇:AS3.0 下载队列类 帮助完成Flash队列下载
下一篇:AS3画渐变圆角矩形
Tags:    
>>> 最新评论:(共有 0 位网友发表了评论)      查看所有评论
  发表评论
用户名: 新注册) 密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
·本站发布内容均为客观表达作者观点,不代表闪无忧立场,请勿攻击和漫骂
·用户发表意见仅代表其个人意见,并且承担一切因发表内容引起的纠纷和责任
·本站管理人员有权在不通知用户的情况下删除不符合规定的评论信息或留做证据
·请客观的评价您所看到的资讯,提倡就事论事,杜绝漫骂和人身攻击等不文明行为
  教程分类
  基础操作   动画特效
  应用开发   组件学习
  As程序   动画教程
  Flash cs3   AS 3.0
  FCS/FMS教程   Loading教程
  Flash与Web   Flash教程连载
  相关文章
·ActionScript 3.0垃圾回收
·Flash上传客户端
·AS3编码转换函数
·flash as3的binding-ObjectProxy
·as3的ComboBox组件应用小问题
·小球的弹性碰撞
·小球的弹性碰撞
·小球的弹性碰撞
·ActionScript 3设计模式类图(二)
·ActionScript 3设计模式类图(一)
  热门文章
·Flash进度条的制作详细讲解(组图)
·flash幻灯片网页效果
·Flash打造简单的飘雪动画视觉特效
·Flash旋转拖尾文字效果的制作教程
·flash水影效果字
·全Flash动画网站实现的基础教学
·超酷flash光晕移动效果
·flash春雷闪电效果
·Flex 3 AdvancedDataGrid的使用(第二
·Flash制作大雪纷飞效果动画
·即拷即用的loading代码
关于我们 - 免责声明 - 网站地图 - 商务服务 - 联系我们 - RSS地图
©CopyRight 2006-2008, 5UFlash.COM, Inc. All Rights Reserved
鲁ICP备06034971号