openal教程.docx
《openal教程.docx》由会员分享,可在线阅读,更多相关《openal教程.docx(33页珍藏版)》请在冰豆网上搜索。
openal教程
openal教程
(一)
简介
欢迎来到OPENAL的世界!
OPENAL一直在不断的创新,几乎没有一个API能达到
她的全部潜能。
一个很大的原因是因为hardware加速建立在特殊的版卡上。
然而,
CreativeLabs是APENAL的主要支持者,同时也是最大声卡厂商之一。
OPENAL的另
一个主要支持者LOKI。
OPENAL不是商业产品,那样做限制了她的发展。
我只知道在PC游戏中用OPENAL。
OPENAL有许多的潜能,有许多的声音库工作在最底层的hardware上。
但OPENAL的
设计者经过无数的测试使她成为一个高级的API。
她的风格是自由的,不同的编码
风格和hardware部件将充分运用她的功能。
有OPENGL编程精练的人将很快掌握OPEN
AL。
OPENAL有建立3D环境音效的能力。
OPENAL是verycool,她是一个非常清晰的API并且能融入你的代码。
你将做出
很COOL的音效,下面让我们进入COOLCOOL的OPENAL世界。
#include
#include
#include
#include
#include
#include
你会发现再OPENAL头和OPENGL头的定义上有许多的相似之处。
除了“al.h","al
u.h","alut.h"与”gl.h","glu.h","glut.h"相似,还增加了一个"alc.h".ALC(
AUDIOLIBRARYCONTEXT)处理声音通过不同的平台,她也处理你在几个窗口下共
享设备的环境。
//存储声音数据
ALuintBuffer;
//用于播放声音
ALuintSource;
这是程序处理结构的初始化。
在OPENAL中三种不同的结构,所有关于声音播放和
声音数据存储在一个内存中,源(source)是指向放声音的空间。
明白源是非常
的重要。
源只播放内存中的背景声音数据。
源也给出了特殊的属性如位置和速度。
第三个对象是听者,用户就是那唯一的听者。
听者属性属于源属性,决定如何
听声音。
例如,不同位置将决定声音的速度。
//源声音的位置
ALfloatSourcePos[]={0.0,0.0,0.0};
//源声音的速度
ALfloatSourceVel[]={0.0,0.0,0.0};
//听者的位置
ALfloatListenerPos[]={0.0,0.0,0.0};
//听者的速度
ALfloatListenerVel[]={0.0,0.0,0.0};
//听者的方向(first3elementsare"at",second3are"up")
ALfloatListenerOri[]={0.0,0.0,-1.0, 0.0,1.0,0.0};
在上面的代码中,我们定义了源和听者对象的位置和速度。
这些数组是基于笛
卡儿坐标的矢量。
你能很容易用结构或类做相同的事情。
ALbooleanLoadALData()
{
//载入变量.
ALenumformat;
ALsizeisize;
ALvoid*data;
ALsizeifreq;
ALbooleanloop;
在这里我们建立一个函数用于从一个文件中载入声音数据。
变量用于存储适合
我们的ALUT信息。
//载入WAV数据
alGenBuffers(1,&Buffer);
if(alGetError()!
=AL_NO_ERROR)
returnAL_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)
returnAL_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)
returnAL_TRUE;
returnAL_FALSE;
在函数的结尾,我们将做更多的检测,以确定她的正确。
voidSetListenervalues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION,ListenerOri);
}
我们建立一个函数用于更新听者速度。
voidKillALData()
{
alDeleteBuffers(1,&Buffer);
alDeleteSources(1,&Source);
alutExit();
}
这是一个关闭函数,用于释放内存和音频设备。
intmain(intargc,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文件是否正确载入。
如果没有退出程序。
正确后,更新听者参数,最后退出。
ALubytec='';
while(c!
='q')
{
c=getche();
switch(c)
{
//Pressing'p'willbeginplayingthesample.
case'p':
alSourcePlay(Source);break;
//Pressing's'willstopthesamplefromplaying.
case's':
alSourceStop(Source);break;
//Pressing'h'willpause(hold)thesample.
case'h':
alSourcePause(Source);break;
};
}
return0;
}
openal教程
(二)
循环和消退
希望你觉得上一章有用,这一章将更容易。
#include
#include
#include
#include
#include
#include
#include
//存储声音数据.
ALuintBuffer;
//用于播放声音.
ALuintSource;
// 源声音的位置.
ALfloatSourcePos[]={0.0,0.0,0.0};
//源声音的速度.
ALfloatSourceVel[]={0.0,0.0,0.1};
//听者的位置.
ALfloatListenerPos[]={0.0,0.0,0.0};
//听者的速度
ALfloatListenerVel[]={0.0,0.0,0.0};
//听者的方向(first3elementsare"at",second3are"up")
ALfloatListenerOri[]={0.0,0.0,-1.0, 0.0,1.0,0.0};
这一章与上一章唯一的不同是源速度的改变,他的‘Z’现在是0.1.
ALbooleanLoadALData()
{
//载入变量
ALenumformat;
ALsizeisize;
ALvoid*data;
ALsizeifreq;
ALbooleanloop;
//载入WAV数据.
alGenBuffers(1,&Buffer);
if(alGetError()!
=AL_NO_ERROR)
returnAL_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)
returnAL_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)
returnAL_FALSE;
returnAL_TRUE;
}
在这一节中有两处改变,首先是导入“FOOTSTES。
WAV”,设置源‘AL_LOOPING’
为‘AL_TRUE’。
这意味着源播放直到停止时结束。
他将不断的循环播放。
voidSetListenervalues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION,ListenerOri);
}
voidKillALData()
{
alDeleteBuffers(1,&Buffer);
alDeleteSources(1,&Source);
alutExit();
}
这里没有改变。
intmain(intargc,char*argv[])
{
// 初始OPENAL并清错误字节
alutInit(NULL,0);
alGetError();
//载入WAV数据.
if(LoadALData()==AL_FALSE)
return0;
SetListenervalues();
// 设置退出函数.
atexit(KillALData);
//开始源的播放.
alSourcePlay(Source);
//循环
ALinttime=0;
ALintelapse=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);
}
}
return0;
}
openal教程(三)
多源
你好,在这一章中,我们将在上一章的例程中加入一些元素,使他能同时
播放超过一种的音乐。
通常在一个优秀的游戏中有各种不同的音夹(clip),这是怎样实现的呢?
下面将介绍。
#include
#include
#include
#include
#include
#include
#include
//我们需要的最大的数据缓冲.
#defineNUM_BUFFERS3
//我们需要放三种声音.
#defineNUM_SOURCES3
//缓冲和源标志.
#defineBATTLE 0
#defineGUN1 1
#defineGUN2 2
//存储声音数据.
ALuintBuffers[NUM_BUFFERS];
//用于播放声音.
ALuintSources[NUM_SOURCES];
//源声音的位置.
ALfloatSourcesPos[NUM_SOURCES][3];
//源声音的速度.
ALfloatSourcesVel[NUM_SOURCES][3];
//听者的位置.
ALfloatListenerPos[]={0.0,0.0,0.0};
//听者的速度.
ALfloatListenerVel[]={0.0,0.0,0.0};
//听者的方向(first3elementsare"at",second 3are"up")
ALfloatListenerOri[]={0.0,0.0,-1.0,0.0,1.0,0.0};
在这一章中,唯一的不同是多了3种将导入Openal系统的不同的声音效果。
ALbooleanLoadALData()
{
//载入变量.
ALenumformat;
ALsizeisize;
ALvoid*data;
ALsizeifreq;
ALbooleanloop;
//载入WAV数据.
alGenBuffers(NUM_BUFFERS,Buffers);
if(alGetError()!
=AL_NO_ERROR)
returnAL_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)
returnAL_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)
returnAL_FALSE;
returnAL_TRUE;
}
首先,我们导入文件数据到3个缓冲区,然后把3个缓冲区和3个源锁在
一起。
唯一的不同是文件“battle.wav”在不停止时循环。
voidSetListenervalues()
{