A Closer Look at ALC: Lesson 4
Author: Jesse Maurais | From: devmaster.net
Modified for LWJGL by: Brian Matzon
Note:This article originally deals with ALC Context management, and especially using multiple contexts. The LWJGL binding does not expose multiple contexts, nor do we have any plans to do so. It is an advanced feature, not used in games. This article has also been edited heavily to make sense in an LWJGL environment which doesn't expose ALC directly.
Up until now we have been letting AL.create()
do all the real
tricky stuff for us. For example handling the audio devices. It's really
nice that the AL.create()
method is there to provide this
functionality, but any smart coder will want to know exactly what their
doing. We may want to, at some point, use the verbose
AL.create(String deviceArguments, int
contextFrequency, int contextRefresh,
boolean contextSynchronized)
method.
In this tutorial we will expose the Alc layer and take a look at how to
handle the devices on our own.
When using either of the two create methods of AL
, a default
context and device is created for you. You cannot create multiple contexts
nor can you access multiple devices. Thus a lot of the ALC methods are not
available, since they simply don't make any sense. Methods that are
available also no longer take a device or context parameter since they are
managed internally.
// Initialize OpenAL and clear the error bit. try{ AL.create(); } catch (LWJGLException le) { le.printStackTrace(); return; } AL10.alGetError();
Using the default create method is the simplest way to create a context and access a device. Default values are used, and once called OpenAL is initialized and ready to go.
// Initialize OpenAL and clear the error bit. try{ AL.create("DirectSound3D", 44100, 15, false); } catch (LWJGLException le) { le.printStackTrace(); return; } AL10.alGetError();
Here we initialize OpenAL using arguments for ALC. The first argument tells
ALC which device to access. Passing null is a perfectly valid argument. It
forces the ALC to use a default device.
The second argument tells ALC the frequency for mixing output buffer, in
units of Hz. Third argument tells ALC how often it should update it's
internal state and buffers. The final argument determines whether the ALC
should run in synchronous mode.
public static int alcGetError(); public static boolean alcIsExtensionPresent(String extName); public static int alcGetEnumValue(String enumName); public static String alcGetString(int pname); public static void alcGetInteger(int pname, IntBuffer integerdata);
It may be pretty obvious to you what these do, but lets humour ourselves and
have a closer look. First we have 'alcGetError' which is just like
'alGetError' but will return Alc errors. The next two functions are for
querying Alc extensions. This was just the creators planning ahead, as there
are no Alc extensions either. The last function, 'alcGetInteger', will
return the Alc version when passed 'ALC_MAJOR_VERSION' or 'ALC_MINOR_VERSION'.
The function 'alcGetString' is pretty cool. It can take any of the following
three parameters to 'token':
* ALC_DEFAULT_DEVICE_SPECIFIER
* ALC_DEVICE_SPECIFIER
* ALC_EXTENSIONS
The first will return the device string which your OpenAL implementation
will prefer you to use. In current OpenAL this should be "DirectSound3D",
like we used above. The second token will return a list of specifiers, but
in current OpenAL will only return "DirectSound" (without the "3D" for some
reason). The last will return a list of Alc extensions, of which none exist
yet.
Well that's most of Alc for you. I hope it gave you a better understanding
of how OpenAL interacts with the operation system.