Corona中文站

强大、易学的跨平台(iOS/Android)开发框架。QQ群1:74390406(满) 群2:221929599

导航

五分钟学会Corona(九) - 音频系统
一般介绍

Corona音频系统让你可以访问高级OpenAL特性。最终它将替换Corona Event Sound系统。然而,目前它还是在计划中。请阅读这一节中对android限制,文件格式以及性能提示的重要信息。

Android: 音频文件名限制

在Android上,文件名相同但扩展名不同的文件在编译期,被映射为同一个资源名称。现在这个不优雅的错误,会携带一个连接错误:( corona.get)message。唯一的解决办法,就是修改文件名。例如,AudioPlayer范例app使用一个命名方案,简单的把扩展名合并到文件名中:

note2_aac.aacnote2_aif.aifnote2_caf.cafnote2_mp3.mp3note2_ogg.ogg

同步通道的最大个数

目前通道的最大个数是32。这意味着你可以同时播放32个不同的音频。有一个API可以获得这个数字。



audio.totalChannels




Best Effort Timing

这个音频系统是一个。你告诉我们播放,然而我们试着尽可能快地播放。但没有人保证会在精确的哪个事件开始或结束。例如,如果你正在流化一个歌曲音频,此时已有一个缓冲正在cpu上处理的话,它就会在有机会的时候,试着继续播放自己。因为这个原因,如果有一秒的延时,那么歌曲将会比没有中断的情况要晚一秒结束。

Streams vs. Sounds

注意,在 new audio API 中不再有“event sound”和非 event sound的区别,也不再有两个音频API来分别处理它们。取而代之的区别是,你如何加载你的音频。 loadSound( ) 预加载整个音频到内存中,而 loadStream( )是为了节省内存一次读取一个准备播放的音频小块。所有新的音频API可用任何方式应用在被加载的文件上。然而,有时会有一些微妙的副作用,就是其差别并没有完全透明。

通用文件格式(支持格式不再取决于event或非event)

以前,支持不同的格式取决于你是否使用event sound。这个限制已经解除。 audio.loadSound( ) 和 audio.loadStream( ) 完全支持相同的文件格式。

共享/多通道同步回放

用 loadSound( ) 加载音频,可以在多个通道同时回放。例如,你可以加载一个爆炸音效:

explosionSound = audio.loadSound("explosion.wav")



现在你需要让你的游戏里多个东西爆炸,敌机、小行星、导弹,等等。我们的音频引擎为处理这种情况已做了高度的优化。根据你的需要,多次调用audio.play() 即可(不要超过最大通道数)。

例如:

audio.play(explosionSound)

audio.play(explosionSound)

audio.play(explosionSound)

audio.play(explosionSound)

audio.play(explosionSound)


不要多次用 loadSound 加载 "explosion.wav"。那样就太浪费内存了。

但是如果用 audio.loadStream( )加载的音频,就不能通过多通道同时播放了。一个单独的流处理只能在一个时间内播放一个通道。所以如果你需要播放同一个文件的多通道实例,你就只好多次加载它的实例。例如:

musicHandle1 = audio.loadStream("music.wav")

musicHandle2 = audio.loadStream("music.wav")


因为stream并不使用太多内存(之前说了是一小块一小块加载),所以这也就不是什么严重的问题了。好在,通常也不需要经常在同一个时间在多个通道上播放同一个流(stream)。


Seeking and Rewinding

loadSound和 loadStream其实还是有微妙的差别,关于这一点可以参看API文档。

Latency 延迟

通过loadSound加载的音频,只有非常低的延迟。它们将会尽可能快的播放。相反,用loadStream加载的音频需要为第一小块解码,所以可能有比较高的延迟。我们尽最大可能减小这种延迟,但是通常如果是需要有非常小延迟的情况,例如游戏中的音效,就应该尽量用 loadSound来加载。

内存管理

现阶段,如果你的音频使用完毕打算回收这块内存的话,你需要调用 audio.dispose()。如果你打算在整个程序生命周期内使用这个音频,你可能就不需要担心这个问题了。

性能提示

预加载阶段

强烈推荐你在各种启动阶段预加载你所有的文件。无论是 loadSound( ) ,还是 loadStream( ) 的块。 loadStream( ) 通常比较快,因为 loadSound( )在它加载的时候需要把整个文件都解码出来所以需要花点时间。通常你不应该在用户期望得到快速响应的时候,才 loadSound( ),应提前加载好。(例如不要在游戏进行中加载)

卸载阶段

反过来,你应该在某个时期卸载你加载过的文件。对于在整个程序生命周期里都使用的sound你可以跳过这段。但是想象一下,一个有多个级别或关卡的游戏。当玩家进入到第2关,你可能想要卸载第一个关的所有音频文件,使你有足够的内存来加载第2关的sound。(关卡间加载是一个很好的时机,这时候当然也可以加载下一个分支的音频)

audioPlayFrequency

在你的config.lua文件中,你可以指定一个 audioPlayFrequency 字段,例如:

application =

{

content =

{

width = 320,

height = 480,

scale = "letterbox",

audioPlayFrequency = 22050

},

}



这是一个优化提示,告诉底层的OpenAL系统使用什么样的采样率来混合和回放音频。为了达到最好的结果,不要把这个值设置的比你实际需要的更高。所以如果你不需要比 22050Hz 更高的回放,就设置它为 22050。但是如果你确实需要高质量,那么把它设为 44100。注意这只是对音频系统的一个建议。底层音频系统也完全可能忽略这个建议值。但是在mac和iOS上,它似乎会被严格遵守。为了达到更好的效果,所有你包含的文件本身也应该被编码到你设置的相同的频率。例如,如果你设置这个值为 22050,你的文件也应该被编码到 22050 Hz。


支持的值有 11025, 22050, 44100. 其他值未经过测试。


尽可能使用单声道音频

单声道音频有两个好处。第一,和立体声相比可以节省一般的内存。第二,OpenAL只能把空间化和3D效果用在单声道音频上。OpenAL还不能对立体声样本应用3D效果。虽然目前框架版本,我们还不支持3D效果,但是将来的版本我们应该会支持。

线性PCM

为了更快的加载和解码时间,使用线性16位有符号小顶原始PCM样本。最常见的,.wav文件就是使用这种格式。(然而有时.wav文件也使用其他编码器)

硬件解码加速

iOS提供了一个硬件解码芯片,其可以处理这些格式:.mp3, .aac / .mp4 / .m4a / .3gp / .3gp2 以及苹果的无损格式( ALAC)。技术上讲,硬件解码器只能一次解码上述文件中的一个。如果硬件解码器已被占用,系统就会该用软件解码,但是解码这些格式是相当消耗移动处理器的。

通常只有一个顾虑,就是当播放一个流音频时(因为你以串行次序预加载非流音频),一般来说,你可能在在后台编码音乐比如mp3或aac,但是你可能需要播放第二轨,比如说话。那你最好把它编码成wav(或者如果只是iPhone,在a.caf中的IMA4容器有 更好的压缩率并且cpu消耗在解码wav上的时间并不多)。然而作为一个实现细节,事实上我们大部分解码都是串行处理,所以可能这并不是一个真正值得担忧的问题。很难说在iOS上的回放是软件方式还是硬件方式。你唯一的线索是CPU利用率的显著上涨,如果如果你向我们反馈你达到边界时它如何变化,我们将非常感谢。

音量(状态)持久化

当你设置一个声道的音量,或者使用渐变APIs(实际上也是设置声道的音量),这些值会持久保存,直到你再次改变它。当 audio.play() 使用自动分配的回放声道,如果你不小心,你将会遇到一些恼人的以外。

所以想象一下你播放一些音乐,其被自动分配道声道1,然后你在这个声道上改变了音量。现在过了一会儿,哪个音乐结束了,这个声道也被闲置了。然后你又播放一个新的音频。自动分配又启用了声道1,可你听到的音量也许不是你要的,甚至有可能什么也听不到,因为这个声道也许被设成0.0。

这里有一些有关的技术细节。

第一,常见的情况是,你只需要为特定分类(如“音乐”,“讲话”,“音效”)设置每个声道的音量。如果这是这样的话,我建议你使用 audio.reserveChannels() 来阻塞某个声道使其免于被自动分配。例如,使用 audio.reserveChannels(2)来组织1和2被自动分配。然后一直在声道1上播放音乐和在声道2上播放语音。然后直接用声道数字来设置它们的音量,这样你就不会再有奇怪的事发生了。

如果不是这样,那你可以用onComplete回调系统,当作重置那个已完成播放的声道的音量的机会。

或者在你播放之前,你可以用 audio.findFreeChannel() 来获得一个自动分配的声道,设置音量,然后在这个声道上播放。

还是应该小心使用声道音量,因为在将来的版本里,这可能会影响3D效果。

其他编码格式提示

专利和特许权使用

更高压缩格式,如mp3和aac(aka mp4),AAC是更好的选择。AAC是MPEG组织提到的MP3的官方继任者。MP3技术是有专利和使用权的,这说明如果你要分发你的程序,你得考虑这一点。请咨询你的律师。当AAC被最终批准的话,它将可以无需使用权就可以分发。

Ogg Vorbis 是一种免版税和使用权费用的格式。当然,它不支持iOS。

跨平台

线性16位小顶。WAV任何地方都可以工作。MP3也是在任何地方都被支持的。(参看官方说明)。我们都想获得AAC/MP4,但这在android下是有问题的。如果任何人知道开源的AAC解码器(非GPL许可),请告诉我哦~

循环

要注意某些格式(特别是高压缩有损格式,例如mp3,aac,ogg vorbis)可以在音频样本的尾部添加和删除样本,并且可能打破一个“完美循环”的剪辑。如果你也遇到循环回放的落差,试着用wav格式并且确保你的引入和结束点都是干净的。

getDuration

audio.getDuration 可能返回不正确的信息,尤其通过 loadStream 加载的文件。你使用的编码格式可能导致不同的结果,所以如果你希望得到更准确的信息,你应该使用别的格式。MP3 是给出坏的信息最臭名昭著的。
<< 五分钟学会Corona(八) - Sprite高级动画五分钟学会Corona(十) - 视频 >>

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最近发表

Powered By Z-Blog 1.8 Walle Build 100427 Copyright 2011-2015 BuildApp.Net. All Rights Reserved.