JOAL v2.6.0-rc-20250712
JOAL, OpenAL® API Binding for Java™ (public API).
AudioSystem3D.java
Go to the documentation of this file.
1/**
2 * Copyright (c) 2010-2023 JogAmp Community. All rights reserved.
3 * Copyright (c) 2003 Sun Microsystems, Inc. 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 met:
7 *
8 * -Redistribution of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * -Redistribution in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
16 * be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind.
20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
21 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
22 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS
23 * LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A
24 * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
25 * IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT
26 * OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
27 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
28 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
29 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
30 *
31 * You acknowledge that this software is not designed or intended for use in the
32 * design, construction, operation or maintenance of any nuclear facility.
33 */
34
35package com.jogamp.openal.sound3d;
36
37import java.io.BufferedInputStream;
38import java.io.IOException;
39import java.io.InputStream;
40
41import com.jogamp.openal.AL;
42import com.jogamp.openal.ALC;
43import com.jogamp.openal.ALCConstants;
44import com.jogamp.openal.ALCcontext;
45import com.jogamp.openal.ALCdevice;
46import com.jogamp.openal.ALConstants;
47import com.jogamp.openal.ALException;
48import com.jogamp.openal.ALExt;
49import com.jogamp.openal.ALFactory;
50import com.jogamp.openal.UnsupportedAudioFileException;
51import com.jogamp.openal.util.WAVData;
52import com.jogamp.openal.util.WAVLoader;
53
54import jogamp.openal.Debug;
55
56/**
57 * The AudioSystem3D class provides a set of methods for creating and
58 * manipulating a 3D audio environment.
59 *
60 * @author Athomas Goldberg, Sven Gothel, et al.
61 */
62public class AudioSystem3D {
63 static boolean DEBUG = Debug.debug("AudioSystem3D");
64 static final AL al;
65 static final ALC alc;
66 static final ALExt alExt;
67 static final boolean staticAvailable;
68 static Listener listener;
69
70 static {
71 ALC _alc = null;
72 AL _al = null;
73 ALExt _alExt = null;
74 try {
75 _alc = ALFactory.getALC();
76 _al = ALFactory.getAL();
77 _alExt = ALFactory.getALExt();
78 } catch(final Throwable t) {
79 if( DEBUG ) {
80 System.err.println("AudioSystem3D: Caught "+t.getClass().getName()+": "+t.getMessage());
81 t.printStackTrace();
82 }
83 }
84 alc = _alc;
85 al = _al;
86 alExt = _alExt;
87 staticAvailable = null != alc && null != al && null != alExt;
88 }
89
90 /**
91 * Initialize the Sound3D environment.
92 * @deprecated Not required to be called due to static initialization
93 */
94 @Deprecated
95 public static void init() throws ALException { }
96
97 /**
98 * Returns the <code>available state</code> of this instance.
99 * <p>
100 * The <code>available state</code> is affected by this instance
101 * overall availability, i.e. after instantiation.
102 * </p>
103 */
104 public static boolean isAvailable() { return staticAvailable; }
105
106 /** Return OpenAL global {@link AL}. */
107 public static final AL getAL() { return al; }
108 /** Return OpenAL global {@link ALC}. */
109 public static final ALC getALC() { return alc; }
110 /** Return OpenAL global {@link ALExt}. */
111 public static final ALExt getALExt() { return alExt; }
112
113 public static int getALError() {
114 return al.alGetError();
115 }
116
117 /**
118 * Returns true if an OpenAL ALC or AL error occurred, otherwise false
119 * @param device referencing an {@link ALCdevice}, may be null
120 * @param prefix prefix to print on error and if `verbose`
121 * @param verbose pass true to show errors
122 * @param throwException true to throw an ALException on error
123 * @return true if an error occurred, otherwise false
124 */
125 public static boolean checkError(final Device device, final String prefix, final boolean verbose, final boolean throwException) {
126 if( !checkALCError(device, prefix, verbose, throwException) ) {
127 return checkALError(prefix, verbose, throwException);
128 }
129 return false; // no error
130 }
131
132 /**
133 * Returns true if an OpenAL AL error occurred, otherwise false
134 * @param prefix prefix to print on error and if `verbose`
135 * @param verbose pass true to show errors
136 * @param throwException true to throw an ALException on error
137 * @return true if an error occurred, otherwise false
138 */
139 public static boolean checkALError(final String prefix, final boolean verbose, final boolean throwException) {
140 final int alErr = al.alGetError();
141 if( ALConstants.AL_NO_ERROR != alErr ) {
142 final String msg = prefix+": AL error 0x"+Integer.toHexString(alErr)+", '"+al.alGetString(alErr)+"'";
143 if( verbose ) {
144 System.err.println(msg);
145 }
146 if( throwException ) {
147 throw new ALException(msg);
148 }
149 return true;
150 }
151 return false;
152 }
153 /**
154 * Returns true if an OpenAL ALC error occurred, otherwise false
155 * @param device referencing an {@link ALCdevice}, may be null
156 * @param prefix prefix to print on error and if `verbose`
157 * @param verbose pass true to show errors
158 * @param throwException true to throw an ALException on error
159 * @return true if an error occurred, otherwise false
160 */
161 public static boolean checkALCError(final Device device, final String prefix, final boolean verbose, final boolean throwException) {
162 final ALCdevice alcDevice = null != device ? device.getALDevice() : null;
163 final int alcErr = alc.alcGetError( alcDevice );
164 if( ALCConstants.ALC_NO_ERROR != alcErr ) {
165 final String msg = prefix+": ALC error 0x"+Integer.toHexString(alcErr)+", '"+alc.alcGetString(alcDevice, alcErr)+"'";
166 if( verbose ) {
167 System.err.println(msg);
168 }
169 if( throwException ) {
170 throw new ALException(msg);
171 }
172 return true;
173 }
174 return false;
175 }
176
177 /**
178 * Creates a new Sound3D Context for a specified device including native {@link ALCcontext} creation.
179 *
180 * @param device The device the Context is being created for, must be valid
181 * @return The new Sound3D context.
182 */
183 public static Context createContext(final Device device) {
184 return new Context(device, null);
185 }
186
187 /**
188 * Creates a new Sound3D Context for a specified device including native {@link ALCcontext} creation.
189 *
190 * @param device The device the Context is being created for, must be valid.
191 * @param attributes list of {@link ALCcontext} attributes for context creation, maybe empty or null
192 * @return The new Sound3D context.
193 */
194 public static Context createContext(final Device device, final int[] attributes) {
195 return new Context(device, attributes);
196 }
197
198 /**
199 * Returns this thread current context.
200 * If no context is current, returns null.
201 *
202 * @return the context current on this thread, or null if no context is current.
203 * @see Context#getCurrentContext()
204 * @see #makeContextCurrent(Context)
205 * @see #releaseContext(Context)
206 */
207 public static Context getCurrentContext() {
208 return Context.getCurrentContext();
209 }
210
211 /**
212 * Makes the audio context current on the calling thread.
213 * <p>
214 * Recursive calls are supported.
215 * </p>
216 * <p>
217 * At any point in time one context can only be current by one thread,
218 * and one thread can only have one context current.
219 * </p>
220 * @param context the context to make current.
221 * @param throwException if true, throws ALException if {@link #getALContext()} is null, current thread holds another context or failed to natively make current
222 * @return true if current thread holds no other context and context successfully made current, otherwise false
223 * @see Context#makeCurrent()
224 * @see #releaseContext(Context)
225 */
226 public static boolean makeContextCurrent(final Context context, final boolean throwException) {
227 return context.makeCurrent(throwException);
228 }
229
230 /**
231 * Releases control of this audio context from the current thread, if implementation utilizes context locking.
232 * <p>
233 * Recursive calls are supported.
234 * </p>
235 * @param context the context to release.
236 * @param throwException if true, throws ALException if context has not been previously made current on current thread
237 * or native release failed.
238 * @return true if context has previously been made current on the current thread and successfully released, otherwise false
239 * @see Context#release()
240 * @see #makeContextCurrent(Context)
241 */
242 public static boolean releaseContext(final Context context, final boolean throwException) {
243 return context.release(throwException);
244 }
245
246 /**
247 * Opens the named audio device.
248 *
249 * @param deviceName The specified device name, null for default.
250 *
251 * @return The device described by the specified name
252 */
253 public static Device openDevice(final String deviceName) {
254 return new Device(deviceName);
255 }
256
257 /**
258 * Generate an array of Sound3D buffers.
259 *
260 * @param numBuffers The number of Sound3D buffers to generate.
261 *
262 * @return an array of (initially enpty) Sound3D buffers.
263 */
264 public static Buffer[] generateBuffers(final int numBuffers) {
265 final Buffer[] result = new Buffer[numBuffers];
266 final int[] arr = new int[numBuffers];
267 al.alGenBuffers(numBuffers, arr, 0);
268
269 for (int i = 0; i < numBuffers; i++) {
270 result[i] = new Buffer(arr[i]);
271 }
272
273 return result;
274 }
275
276 /**
277 * Loads a Sound3D buffer with the specified audio file.
278 *
279 * @param filename the name of the file to load.
280 *
281 * @return a new Sound3D buffer containing the audio data from the
282 * specified file.
283 *
284 * @throws IOException If the file cannot be found or some other IO error
285 * occurs.
286 * @throws UnsupportedAudioFileException If the format of the audio data is
287 * not supported
288 */
289 public static Buffer loadBuffer(final String filename)
290 throws IOException, UnsupportedAudioFileException {
291 Buffer result;
292 final Buffer[] tmp = generateBuffers(1);
293 result = tmp[0];
294
295 final WAVData wd = WAVLoader.loadFromFile(filename);
296 result.configure(wd.data, wd.format, wd.freq);
297
298 return result;
299 }
300
301 /**
302 * Loads a Sound3D buffer with the specified audio file.
303 *
304 * @param stream contains the stream associated with the audio file.
305 *
306 * @return a new Sound3D buffer containing the audio data from the
307 * passed stream.
308 *
309 * @throws IOException If the stream cannot be read or some other IO error
310 * occurs.
311 * @throws UnsupportedAudioFileException If the format of the audio data is
312 * not supported
313 */
314 public static Buffer loadBuffer(InputStream stream)
315 throws IOException, UnsupportedAudioFileException {
316 Buffer result;
317 final Buffer[] tmp = generateBuffers(1);
318 result = tmp[0];
319
320 if (!(stream instanceof BufferedInputStream)) {
321 stream = new BufferedInputStream(stream);
322 }
323 final WAVData wd = WAVLoader.loadFromStream(stream);
324
325 result.configure(wd.data, wd.format, wd.freq);
326
327 return result;
328 }
329
330 /**
331 * Loads a Sound3D Source with the specified audio file. This is
332 * functionally equivalent to generateSource(loadBuffer(fileName));
333 *
334 * @param filename the name of the file to load.
335 *
336 * @return a new Sound3D Source containing the audio data from the
337 * specified file.
338 *
339 * @throws IOException If the file cannot be found or some other IO error
340 * occurs.
341 * @throws UnsupportedAudioFileException If the format of the audio data is
342 * not supported
343 */
344 public static Source loadSource(final String filename)
345 throws IOException, UnsupportedAudioFileException {
346 final Buffer buffer = loadBuffer(filename);
347
348 return generateSource(buffer);
349 }
350
351 /**
352 * Loads a Sound3D Source with the specified audio stream. This is
353 * functionally equivalent to generateSource(loadBuffer(stream));
354 *
355 * @param stream contains the stream associated with the audio file.
356 *
357 * @return a new Sound3D Source containing the audio data from the
358 * passed stream.
359 *
360 * @throws IOException If the file cannot be found or some other IO error
361 * occurs.
362 * @throws UnsupportedAudioFileException If the format of the audio data is
363 * not supported
364 */
365 public static Source loadSource(final InputStream stream)
366 throws IOException, UnsupportedAudioFileException {
367 final Buffer buffer = loadBuffer(stream);
368
369 return generateSource(buffer);
370 }
371
372 /**
373 * Generates a set of uninitialized Source3D sources
374 *
375 * @param numSources the number of Sound3D sources to generate.
376 *
377 * @return an array of uninitialized sources.
378 */
379 public static Source[] generateSources(final int numSources) {
380 final Source[] result = new Source[numSources];
381 final int[] arr = new int[numSources];
382 al.alGenSources(numSources, arr, 0);
383
384 for (int i = 0; i < numSources; i++) {
385 result[i] = new Source(arr[i]);
386 }
387
388 return result;
389 }
390
391 /**
392 * Generate a Sound3D source from an initialized Buffer.
393 *
394 * @param buff The buffer to be associate with the source.
395 *
396 * @return the newly generated Source.
397 */
398 public static Source generateSource(final Buffer buff) {
399 Source result = null;
400 final Source[] tmp = generateSources(1);
401 result = tmp[0];
402 result.setBuffer(buff);
403
404 return result;
405 }
406
407 /**
408 * Get the listener object associated with this Sound3D environment.
409 *
410 * @return The listener object.
411 */
412 public static Listener getListener() {
413 if (listener == null) {
414 listener = new Listener();
415 }
416 return listener;
417 }
418}
A generic exception for OpenAL errors used throughout the binding as a substitute for RuntimeExceptio...
This class provides factory methods for generating AL and ALC objects.
Definition: ALFactory.java:62
static AL getAL()
Get the default AL object.
Definition: ALFactory.java:122
static ALExt getALExt()
Get the default ALExt object.
Definition: ALFactory.java:150
static ALC getALC()
Get the default ALC object.
Definition: ALFactory.java:136
The AudioSystem3D class provides a set of methods for creating and manipulating a 3D audio environmen...
static Listener getListener()
Get the listener object associated with this Sound3D environment.
static Buffer loadBuffer(InputStream stream)
Loads a Sound3D buffer with the specified audio file.
static final ALC getALC()
Return OpenAL global ALC.
static Source loadSource(final String filename)
Loads a Sound3D Source with the specified audio file.
static Source[] generateSources(final int numSources)
Generates a set of uninitialized Source3D sources.
static Source generateSource(final Buffer buff)
Generate a Sound3D source from an initialized Buffer.
static Buffer loadBuffer(final String filename)
Loads a Sound3D buffer with the specified audio file.
static boolean releaseContext(final Context context, final boolean throwException)
Releases control of this audio context from the current thread, if implementation utilizes context lo...
static boolean checkError(final Device device, final String prefix, final boolean verbose, final boolean throwException)
Returns true if an OpenAL ALC or AL error occurred, otherwise false.
static boolean checkALCError(final Device device, final String prefix, final boolean verbose, final boolean throwException)
Returns true if an OpenAL ALC error occurred, otherwise false.
static Device openDevice(final String deviceName)
Opens the named audio device.
static final AL getAL()
Return OpenAL global AL.
static boolean makeContextCurrent(final Context context, final boolean throwException)
Makes the audio context current on the calling thread.
static void init()
Initialize the Sound3D environment.
static boolean checkALError(final String prefix, final boolean verbose, final boolean throwException)
Returns true if an OpenAL AL error occurred, otherwise false.
static Buffer[] generateBuffers(final int numBuffers)
Generate an array of Sound3D buffers.
static Context createContext(final Device device)
Creates a new Sound3D Context for a specified device including native ALCcontext creation.
static boolean isAvailable()
Returns the available state of this instance.
static final ALExt getALExt()
Return OpenAL global ALExt.
static Source loadSource(final InputStream stream)
Loads a Sound3D Source with the specified audio stream.
static Context getCurrentContext()
Returns this thread current context.
static Context createContext(final Device device, final int[] attributes)
Creates a new Sound3D Context for a specified device including native ALCcontext creation.
The Sound3D Buffer is a container for audio data used in the Sound3D environment.
Definition: Buffer.java:48
void configure(final ByteBuffer data, final int alFormat, final int freq)
Configure the Sound3D buffer.
Definition: Buffer.java:91
This class provides a Sound3D Context associated with a specified device.
Definition: Context.java:49
boolean release(final boolean throwException)
Releases control of this audio context from the current thread, if implementation utilizes context lo...
Definition: Context.java:302
boolean makeCurrent(final boolean throwException)
Makes the audio context current on the calling thread.
Definition: Context.java:231
static Context getCurrentContext()
Returns this thread current context.
Definition: Context.java:206
This class provides a handle to a specific audio device.
Definition: Device.java:46
ALCdevice getALDevice()
Returns the OpenAL ALCdevice.
Definition: Device.java:65
This class represents the human listener in the Sound3D environment.
Definition: Listener.java:46
This class is used to represent sound-producing objects in the Sound3D environment.
Definition: Source.java:48
void setBuffer(final Buffer buffer)
Associates the buffer with this source if buffer is not null, otherwise disassociates the previously ...
Definition: Source.java:526
This class is a holder for WAV (.wav ) file Data returned from the WavLoader, or directly via loadFro...
Definition: WAVData.java:53
final int format
the format of the Data.
Definition: WAVData.java:66
final ByteBuffer data
The audio data.
Definition: WAVData.java:55
final int freq
The frequency of the data.
Definition: WAVData.java:72
A Loader utility for (.wav) files.
Definition: WAVLoader.java:51
static WAVData loadFromStream(final InputStream stream)
This method loads a (.wav) file into a WAVData object.
Definition: WAVLoader.java:81
static WAVData loadFromFile(final String filename)
This method loads a (.wav) file into a WAVData object.
Definition: WAVLoader.java:64
static final int ALC_NO_ERROR
Define "ALC_NO_ERROR" with expression '0', CType: int.
int alcGetError(ALCdevice device)
Entry point (through function pointer) to C language function: ALCenum alcGetError(ALCdevice * dev...
String alcGetString(ALCdevice device, int param)
Entry point (through function pointer) to C language function: const ALCchar * alcGetString(ALCdevi...
static final int AL_NO_ERROR
Define "AL_NO_ERROR" with expression '0', CType: int.
int alGetError()
Entry point (through function pointer) to C language function: ALenum alGetError()
void alGenBuffers(int n, IntBuffer buffers)
Entry point (through function pointer) to C language function: void alGenBuffers(ALsizei n,...
void alGenSources(int n, IntBuffer sources)
Entry point (through function pointer) to C language function: void alGenSources(ALsizei n,...
String alGetString(int param)
Entry point (through function pointer) to C language function: const ALchar * alGetString(ALenum pa...