OpenAL Lesson 1: Simple Static Sound(转载)

转自http://www.devmaster.net/articles/openal-tutorials/lesson1.php

Welcome to the exciting world of OpenAL! OpenAL is still in a stage of growth, and even though there is an ever larger following to the API it still hasn't reached it's full potential. One of the big reasons for this is that there is still not yet hardware acceleration built in for specific cards. However, Creative Labs is a major contributor to the OpenAL project and also happens to be one of the largest soundcard manufacturers. So there is a promise of hardware accelerated features in the near future. OpenAL's only other major contributor, Loki, has gone the way of the dinosaur. So the future of OpenAL on Linux platforms is uncertain. You can still obtain the Linux binaries on some more obscure websites.

OpenAL has also not been seen in many major commercial products, which may have also hurt it's growth. As far as I know the only pc game to use OpenAL has been Metal Gear 2 (although recently I've discovered that Unreal 2 does as well). The popular modeling program, Blender3D, was also known to use OpenAL for all it's audio playback. Aside from these however the only other OpenAL uses have been in the sdk examples and a few obscure tutorials on the internet.

But lets face it, OpenAL has a lot of potential. There are many other audio libraries that claim to work with the hardware on a lower level (and this may be true), but the designers of OpenAL did several things in it's design which make it a superior API. First of all they emulated the OpenGL API which is one of the best ever designed. The API style is flexible, so different coding methods and hardware implementations will take advantage of this. People who have had a lot of experience with OpenGL will be able to pick up OpenAL quite fast. OpenAL also has the advantage of creating 3D surround sound which a lot of other API's cannot boast. On top of all of that it also has the ability to extend itself into EAX and AC3 flawlessly. To my knowledge no other audio library has that capability.

If you still haven't found a reason here to use OpenAL then here's another. It's just cool. It's a nice looking API and will integrate well into your code. You will be able to do many cool sound effects with it. But before we do that we have to learn the basics.

So let's get coding!

 
 
#include  < conio.h >
#include 
< stdlib.h >
#include 
< al / al.h >
#include 
< al / alc.h >
#include 
< al / alu.h >
#include 
< al / alut.h >

You will notice there are similarities between the OpenAL headers and the OpenGL headers. There is an "al.h", "alu.h", and "alut.h" just like "gl.h", "glu.h", and "glut.h", but there is also an "alc.h". The Alc stands for Audio Library Context and it handles the sound devices across different platforms. It also handles situations where you would want to share a device over several windows. If you want to liken Alc to anything in OpenGL, it's probably most like the wgl and glX extensions. We won't go much into Alc since the Alut library handles it internally for us, and for now we'll just let it be. We will also not use Alu very much since it only provides some math functionality which we will not need for small demo's.

 
 
//  Buffers hold sound data.
ALuint Buffer;

//  Sources are points emitting sound.
ALuint Source;

Those familiar with OpenGL know that it uses "texture objects" (or "texture names") to handle textures used by a program. OpenAL does a similar thing with audio samples. There are essentially 3 kinds of objects in OpenAL. A buffer which stores all the information about how a sound should be played and the sound data itself, and a source which is a point in space that emits a sound. It's important to understand that a source is not itself an audio sample. A source only plays back sound data from a buffer bound to it. The source is also given special properties like position and velocity.

The third object which I have not mentioned yet is the listener. There is only one listener which represents where 'you' are, the user. The listener properties along with the source properties determine how the audio sample will be heard. For example their relative positions will determine the intensity of the sound.

 
 
//  Position of the source sound.
ALfloat SourcePos[]  =   ... ;

//  Velocity of the source sound.
ALfloat SourceVel[]  =   0.00.00.0 } ;


//  Position of the listener.
ALfloat ListenerPos[]  =   0.00.00.0 } ;

//  Velocity of the listener.
ALfloat ListenerVel[]  =   0.00.00.0 } ;

//  Orientation of the listener. (first 3 elements are "at", second 3 are "up")
ALfloat ListenerOri[]  =   0.00.0-1.0,  0.01.00.0 } ;

In the above code we specify the position and velocity of the source and listener objects. These arrays are vector based Cartesian coordinates. You could easily build a structure or class to do the same thing. In this example I used arrays for simplicity.

 
 
ALboolean LoadALData()
{
    
// Variables to load into.

    ALenum format;
    ALsizei size;
    ALvoid
* data;
    ALsizei freq;
    ALboolean loop;

Here we will create a function that loads all of our sound data from a file. The variables are necessary to store some information that Alut will be giving us.

    
   
   
//  Load wav data into a buffer.
    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);

The function 'alGenBuffers' will create the buffer objects and store them in the variable we passed it. It's important to do an error check to make sure everything went smoothly. There may be a case in which OpenAL could not generate a buffer object due to a lack of memory. In this case it would set the error bit.

The Alut library is very helpful here. It opens up the file for us and gives us all the information we need to create the buffer. And after we have attached all this data to the buffer it will help use dispose of the data. It all works in a clean and efficient manner.

    
 
 
//  Bind buffer with a source.
    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     );

We generate a source object in the same manner we generated the buffer object. Then we define the source properties that it will use when it's in playback. The most important of these properties is the buffer it should use. This tells the source which audio sample to playback. In this case we only have one so we bind it. We also tell the source it's position and velocity which we defined earlier.

One more thing on 'alGenBuffers' and 'alGenSources'. In some example code I have seen these functions will return an integer value for the number of buffers/sources created. I suppose this was meant as an error checking feature that was left out in a later version. If you see this done in other code don't use it yourself. If you want to do this check, use 'alGetError' instead (like we have done above).

    
 
 
//  Do another error check and return.
     if  (alGetError()  ==  AL_NO_ERROR)
        
return  AL_TRUE;

    
return  AL_FALSE;

To end the function we just do one more check to make sure all is well, then we return success.

 
 
void  SetListenerValues()
{
    alListenerfv(AL_POSITION,    ListenerPos);
    alListenerfv(AL_VELOCITY,    ListenerVel);
    alListenerfv(AL_ORIENTATION, ListenerOri);
}

We created this function to update the listener properties.

 
 
void  KillALData()
{
    alDeleteBuffers(
1&Buffer);
    alDeleteSources(
1&Source);
    alutExit();
}

This will be our shutdown procedure. It is necessary to call this to release all the memory and audio devices that our program may be using.

 
 
int  main( int  argc,  char   * argv[])
{
    
// Initialize OpenAL and clear the error bit.

    alutInit(
&argc, argv);
    alGetError();
    The function 'alutInit' will setup everything that the Alc needs to do for us. Basically Alut creates a single OpenAL context through Alc and sets it to current. On the Windows platform it initializes DirectSound. We also do an initial call to the error function to clear it. Every time we call 'glGetError' it will reset itself to 'AL_NO_ERROR'.
//  Load the wav data.
     if  (LoadALData()  ==  AL_FALSE)
        
return   - 1 ;

    SetListenerValues();

    
//  Setup an exit procedure.
    atexit(KillALData);

We will check to see if the wav files loaded correctly. If not we must exit the program. Then we update the listener values, and finally we set our exit procedure.

    
 
 
   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. 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ALUT(OpenAL Utility Toolkit)是一个用于OpenAL的工具包,它提供了一些方便的函数来简化OpenAL的使用。下面是使用ALUT库的步骤: 1. 下载OpenAL-Soft库,可以从官网下载:https://www.openal.org/downloads/ 。 2. 下载ALUT库,可以从官网下载:https://github.com/vancegroup/freealut/releases 。 3. 解压OpenAL-Soft和ALUT库。 4. 进入OpenAL-Soft源码目录,建立build目录(如果没有),进入build目录,执行cmake ..,生成vs2019工程文件OpenAl.sln。 5. 用vs2019打开OpenAl.sln工程文件,编译64位目标文件。 6. 在你的代码中包含AL/alut.h头文件。 7. 在你的代码中使用ALUT库提供的函数,例如alutInit()、alutCreateBufferFromFile()、alutCreateSource()等。 8. 在你的代码中使用OpenAL库提供的函数,例如alGenSources()、alSourcei()、alSourcePlay()等。 下面是一个使用ALUT库的例子: ```c #include <AL/alut.h> #include <AL/al.h> int main(int argc, char **argv) { // 初始化ALUT库 alutInit(&argc, argv); // 创建一个缓冲区并从文件中读取数据 ALuint buffer = alutCreateBufferFromFile("sound.wav"); // 创建一个源并将缓冲区分配给它 ALuint source; alGenSources(1, &source); alSourcei(source, AL_BUFFER, buffer); // 播放声音 alSourcePlay(source); // 等待声音播放完毕 ALint state; do { alGetSourcei(source, AL_SOURCE_STATE, &state); } while (state == AL_PLAYING); // 清理资源 alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); alutExit(); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值