|
Openal教程(五)
源共享缓冲区
在这一章中,我们将讲解如何在你的缓冲区中共享多个源。这是个非常
合理,自然的步筹,非常的容易。你完全可以跳过这章。但对于愿意读
这一章的朋友,你将发现他非常有趣。我们将准备好ALC层以便我们能
用第四章的知识。
让我们开始吧,在这一章中,我们将用的矢量来自标准模板库,因此,确定
你是否安装了他,最好还有一些关于他的知识。在这一章中,我不会讲
STL。
// 表明缓冲区.
#define THUNDER 0
#define WATERDROP 1
#define STREAM 2
#define RAIN 3
#define CHIMES 4
#define OCEAN 5
#define NUM_BUFFERS 6
// 存贮声音数据.
ALuint Buffers[NUM_BUFFERS];
// 播放多个声音的源的矢量表
vector<ALuint> Sources;
首先,我写出了我们用于表明缓冲区数组的一些指令。我们将用几个WAV
文件,因此我们需要几个缓冲区。我们将用一个STL矢量代替用于存贮源
的一个数组。我们能做这些是因为他让我们能有一个源的动态数。我们能
一直添加源到场景,直到OPENAL脱离他们运行。
ALboolean InitOpenAL()
{
ALCdevice* pDevice;
ALCcontext* pContext;
ALCubyte* deviceSpecifier;
ALCubyte deviceName[] = "DirectSound3D";
// 得到设备句柄
pDevice = alcOpenDevice(deviceName);
// 得到设备说明.
deviceSpecifier = alcGetString(pDevice, ALC_DEVICE_SPECIFIER);
printf("Using device '%s'.\n", szDeviceSpecifier);
// 建立声音文本描述.
pContext = alcCreateContext(pDevice, NULL);
// 设置行为文本描述.
alcMakeContextCurrent(pContext);
// 检查错误.
if (alcGetError() != ALC_NO_ERROR)
return AL_FALSE;
return AL_TRUE;
}
这是来自上一章的代码。首先,我们得到 "DirectSound3D"设备的句柄,
然后获得用于程序的表明文本描述。
这个文本描述设置当前,函数将检查在我们返回成功前,是否出错。
void ExitOpenAL()
{
ALCcontext* pCurContext;
ALCdevice* pCurDevice;
// 得到当前文本描述
pCurContext = alcGetCurrentContext();
// 得到用于当前文本描述的设备?
pCurDevice = alcGetContextsDevice(pCurContext);
// 重置当前文本描述为NULL
alcMakeContextCurrent(NULL);
//释放文本描述和设备
alcDestroyContext(pCurContext);
alcCloseDevice(pCurDevice);
}
我们用和释放的文本描述和设备将收回。另外,在OPENAL暂停程序时,设置
当前文本描述为NULL。但是这些都不可预料。如果你用了多个文本描述,
你也许需要更好的方法来做这些事。我将介绍一些比较好的方法。
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/thunder.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffers[THUNDER], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/waterdrop.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffers[WATERDROP], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/stream.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffers[STREAM], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/rain.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffers[RAIN], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/ocean.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffers[OCEAN], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
alutLoadWAVFile("wavdata/chimes.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffers[CHIMES], format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
// 错误检测
if (alGetError() != AL_NO_ERROR)
return AL_FALSE;
return AL_TRUE;
}
在这个函数中,我将移动产生源,这是因为我们将一个一个的初始化。
void AddSource(ALint type)
{
ALuint source;
alGenSources(1, &source);
if (alGetError() != AL_NO_ERROR)
{
printf("Error generating audio source.");
exit(-1);
}
alSourcei (source, AL_BUFFER, Buffers[type]);
alSourcef (source, AL_PITCH, 1.0 );
alSourcef (source, AL_GAIN, 1.0 );
alSourcefv(source, AL_POSITION, SourcePos );
alSourcefv(source, AL_VELOCITY, SourceVel );
alSourcei (source, AL_LOOPING, AL_TRUE );
alSourcePlay(source);
Sources.push_back(source);
}
这个函数将产生源,他将为我们载入的缓冲区中的一个产生一个源。用
‘TYPE’表示缓冲区,我们文章开始建立的指令将做这些事情。然后做
错误检测,确定源能播放。如果源不能将退出。
void KillALData()
{
for (vector<ALuint>::iterator iter = Sources.begin(); iter != Sources.end(); ++iter)
alDeleteSources(1, iter);
Sources.clear();
alDeleteBuffers(NUM_BUFFERS, Buffers);
ExitOpenAL();
}
这个函数将修改STL表。我们不得不删除每个源并且清除表上的内容。
ALubyte c = ' ';
while (c != 'q')
{
c = getche();
switch (c)
{
case 'w': AddSource(WATERDROP); break;
case 't': AddSource(THUNDER); break;
case 's': AddSource(STREAM); break;
case 'r': AddSource(RAIN); break;
case 'o': AddSource(OCEAN); break;
case 'c': AddSource(CHIMES); break;
};
}
这是程序的主函数,他等待键盘输入,建立源,播放声音。
The program can be expanded for using more wav files, and have the added feature of placing
the sources around the scene in arbitrary positions. You could even allow for sources to
play with a given frequency rather than have them loop. However this would require GUI routines
that go beyond the scope of the tutorial. A full featured "Weathering Engine" would be a nifty
program to make though. ;)
如果大家有什么问题,请告诉我e-mail uyunfei12@mail.china.com.
|
|