[譯文]JOAL教程 第四課 進一步瞭解ALC

[譯文]JOAL教程

原文地址:http://jogamp.org/joal-demos/www/devmaster/lesson4.html

原文作者:Athomas Goldberg

譯文:三向板磚

轉載請保留以上信息。


本次教程對應的學習筆記:http://blog.csdn.net/shuzhe66/article/details/40264341


第四課 進一步瞭解ALC

 

本文是DevMaster.net(http://devmaster.net/)的OpenAL教程對應的JOAL版本。C語言版原文作者爲JesseMaurais


到目前爲止,我們遇到的一切複雜問題都交給了Alut來解決,例如處理音頻設備等。Alut提供了這些非常不錯的功能,但是聰明的編碼者總是希望瞭解它到底做了些什麼,我們有時也許會希望直接對ALC進行調用,在這篇教程中我們將一探Alc層並詳細瞭解如何自己處理音頻設備[ALC是Audio Library Context的縮寫,意爲音頻庫上下文——譯者注]。

ALC alc = ALFactory.getALC();
String deviceName = "DirectSound3D";
// deviceName = null; 
// 當null作爲參數傳入alcOpenDevice時將會打開默認設備。

ALCdevice device = alc.alcOpenDevice(deviceName);

那麼,什麼是ALC設備呢?可以將它想象成某種資源,它是OpenAL獲取將要使用的音頻硬件設備句柄,該句柄被整個系統共享訪問。設備是由特定硬件設備在底層的實現,在本例當中我們使用的設備是DirectSound。上面的代碼獲得了設備的句柄,並對其進行初始化以供程序使用。最後,我們可以看到很多由其它具體聲卡實現的對應設備。[這裏的”設備”指的是程序上下文中使用的ALCdevice實例,並非指具體的硬件設備,在翻譯中,我會使用”硬件設備”來表示真實的物理設備——譯者注]

向alcOpenDevice函數傳遞null參數是完全合法的,這將強制其使用默認設備。


ALCcontext context = alc.alcCreateContext(device, null);
alc.alcMakeContextCurrent(context);

什麼又是ALC上下文呢?OpenGL程序員也許會想起OpenGL的渲染上下文,不同的上下文控制着窗口不同的渲染狀態,通過對’HGLRC’的多次創建來渲染多個窗口,而且,可以爲每一個窗口的上下文設置不同的渲染模式。ALC上下文也是同樣的道理。首先我們告訴它應當使用哪一個設備(當然是我們已經創建好的),之後我們把這個上下文設置爲當前上下文。理論上你可以爲不同的聽覺情景創建多個渲染上下文,並設置不同的狀態變量。雖然“渲染上下文”這一術語一般應用於視覺渲染,但SDK文檔中確實使用了這一詞彙,所以我在此處也應當使用它。

你可能也注意到了,alcCreateContext的第二個參數被設置爲null,Creative Labs的OpenAL SDK中定義了該參數可爲下列值之一:

·  ALC_FREQUENCY

·  ALC_REFRESH

·  ALC_SYNC

如果你創建了多個上下文,可以使用alcMakeContextCurrent來在這些上下文中切換。將null傳給alcMakeContextCurrent同樣是合法的,這將停止任何音頻的處理過程。請記住儘管你有多個上下文,但在同一時刻只有一個可以被設置爲當前上下文。當你的應用程序需要在兩個上下文間交換時,你必須決定哪一個成爲當前上下文更加合適。如果你決定做這些工作,即使不對整個系統進行一輪大檢測,也能夠獲得準確的當前上下文的。


ALCcontext curContext = alc.alcGetCurrentContext();

一旦你獲得了上下文,你便可以訪問到該上下文所使用的設備了。


ALCdevice curDevice = alc.alcGetContextsDevice(curContext);
在上面的代碼中,我們使用重新得到的上下文來確定出正在被使用的設備。


Alc中還有另一個非常酷的上下文處理方式:

alc.alcSuspendContext(context);//掛起上下文
alc.alcProcessContext(context);//繼續上下文

如上所示代碼將掛起並繼續指定上下文的音頻處理。當處理被掛起時,任何送入該上下文的音頻數據都不會產生實際的聲音。關於渲染上下文還必須提到一點:OpenAL 1.0標準並未明確聲明聲源與緩衝區可被在不同上下文間複用。聲源與緩衝區在應用程序中的生存期持續到其對應ID被銷燬之時。(即ID未被刪除時都有效)


alc.alcMakeContextCurrent(null);
alc.alcDestroyContext(context);
alc.alcCloseDevice(device);

上面的代碼就是清理無用上下文時需要寫的。將當前上下文置爲null,並將之前創建的上下文釋放,之後設備的句柄會交還給操作系統的資源當中。


還剩下幾個未被涉及到的Alc方法:

public int alcGetError();
public boolean alcIsExtensionPresent(ALCdevice device, String extName);
public int alcGetEnumValue(ALCdevice device, String enumName);
public String alcGetString(ALCdevice device, int token);
public void alcGetIntegerv(ALCdevice device, int token, int size, int[] dest);

也許它們的功能對你來說是顯而易見的,但我們還是一起來好好看一下吧。

首先,alcGetError方法與之前的alGetError十分相似,但它返回的是Alc錯誤。

之後的兩個函數僅僅是爲了檢測Alc的拓展,這是開發者預留的,目前尚未有這類拓展出現。

最後一個函數,alcGetInteger,當以ALC_MAJOR_VERSION或ALC_MINOR_VERSION做參數時將會返回Alc版本。

 

alcGetString非常的有用,它的token參數可以是下列三值之一:

·  ALC_DEFAULT_DEVICE_SPECIFIER

·  ALC_DEVICE_SPECIFIER

·  ALC_EXTENSIONS

第一個會返回你所使用的OpenAL實現設備名稱,這裏應當是"DirectSound3D",就像我們上面所用到的那個名字一樣。

第二個會返回一個標識符列表,但本例中僅會返回一個"DirectSound"(出於某種原因,並沒有"3D"兩字)。

最後的參數會返回Alc拓展列表,但這類拓展目前並不存在。

 

以上就是Alc的大部分內容了,我希望通過它你能更好的理解OpenAL與系統的交互方式。你可以嘗試一下不使用Alut來初始化你的程序。無論哪種方式都有它的樂趣。



發佈了42 篇原創文章 · 獲贊 50 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章