GameDesign 板


LINE

好像很少人讨论到声音这一块,因此我就献丑了。下面所说的是我使用 FMOD 第一天的小小成果,因为我并没有声音方面的专业知识,如有错误 请多多指教。 * * * 声音一向是游戏中不可或缺的一部份,不管是动人的背景音乐或营造气 氛的音效,少了声音就完全没有玩游戏的感觉,甚至许多游戏的重点就 放在声音上,比如说利用声音来判断敌人的位置等等。 从游戏开发者的角度来看,在声音方面至少有以下的需求: 1. 读取音乐/音效档案。当然,音乐资料不一定存在档案上,也可能 放在 CD 音轨上,甚至使用 streaming 的方式由网路传输(很少 见,但也并非不可能)。 2. 背景播放。除了把声音放出来,播放的同时也要能让游戏继续执行。 3. 混音。对於硬体来说,同一时间只能播放一个声音。有些硬体内建 混音的功能,因此可以同时播放多道声音,不过数量还是有上限。 超过上限时就需要把所有正在播出的声音进行混合後,再送到音效 卡上。 (在 Windows 上,送到音效卡之前似乎会自行帮你混音,所以这点 对 Windows 开发者也许不是太大的问题) 4. 各种声音效果,比如设定声源的位置以模拟方向与远近的不同,或 是设定速度来模拟运动物体的都卜勒效应 (Dopplar effect),甚至 各种 DSP 处理等等。 而我今天要讲的,称之为 FMOD 的音效函式库,正具备了以上所有功能。 除此之外,它也有跨平台的优点,除了 Windows 外,也支援 MacOS、 Linux 甚至所有的次世代主机,如 PS3、Xbox 360、Wii 等等。而且在 非商业用途下完全免费,是个很理想的音效解决方案。 废话不多说,下面就来讲 FMOD 的使用。 * * * 在 FMOD 中主要有三种物件:System、Sound 以及 Channel。因为我才 用一个晚上而已,所以像是 ChannelGroup、DSP 及 Geometry 的部份 就不深入了... * System 管理与系统相关的工作,比如说从档案系统中读取声音檨本、 设定输出的音效卡(FMOD 可以同时控制多张音效卡)、设定 DSP buffer 大小、或是载入其它的 plug-in 等。 * Sound 则是一段声音的样本 (sample),已经准备好送往音效卡播出。 Sound 的内部格式可能有三种:无压缩、压缩或串流: * 无压缩 最单纯的格式,直接把所有资讯存在记忆体中,播放 时几乎不需要 CPU 资源,但也很吃记忆体。适合长度 短、会重覆播放许多次的音效。 * 压缩 如果使用 mp3 或 ogg 之类的格式储存声音,可以把 资料以尚未解压缩的方式先读进记忆体中,播放时再 即时解压缩。这会需要多一点 CPU 资源,但可以减少 记忆体用量,适合中等长度的声音。 * 串流 在串流模式下,读取和播放是同时进行的,而记忆体 中只会保留一小部分的样本,因此几乎不吃记忆体, 但缺点是无法重覆播放,必需重开档案或重新连线才 能再播放一次。适合很长的背景音乐或是由网路传输 的声音。 * Channel 代表正在播放声音的实体。对於 Channel,你可以设定它 的音量、播放的时间点、或是它在 3D 空间中的位置与速度。一个 Channel 只能播放一个 Sound,但同一个 Sound 可以让由不同的 Channel 共享并同时播放。 马上就来写一个简单的音乐播放程式。 * * * 一开始我们要先产生一个 System 物件,这可以用 FMOD_Create_System 达成: FMOD_SYSTEM* sys; FMOD_RESULT r = FMOD_Create_System(&sys); if(r != FMOD_OK){ cerr << "Unable to create FMOD system: " << FMOD_ErrorString(r) << endl; exit(1); } 所有 FMOD 的函式都会传回 FMOD_RESULT 作为结果,我们可以检查它是 否等於 FMOD_OK 来判断是否有错误发生。为了简单起见,下面的 code 中我会把这些检查省略。(开始写游戏时可别省啊!) 接下来是对 System 初始化,并且载入一段 mp3 声音: FMOD_System_Init(sys, 32, FMOD_INIT_NORMAL, 0); FMOD_SOUND* sound; FMOD_System_CreateSound(sys, "test.mp3", FMOD_DEFAULT, 0, &sound); 在 FMOD_System_Init 中,第一个参数是先前产生的 System 物件,第 二个 32 则表示这个系统最多可以有 32 的 Channel,也就是最多可以 同时播放 32 道声音。第三和第四个参数可以设定一些进阶的选项,在 这个例子中都使用预设值即可。 而 FMOD_System_CreateSound 则会产生一个 Sound 物件。第一个参数 同样是 System,第二个则是我们要载入的声音档名称,FMOD 会自行判 断档案格式并把它解压缩。如果想用压缩或串流的方式读档,则需要设 定第三个参数,这边我们就先使用预设值。 最後就是把声音放出来: FMOD_CHANNEL* channel; FMOD_System_PlaySound(sys, FMOD_CHANNEL_FREE, sound, 0, &channel); FMOD_System_PlaySound 会让某个 channel 开始播放声音。其中第二个 参数可以指定我们要拿哪一个 Channel 来播放,传入 FMOD_CHANNEL_FREE 则是叫 FMOD 自行找一个可使用的 Channel 来播放。 但,程式并非到此就结束,别忘了声音播放是在背景执行的,如果在这 边就结束程式,声音也会马上停止。因为这只是个简单的播放程式,因 此只要进入一段回圈等声音播完即可: FMOD_BOOL playing = 1; while(playing){ #ifdef WIN32 Sleep(10); #else usleep(10000); #endif FMOD_Channel_IsPlaying(channel, &playing); FMOD_System_Update(sys); } 我使用了 unix 上的 usleep,因此回圈中的程式码每 0.01 秒会执行一 次。Windows 上则改用 Sleep。 FMOD_Channel_IsPlaying 可以拿来检查 Channel 是否已经放完全部的 声音,因此声音播放完就可以跳出回圈。FMOD_System_Update 则是更新 System,包括呼叫 callback 或是设定声音的 3D 位置等。在这例子中 可能不太重要,但若使用到其它功能时就一定要呼叫 update 了。 最後播放完,则使用 FMOD_Sound_Release 与 FMOD_System_Release 释 放系统资源: FMOD_Sound_Release(snd); FMOD_System_Release(sys); 这麽一来这个简单的播放程式就完成了!接下来我们加上一点 3D 效果 吧。首先我们要在建立 Sound 时指定 3D 的功能: FMOD_System_CreateSound( sys, "test.mp3", FMOD_LOOP_OFF | FMOD_3D | FMOD_HARDWARE, 0, &sound ); 这边看起来有点复杂,但其实只是指定这个声音并不重覆播放 (FMOD_LOOP_OFF)、 加入 3D 效果 (FMOD_3D) 以及使用硬体加速 (FMOD_HARDWARE)。先前所 使用的 FMOD_DEFAULT 其实只是把 3D 改成 2D 而已,其它选项完全相同。 接下来我们可以用 FMOD_Channel_Set3DAttributes 来设定 Channel 在 空间中的位置及速度: FMOD_VECTOR pos; pos.x = 0.0f; pos.y = 0.0f; pos.z = 2.0f; FMOD_Channel_Set3DAttributes(channel, &pos, NULL); 第二个参数即为位置,使用者预设是位於 (0,0,0) 的地方,前方为正Z 轴,左方为正X,上方为正Y。第三个参数则是速度,如果不需要模拟 都卜勒效应,给 NULL 即可。 上面的程式码会把音源放在使用者前方两个单位的位置。当然,如果声 源不会移动,就没有意思了: while(playing){ #ifdef WIN32 Sleep(10); #else usleep(10000); #endif FMOD_Channel_IsPlaying(channel, &playing); unsigned int msec; FMOD_Channel_GetPosition(channel, &msec, FMOD_TIMEUNIT_MS); float angle = 3.1415926f * msec / 4000.0f; pos.x = 2.0f * sin(angle); pos.z = 2.0f * cos(angle); FMOD_Channel_Set3DAttributes(channel, &pos, NULL); FMOD_System_Update(sys); } 这边我们会让声源绕着使用者转圈圈,使用 FMOD_Channel_GetPosition 可以得到目前播放的时间点,由这个时间乘上速度(八秒钟一圈,也就 是四秒钟所转动的弧度为 PI),即可得到转动角,再套上 sin/cos 就 可以得到新的位置了。 完整的程式码如下: http://nopa.csie.org/bd9c9 完整程式加了一些错误处理,并且使用命令列参数当作播放档案。执行 时要先等一段时间(因为使用非压缩的方式),然後应该能听到声音在 绕着使用者转圈圈。 * * * FMOD 在使用上还满简单的,复杂的解压缩、混音、硬体控制等全部都被 包装起来,因此游戏制作人员不需要再花额外的功夫处理。唯一不满的 地方就是它的 C++ interface 实在设计不良,完全没有用到 C++ 威力 (连 OOP 都沾不上边),这也是为什麽我都使用 C interface 的原因: 两者并没有明显的不同。 撇开这不谈,FMOD 功能够强、跨平台又免费,的确很适合制作游戏。当然 早有许多商业或免费游戏使用 FMOD 来播放声音。 --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.62.3.35 ※ 编辑: littleshan 来自: 140.112.29.131 (12/30 17:14)
1F:推 rigeltrue:这篇赞 推~ 12/30 17:16
2F:推 yoco315:感谢前辈的分享 12/31 04:22
3F:推 Attui:推 期待您的下一篇 12/31 11:13
4F:推 doomleika:刚刚查了一下,如果商业话化的话要3000USD ._.a 12/31 20:50
5F:推 meltice:便宜啊 你找个programmer付他3000USD还不见得写的出FMOD 01/01 00:10
6F:推 doomleika:也是._.a 01/01 20:22
7F:推 whereweare:push!!! 01/02 11:29
8F:推 moonjustin:push! 04/06 23:29







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:e-shopping站内搜寻

TOP