OpenAL Tutorial 4 - A Closer Look at ALC

From LWJGL
Jump to: navigation, search

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.



Credit

Author: Jesse Maurais

From: DevMaster.net

Modified to LWJGL: Brian Matzon