分类:
2010-01-05 13:03:00
ALuint LoadALBuffer(string path);
/*
* 1) 建立缓冲区
* 2) 导入WAV文件
* 3) 返回缓冲区ID
*/
ALuint GetLoadedALBuffer(string path);
/*
* 1) 检测文件是否载入
* 2) 如果载入,返回缓冲区ID
* 3) 如果失败,重新载入并返回缓冲区ID
*/
ALuint LoadALSample(string path, bool loop);
/*
* 1) 建立源
* 2) 调用‘GtLoadedALBuffer' 中的’PATH‘加载文件?
* 3)返回源ID
*/
void KillALLoadedData();
/*
* 1)释放数据?
*/
bool LoadALData();
/*
* 1) 载入所有的源和缓冲区
*/
void KillALData();
/*
* 1) 释放所有的缓冲区
* 2) 释放所有的源
*/
vector
vector
vector
看一下这个函数,想一下他做什么。我们试着建立一个关于缓冲区和源
的系统。我们能调用来自文件的源并且系统能处理缓冲区的建立,因此,
我们不用复制缓冲区。系统将处理缓冲区并且将有效的处理资源。
string GetALErrorString(ALenum err)
{
switch(err)
{
case AL_NO_ERROR:
return string("AL_NO_ERROR");
break;
case AL_INVALID_NAME:
return string("AL_INVALID_NAME");
break;
case AL_INVALID_ENUM:
return string("AL_INVALID_ENUM");
break;
case AL_INVALID_value:
return string("AL_INVALID_value");
break;
case AL_INVALID_OPERATION:
return string("AL_INVALID_OPERATION");
break;
case AL_OUT_OF_MEMORY:
return string("AL_OUT_OF_MEMORY");
break;
};
}
函数的功能是转换错误代码为字符。OPENAL SDK说返回'AL_OUT_OF_MEMORY'
是错误的,我们应认真对待所有错误,使我们的代码用最新的版本处理
数据。
string GetALCErrorString(ALenum err)
{
switch(err)
{
case ALC_NO_ERROR:
return string("AL_NO_ERROR");
break;
case ALC_INVALID_DEVICE:
return string("ALC_INVALID_DEVICE");
break;
case ALC_INVALID_CONTEXT:
return string("ALC_INVALID_CONTEXT");
break;
case ALC_INVALID_ENUM:
return string("ALC_INVALID_ENUM");
break;
case ALC_INVALID_value:
return string("ALC_INVALID_value");
break;
case ALC_OUT_OF_MEMORY:
return string("ALC_OUT_OF_MEMORY");
break;
};
}
这个函数的功能是说明ALC错误。OPENAL和ALC共享ID,但是他们在一些功能上
不相等。
函数 'alGetError'应注意:OPENAL SDK定义一次只能得到一个错误。
当函数被调用时,他返回他得到的第一个错误,并且清错误为'AL_NO_ERROR'
ALuint LoadALBuffer(string path)
{
// Variables to store da
ALenum format;
ALsizei size;
ALvoid* da
ALsizei freq;
ALboolean loop;
// 缓冲区ID和错误检测变量
ALuint buffer;
ALenum result;
// 产生缓冲区,看他是否成功建立.
alGenBuffers(1, &buffer);
if ((result = alGetError()) != AL_NO_ERROR)
throw GetALErrorString(result);
// 读WAV数据,检测是否成功。
alutLoadWAVFile(szFilePath, &format, &da
if ((result = alGetError()) != AL_NO_ERROR)
throw GetALErrorString(result);
// 装载WAV数据,检测是否成功
alBufferData(buffer, format, da
if ((result = alGetError()) != AL_NO_ERROR)
throw GetALErrorString(result);
// 出去临时数据
alutUnloadWAV(format, da
if ((result = alGetError()) != AL_NO_ERROR)
throw GetALErrorString(result);
//返回缓冲区ID
return buffer;
}
在导入数据时,我们做了错误检测。没有任何错误将通过。当数据导入时,
没有足够的内存,WAV文件可能不退出,或者OPENAL函数中的错误数据
将产生错误。
ALuint GetLoadedALBuffer(string path)
{
int count = 0; // 'count' 表明缓冲区列表
ALuint buffer; // 用于导入缓冲区的缓冲区ID
// 重复列表中的每个文件
for(vector
{
// 如果文件已经导入,返回他的缓冲区ID.
if(*iter == path)
return Buffers[count];
}
// 如果文件是新的,我们将为他建立缓冲区.
buffer = LoadALBuffer(path);
// 添加缓冲区到列表,记录他已添加.
Buffers.push_back(buffer);
LoadedFiles.push_back(path);
return buffer;
}
人们的麻烦通常在这里,但他确实不是很复杂。我们通过包含文件路径的列表
来检索。如果其中一个符合要求,我们直接返回他的ID到缓冲区。我们通过
这个函数导入我们的文件,这样就避免了复制时的浪费。每个文件应该保证
在自己的列表中。'Buffers'表类士于'LoadedFiles'表。
ALuint LoadALSample(string path, bool loop)
{
ALuint source;
ALuint buffer;
ALenum result;
// 得到文件缓冲区ID
buffer = GetLoadedALBuffer(path);
// 产生源.
alGenSources(1 &source);
if ((result = alGetError()) != AL_NO_ERROR)
throw GetALErrorString(result);
// 设置源属性.
alSourcei (source, AL_BUFFER, buffer );
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, loop );
// 保存源ID.
Sources.push_back(source);
// 返回源ID.
return source;
}
现在我们已经建立处理缓冲区的系统,我们需要得到源的伸展。在这里,我们
得到了导入文件的缓冲区ID。这个缓冲区是一个新源,我们保存他并返回。
void KillALLoadedData()
{
LoadedFiles.clear();
}
'gLoadedFilesv'存储在导入缓冲区的WAV文件的路径下,我们要处理他。
// 源ID's.
ALuint phaser1;
ALuint phaser2;
void LoadALData()
{
// 你的应用在这里,不用担心缓冲区。
phaser1 = LoadALSample("wavdata/phaser.wav", false);
phaser2 = LoadALSample("wavdata/phaser.wav", true);
KillLoadedALData();
}
他表示用于程序的所有的WAV应用的程序。我们能调用导入相同的WAV文件到不同的源,
'phaser.wav' 的缓冲区建立了一次,'gPhaser1' and 'gPhaser2' 用于背景
音乐的缓冲区。不用处理缓冲区因为系统会自动处理。
void KillALData()
{
// 释放所有的缓冲区数据.
for (vector
alDeleteBuffers(1, iter);
// 释放所有的源数据.
for (vector
alDeleteBuffers(1, iter);
// 清除列表.
Buffers.clear();
Sources.clear();
}
我们已完成了前述的工作。然后就是释放他们。
try
{
InitOpenAL();