人气 112

如何高效设计游戏——增强游戏体验游戏背景音乐无缝循环 [复制链接] ... [复制链接]

九艺网 2017-4-24 13:04:26

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
如有游戏背景音乐外包需求,请联系。专注制作真正的游戏背景音乐。

作者:Einsphoton (任江枫)
Email:rjflx@hotmail.com
个人博客:http://blog.sina.com.cn/u/2673256031
个人微博:http://weibo.com/u/2673256031
关注以获得更多内容
版权所有,转载须注明出处以及作者
欢迎加入游戏设计群 http://q.weibo.com/1543457
前言
    有关于本文内容,作者想说的太多。
    还记得小的时候玩《最终幻想》系列以及《Chrono Trigger》,第一印象就是哪美妙的背景音乐以及整体音效的流畅度。这种体验至关重要,它可以直接吸引你深入游戏,引导你跟随着剧情的情感起伏。紧张激烈,舒缓柔情,飘渺悠扬。至今那些熟悉而又令人感动的旋律依然徘徊在脑中。那个年代,FC、SFC中的各种神级作品,至今未曾被人们遗忘。
    然而技术发展到如今,我们国内的游戏产品,用着比以往优越几百倍的技术以及性能,缺没能做出以前国外产品十分之一的游戏体验。其中涉及到的原因多种,诸如设计理念落后、缺乏游戏文化以及内涵、游戏内容趋之若鹜、极致的商业化等、不尊重用户实际的游戏需求体验而想方设法的骗取留存率等。但我们今天只探讨其中一点,关于游戏体验中的音乐音效问题。
    纵观国内各种游戏产品并与国外游戏产品比较,我们不难发现,在游戏背景音乐和音效上我们严重缺乏关注。至今仍有多数厂家的产品显得光秃宁静。余下的虽然有背景音乐但没能有条件在这里给予过多的关注,至少现在来看,多数游戏背景音乐不但没有增益反而影响体验,以至于好长一段时间玩家都是关闭声音来游戏的。这相比国外游戏公司单独设立音效部门的这一状况,我们着实气力不足。尽管没有这种条件,但我们也要做足了功课。
    目前国内游戏背景音乐方面,通常大家是通过外包的形式,然而国内的各种知名音乐外包团队,尽管有着很多项目经验,但是终究缺乏做【游戏背景音乐】的理念以及技术。于是导致了国内游戏作品中的背景音乐都是4分钟多的一整段,最后来个结束乐句然后等着重新播放,或者更甚者直接30s一小段并且没有无缝衔接,这都会对玩家造成审美疲劳降低体验。游戏背景音乐还是和其他背景音乐有区别的,所以不能一整段的播放然后循环,除非像上古卷轴5那样,多个音乐根据场景算法来播放。
    首先我们先来看看背景音乐的无缝循环会给我们带来什么好处:
    ①        增强游戏体验,不会出现断续的尴尬局面,让玩家有种“有头无尾”“一段无限长的音乐”的感觉。避免断断续续造   成的审美疲劳。
    ②        减少外包成本,现在多数音乐外包都是按时间来计算的,然后一段音乐不可能内容完全不一样持续4分多种,多数都是在循环主体乐句。这样浪费了好多资源。如果可以采用“前奏+主循环体+主循环体……”的形式,这样外包只要交付不超过2分钟的“前奏+主循环体”就可以了。而且也大大节省了资源大小。
    这两条每一条都是足够分量的优化点,而并不是某些眼里可大可小的部分。所以本文将会致力于提出一种游戏背景音乐无缝循环的解决方案。
    想要实现游戏背景音乐无缝循环,我们必须做好3方面的准备:音乐创作上需要Loop形式、音频格式的限制需求、技术上的准备。其中音乐创作层面上的准备,本文不做过多讲解,能看到这篇文章的人基本上都是做技术的:)如果需要音乐创作方面的讲解,请联系作者。
    下面就后两方面做出详细讲解。
音频格式的需求
    可能会有一些读者体验过这一情况,当我们使用播放器循环播放我们喜欢的音乐或者已经在游戏作品中尝试循环播放的时候,总会在循环衔接处听到短促有力的“pang”的一声或者一阵停顿亦或者有种循环体没有播放完就被重新循环的感觉,这会让我们从音乐的沉静中惊醒,造成不好的体验。而出现这一现象的情况多数存在于低品质音频文件或压缩过的MP3文件。这是因为音频文件在被压缩过之后会在音频波形的前后产生一小段“空白”或者整段音频波形长度被压缩的原因。通过下图我们可以观察出问题所在:
53c13de5c71e39b40dc93f9aab70499c.gif


    为此就目前条件来看,我们需要准备音乐的音频格式最好为WAV、OGG或者低压缩MP3(Bit率:320kBit)。
    难道我们再没有其他办法了么?
LAME编码引擎
    LAME是目前最好的MP3编码引擎。LAME编码出来的MP3音色纯厚、空间宽广、低音清晰、细节表现良好,它独创的心理音响模型技术保证了CD音频还原的真实性,配合VBR和ABR参数,音质几乎可以媲美CD音频,但文件体积却非常小。对于一个免费引擎,LAME的优势不言而喻。LAME本身是DOS下的文件,需要加外壳程序才比较容易使用,也可以在别的软件(比如EAC)中间调用。但目前很少有马甲能够适用于无缝循环的压缩。所以本文在此也会推出一些关于LAME的简单教程。
2744083b49bb5464483252aecbf5477c.gif

    首先我们需要登录LAME引擎的官方网站http://lame.sourceforge.net/,下载最新版本的LAME编码引擎V3.99(需要和谐上网,或者读者自己手动搜索)。
    下载完成后得到的是一个压缩包,解压之后我们找其中的可执行文件“lame.bat”,不过我们需要从命令窗口中执行。
    按“窗口键+R”调出运行窗口,在打开中键入cmd并确认。
    在命令窗口中使用“cd”命令进入lame所在目录如图
aa49d7467d2290065bfcfe36b5a53957.gif

    下一步我们只要执行编码器就可以了,命令为: lame  -V2 ?vbr-new ?nogap 。
    例如:lame test.wav -V2 ?vbr-new ?nogap 。
aaa69cbed79d4d1a5cea54fb0cb3d50d.gif

    LAME还可以帮助用户压制其他格式要求的MP3,具体参数参考如下:
LAME 64bits version 3.99.3 (http://lame.sf.net)

usage: lame3.99.3-64lame.exe [options]  [outfile]

and/or  can be "-", which means stdin/stdout.

RECOMMENDED:
lame -V2 input.wav output.mp3

OPTIONS:
Input options: 输入文件选项
--scale  scale input (multiply PCM data) by
--scale-l  scale channel 0 (left) input (multiply PCM data) by
--scale-r  scale channel 1 (right) input (multiply PCM data) by
--mp1input input file is a MPEG Layer I file
--mp2input input file is a MPEG Layer II file
--mp3input input file is a MPEG Layer III file
--nogap    指定连续输入一系列的文件,输出一个连续完整的文件,也就是合并功能
gapless encoding for a set of contiguous files
--nogapout  在上面的选项启用的情况下,指定输出文件目录
output dir for gapless encoding (must precede --nogap)
--nogaptags allow the use of VBR tags in gapless encoding

Input options for RAW PCM:
-r input is raw pcm
-x force byte-swapping of input
-s sfreq sampling frequency of input file (kHz) - default 44.1 kHz
--bitwidth w input bit width is w (default 16)
--signed input is signed (default)
--unsigned input is unsigned
--little-endian input is little-endian (default)
--big-endian input is big-endian


Operational options:
-a downmix from stereo to mono file for mono encoding
-m  (j)oint, (s)imple, (f)orce, (d)ual-mono, (m)ono (l)eft (r)ight
default is (j) or (s) depending on bitrate
joint = joins the best possible of MS and LR stereo
simple = force LR stereo on all frames
force = force MS stereo on all frames.
--preset type type must be "medium", "standard", "extreme", "insane", 使用预置方案:"medium"=较差质量,"standard"="标准质量" (192), "extreme"=高质量 (256左右), "insane"=极限品质
or a value for an average desired bitrate and depending
on the value specified, appropriate quality settings will
be used.
"--preset help" gives more info on these
--comp  choose bitrate to achieve a compression ratio of  指定压缩比,lame将使用能达到该压缩比的最佳比特率压缩。
--replaygain-fast compute RG fast but slightly inaccurately (default)
--replaygain-accurate compute RG more accurately and find the peak sample
--noreplaygain disable ReplayGain analysis
--clipdetect enable --replaygain-accurate and print a message whether 进行消波处理
clipping occurs and how far the waveform is from full scale
--flush flush output stream as soon as possible
--freeformat produce a free format bitstream
--decode input=mp3 file, output=wav 转入解码模式,解码生成wav文件
--swap-channel swap L/R channels
-t disable writing wav header when using --decode


Verbosity:
--disptime print progress report every arg seconds
-S don't print progress report, VBR histograms
--nohist disable VBR histogram display
--quiet don't print anything on screen
--silent don't print anything on screen, but fatal errors
--brief print more useful information
--verbose print a lot of useful information

Noise shaping & psycho acoustic algorithms: 信号噪音处理和听觉心理学算法
-q   = 0...9. Default -q 5 噪音处理方式,取值为0~9,0最好,9最差,整数。
-q 0: Highest quality, very slow
-q 9: Poor quality, but fast
-h Same as -q 2. Recommended.
-f Same as -q 7. Fast, ok quality


CBR (constant bitrate, the default) options:
-b  set the bitrate in kbps, default 128 kbps
--cbr enforce use of constant bitrate

ABR options:
--abr  specify average bitrate desired (instead of quality)

VBR options:
-V n quality setting for VBR. default n=4 使用VBR压缩,并指定压缩质量, 0最好,9最差
0=high quality,bigger files. 9=smaller files
-v the same as -V 4
--vbr-old use old variable bitrate (VBR) routine
--vbr-new use new variable bitrate (VBR) routine (default)
-Y lets LAME ignore noise in sfb21, like in CBR
-b  specify minimum allowed bitrate, default 32 kbps 指定动态比特率最低比特率,建议256或320,单位kbits/s
-B  specify maximum allowed bitrate, default 320 kbps
-F strictly enforce the -b option, for use with players that 增强动态比特率文件的兼容性
do not support low bitrate mp3
-t disable writing LAME Tag
-T enable and force writing LAME Tag


MP3 header/stream options:
-e  de-emphasis n/5/c (obsolete)
-c mark as copyright 标记为有版权的
-o mark as non-original
-p error protection. adds 16 bit checksum to every frame 生成校验信息,会导致文件增大,但也能提供更强劲纠错。
(the checksum is computed correctly)
--nores disable the bit reservoir
--strictly-enforce-ISO comply as much as possible to ISO MPEG spec
--buffer-constraint  available values for constraint:
default, strict, maximum

Filter options:
--lowpass  frequency(kHz), lowpass filter cutoff above freq
--lowpass-width  frequency(kHz) - default 15% of lowpass freq
--highpass  frequency(kHz), highpass filter cutoff below freq
--highpass-width  frequency(kHz) - default 15% of highpass freq
--resample  sampling frequency of output file(kHz)- default=automatic


ID3 tag options:
--tt  audio/song title (max 30 chars for version 1 tag) 曲目标题
--ta  audio/song artist (max 30 chars for version 1 tag) 表演者
--tl  audio/song album (max 30 chars for version 1 tag) 专辑
--ty  audio/song year of issue (1 to 9999) 年代
--tc  user-defined text (max 30 chars for v1 tag, 28 for v1.1) 注视
--tn  audio/song track number and (optionally) the total 曲目编号/总曲目数
number of tracks on the original recording. (track
and total each 1 to 255. just the track number
creates v1.1 tag, providing a total forces v2.0).
--tg  audio/song genre (name or number in list) 流派
--ti  audio/song albumArt (jpeg/png/gif file, v2.3 tag) 封面图片路径
--tv  user-defined frame specified by id and value (v2.3 tag) 自定义标签
--add-id3v2 force addition of version 2 tag
--id3v1-only add only a version 1 tag
--id3v2-only add only a version 2 tag
--id3v2-utf16 add following options in unicode text encoding 使用unicode字符集,推荐
--id3v2-latin1 add following options in latin-1 text encoding 使用latin-1字符集,慎用
--space-id3v1 pad version 1 tag with spaces instead of nulls
--pad-id3v2 same as '--pad-id3v2-size 128'
--pad-id3v2-size  adds version 2 tag, pad with extra  bytes
--genre-list print alphabetically sorted ID3 genre list and exit
--ignore-tag-errors ignore errors in values passed for tags

Note: A version 2 tag will NOT be added unless one of the input fields
won't fit in a version 1 tag (e.g. the title string is longer than 30
characters), or the '--add-id3v2' or '--id3v2-only' options are used,
or output is redirected to stdout.


MS-Windows-specific options:
--priority  sets the process priority:
0,1 = Low priority (IDLE_PRIORITY_CLASS)
2 = normal priority (NORMAL_PRIORITY_CLASS, default)
3,4 = High priority (HIGH_PRIORITY_CLASS))
Note: Calling '--priority' without a parameter will select priority 0.

Misc:
--license print License information


MPEG-1 layer III sample frequencies (kHz): 32 48 44.1
bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320

MP3可用的采样频率和比特率:
32 KHz, 44.1 KHz, 48 KHz
32 kbps, 8=40, 48, 56, 64; 16=80,96,112,128; 32=160,192,224,256; 64=320

代码上的优化
    正如各位游戏开发者所意识到的,游戏背景音乐是游戏的一个重要部分,它可以使得游戏主题更加深刻,来渲染出紧张、愉悦、悲伤等情感。为了应对各种需求我们需要动态配乐,这样我们就需要一种特殊灵活的方法来连接每一段音乐。
    如果你曾经尝试过把MP3音乐放入游戏中并且无缝循环,那么你可能已有体验,那其实并不是你预期的那么好做。还有一些问题等待解决。所以本文将会在极大程度上解决这一困惑。
    MP3无缝播放技术可以让你实现多个MP3片段之间流畅地无缝地播放。下面我们来看看有一个无缝循环的背景音乐会是什么样子的:
0df9e1cf6a577219f7771bc33a5a0750.gif

    利用无缝播放我们可以做很多事情,例如,我们可以在教程对话框打开的时候播放一个简短的Loop音乐,当教程被关闭后立马流畅的切换到主场景音乐。或者像上古卷轴那样,当遭遇战斗的时候很自然的切换紧张激烈的音乐,当战斗结束后又很自然的回到舒缓的音乐,而其中无任何停顿、Pong~的声音。当然利用MP3无缝播放技术你还可以做出很多丰富精彩的游戏体验。
在上一个章节的准备之下,我们继续我们的代码优化。以下以IOS平台开发为例。
使用“Audio Queue Services”
    一般情况下我们使用的是AVAudioPlayer类来播放MP3文件,它可以慢慢的从硬盘中缓冲式的播放MP3而不是把Mp3数据全部读取到内存中。由于其性能以及使用方便,而广泛被开发者使用,而且是硬解码。
另一种方法,就是使用“Audio Queue Services”,基于AVAudioPlayer的底层。Audio Queue Services使用起来不是很方便,但是却给你提供很大的利用空间。但即使是使用这个方法,也会存在一些问题:
        ★无论是AVAudioPlayer还是Audio Queue Service都会存在一定的延迟,虽然微小到300毫秒,但却足以辨析,且延迟效果明显。
        ★硬解码器一次只能处理一个音频音频会话(audio queue),如果你在硬解码器繁忙的时候开启了一个新的音频会话,那么系统会调用费电的软解码器,或者对于老型号的机器就干脆就抛出一个“Hardware in use”的错无提示。
        ★当一个音频会话完成是,需要一定的时间来释放资源,在此期间硬解码器不能开启另一个音频会话。
2769c8a66d570862263718cf8380a098.gif

    如果你想通过传统方式播放MP3音乐,那么你需要等待上一个音频片段释放资源才可以下一步的播放,这样在再次播放之前就会有一个很小的延迟。延迟的长度不可预测,并且这一长度在老设备上会更加长。
解决这些问题的唯一办法就是使用同一个音频会话来播放所有的MP3片段,使用Audio Queue Services,就可以做到。
ca09d0caf5dc801580ba609c56a57104.gif

    由于Audio Queue的初始化配置,所有的MP3片段必须使用相同的解码器、属性以及参数,所以在一个会话期间没有办法重新配置解码器。
    回调函数会帮你完成所有的繁琐事情,从文件中读取音频数据,然后再填入音频缓冲池里。默认情况下,如果没有数据可以读取,则回调函数停止。而我们制定的回调函数则会继续从下一个MP3文件中读取数据并填入缓冲池。
MP3无缝播放器程序
    这一解决方案已经应用于Gapless MP3 Audio Player for iOS ,读者们待会可以从附件中下载完整的代码。(来源Github: Gapless-MP3-Player on GitHub)。
    Gapless MP3 Player 是完全免费的,并且你也可以运用到你自己的项目中。其中包含一个特别的“SPGAudioPlayer”类可以在游戏引擎中使用。这个类可以操控内部音频系统事件,并且拥有一个简单的接口。
下面的实例将演示添加两个音频片段到队列中进行播放:
45678138a6ed99d2ffb35f48c7bd75ef.gif

    第一个片段部分不执行循环,第二个片段无限循环(其中loop参数-1=无限循环,0=不循环,大于0的整数代表循环播放次数)。
    如果你想使用同一个播放器对象来播放另一组片段,可以调用“[player clearQueue]”来清空队列。
当当前loop片段播放完成时,你也可以调用“[player breakLoop]”来移除下一个片段的播放。下面将展示另一个实例:
c40d6d86ef2fe31df7004d23c9ab628f.gif

    下面的方法也同样可以控制播放:
5abfc48bdc5c3e4124d9eccbfb3209a2.gif

    MP3的无缝循环技术可以使你的游戏体验有着质的提升,并且可以使玩家深入游戏。现在你可以尽情发挥到你的游戏作品中了!。








参阅文献:http://gamua.com/blog/2012/05/gapless-mp3-audio-on-ios/


感谢Daniel Sperl以及GitHub的技术提供!
版权所有
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|小黑屋|九艺游戏动画论坛 ( 津ICP备2022000452号-1 )

GMT+8, 2024-5-9 11:36 , Processed in 0.084820 second(s), 26 queries .

Powered by Discuz! X3.4  © 2001-2017 Discuz Team.