Monday, February 05, 2007

New Audio Module

For the past few weeks I have been working on the new audio engine.

The SDL_Mixer is a great library and I just love its simplicity and straightforward API code. However there is one significant feature missing. It is 3D sound support. Off course it could be faked, but I decided to give OpenAL a try.

The library itself is a well-known standard right now for 3D Sound audio and allot of new games are using it for their audio support.

The library itself is fairly low level. Its API is somewhat similar to the OpenGL. The API has 3 major parts:

1. Device
2. Buffer
3. Source

The device is an output device that is available on the machine. On my machine there are 2 devices:

1. Software
1. Hardware

It is possible to select either of them. On some other machines another devices are available. Usually device can have additional features included, which can be requested through the extension system. Quite similar to OpenGL.

When the device is created the OpenAL allows you to request sources to be played on that device. Source is like a point in space where sound is playing. It is possible to specify allot of different properties to the source such as position , velocity , volume (Gain) and more. There is also a Listener it is exactly what it is named like . There can be only one Listener and this Listener is who can "hear" the sounds.

The sound itself is loaded into buffer or multiple buffers, which are then assigned to the source and OpenAL starts playing them.

This is probably all it can generally do. But the best part off course is the 3d positioning and the doppler shift. The extensions are also one cool thing as it allows to create plenty effects to simulate different audio environments.


For the audio file I decided to use ogg/vorbis. It is royalty free audio format which has become quite popular now. I decided to use ogg instead of regular .wav files to save memory space. Off course it would add additional impact on the processor but this wouldn't be so hard I think.


So generally I have integrated all of this into one easy to use and intuitive audio engine.

The following flow chart or class structure illustrates the whole picture:



There is one singleton factory called AudioManager class. Its primary job is to manage all the audio data, creation and destruction. Throught it sources and streams are requested.

The AudioManager contains the StreamList class which is collection of Streams.
Each Stream represents Ogg file (either in the loaded memory or on the local hard drive). Stream itself allows to read from this file and contains reference counter to automatically destroy itself when required.

There is also an AudioThread. Its primary job is to continuously stream the Ogg files fill the Audio buffers to the source.

AudioThread manages 4 lists :

1. List of Passive 3d sources
2. List of Active 3d sources
3. List of Passive 1d sources
4. List of Active 1d sources


Generally when the application starts a fixed number of sources is created. Usually 1-4 of 1D sources and 5-20 of 3D sources.

Now when any sound request the source for playing, then audio thread requests source from passive sources and if successful, puts it to the active sources and returns reference to the source. If not well it ignores the command then.

All the active sources are walked through by the AudioThread and get streamed.

The most important part is that only the AudioThread can change any of the list. So the requests are synchronized with a mutex.


Now about user Interface.

There are only 3 classes available :

1. Sound1D
2. Sound3D
3. Music


Sound1D is used for the stereo sounds, such as playing GUI elements or videos in the game. It contains all the required basic operation : Loading , Playing , Stopping , Pausing and so on. Each sound contains StreamReader. The StreamReader just holds the position on the stream that gets streamed. This is used to assure that any 2 sounds that are playing the same Stream wouldn't interfer with each other.

Sound3D is used for the in-game 3d sounds. It is important that the sounds used is mono. Otherwise it wouldn't play or cause not desirable side effects. Sound3D has the same functions as the Sound1D , but also has additional functions that specify position in the 3D space and velocity. I am also planning to add a binding option so it would automatically synchronize itself with physical engine.

Music is a singleton class. It is actually available only by calling through the AudioManager. Generally it holds Sound1D inside itself and calls its functions. The only difference is the volume control, that allows music to have different volume then just sounds.

This is not all the stuff that is implemented, but I just explained general idea, and saved it for my own future reference.

P.S. I am using gliffy for this diagram. Check it out, its cool !

Labels: , , , , , , , , , , ,

2 Comments:

At 4:41 PM, Blogger roger said...

OpenAL is the API for Windows Vista. I guess we will see a big boost in its development, use and support by manufacturers in the near future.

 
At 7:34 PM, Blogger Dmitri Kuznetsov said...

I didn't know that. But yes OpenAL is a really good choice for game developers and there is no other alternative right now.

 

Post a Comment

Links to this post:

Create a Link

<< Home