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 }; // Position of the listener. static float[] listenerPos = { 0.0f,0.0f }; // Velocity of the listener. static float[] listenerVel = { 0.0f,0.0f }; // Orientation of the listener. (first 3 elements are "at",second 3 are // "up") static float[] listenerOri = { 0.0f,-1.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,0); al.alDeleteSources(1,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查了一下才知道是什么意思。