Chinaunix首页 | 论坛 | 博客
  • 博客访问: 283661
  • 博文数量: 48
  • 博客积分: 2931
  • 博客等级: 少校
  • 技术积分: 720
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-19 22:12
文章分类

全部博文(48)

文章存档

2012年(1)

2011年(6)

2010年(33)

2009年(5)

2008年(3)

我的朋友

分类:

2010-01-05 13:01:44

OpenAL教程(五)

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 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::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;
        };
    }
这是程序的主函数,他等待键盘输入,建立源,播放声音。

阅读(1261) | 评论(0) | 转发(0) |
0

上一篇:OpenAL教程(四)

下一篇:OpenAL教程(六)

给主人留下些什么吧!~~