2017年8月16日 星期三

Audio Effects on Unity–Native Audio Plugin SDK(1)

Reference:

1. Unity manual  for Native Audio Plugin SDK

2. Native Audio Plugins Bitbucket


在介紹主題之前,我先簡介一下 Unity 的聲音傳導過程。

Unity的元件列表中,可以找到 audio source 與 audio listener ,前者就像是喇叭,後者則是麥克風。假設我們將 audio source attach 在一個球體物件上,將 audio listener attach 在 main camera 上,再將音檔拖曳至 audio source 的 audio clip 欄位上,在按下 play 鍵時,audio source 會開始在場景中播放音檔,audio listener 則接收音訊資料並將結果輸出至電腦的音效裝置,完成這回合。只要你將任何一個人 disable 掉 (取消勾勾),就聽不到聲音。

由上圖 audio source 的屬性頁可以發現, Unity 已經提供了一些很基本 3D Sound Effect 的功能了,因此,在 Play 後你改變了兩者的相對位置及距離的話,就可以聽到聲音的方向有些許的改變。

這時候問題來了:如果我想要改變聲音的特性,或加上一些音效,該怎麼做呢?

一、MonoBehaviour.Update()

只要有一個元件它是繼承自 MonoBehaviour,當它有被 Enable,則 Unity 每過一段時間就會執行它的 Update,我們可以在取得 audio source 的 audio clip 後開始播放它,然後另外新增一個 audio clip 的物件,當 Update 被執行時將 original audio clip 丟進音效處理器,再將 output 寫去 new audio clip ,最後就是將 new audio clip attach 回 audio source 給它播放。

老實說這個作法在邏輯上看起來就怪怪的,我目前還是不懂為什麼可以新舊兩個 audio clip 同時播,卻只有新的被 attach 到 audio source,另個團隊能想到這個作法真的很厲害。

二、MonoBehaviour.OnAudioFilterRead()

原理跟上面差不多,但這個就是直接拿 original audio clip 來做,做完就寫回去並播放,在邏輯上比較合理。另外,這個 function 是由另一條 audio thread 所呼叫,因此在程式執行上比前者更有效率。

三、鏘鏘鏘鏘

沒錯!最有效率的當然是做成 Native Audio Plugin 了,原因無它,前兩者看到的函式都是 C# script,而這個方法則是在底層 (C++) 就做掉了,所以當你在 trace 其他家廠商寫的 Plugin 時,是看不到哪邊有 audio I/O 的行為的。

 

つづく

Audio Effects on Unity–Preface

好久沒有寫blog,心裡有種莫名的感動,工作兩年半來,總算在換工作後有時間可以沉澱自己所做所學並留下紀錄,做筆記對像我這個記性不好的人來說是個加深印象的好方法。

五月底加入新團隊後才剛開始接觸 Unity,在這之前我們實驗的 Unity 場景是商請另外一個團隊幫忙制作,但該團隊對於 Unity 的 audio 運作機制也不熟,所以用了一個很奇特的方式將 audio input buffer 導入某個函式內,讓我們統一在裡面處理完後再丟到 output buffer 。好處是,audio 演算法開發者不需要懂 Unity,只要寫一個 DLL export function 讓 Unity 執行到該函式時可以呼叫即可,我接手程式後上手很快,同事需要橋接新的參數也很容易;缺點是,會有 latency。

老實說我不覺得自己程式功力有多熟練,系統程式的概念多半在碩班建立,在前公司也只是寫一些小模組套用到前人已經完成的系統上。到了新團隊後,我才體會到我對程式也有某種程度上的潔癖,命名規則倒還好,我比較受不了程式架構的雜亂無章,各種神奇的全域變數飛來飛去。因此,我主動向主管提出說我自願幫忙做 code refactor 。另一方面,因為工作任務的關係我也開始研究 Unity 上各家廠商的 SDK,也可擷取別人的長處來改善現行的架構。

新工作即將到職滿三個月,就以一系列的技術文作為慶祝(?)吧!希望日後能夠持續做筆記,讓後輩們能夠更快找到出路。

喔對了,希望台電不要這時候停電,大家快用愛發電吧!