【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2557|回复: 1

openal教程

[复制链接]
发表于 2006-11-9 16:32:46 | 显示全部楼层 |阅读模式

发布时间:2005-11-10 11:32:12  作者:antking

简介
欢迎来到OPENAL的世界!OPENAL一直在不断的创新,几乎没有一个API能达到
她的全部潜能。一个很大的原因是因为hardware加速建立在特殊的版卡上。然而,
Creative Labs是APENAL的主要支持者,同时也是最大声卡厂商之一。OPENAL的另
一个主要支持者LOKI。
OPENAL不是商业产品,那样做限制了她的发展。我只知道再PC游戏中用OPENAL。
OPENAL有许多的潜能,有许多的声音库工作在最地层的hardware上。但OPENAL的
设计者经过无数的测试使她成为一个高级的API。她的风格是自由的,不同的编码
风格和hardware部件将充分运用她的功能。有OPENGL编程精练的人将很快掌握OPEN
AL。OPENAL有建立3D环境音效的能力。
OPENAL是very cool,她是一个非常清晰的API并且能熔入你的代码。你将做出
很COOL的音效,下面让我们进入COOL COOL的OPENAL世界。
#include <conio.h>
#include <stdlib.h>
#include <al/al.h>
#include <al/alc.h>
#include <al/alu.h>
#include <al/alut.h>
你会发现再OPENAL头和OPENGL头的定义上有许多的相似之处。除了“al.h","al
u.h","alut.h"与”gl.h","glu.h","glut.h"相似,还增加了一个"alc.h".ALC(
AUDIO LIBRARY CONTEXT)处理声音通过不同的平台,她也处理你在几个窗口下共
享设备的环境。
// 存储声音数据
ALuint Buffer;

// 用于播放声音
ALuint Source;
这是程序处理结构的初始化。在OPENAL中三种不同的结构,所有关于声音播放和
声音数据存储在一个内存中,源(source)是指向放声音的空间。明白源是非常
的重要。源只播放内存中的背景声音数据。源也给出了特殊的属性如位置和速度。
第三个对象是听者,用户就是那唯一的听者。听者属性属于源属性,决定如何
听声音。例如,不同位置将决定声音的速度。
// 源声音的位置
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };

// 源声音的速度
ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };


// 听者的位置
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 };
在上面的代码中,我们定义了源和听者对象的位置和速度。这些数组是基于笛
卡儿坐标的矢量。你能很容易用结构或类做相同的事情。
ALboolean LoadALData()
{
// 载入变量.

ALenum format;
ALsizei size;
ALvoid* data;
ALsizei freq;
ALboolean loop;
在这里我们建立一个函数用于从一个文件中载入声音数据。变量用于存储适合
我们的ALUT信息。
// 载入WAV数据
alGenBuffers(1, &Buffer);
if (alGetError() != AL_NO_ERROR)
return AL_FALSE;

alutLoadWAVFile("wavdata/FancyPants.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffer, format, data, size, freq);
alutUnloadWAV(format, data, size, freq);
函数alGenBufers用于建立对象内存并把他们存储在我们定义的变量中。然后判断
数据是否存储。
ALUT库为我们打开文件,提供我们建立内存所需的信息,并且在我们归属所有
数据到内存后,她将处理这些数据。
// 捆绑源
alGenSources(1, &Source);

if (alGetError() != AL_NO_ERROR)
return AL_FALSE;

alSourcei (Source, AL_BUFFER, Buffer );
alSourcef (Source, AL_PITCH, 1.0f );
alSourcef (Source, AL_GAIN, 1.0f );
alSourcefv(Source, AL_POSITION, SourcePos);
alSourcefv(Source, AL_VELOCITY, SourceVel);
alSourcei (Source, AL_LOOPING, loop );
我们用建立内存对象的方法建立了源对象。然后,我们定义源属性用于录放。
最重要的属性是她用的内存。这告诉源用于录放。因此,我们只有捆绑她。同时,
我们也告诉她我们定义的源位置和速度。
// 做错误检测并返回
if (alGetError() == AL_NO_ERROR)
return AL_TRUE;

return AL_FALSE;
在函数的结尾,我们将做更多的检测,以确定她的正确。
void SetListenervalues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION, ListenerOri);
}
我们建立一个函数用于更新听者速度。
void KillALData()
{
alDeleteBuffers(1, &Buffer);
alDeleteSources(1, &Source);
alutExit();
}
这是一个关闭函数,用于释放内存和音频设备。
int main(int argc, char *argv[])
{
// 初始OPENAL并清错误字节

alutInit(&argc, argv);
alGetError();
函数alutInit将安装ALC需要的东西。ALUT通过ALC并设置她为当前建立OPENAL
环境描述。在WINDOWS平台上初始DIRECTSOUND。然后用‘GLGETERROR’检测错误。
// 载入WAV数据
if (LoadALData() == AL_FALSE)
return -1;

SetListenervalues();

// 设置退出函数
atexit(KillALData);
我们将检测WAV文件是否正确载入。如果没有退出程序。
正确后,更新听者参数,最后退出。
ALubyte c = ' ';

while (c != 'q')
{
c = getche();

switch (c)
{
// Pressing 'p' will begin playing the sample.
case 'p': alSourcePlay(Source); break;

// Pressing 's' will stop the sample from playing.
case 's': alSourceStop(Source); break;

// Pressing 'h' will pause (hold) the sample.
case 'h': alSourcePause(Source); break;
};
}

return 0;
}
This is the interesting part of the tutorial. It's a very basic loop that lets us control the playback of the audio sample. Pressing 'p' will replay the sample, pressing 's' will stop the sample, and pressing 'h' will pause the sample. Pressing 'q' will exit the program.

Well there it is. Your first delve into OpenAL. I hope it was made simple enough for you. It may have been a little too simple for the 1337 h4X0r, but we all got to start somewhere. Things will get more advanced as we go along.

Download the Dev-C++ source and project file

如果大家有什么问题,请告诉我e-mailuyunfei12@mail.china.com.

 楼主| 发表于 2006-11-9 16:55:53 | 显示全部楼层

openal教程(二)
循环和消退
希望你觉得上一章有用,这一章将更容易。
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <al/al.h>
#include <al/alc.h>
#include <al/alu.h>
#include <al/alut.c>

// 存储声音数据.
ALuint Buffer;

// 用于播放声音.
ALuint Source;

// 源声音的位置.
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };

// 源声音的速度.
ALfloat SourceVel[] = { 0.0, 0.0, 0.1 };

// 听者的位置.
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 };
这一章与上一章唯一的不同是源速度的改变,他的‘Z’现在是0.1.
ALboolean LoadALData()
{
// 载入变量
ALenum format;
ALsizei size;
ALvoid* data;
ALsizei freq;
ALboolean loop;

// 载入WAV数据.

alGenBuffers(1, &Buffer);

if (alGetError() != AL_NO_ERROR)
return AL_FALSE;

alutLoadWAVFile("wavdata/Footsteps.wav", &format, &data, &size, &freq, &loop);
alBufferData(Buffer, format, data, size, freq);
alutUnloadWAV(format, data, size, freq);

// 捆绑源

alGenSources(1, &Source);

if (alGetError() != AL_NO_ERROR)
return AL_FALSE;

alSourcei (Source, AL_BUFFER, Buffer );
alSourcef (Source, AL_PITCH, 1.0f );
alSourcef (Source, AL_GAIN, 1.0f );
alSourcefv(Source, AL_POSITION, SourcePos);
alSourcefv(Source, AL_VELOCITY, SourceVel);
alSourcei (Source, AL_LOOPING, AL_TRUE );

// 做错误检测并返回

if (alGetError() != AL_NO_ERROR)
return AL_FALSE;

return AL_TRUE;
}
在这一节中有两处改变,首先是导入“FOOTSTES。WAV”,设置源‘AL_LOOPING’
为‘AL_TRUE’。这意味着源播放直到停止时结束。他将不断的循环播放。
void SetListenervalues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION, ListenerOri);
}

void KillALData()
{
alDeleteBuffers(1, &Buffer);
alDeleteSources(1, &Source);
alutExit();
}
这里没有改变。
int main(int argc, char *argv[])
{
// 初始OPENAL并清错误字节
alutInit(NULL,0);
alGetError();

// 载入WAV数据.
if (LoadALData() == AL_FALSE)
return 0;

SetListenervalues();

// 设置退出函数.
atexit(KillALData);

// 开始源的播放.
alSourcePlay(Source);

//循环
ALint time = 0;
ALint elapse = 0;

while (!kbhit())
{
elapse += clock() - time;
time += elapse;

if (elapse > 50)
{
elapse = 0;

SourcePos[0] += SourceVel[0];
SourcePos[1] += SourceVel[1];
SourcePos[2] += SourceVel[2];

alSourcefv(Source, AL_POSITION, SourcePos);
}
}


return 0;
}
这里唯一的改变是增加了一个循环。他将代替播放和停止按钮。
We do this by slowly incrementing the position by it's velocity over
time. The time is sampled by checking the system clock which gives
us a tick count. It shouldn't be necessary to change this, but if the
audio clip fades too fast you might want to change 50 to some higher n
umber. Pressing any key will end the loop
如果大家有什么问题,请告诉我e-mailuyunfei12@mail.china.com

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 03:58

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表