1 /* 2 * Copyright (c) 2002-2010 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.openal; 33 34 import static org.lwjgl.openal.AL10.*; 35 import static org.lwjgl.openal.EFX10.*; 36 37 /** 38 * Utility class for the OpenAL extension ALC_EXT_EFX. Provides functions to check for the extension 39 * and support of various effects and filters. 40 * <p> 41 * Currently supports ALC_EXT_EFX version 1.0 effects and filters. 42 * 43 * @author Ciardhubh <ciardhubh[at]ciardhubh.de> 44 * @version $Revision$ 45 * $Id$ 46 */ 47 public final class EFXUtil { 48 49 /** Constant for testSupportGeneric to check an effect. */ 50 private static final int EFFECT = 1111; 51 /** Constant for testSupportGeneric to check a filter. */ 52 private static final int FILTER = 2222; 53 54 /** Utility class, hidden contructor. */ EFXUtil()55 private EFXUtil() { 56 } 57 58 /** 59 * Checks if OpenAL implementation is loaded and supports ALC_EXT_EFX. 60 * 61 * @return True if ALC_EXT_EFX is supported, false if not. 62 * @throws OpenALException If OpenAL has not been created yet. 63 */ isEfxSupported()64 public static boolean isEfxSupported() { 65 if (!AL.isCreated()) { 66 throw new OpenALException("OpenAL has not been created."); 67 } 68 return ALC10.alcIsExtensionPresent(AL.getDevice(), ALC_EXT_EFX_NAME); 69 } 70 71 /** 72 * Tests OpenAL to see whether the given effect type is supported. This is done by creating an 73 * effect of the given type. If creation succeeds the effect is supported. 74 * 75 * @param effectType Type of effect whose support is to be tested, e.g. AL_EFFECT_REVERB. 76 * @return True if it is supported, false if not. 77 * @throws OpenALException If the request fails due to an AL_OUT_OF_MEMORY error or OpenAL has 78 * not been created yet. 79 * @throws IllegalArgumentException effectType is not a valid effect type. 80 */ isEffectSupported(final int effectType)81 public static boolean isEffectSupported(final int effectType) { 82 // Make sure type is a real effect. 83 switch (effectType) { 84 case AL_EFFECT_NULL: 85 case AL_EFFECT_EAXREVERB: 86 case AL_EFFECT_REVERB: 87 case AL_EFFECT_CHORUS: 88 case AL_EFFECT_DISTORTION: 89 case AL_EFFECT_ECHO: 90 case AL_EFFECT_FLANGER: 91 case AL_EFFECT_FREQUENCY_SHIFTER: 92 case AL_EFFECT_VOCAL_MORPHER: 93 case AL_EFFECT_PITCH_SHIFTER: 94 case AL_EFFECT_RING_MODULATOR: 95 case AL_EFFECT_AUTOWAH: 96 case AL_EFFECT_COMPRESSOR: 97 case AL_EFFECT_EQUALIZER: 98 break; 99 default: 100 throw new IllegalArgumentException("Unknown or invalid effect type: " + effectType); 101 } 102 103 return testSupportGeneric(EFFECT, effectType); 104 } 105 106 /** 107 * Tests OpenAL to see whether the given filter type is supported. This is done by creating a 108 * filter of the given type. If creation succeeds the filter is supported. 109 * 110 * @param filterType Type of filter whose support is to be tested, e.g. AL_FILTER_LOWPASS. 111 * @return True if it is supported, false if not. 112 * @throws OpenALException If the request fails due to an AL_OUT_OF_MEMORY error or OpenAL has 113 * not been created yet. 114 * @throws IllegalArgumentException filterType is not a valid filter type. 115 */ isFilterSupported(final int filterType)116 public static boolean isFilterSupported(final int filterType) { 117 // Make sure type is a real filter. 118 switch (filterType) { 119 case AL_FILTER_NULL: 120 case AL_FILTER_LOWPASS: 121 case AL_FILTER_HIGHPASS: 122 case AL_FILTER_BANDPASS: 123 break; 124 default: 125 throw new IllegalArgumentException("Unknown or invalid filter type: " + filterType); 126 } 127 128 return testSupportGeneric(FILTER, filterType); 129 } 130 131 /** 132 * Generic test function to see if an EFX object supports a given kind of type. Works for 133 * effects and filters. 134 * 135 * @param objectType Type of object to test. Must be either EFXUtil.EFFECT or EFXUtil.FILTER. 136 * @param typeValue OpenAL type the object should be tested for support, e.g. AL_FILTER_LOWPASS 137 * or AL_EFFECT_REVERB. 138 * @return True if object supports typeValue, false else. 139 */ testSupportGeneric(final int objectType, final int typeValue)140 private static boolean testSupportGeneric(final int objectType, final int typeValue) { 141 // Check for supported objectType. 142 switch (objectType) { 143 case EFFECT: 144 case FILTER: 145 break; 146 default: 147 throw new IllegalArgumentException("Invalid objectType: " + objectType); 148 } 149 150 boolean supported = false; 151 if (isEfxSupported()) { 152 153 // Try to create object in order to check AL's response. 154 alGetError(); 155 int genError; 156 int testObject = 0; 157 try { 158 switch (objectType) { // Create object based on type 159 case EFFECT: 160 testObject = alGenEffects(); 161 break; 162 case FILTER: 163 testObject = alGenFilters(); 164 break; 165 default: 166 throw new IllegalArgumentException("Invalid objectType: " + objectType); 167 } 168 genError = alGetError(); 169 } catch (final OpenALException debugBuildException) { 170 // Hack because OpenALException hides the original error code (short of parsing the 171 // error message String which would break if it gets changed). 172 if (debugBuildException.getMessage().contains("AL_OUT_OF_MEMORY")) { 173 genError = AL_OUT_OF_MEMORY; 174 } else { 175 genError = AL_INVALID_OPERATION; 176 } 177 } 178 179 if (genError == AL_NO_ERROR) { 180 // Successfully created, now try to set type. 181 alGetError(); 182 int setError; 183 try { 184 switch (objectType) { // Set based on object type 185 case EFFECT: 186 alEffecti(testObject, AL_EFFECT_TYPE, typeValue); 187 break; 188 case FILTER: 189 alFilteri(testObject, AL_FILTER_TYPE, typeValue); 190 break; 191 default: 192 throw new IllegalArgumentException("Invalid objectType: " + objectType); 193 } 194 setError = alGetError(); 195 } catch (final OpenALException debugBuildException) { 196 // Hack because OpenALException hides the original error code (short of parsing 197 // the error message String which would break when it gets changed). 198 setError = AL_INVALID_VALUE; 199 } 200 201 if (setError == AL_NO_ERROR) { 202 supported = true; 203 } 204 205 // Cleanup 206 try { 207 switch (objectType) { // Set based on object type 208 case EFFECT: 209 alDeleteEffects(testObject); 210 break; 211 case FILTER: 212 alDeleteFilters(testObject); 213 break; 214 default: 215 throw new IllegalArgumentException("Invalid objectType: " + objectType); 216 } 217 } catch (final OpenALException debugBuildException) { 218 // Don't care about cleanup errors. 219 } 220 221 } else if (genError == AL_OUT_OF_MEMORY) { 222 throw new OpenALException(genError); 223 } 224 } 225 226 return supported; 227 } 228 } 229