加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 苏小脉 于 2012-12-31 05:40 编辑
Scorched End Audio Library
原本是給 RGE2 做的音頻渲染庫,但由於 RGE2 目前基本沒有活躍開發,故而先獨立出來給各位 RM 用戶試用。這個庫可以給 3D 遊戲用,但也兼容 2D。
Seal 是 Scorched End Audio Library 的簡稱,是從「焦尾音頻庫」翻譯過來的。相傳焦尾是東漢蔡邕所製名琴,與號鐘、繞梁、綠綺並稱為四大名琴。Seal 的底層是 OpenAL(相當於音頻界的 OpenGL),在其基礎上添加了對 Ogg Vorbis、MPEG1、2、3 和簡單 WAVE 格式的支持,同時也抽象了流式音頻的播放,在未來還會根據用戶的需求提供各種便捷的輔助方法、抽象層等。Seal 在原本的 OpenAL 的 C API 基礎上建立了 Ruby 綁定。
Seal 與默認的音頻模塊
默認的音頻模塊提供的是純粹的音頻重放,外加調節音量和音調的能力,除此之外並無其他特效。Seal 目前通過 OpenAL 支持對以下自然界的聲音現象的模擬:
聲音的增長和衰減
通俗的說就是聲源和觀察者之間的距離與觀察者聽到的聲音強度成正比。一個發聲物體離得越遠,觀察者附近的壓強震動就越小。比如牆上一把火炬,靠近它時燃燒的聲音變大,遠離它時聲音變小。RPG的場景中隨處都可以有這方面的應用——玩家走近市井,漸聞喧嘩;NPC 漸行漸遠,腳步聲漸悄。
多普勒效應
聲源和觀察者保持相對運動,當觀察者接收到聲波時,聲波的頻率與最初聲源發出的頻率和波長產生了差別的現象。比如當一輛救護車朝朝觀察者行駛而來,觀察者聽到的鳴笛聲會變得很急促,這是由於頻率變高、波長變短;當救護車駛過並遠離觀察者時,觀察者聽到的鳴笛聲則會變得很低沉,這是由於頻率變低、波長變長。遊戲中,法師的一個火球飛來,擦身而過的馬車都應該產生多普勒效應。
聲音的空間定位
人類通常可以識別出聲源在空間中的位置。前面提到的聲音的增長和衰減實際上是空間定位的一部分,因為通過聲音強度通常就能反過來推出發聲物體的距離,但僅限於距離,不含方向。玩家理應識別出兩個正在左手邊決鬥的NPC所發出的刀劍交擊聲是從左方傳來,而不是從右方。這個效果的具體表現手法是將音頻輸出到在不同位置的音頻輸出設備終端上。一對音箱或是當代筆記本電腦內置的揚聲器都有一左一右兩個輸出口,如此就把聲音的渲染從一個點提升到了一條線——聲音可以來自左邊,中間或者右邊。更多的輸出聲道和終端的搭配可以產生更真實的環繞音,把線提升到平面,平面提升到空間。
迴響
在特殊的環境中,一部分聲波被物體反射並逆向運動,與原有聲波交融所形成的效果(在特定場合下,反射回來的波甚至會再次被反射)。同樣的音效在不同的環境中會產生不同屬性的迴響——小屋內,管道中,森林中,空間站中,冰霜宮殿中……總之,有了對迴響效果的渲染,聲音的真實度便能大幅提升,尤其是在從一個環境切換到另一個環境中的時候那種聲音的驟變。
其它
除特效外,Seal 目前還具備 RM 所沒有的諸如播放時調節音量、音調,暫停播放、獲取音頻屬性等能力,當然仍然還有很多功能待實現,見「待完成」一欄。
編程模型
一個音頻數據文件的通過 Buffer 類或者 Stream 類對象加載——小巧的音頻數據用 Buffer 加載,大體積的音頻數據用 Stream 流式傳播。Buffer 或 Stream 的實例會被關聯上一個抽象地代表聲源的 Source 類對象,並通過 Source 的各種接口對音頻就行各種實時的操控、加工和過濾。全局可以有 n 個 Source 實例(遊戲中各種發聲的物體通常都是不同的 Source 實例),但只有一個 Listener 類的單一實例,表示觀察者(通常是場景中移動的玩家)。Source 的實例和觀察者都有位置和速度屬性,而實時更新這些屬性就能自動改變聲音在空間定位和減淡上的渲染。此間涉及到的大量數學計算都是底層引擎負責的,它最終會渲染出在某一時刻觀察者所在的地點聽到的把所有 Source 的聲音混合後的聲音。
Seal 的模型和 RGSS 的圖形編程模型有很大的可比性,彼此的對象之間有大致的對應關係。
Source 類似於 RGSS 的 Sprite,一個表示音頻,一個表示圖形,前者的不同實例最終集成於混音器的輸出,後者的不同實例最終集成到整個遊戲的圖形場景,兩者的存在都是為了方便對原有數據的實時加工渲染。
Buffer 類似 Bitmap,前者是音頻數據的容器,後者是圖像數據的容器。通常用於加載小橋的音頻文件,比如 RM 的各種 BGS、ME 和 SE。
Stream 從抽象層來看也基本等同於 Buffer,但從程序效率角度來看的話則大有不同——Buffer是將音頻一次性讀入內存,而 Stream 是流式數據傳輸。音頻數據通常比圖像數據大,一首5分鐘的MP3解壓之後會佔據50MB的空間,如果一次性讀入主內存那將會是很大的開銷。由於音頻播放的特性是只需要當前正在播放的這一部分數據,所以流式每次只讀取一小塊數據並傳輸給音頻輸出設備,而之前的數據佔據的內存則可以直接被釋放或重用。一個流隨時保持在內存中的數據只是原有音頻數據的很小一部分,就不會導致各種內存效率的問題(Cache miss,碎片,大量的頁缺失、內存顛簸)。通常需要用到流式的是背景音樂,比如 RM 的各種 BGM。
迴響是 OpenAL 軟件實現的的特效擴展系列之一。在 Seal 中,迴響是通過控制另外兩種對象實現的:EffectSlot 和 Reverb(Reverb 是迴響的英文 Reverberation 的簡寫)。Reverb 的實例有各種關於迴響的參數設置,表示一種特定環境的迴響。Source 的實例可以選擇應用某種迴響,這時就需要使用 EffectSlot。EffectSlot 可以看作是流水線上作業的一個過濾器,負責過濾數字信號,將輸入的音頻應用上迴響的效果。EffectSlot 可以插入不同類型的效果,但由於目前 Seal 只實現了迴響的效果,所以目前僅限 Reverb。從設計模式角度來看,EffectSlot 就是適配器,統一了 Source 和特效對象之間的關聯接口。
簡單流程
初始化 Seal:
Seal.startup include Seal # Seal 模塊是 Seal 的頂層命名空間,必要的時候可以 include 一下避免重複修飾 Seal::*
Seal.startup
include Seal # Seal 模塊是 Seal 的頂層命名空間,必要的時候可以 include 一下避免重複修飾 Seal::*
利用 Source 對象表示聲源,並關聯上一個 Buffer 對象:
source = Source.new source.buffer = Buffer.new("audio.ogg")
source = Source.new
source.buffer = Buffer.new("audio.ogg")
改變 source 的位置:
source.position = 3, 2, -4 # 歐幾里德 3D 空間座標體系,2D 遊戲只要永遠保持第三個座標為 0 即可
source.position = 3, 2, -4 # 歐幾里德 3D 空間座標體系,2D 遊戲只要永遠保持第三個座標為 0 即可
改變 listener (觀察者,Seal::Listener 的單例)的位置:
Seal.listener.position = -1, -1, 0
Seal.listener.position = -1, -1, 0
播放 source:
需要播放大體積的音頻資源時則採用 Stream:
source.stream = Stream.open("background_music.ogg")
source.stream = Stream.open("background_music.ogg")
從一個 buffer 切換到 stream 及其相反:
source.buffer = ... # ... source.buffer = nil source.stream = ... # ... source.stream = nil source.buffer = ...
source.buffer = ...
# ...
source.buffer = nil
source.stream = ...
# ...
source.stream = nil
source.buffer = ...
應用迴響效果:
# 分配一個 EffectSlot 對象,並關聯上一個 Reverb 對象 slot = EffectSlot.new(Reverb.new(Reverb::Preset::FOREST)) # 開始進行迴響效果的過濾 source.feed(slot, 0)
# 分配一個 EffectSlot 對象,並關聯上一個 Reverb 對象
slot = EffectSlot.new(Reverb.new(Reverb::Preset::FOREST))
# 開始進行迴響效果的過濾
source.feed(slot, 0)
其中 Reverb::Preset 包含一系列預定義的迴響效果,如城堡、工廠、戶外、城市等。詳見:
http://zhang.su/seal/Seal/Reverb/Preset.html
最終化 Seal:
詳細文檔
在以下兩個地方都可以查閱:
http://zhang.su/seal/
http://rubydoc.info/gems/seal
rubydoc.info 上那個可以看以前版本的。暫時還沒有精力寫中文文檔 TvT,先湊合看著英文吧……
這裡有一些命令行的 demo 程序:
https://github.com/zhangsu/seal/tree/master/demo
注意事項
- 只有單聲道的音頻數據文件在被 Seal 加載後才有空間定位、聲音減淡的效果。OpenAL 默認多聲道的音頻在設計的時候就考慮了立體音,所以不會強制改變它切換聲道的效果。多聲道音頻需要被事先轉換為單聲道音頻文件才能利用 Seal 的空間定位和減淡。
- Seal 並不支持解碼所有 WAVE 的子格式。Seal 只是出於測試的目的提供了對無壓縮的小於等於 16bps 的 WAVE 的支持,但實際上微軟官方的規格中有很多 WAVE 的子格式(包括壓縮失真格式)。建議大家統一使用 Ogg Vorbis 格式,開放自由。
- 當 Source 被 GC 回收時,底層的對象被釋放,聲音的播放自然也會終止。管理好 Source 的作用域和生命週期,慎用局部變量。使用局部變量極容易出現聲音還沒有播放完就突然中斷的情況,原因是被 GC 回收了對象。
- 用 VA 測試時發現有很小的幾率在調用 Seal.startup 時出現打開設備失敗的異常,但重試又好使了,原因不明,而且只是在 RM 環境中出現。目前的救急方案是:
begin Seal.startup rescue Seal::SealError retry end
begin
Seal.startup
rescue Seal::SealError
retry
end
或者限制重試次數:
3.times do begin Seal.startup break rescue Seal::SealError next end end
3.times do
begin
Seal.startup
break
rescue Seal::SealError
next
end
end
下載
首先必需的是 OpenAL 庫,這裡提供 MSVC 10.0 預編譯的 32 位二進制,你也可以自己編譯,只要是這裡的 OpenAL 軟件實現。
OpenAL32.zip
(220.15 KB, 下载次数: 163)
|