OpenAL Tutorial
Deprecated
Hello, Internet! Even though it has been many years since this OpenAL
tutorial was first created, it continues to be one of Google's top hits
for an OpenAL tutorial on Mac OS X. Unfortunately, Apple
removed
the alut.h header file from their version of the OpenAL framework
in Mac OS X 10.4.7, so this tutorial has been essentially non-working for
well over the past decade. If you are interested in trying to revive any of these examples, here is a
blog entry
which offers some work arounds. Apple has its own example,
but it relies heavily on Mac-only frameworks to work with OpenAL.
As part of my efforts to develop a game engine which utilizes as many
platform compliant technologies as possible, I have decided to use the
fairly young OpenAL to produce sounds. OpenGL has been around for
several years and has had a nearly countless number of books and other
references based upon it, but OpenAL is still in its earlier years, and
has not built up the following and resources that its graphics counterpart
has. Finding few resources, I was forced to go exploring mostly on my
own, with few guides to help lead me. This is one of the new paths that
PIGE is helping to create, by exploring, by experimenting, and by finally
documenting my adventures so that others can walk the same path, just much
quicker.
This tutorial was initially designed on Mac OS X (10.1). While some
references will also work for Linux and/or Windows, there are parts which
are specific to Mac OS X and the Project Builder IDE. Below are several
steps which I will cover in this tutorial to help you get on your way to
using OpenAL. My main focus of this project is just to get sound working,
not to concentrate on more complicated features such as the Doppler Effect.
- Download & Install the OpenAL Framework
- First thing you need to do is to download and install the
OpenAL library/framework. For Windows and Mac users, I highly
suggest going to
http://developer.creative.com/landing.asp?cat=1&sbcat=31&top=38
and downloading the appropriate SDK Installer. For you Linux users
(or Mac OS X users who just want to take the hard route about doing
things), you will need to open up a terminal window and use CVS to
download the appropriate files. Have fun reading the README files.
Here are the CVS commands:
cvs -d:pserver:guest@opensource.creative.com:/usr/local/cvs-repository login
(use password "guest")
cvs -d:pserver:guest@opensource.creative.com:/usr/local/cvs-repository co
openal
For Mac OS X users, when I originally tried this method, I had to do a
little bit of manipulating to get the framework to place itself properly.
Since the /System/Library/Frameworks folder is owned by root, I had to use this command to copy the framework
into the Frameworks directory:
sudo chmod 777 /System/Library/Frameworks/
Then I created an OpenAL.framework directory and copied the files in
there. Once finished, I reverted the /System/Library/Frameworks folder
back to its original 755 permissions. And if this is Greek to you, you
probably should just use Creative's SDK Installer instead, so you
wouldn't have to mess around with UNIX commands. At this point, I have
not tried this on Linux, but there are probably some similiarities, and
some dis-similiarities between Linux and Mac OS X.
If you just need to run an OpenAL application, then you just need the
OpenAL Installer which will place the proper files on your system (such as OpenAL32.dll for Windows users).
- Read the OpenAL Guide
- Download and read Creative's
OpenAL
Guide. You don't need to read everything, but it has a decent
introduction which helped me quite a bit in setting up my OpenAL
program. Also, it gives a run-down of many of the functions and
capabilities of OpenAL. If you are having problems with your OpenAL
program, search through this documentation and see if it helps.
- Set Up the Project
-
Mac OS X
Start up a new project in Project Builder, as if you were creating an OpenGL project.
Add these frameworks: CoreServices, GLUT, OpenGL, OpenAL. OpenAL may be located in a different
folder than where the other three might be. Look in /Library/Frameworks, /System/Library/Frameworks,
and ~/Library/Frameworks to search for any hiding Frameworks. The wave files need to be moved into
the my-openal.app/Contents/MacOS/ directory so the executable can find them easily. Once these wave
files have been moved to their proper location, also add them to your project and place them in the
Resources folder.
Windows
Read the Compiling Windows with CodeWarrior page for more information
on setting up CodeWarrior on Windows to work with OpenAL.
Linux
I have successfully been able to get OpenAL to work on a Linux system before, but I do not currently
have a Linux system on which to test and document an OpenAL project.
- The Code
-
The content for this section is from the thesis developed for PIGE (© 2003)
The standard set of headers are these:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <AL/al.h>
#include <AL/alut.h>
However, for Mac OS X, there are slight changes necessary for the GLUT and OpenAL libraries.
#include <stdio.h>
#include <stdlib.h>
#include <GLUT/glut.h>
#include <OpenAL/alut.h>
A standard has been developed to avoid the use of global variables, because they are generally considered bad programming style. This is to help avoid odd programming errors which can occur if global variables are used. When used with proper care, they can be useful and make programming an easier process, especially with OpenGL and OpenAL. Good practice dictates that most variables should remain local to several functions, and if the variables need to be shared, they are then passed as parameters. Such careful programming style can create unnecessary complications when working with OpenGL and OpenAL, so several global variables are made available to the program.
In this example, only one sound is being loaded, which explains why only one buffer and source is being declared.
#define NUM_BUFFERS 1
#define NUM_SOURCES 1
#define NUM_ENVIRONMENTS 1
There is only one listener, and these arrays define the initial set up of the listener for its position, direction, and velocity. The listener is not moving at the start, but can move around any other sound source.
ALfloat listenerPos[]={0.0,0.0,4.0};
ALfloat listenerVel[]={0.0,0.0,0.0};
Alfloat listenerOri[]={0.0,0.0,1.0, 0.0,1.0,0.0};
Each sound source has similar properties that the listener has. The source0Pos and source0Vel arrays show the position and velocity of the sound source.
ALfloat source0Pos[]={ -2.0, 0.0, 0.0};
ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
Sounds need to be stored in an array, similar to textures. Several buffers are needed to contain the sounds and other necessary information. The size, freq, format, and data variables are used when loading the sound files.
Aluint buffer[NUM_BUFFERS];
Aluint source[NUM_SOURCES];
ALuint environment[NUM_ENVIRONMENTS];
ALsizei size,freq;
ALenum format;
ALvoid *data;
The init function is called from the program's main function. It begins by setting the initial positions for the listener position, velocity, and orientation.
void init(void)
{
alListenerfv(AL_POSITION,listenerPos);
alListenerfv(AL_VELOCITY,listenerVel);
alListenerfv(AL_ORIENTATION,listenerOri);
Next, the program creates the buffers and checks for any problems in the process.
alGetError(); // clear any error messages
// Generate buffers, or else no sound will happen!
alGenBuffers(NUM_BUFFERS, buffer);
if(alGetError() != AL_NO_ERROR)
{
printf("- Error creating buffers !!\n");
exit(1);
}
else
{
printf("init() - No errors yet.");
}
The next three lines are the most important in loading the wave file. If more than one sound is loaded, then these three lines of code are repeated, but they reference different sound files and buffer positions. Refer to the table below to view how the alutLoadWAVFile call differs between platforms.
Operating System
|
Source Code
|
Linux
|
alutLoadWAVFile((Albyte *) "c.wav", &format, &data, size,&freq, &al_bool);
|
Macintosh
|
alutLoadWAVFile("c.wav", &format, &data, &size, &freq);
|
Windows
|
alutLoadWAVFile("c.wav", &format, &data, &size, &freq, &al_bool);
|
alutLoadWAVFile("a.wav",&format,&data,&size,&freq);
alBufferData(buffer[0],format,data,size,freq);
alutUnloadWAV(format,data,size,freq);
Similar to how the buffers were created, the sources are now created and checked for any errors.
alGetError(); /* clear error */
alGenSources(NUM_SOURCES, source);
if(alGetError() != AL_NO_ERROR)
{
printf("- Error creating sources !!\n");
exit(2);
}
else
{
printf("init - no errors after alGenSources\n");
}
Finally, the properties of the sound are set. First, the sound pitch and gain are set, then the source's position and orientation are defined, and finally the source is associated with its buffer to make it loop through the wave file. Setting the AL_LOOPING value to AL_TRUE determines whether or not the sound will play continuously, or if it will just play once and then stop. For ambient, background music, one might consider setting this to AL_TRUE, but for a sporadic sound such as a gun shot or a foot stomp, then AL_LOOPING should be AL_FALSE.
alSourcef(source[0], AL_PITCH, 1.0f);
alSourcef(source[0], AL_GAIN, 1.0f);
alSourcefv(source[0], AL_POSITION, source0Pos);
alSourcefv(source[0], AL_VELOCITY, source0Vel);
alSourcei(source[0], AL_BUFFER,buffer[0]);
alSourcei(source[0], AL_LOOPING, AL_TRUE);
}
- Compile & Test
- Now for the moment of truth. Compile your project and
see if it runs. For some odd reason under Mac OS X, I received four prebind
errors, but it still ran. The Windows version had around 20 warnings, but it
also ran without an obvious problems.
If you want to compile the openal.cpp file from the command line in Mac OS X, type in the following line from the Terminal:
g++ -framework OpenGL -framework GLUT -framework OpenAL -framework Foundation -Wall -o openal-demo openal.cpp
In this program, press the keys 1
through 3 to start the three different sounds, and press 4
through 6 to turn them off. Using the arrow keys will move
the white box 'listener' around the various sound sources.
Hitting the ESC key or using the shortcut ⌘ +
Q will also quit the program.
References
Page created: 19. September 2002
Last modified: 3 April 2018
|