JOAL學習筆記
最近一直在弄數字音頻處理的一些東西,在網上檢索到了OpenAL的相關資料,粗略閱讀後感覺這個API還是很有魅力的,但JOAL教程的漢化版大多爲低質量機翻,不太適合學習,於是決定自己翻譯一下。
第一次嘗試翻譯英文技術原文,自己也就是六級水平,採用人腦爲主詞典爲輔的方式。不期待有多高的翻譯質量,只希望譯文至少能夠讓讀者連貫地讀完並對其意義正確理解。
在翻譯完每一節時,我會親自調試一下課程中的程序實例,並在這裏記錄下值得注意的問題。
如果看過教程,一定發現了它的代碼部分與文章部分融合到了一起,雖然易於解釋,但對於複製調試來講實在是不方便,因此在每篇對應的筆記中會有該實例對應的連續代碼,以方便複製調試。
下面進入正題,首先是連續的代碼頁
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import com.jogamp.openal.AL;
import com.jogamp.openal.ALFactory;
import com.jogamp.openal.util.ALut;
public class SingleStaticSource {
static AL al = ALFactory.getAL();
// Buffers hold sound data.
static int[] buffer = new int[1];;
// Sources are points emitting sound.
static int[] source = new int[1];
// Position of the source sound.
static float[] sourcePos = { 0.0f, 0.0f, 0.0f };
// Velocity of the source sound.
static float[] sourceVel = { 0.0f, 0.0f, 0.0f };
// Position of the listener.
static float[] listenerPos = { 0.0f, 0.0f, 0.0f };
// Velocity of the listener.
static float[] listenerVel = { 0.0f, 0.0f, 0.0f };
// Orientation of the listener. (first 3 elements are "at", second 3 are
// "up")
static float[] listenerOri = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
static int loadALData() {
// variables to load into
int[] format = new int[1];
int[] size = new int[1];
ByteBuffer[] data = new ByteBuffer[1];
int[] freq = new int[1];
int[] loop = new int[1];
// Load wav data into a buffer.
al.alGenBuffers(1, buffer, 0);
if (al.alGetError() != AL.AL_NO_ERROR)
return AL.AL_FALSE;
ALut.alutLoadWAVFile("wavdata/0201.wav", format, data, size,freq, loop);//這裏設置你的Wav文件。
al.alBufferData(buffer[0], format[0], data[0], size[0], freq[0]);
// Bind buffer with a source.
al.alGenSources(1, source, 0);
if (al.alGetError() != AL.AL_NO_ERROR)
return AL.AL_FALSE;
al.alSourcei(source[0], AL.AL_BUFFER, buffer[0]);
al.alSourcef(source[0], AL.AL_PITCH, 1.0f);
al.alSourcef(source[0], AL.AL_GAIN, 1.0f);
al.alSourcefv(source[0], AL.AL_POSITION, sourcePos, 0);
al.alSourcefv(source[0], AL.AL_VELOCITY, sourceVel, 0);
al.alSourcei(source[0], AL.AL_LOOPING, loop[0]);
// Do another error check and return.
if (al.alGetError() == AL.AL_NO_ERROR)
return AL.AL_TRUE;
return AL.AL_FALSE;
}
static void setListenerValues() {
al.alListenerfv(AL.AL_POSITION, listenerPos, 0);
al.alListenerfv(AL.AL_VELOCITY, listenerVel, 0);
al.alListenerfv(AL.AL_ORIENTATION, listenerOri, 0);
}
static void killALData() {
al.alDeleteBuffers(1, buffer, 0);
al.alDeleteSources(1, source, 0);
ALut.alutExit();
}
public static void main(String[] args) {
// Initialize OpenAL and clear the error bit.
ALut.alutInit();
al.alGetError();
// Load the wav data.
if (loadALData() == AL.AL_FALSE)
System.exit(-1);
setListenerValues();
// Setup an exit procedure.
Runtime runtime = Runtime.getRuntime();
runtime.addShutdownHook(new Thread(new Runnable() {
public void run() {
killALData();
}
}));
char[] c = new char[1];
while (c[0] != 'q') {
try {
BufferedReader buf = new BufferedReader(new InputStreamReader(
System.in));
System.out
.println("Press a key and hit ENTER: "
+ "'p' to play, 's' to stop, 'h' to pause and 'q' to quit");
buf.read(c);
switch (c[0]) {
case 'p':
// Pressing 'p' will begin playing the sample.
al.alSourcePlay(source[0]);
break;
case 's':
// Pressing 's' will stop the sample from playing.
al.alSourceStop(source[0]);
break;
case 'h':
// Pressing 'n' will pause (hold) the sample.
al.alSourcePause(source[0]);
break;
}
} catch (IOException e) {
System.exit(1);
}
}
}
}
這裏說明一些需要注意的地方
首先是JOAL依賴jar包的下載地址,這裏給出:
http://jogamp.org/deployment/jogamp-current/archive/我下載的是全平臺版本(all-platform)
之後是實例項目所依賴的最小項是哪些,筆者經過幾次組合後確定了兩個必須的jar包爲:joal.jar和gluegen-rt.jar
在調試音頻時我發現,音頻的播放沒有在JVM中創建新的線程:
至少不用再擔心其與JVM內線程的安全問題了。
最後說句無關的,這個作者在文末冷不丁地來了一句黑客語,我不知道他出於什麼目的提到這句話,但這句話顯然讓一大批機翻暴漏了,我也是Google查了一下才知道是什麼意思。