OpenAL++
Posted: Fri Dec 21, 2007 8:46 am
OpenAL++ is a cross-platform C++ wrapper for OpenAL. It's licensed via LGPL, and free to use, so you shouldn't have any worries.
Lets get one fact straight: There are 2 versions of OpenAL++ floating around. Use the latest, its what we'll be writing with.
(Note: the latest is not the version that shows up on a google search for openalpp tut.)
First things first, get your libraries, set up your project, and link Irrlicht and openalpp. The pure link command is “-lopenalpp”.
Here's our include:
lets go ahead and bring in the namespaces too:
There. We've got all our common namespaces. Personally, I never 'using namespace' unless i'm inside a non-included source file, and rarely even then.
Now lets start with the main:
Now that all the obvious stuff is set up, lets get to openal++
We need to setup a main sound environment:
This gives us access to using a listener. The listener, altho not dependant in code, is dependant on the environment for the main volume and any EAX plugins. Don't worry what EAX is, openal++ will explain that to you well enough.
Lets do a little more Irrlicht calls. we'll make a generic cube, and give it a fly straight animator to notice the 3d sound environment. We'll also add a static camera to view the scene;
All of that is pretty self-evident if you know what you're reading. Our next step is to create our listener. For effect, lets put it at the camera's position.
The Listener class is basically the exact equivalent of an irrlicht camera. You need a Listener to hear the 3d environment, and give it all the qualities of your main camera (or your character, or where ever you want the listener to be).
Now we can setup a Sound source. This is pretty much straight forward.
Here's one part you need to be careful at. If you don't have a valid file, OpenAL++ will throw an exception and quit the program. Depending on your environment, you may need to fiddle with the exact path of your file. You can, of course, catch the thrown error and try to recover gracefully. This is done by putting your init lines into try/catch braces.
Now we need a few more bits of data, a timer, and a few float time variables to determine "deltaTime" (i'll call it dTime)
"velocity" you ask? "Why Would I need velocity?" Well its very simple. We want the velocity to affect the doppler shift. It probably won't be noticable at this level, but I'm showing you how anyway.
Now for our Main Loop. First we need to take care of modifying the velocity.
*NOTE1: the computer's clock is only accurate to milliseconds. So the smallest dTime we should get is 0.001. If you'r getting smaller, it's either a big error, or your dividing by zero and all hell is breaking loose.
*NOTE2: If you plan on having a moving listener, there's a "setVelocity" function there as well.
Now for cleanup. If your using the latest version of OpenAL++, you'll get horrible errors if you try to use 'not-pointers'. So we do this the fun way:
All of this can be nicely wrapped into classes rather easily. The only translations required are for location and velocity. I suggest always using getAbsolutePosition() when modifying linked OpenAL++ types and Irrlicht types.
Remember, OpenAL++, just like OpenAL, and also like OpenGL, uses a left-handed coordinate system. It's up to you the user to determine what efforts are necessary to get it working perfectly. Usually you should only need to tweek simple things.
Gain is Volume. If you can't hear it, increase the gain. If its too loud, decrease. If you still are having trouble, modify the AudioEnvironment's Gain. Its the Master Volume in a sense. Sounds can be made ambient and not require a listener or positioning.
Lastly, OpenAL++ by default can load .ogg files, and play uncompressed and vorbis compressed .avi audio.
Code Happy!
Lets get one fact straight: There are 2 versions of OpenAL++ floating around. Use the latest, its what we'll be writing with.
(Note: the latest is not the version that shows up on a google search for openalpp tut.)
First things first, get your libraries, set up your project, and link Irrlicht and openalpp. The pure link command is “-lopenalpp”.
Here's our include:
Code: Select all
#include <irrlicht.h>
#include <alpp/alpp.h>
//or
#include <openalpp/alpp.h>
//depending on your folder structure
Code: Select all
//bring in the most common irrlicht namespaces
using namespace irr;
using namespace video;
using namespace scene;
using namespace core;
//and the openal++ namespace:
using namespace openalpp;
Now lets start with the main:
Code: Select all
int main()
{
IrrlichtDevice* device = createDevice(); //use the default device driver
ISceneManager* smgr = device->getSceneManager(); //get a scene manager
IVideoDriver* driver = device->getVideoDriver(); //get a driver
We need to setup a main sound environment:
Code: Select all
AudioEnvironment* env = new AudioEnvironment();
env->setGain(1.0);
Lets do a little more Irrlicht calls. we'll make a generic cube, and give it a fly straight animator to notice the 3d sound environment. We'll also add a static camera to view the scene;
Code: Select all
ISceneNode* box = smgr->addCubeSceneNode();
ISceneNodeAnimator* fly = smgr->createFlyStraightAnimator(vector3df(-15,0,10), vector3df(15,0,10), 10000, true);
box->addAnimator(fly);
fly->drop();
ICameraSceneNode* cam = smgr->addCameraSceneNode();
cam->setPosition(vector3df(0,10,-10));
cam->setTarget(vector3df(0,0,10));
Code: Select all
Listener* listener = new Listener();
vector3df cam_pos = cam->getPosition();
vector3df cam_up = cam->getUpVector();
vector3df cam_look = cam->getTarget();
listener->setPosition(cam_pos.X, cam_pos.Y, cam_pos.Z);
listener->setOrientation(cam_look.X, cam_look.Y, cam_look.Z, cam_up.X, cam_up.Y, cam_up.Z);
Now we can setup a Sound source. This is pretty much straight forward.
Code: Select all
Source* sound = new Source("sound.wav");
vector3df box_pos = box->getPosition();
sound->setPosition(box_pos.X, box_pos.Y, box_pos.Z);
sound->setLooping(true);
sound->play();
Now we need a few more bits of data, a timer, and a few float time variables to determine "deltaTime" (i'll call it dTime)
Code: Select all
float dTime = 0.001, oldTime = 0, newTime = 0;
ITimer Time = device->getTimer();
vector3df velocity, box_pos_old = box->getPosition();
Now for our Main Loop. First we need to take care of modifying the velocity.
Code: Select all
while(device->run())
{
box->updateAbsolutePosition();
box_pos = box->getPosition();
newTime = Time->getTime();
dTime = (newTime - oldTime) / 1000; //see note 1
velocity = (box_pos - box_pos_old) / dTime;
sound->setPosition(box_pos.X, box_pos.Y, box_pos.Z);
sound->setVelocity(velocity.X, velocity.Y, velocity.Z); //see note 2
driver->beginScene(true,true,SColor(255,0,0,255)); //blue background
smgr->drawAll();
driver->endScene();
oldTime = Time->getTime();
box_pos_old = box->getPosition();
}
*NOTE2: If you plan on having a moving listener, there's a "setVelocity" function there as well.
Now for cleanup. If your using the latest version of OpenAL++, you'll get horrible errors if you try to use 'not-pointers'. So we do this the fun way:
Code: Select all
box->drop();
cam->drop();
listener->unref();
sound->stop();
sound->unref();
evn->unref();
device->closeDevice();
device->drop();
return 0;
}
Remember, OpenAL++, just like OpenAL, and also like OpenGL, uses a left-handed coordinate system. It's up to you the user to determine what efforts are necessary to get it working perfectly. Usually you should only need to tweek simple things.
Gain is Volume. If you can't hear it, increase the gain. If its too loud, decrease. If you still are having trouble, modify the AudioEnvironment's Gain. Its the Master Volume in a sense. Sounds can be made ambient and not require a listener or positioning.
Lastly, OpenAL++ by default can load .ogg files, and play uncompressed and vorbis compressed .avi audio.
Code Happy!