PIGE
    Home
    .plan
    FAQ
    .log
Compiling
    Linux/UNIX
    Mac OS 8 & 9
    Mac OS X
    Windows
Downloads
    Source Code
    Executable Demos
    Thesis
Screenshots
    Crate
    Room
Tutorials
    Collision Detection
    Creating Icons
    OpenAL
    A*
Resources
    OpenGL
    OpenAL
    Game Dev
    Books
OpenAL Tutorial
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: 24 June 2008