/* * Copyright (c) 2002-2010 LWJGL Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'LWJGL' nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.lwjgl.openal; import static org.lwjgl.openal.AL10.*; import static org.lwjgl.openal.EFX10.*; /** * Utility class for the OpenAL extension ALC_EXT_EFX. Provides functions to check for the extension * and support of various effects and filters. * <p> * Currently supports ALC_EXT_EFX version 1.0 effects and filters. * * @author Ciardhubh <ciardhubh[at]ciardhubh.de> * @version $Revision$ * $Id$ */ public final class EFXUtil { /** Constant for testSupportGeneric to check an effect. */ private static final int EFFECT = 1111; /** Constant for testSupportGeneric to check a filter. */ private static final int FILTER = 2222; /** Utility class, hidden contructor. */ private EFXUtil() { } /** * Checks if OpenAL implementation is loaded and supports ALC_EXT_EFX. * * @return True if ALC_EXT_EFX is supported, false if not. * @throws OpenALException If OpenAL has not been created yet. */ public static boolean isEfxSupported() { if (!AL.isCreated()) { throw new OpenALException("OpenAL has not been created."); } return ALC10.alcIsExtensionPresent(AL.getDevice(), ALC_EXT_EFX_NAME); } /** * Tests OpenAL to see whether the given effect type is supported. This is done by creating an * effect of the given type. If creation succeeds the effect is supported. * * @param effectType Type of effect whose support is to be tested, e.g. AL_EFFECT_REVERB. * @return True if it is supported, false if not. * @throws OpenALException If the request fails due to an AL_OUT_OF_MEMORY error or OpenAL has * not been created yet. * @throws IllegalArgumentException effectType is not a valid effect type. */ public static boolean isEffectSupported(final int effectType) { // Make sure type is a real effect. switch (effectType) { case AL_EFFECT_NULL: case AL_EFFECT_EAXREVERB: case AL_EFFECT_REVERB: case AL_EFFECT_CHORUS: case AL_EFFECT_DISTORTION: case AL_EFFECT_ECHO: case AL_EFFECT_FLANGER: case AL_EFFECT_FREQUENCY_SHIFTER: case AL_EFFECT_VOCAL_MORPHER: case AL_EFFECT_PITCH_SHIFTER: case AL_EFFECT_RING_MODULATOR: case AL_EFFECT_AUTOWAH: case AL_EFFECT_COMPRESSOR: case AL_EFFECT_EQUALIZER: break; default: throw new IllegalArgumentException("Unknown or invalid effect type: " + effectType); } return testSupportGeneric(EFFECT, effectType); } /** * Tests OpenAL to see whether the given filter type is supported. This is done by creating a * filter of the given type. If creation succeeds the filter is supported. * * @param filterType Type of filter whose support is to be tested, e.g. AL_FILTER_LOWPASS. * @return True if it is supported, false if not. * @throws OpenALException If the request fails due to an AL_OUT_OF_MEMORY error or OpenAL has * not been created yet. * @throws IllegalArgumentException filterType is not a valid filter type. */ public static boolean isFilterSupported(final int filterType) { // Make sure type is a real filter. switch (filterType) { case AL_FILTER_NULL: case AL_FILTER_LOWPASS: case AL_FILTER_HIGHPASS: case AL_FILTER_BANDPASS: break; default: throw new IllegalArgumentException("Unknown or invalid filter type: " + filterType); } return testSupportGeneric(FILTER, filterType); } /** * Generic test function to see if an EFX object supports a given kind of type. Works for * effects and filters. * * @param objectType Type of object to test. Must be either EFXUtil.EFFECT or EFXUtil.FILTER. * @param typeValue OpenAL type the object should be tested for support, e.g. AL_FILTER_LOWPASS * or AL_EFFECT_REVERB. * @return True if object supports typeValue, false else. */ private static boolean testSupportGeneric(final int objectType, final int typeValue) { // Check for supported objectType. switch (objectType) { case EFFECT: case FILTER: break; default: throw new IllegalArgumentException("Invalid objectType: " + objectType); } boolean supported = false; if (isEfxSupported()) { // Try to create object in order to check AL's response. alGetError(); int genError; int testObject = 0; try { switch (objectType) { // Create object based on type case EFFECT: testObject = alGenEffects(); break; case FILTER: testObject = alGenFilters(); break; default: throw new IllegalArgumentException("Invalid objectType: " + objectType); } genError = alGetError(); } catch (final OpenALException debugBuildException) { // Hack because OpenALException hides the original error code (short of parsing the // error message String which would break if it gets changed). if (debugBuildException.getMessage().contains("AL_OUT_OF_MEMORY")) { genError = AL_OUT_OF_MEMORY; } else { genError = AL_INVALID_OPERATION; } } if (genError == AL_NO_ERROR) { // Successfully created, now try to set type. alGetError(); int setError; try { switch (objectType) { // Set based on object type case EFFECT: alEffecti(testObject, AL_EFFECT_TYPE, typeValue); break; case FILTER: alFilteri(testObject, AL_FILTER_TYPE, typeValue); break; default: throw new IllegalArgumentException("Invalid objectType: " + objectType); } setError = alGetError(); } catch (final OpenALException debugBuildException) { // Hack because OpenALException hides the original error code (short of parsing // the error message String which would break when it gets changed). setError = AL_INVALID_VALUE; } if (setError == AL_NO_ERROR) { supported = true; } // Cleanup try { switch (objectType) { // Set based on object type case EFFECT: alDeleteEffects(testObject); break; case FILTER: alDeleteFilters(testObject); break; default: throw new IllegalArgumentException("Invalid objectType: " + objectType); } } catch (final OpenALException debugBuildException) { // Don't care about cleanup errors. } } else if (genError == AL_OUT_OF_MEMORY) { throw new OpenALException(genError); } } return supported; } }