登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

秒大刀 博客

好好学习 天天向上

 
 
 

日志

 
 
 
 

[转]FMOD相关  

2010-10-12 11:52:04|  分类: Game |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、术语和基本概念
1.1  Samples vs bytes vs milliseconds
[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
     一组左右声道的数据称为一个sample
    由于是16bit的数据,所以有1 sample = 2 * 16 bit = 4 bytes
    采样率是44.1khz,即每秒采样44100次,有44100 samples = 1 秒
    可以用如下的公式来在这些不同的术语间进行转换:
ms = samples * 1000 / samplerate. 
samples = ms * samplerate / 1000. 
samplerate = samples * 1000 / ms. 
bytes = samples * bits * channels / 8. 
samples = bytes * 8 / bits / channels.
    fmod的一些函数如Sound::getLength提供了不同的长度单位输入来避免这些计算。

1.2  Samples vs compressed samples vs streams.
    一个声音会以上面三种形式之来加载进内存:
  • Samples:解压成PCM的形式载入内存,适用于一些多次播放的小音效,播放时不怎样耗CPU而且能被硬件加速。详见FMOD_CREATESAMPLE。
  • Streams:适用于大形的声音文件,如背景音乐。需要从磁盘以流的形式读入由fmod管理的ringbuffer。会消耗一些CPU和磁盘带宽。一个Stream形式的声音在fmod里只能播放一次,原因在于每一个stream只有一个文件句柄和一个用于解码的ringbuffer。详见FMOD_ CREATESTREAM。
  • Compressed samples:它允许用户加载某种特定的压缩格式(如IMA ADPCM, MP2, MP3 and XMA)进入内存。它们由CPU进行软件混合,因此没有streams的只能播放一次的限制。CPU占用会比普通的PCM sample多些,但会比stream少,而且占用的内存会少很多。详见FMOD_ CREATECOMPRESSEDSAMPLE。
    虽然有这Sample和Stream这些术语在,但在FMOD API中会把它们统一为Sound这类型。使用System::createSound的默认参数,会创建sample。可以通过传入FMOD_CREATESTREAM或是System::createStream来创建stream。对compressed sample则可通过FMOD_CREATECOMPRESSEDSAMPLE来创建。

1.3  Channels and sounds.
    可用System::playSound来播放一个声音,这个函数返回一个Channel / FMOD_CHANNEL的句柄,一般推荐使用FMOD_CHANNEL_FREE作为参数传入,它意味着FMOD会自动选择一个不处于播放状态的channel来使用。

1.4  2D vs 3D.
    3D声源有位置和速度的属性。当3D channel在播放时,它的音量、喇叭位置和高音(pitch)会被listener影响,listener可以是玩家或是相机,它除了象声源一样有位置、速度外,还有面向。
    Listener和声源之间的距离决定音量。
    Listener和声源间的相对速度决定pitch(即多普勒效应)。
    Listener与声源的面向决定pan(相位)或喇叭位置。
    2D的声源是不会被listener影响的,它用可调用Channel::setSpeakerMix, Channel::setSpeakerLevels或Channel::setPan而3D声源是不行的。

二、Ex API入门
2.1  初始化
    先调用FMOD::System_Create获得一个system对象,再调用system::init进行初始化。Init包含一个maxchannel的参数来指定可同时播放的最大声音数,这里指的是virtual voices,其具体含义后章再说。
    如果需要对system的默认参数进行设置,可以在init前调用下面的一系列函数,具体含义就不译了,查文档去吧,不过记住是要在init前调用:
System::setOutput
System::setDriver
System::setHardwareChannels
System::setSoftwareChannels
System::setSoftwareFormat
System::setDSPBufferSize
System::setSpeakerMode

2.2  加载和播放
    前面已经提过,用System::createSound或System::createStream来加载声音资源。然后调用System::playSound就可以播放了。关于播放声音,有几点要注意一下:
    如果不需要操作sound对象,可以不保存channel对象,playSound时传入0 或NULL就可以了。
    可以以暂停(pause)状态开始来playSound,这样通过channel的操制声音属性前的效果别人就听不到了。
    Channel是sound的一个实例。可以同时播放多个声音,每次都会获得一个新的channel句柄。对stream来说,如果尝试播放多次,它只会重新开始播放当前的stream并返回同一个channel句柄。
    FMOD_CHANNEL_FREE和FMOD_CHANNEL_REUSE。FREE允许FMOD按优先给自动选择空闲的channel。REUSE则是使用当前传入的channel,它会停掉当前channel声音播放新的声音。
    当播放结束时,channel就无效了。此时对它的调用会返回错误码FMOD_ERR_INVALID_HANDLE。

2.3  更新
    确保每帧调用System::update。它主要用于虚拟声音更新、3D音效计算、几何计算、非实时输出等。

2.4  关闭
    System::release会关闭所有设备并释放相关对象的内存。而System::close只是关闭系统而没有释放内存,System::release内部会调用System::close,所以release了就不需要再close。

三、频道管理和虚拟声音
3.1  什么是虚拟声音(virtual voices)
[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
     就像这幅图显示的那样,虽然有50个声音在同时播放,但能被听到的只有10个。
    由于有硬件的限制,一般只能有32或64个声音。但FMOD通过分配有限的软硬件资源来播放最重要的声音,满足用户同时播放很多声音的需求。所以,如上图示,除了能被听到的10个外,其余声音都是虚拟的。Virtual voices没有分配任何软硬件资源,通常是些对listener来说较次要的声音。

3.2  当某些声音比其他更重要时
    可以调用Channel::setPriority或Sound::setDefaults来设置优先级,也可以在designer里设置event的Priority参数,0是最高级,128是默认值,255最低。
    当有新的声音要播放时,会检查是否全部资源都使用了。当全部资源都使用中,FMOD会检查当前播放中声音的优先级与新声音的优先级,如果新声音的优先级高,则会把最低优先级的virtual掉,播放新的,否则就是新声音virtual了。
    对优先级相同的声音来说,音量就成为了另一个选择标准,越大声的会被认为越重要。

3.3  当virtual voices全部用完时
    当播放的声音超过virtual voices的上限时,FMOD Ex channel管理器会找出最不重要的声音并替换它。这意味着原有的channel无效了,如果调用它会返回错误码FMOD_ERR_INVALID_HANDLE。

3.4  怎样设置real voice与virtual voice的数量
    Virual voice的数量在System::init中的maxChannel来设置。
    对硬件声音来说,一般是不需要设置的,如果真的要限制最大使用数量,可以用System::setHardwareChannels来设置,其最大值则通过System::getHardwareChannels来查询,硬件声音是通过FMOD_HARDWARE 来指定的。
    软件声音由System::setSoftwareChannels设置,当设为0时表示禁用软件声音,它由FMOD_SOFTWARE 指定。

3.5  应该设置多少virtual voice
    这一般是看实际需求的,不过越多的channel意味着越多的CPU和内存占用,一般1k左右的数量还不会对CPU和内存造成太大负担。实际情况可以用System::getCPUUsage 和FMOD::Memory_GetStats的数据来决定。

3.6  可以令无声的声音变为virtual voice吗?
    可以,在System::init时设置FMOD_INIT_VOL0_BECOMES_VIRTUAL就可以了。也可以结合System::setAdvancedSettings和FMOD_ADVANCEDSETTINGS的vol0virtualvol成员来设置自动变为virtual的最小声量,这个值范围是0到1的浮点数,不过不要调得太大,否则有可能所有声音都被virtual掉了。

3.7  如何判断channel是不是virtual
    使用Channel::isVirtual函数。

3.8  如果不喜欢一个声音播到一半时变成virtual要怎样做
    这种情况会导致某个正在播放的声音突然停掉,像bug似的。要避免这种情况,可以根据需要在System::createSound,System::createStream,Sound::setMode或Channel::setMode中设置FMOD_VIRTUAL_PLAYFROMSTART参数。
    另一个办法是在System::update 后调用Channel::isVirtual并停掉声音。

四、3D Sound
4.1  加载3D声音
    在System::createSound或System::createStream时使用FMOD_3D参数就可以了,当是硬件声音时DirectSound限制了初始化后不能进行2D和3D之间的切换,软件声音可以避免这种情况。

4.2  距离模型和线性衰减vs指数衰减
    其实如果是使用designer的话,这些东西程序都不用管的,由专业人士编辑event时指定一下就好了,所以这里有个粗略了解就可以了。这两种模型可以在sound或channel在create时或是调用setMode来指定,具体表现效果由mindistance和maxdistance两个参数决定,它们可以用Sound::set3DMinMaxDistance或Channel::set3DMinMaxDistance设置。
    指数衰减:用FMOD_3D_LOGROLLOFF指定。在这种衰减方式中,声音每隔mindistance就会减弱一半,超过maxdistance就不再衰减,所以要留意maxdistance不要设得太小。
    线性衰减:就是由maxdistance和mindistance定义一条直线,按比例衰减。

4.3  一些全局的3D设置
    FMOD Ex里有三个主要的参数会影响到所有的3D音效,它们是:
  • 多普勒参数:它可以扩大或缩小多普勒效应。
  • 距离参数:指定距离的单位。
  • 衰减比例:控制声音衰减的快慢
    这三个参数可以由System::set3DSettings来指定。

4.4  左右手坐标的设置
    跟据游戏中的实际需要,可以设置3D声音使用左手坐标系还是右手坐标系,FMOD默认是用左手的,要改成右手可以在System::init 传入FMOD_INIT_3D_RIGHTHANDED参数。

五、FMOD Designer API
5.1  从Designer里Build出来的文件
    .fev:已编辑好的声音事件文件,包含各音声音属性的定义,但并不是真正的音乐数据。要用EventSystem::load载入。
    .fsb:原始的声音数据集合文件,一个.fev可以对应多个.fsb。

5.2  创建和初始化EventSystem对象
    直接粘好了,很简单的流程:
FMOD::EventSystem_Create(&eventsystem);
//可以在这里操作system对象进行一些更详细的初始化配置,就需要可忽略
eventsystem->getSystemObject(&system);
eventsystem->init(64, FMOD_INIT_NORMAL, 0, MOD_EVENT_INIT_NORMAL);
//设置资源根目录
eventsystem->setMediaPath("..\\media\\");
//载入声音事件
eventsystem->load("examples.fev", 0, 0);
    要注意的是,不要用FMOD::System_Create来创建自己的System对象来使用,因为eventSystem已经会自动创建一个了,同时存在两个活动的system意味着声音设置被打开两次,应该会引起些乱七八糟的问题的。

5.3  FMOD Designer类对象的关系
[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
 
    EventSystem:类似于管理器的存在,主要职责是初始化(init),加载project(load),每帧更新(update),释放对象(unload/release)。
    EventProject:对应.fev文件,一个EventSystem里可以有多个project存在。
    EventGroup:不仅仅是为了逻辑上的条理清晰,也起到管理内存分配的作用。
    Event:封装好的音乐音效的对象,好处是程序员基本不用管太专业的音乐参数设置了,因为具体效果可以给sound designer在编辑器里调好并保存,程序里只要通过id或名字指定播放特定的event就行了。当然,如果真的要在程序里手动调效果,可以用Event::setPropertyByIndex来设置。事件中可以定义多个音乐片段。
    EventParameter:对Event来说是一个可选的,需要在designer的编辑器里事先生成。用处有二:选择播放事件中哪一段音乐;在运行中控制声音的属性。具体的音乐效果也是由sound designer定义好的,程序能做的只是在运行是动态用setValue来改变parameter的值。
    EventCategory:Event除了以EventGroup组织外,也可以用EventCategory来组织。Category提供了一个途径让sound designer来批量调整event的音量和音调。默认有两个category:master和music,它们是不可删除。master是最顶层的category且包含所有其他category,music这个则主要是为Xbox360服务的,忽略之。
    MusicSystem:主要用于管理不同主题音乐之间的过渡效果,调用prepareCue就可以获得由某个cue_id指定的主题音乐对象。
    MusicPrompt:各种主题音乐的定义,调用begin来播放,end来停止。
    EventReverb:各种混向效果的定义。

六、内存管理
    推荐手动调用FMOD::Memory_Initialize来为FMOD分配适当的内存,这有助于减小系统堆栈的负担,意味着减少系统堆栈的碎片从而运行得更快。FMOD的内存使用主要集中在三方面:
  • FEV在内存中的数据
  • [转]FMOD相关 - 秒大刀 - 秒大刀的城堡
     
    • 可以把fev信息想像成evnet的定义,当调用EventSystem::load()时FMOD就把.fev文件信息存到内存中,直到调用EventProject::release或EventSystem::unload时,这部分内存才会被释放。
  • 事件实例对象
[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
    事件实例中还包含DSP效果所需的内存,只要sound designer不为事件指定DSP效果如reverb, echo, chorus 或flang,其实事件实例占的内存并不算多。
    事件实例在下面两种情况下被创建:调用getGroupXXX 时传入的cacheevents参数为true时,FMOD事件系统会为这个group级其子group下的所有事件创建实例;当调用getEventXXX()时为这个事件创建实例。只有当调用EventGroup::freeEventData()或者整个project被释放时,事件实例占用的内存才会被释放。
  • 声音数据:
    .fsb中的声音数据,这部分数据占的内存是最多的。FMOD Designer工具在提供了三种声音文件在内存中的表现方式的选项,分别是:
    • 1. Decompress into memory。若是mp3或ADPCM等压缩格式会先解压为PCM再加载进内存。
[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
 
    • 2.Load into memory。直接以压缩的形式加载进内存,使用的时候再解压。

[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
 
    • 3.Stream from disk:是从磁盘中直接读入。

[转]FMOD相关 - 秒大刀 - 秒大刀的城堡
 

参考资料:

  评论这张
 
阅读(5010)| 评论(3)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018