/*
* 游戏离不开美妙的声音特效,强大的LWJGL已经提供了Java与OpenAL的绑定
*/
多源
你好,在这一章中,我们将在上一章的例程中加入一些元素,使他能同时播放超过一种的音乐。通常在一个优秀的游戏中有各种不同的音夹(clip),这是怎样实现的呢?下面将介绍。
#include
#include
#include
#include
#include
#include
#include // 我们需要的最大的数据缓冲.
#define NUM_BUFFERS 3 // 我们需要放三种声音.
#define NUM_SOURCES 3 // 缓冲和源标志.
#define BATTLE 0
#define GUN1 1
#define GUN2 2 // 存储声音数据.
ALuint Buffers[NUM_BUFFERS]; // 用于播放声音.
ALuint Sources[NUM_SOURCES]; // 源声音的位置.
ALfloat SourcesPos[NUM_SOURCES][3]; // 源声音的速度.
ALfloat SourcesVel[NUM_SOURCES][3];
// 听者的位置.
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 }; // 听者的速度.
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 }; // 听者的方向 (first 3
elements are "at", second 3 are "up")
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
在这一章中,唯一的不同是多了3种将导入Openal系统的不同的声音效果。
ALboolean LoadALData()
{
// 载入变量. ALenum format;
ALsizei size;
ALvoid* data;
ALsizei freq;
ALboolean loop; // 载入WAV数据. alGenBuffers(NUM_BUFFERS, Buffers);
if (alGetError() != AL_NO_ERROR)
return AL_FALSE; alutLoadWAVFile("wavdata/Battle.wav", &format,
&data, &size, &freq, &loop);
alBufferData(Buffers[BATTLE], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/Gun1.wav", &format, &data,
&size, &freq, &loop);
alBufferData(Buffers[GUN1], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/Gun2.wav", &format, &data,
&size, &freq, &loop);
alBufferData(Buffers[GUN2], format, data, size, freq);
alutUnloadWAV(format, data, size, freq); // 捆绑源.
alGenSources(NUM_SOURCES, Sources); if (alGetError() !=
AL_NO_ERROR)
return AL_FALSE; alSourcei (Sources[BATTLE], AL_BUFFER,
Buffers[BATTLE] );
alSourcef (Sources[BATTLE], AL_PITCH, 1.0 );
alSourcef (Sources[BATTLE], AL_GAIN, 1.0 );
alSourcefv(Sources[BATTLE], AL_POSITION, SourcePos[BATTLE]);
alSourcefv(Sources[BATTLE], AL_VELOCITY, SourceVel[BATTLE]);
alSourcei (Sources[BATTLE], AL_LOOPING, AL_TRUE ); alSourcei
(Sources[GUN1], AL_BUFFER, Buffers[GUN1] );
alSourcef (Sources[GUN1], AL_PITCH, 1.0 );
alSourcef (Sources[GUN1], AL_GAIN, 1.0 );
alSourcefv(Sources[GUN1], AL_POSITION, SourcePos[GUN1]);
alSourcefv(Sources[GUN1], AL_VELOCITY, SourceVel[GUN1]);
alSourcei (Sources[GUN1], AL_LOOPING, AL_FALSE ); alSourcei
(Sources[GUN2], AL_BUFFER, Buffers[GUN2] );
alSourcef (Sources[GUN2], AL_PITCH, 1.0 );
alSourcef (Sources[GUN2], AL_GAIN, 1.0 );
alSourcefv(Sources[GUN2], AL_POSITION, SourcePos[GUN2]);
alSourcefv(Sources[GUN2], AL_VELOCITY, SourceVel[GUN2]);
alSourcei (Sources[GUN2], AL_LOOPING, AL_FALSE ); //
做错误检测并返回 if( alGetError() != AL_NO_ERROR)
return AL_FALSE; return AL_TRUE;
}
首先,我们导入文件数据到3个缓冲区,然后把3个缓冲区和3个源锁在
一起。唯一的不同是文件“battle.wav”在不停止时循环。
void SetListenervalues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION, ListenerOri);
} void KillALData()
{
alDeleteBuffers(NUM_BUFFERS, &Buffers[0]);
alDeleteSources(NUM_SOURCES, &Sources[0]);
alutExit();
}
在这段代码中,我们没有改变。
int main(int argc, char *argv[])
{
// Initialize OpenAL and clear the error bit.
alutInit(NULL, 0);
alGetError(); // Load the wav data.
if (LoadALData() == AL_FALSE)
return 0; SetListenervalues(); // Setup an exit procedure.
atexit(KillALData); // Begin the battle sample to play.
alSourcePlay(Sources[BATTLE]); // Go through all the sources and
check that they are playing.
// Skip the first source because it is looping anyway (will always
be playing).
ALint play; while (!kbhit())
{
for (int i = 1; i < NUM_SOURCES; i++)
{
alGetSourcei(Sources[i], AL_SOURCE_STATE, &play); if (play !=
AL_PLAYING)
{
// Pick a random position around the listener to play the source.
double theta = (double) (rand() % 360) * 3.14 / 180.0;
SourcePos[i][0] = -float(cos(theta));
SourcePos[i][1] = -float(rand()%2);
SourcePos[i][2] = -float(sin(theta)); alSourcefv(Sources[i],
AL_POSITION, SourcePos[i] ); alSourcePlay(Sourcev[i]);
}
}
} return 0;
}
这段是这篇文章最有趣的地方。我们在这里将播放。如果他不播放,我们将在3D空间中选一个点播放(点击)。
And bang! We are done. As most of you have probably seen, you don't
have to do anything special to play more than one source at a time.
OpenAL will handle all the mixing features to get the sounds right
for their respective distances and velocities. And when it comes
right down to it, isn't that the beauty of OpenAL? You know that
was a lot easier than I thought. I don't know why I waited so long
to write it. Anyway, if anyone reading wants to see something
specific in future tutorials (not necessarily pertaining to OpenAL,
I have quite an extensive knowledge base) drop me a line at
lightonthewater@hotmail.com I plan to do tutorials on sharing
buffers and the Doppler effect in some later tutorial unless there
is request for something else. Have fun with the code!