summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/java/com/jogamp/openal/util/ALHelpers.java376
1 files changed, 376 insertions, 0 deletions
diff --git a/src/java/com/jogamp/openal/util/ALHelpers.java b/src/java/com/jogamp/openal/util/ALHelpers.java
new file mode 100644
index 0000000..9592b95
--- /dev/null
+++ b/src/java/com/jogamp/openal/util/ALHelpers.java
@@ -0,0 +1,376 @@
+/*
+ * OpenAL Helpers
+ *
+ * Copyright (c) 2011 by Chris Robinson <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This file contains routines to help with some menial OpenAL-related tasks,
+ * such as opening a device and setting up a context, closing the device and
+ * destroying its context, converting between frame counts and byte lengths,
+ * finding an appropriate buffer format, and getting readable strings for
+ * channel configs and sample types. */
+package com.jogamp.openal.util;
+
+import com.jogamp.openal.AL;
+import com.jogamp.openal.ALConstants;
+import static com.jogamp.openal.ALConstants.*;
+import com.jogamp.openal.ALExt;
+// import com.jogamp.openal.ALExtConstants;
+import static com.jogamp.openal.ALExtConstants.*;
+
+
+/* This file contains routines to help with some menial OpenAL-related tasks,
+ * such as converting between frame counts and byte lengths,
+ * finding an appropriate buffer format, and getting readable strings for
+ * channel configs and sample types. */
+public class ALHelpers {
+
+ /**
+ * Returns a compatible AL buffer format given the AL channel layout and
+ * AL sample type. If <code>hasSOFTBufferSamples</code> is true,
+ * it will be called to find the closest-matching format from
+ * <code>AL_SOFT_buffer_samples</code>.
+ * <p>
+ * Returns {@link ALConstants#AL_NONE} if no supported format can be found.
+ * </p>
+ *
+ * @param alChannelLayout AL channel layout, see {@link #getDefaultALChannelLayout(int)}
+ * @param alSampleType AL sample type, see {@link #getALSampleType(int, boolean, boolean)}.
+ * @param hasSOFTBufferSamples true if having extension <code>AL_SOFT_buffer_samples</code>, otherwise false
+ * @param al AL instance
+ * @param alExt ALExt instance
+ * @return AL buffer format
+ */
+ public static final int getALFormat(final int alChannelLayout, final int alSampleType,
+ final boolean hasSOFTBufferSamples, final AL al, final ALExt alExt) {
+ int format = AL_NONE;
+
+ /* If using AL_SOFT_buffer_samples, try looking through its formats */
+ if(hasSOFTBufferSamples)
+ {
+ /* AL_SOFT_buffer_samples is more lenient with matching formats. The
+ * specified sample type does not need to match the returned format,
+ * but it is nice to try to get something close. */
+ if(alSampleType == AL_UNSIGNED_BYTE_SOFT || alSampleType == AL_BYTE_SOFT)
+ {
+ if(alChannelLayout == AL_MONO_SOFT) format = AL_MONO8_SOFT;
+ else if(alChannelLayout == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
+ else if(alChannelLayout == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
+ else if(alChannelLayout == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
+ else if(alChannelLayout == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
+ else if(alChannelLayout == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
+ }
+ else if(alSampleType == AL_UNSIGNED_SHORT_SOFT || alSampleType == AL_SHORT_SOFT)
+ {
+ if(alChannelLayout == AL_MONO_SOFT) format = AL_MONO16_SOFT;
+ else if(alChannelLayout == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
+ else if(alChannelLayout == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
+ else if(alChannelLayout == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
+ else if(alChannelLayout == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
+ else if(alChannelLayout == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
+ }
+ else if(alSampleType == AL_UNSIGNED_BYTE3_SOFT || alSampleType == AL_BYTE3_SOFT ||
+ alSampleType == AL_UNSIGNED_INT_SOFT || alSampleType == AL_INT_SOFT ||
+ alSampleType == AL_FLOAT_SOFT || alSampleType == AL_DOUBLE_SOFT)
+ {
+ if(alChannelLayout == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
+ else if(alChannelLayout == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
+ else if(alChannelLayout == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
+ else if(alChannelLayout == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
+ else if(alChannelLayout == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
+ else if(alChannelLayout == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
+ }
+
+ if(format != AL_NONE && !alExt.alIsBufferFormatSupportedSOFT(format))
+ format = AL_NONE;
+
+ /* A matching format was not found or supported. Try 32-bit float. */
+ if(format == AL_NONE)
+ {
+ if(alChannelLayout == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
+ else if(alChannelLayout == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
+ else if(alChannelLayout == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
+ else if(alChannelLayout == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
+ else if(alChannelLayout == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
+ else if(alChannelLayout == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
+
+ if(format != AL_NONE && !alExt.alIsBufferFormatSupportedSOFT(format))
+ format = AL_NONE;
+ }
+ /* 32-bit float not supported. Try 16-bit int. */
+ if(format == AL_NONE)
+ {
+ if(alChannelLayout == AL_MONO_SOFT) format = AL_MONO16_SOFT;
+ else if(alChannelLayout == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
+ else if(alChannelLayout == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
+ else if(alChannelLayout == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
+ else if(alChannelLayout == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
+ else if(alChannelLayout == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
+
+ if(format != AL_NONE && !alExt.alIsBufferFormatSupportedSOFT(format))
+ format = AL_NONE;
+ }
+ /* 16-bit int not supported. Try 8-bit int. */
+ if(format == AL_NONE)
+ {
+ if(alChannelLayout == AL_MONO_SOFT) format = AL_MONO8_SOFT;
+ else if(alChannelLayout == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
+ else if(alChannelLayout == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
+ else if(alChannelLayout == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
+ else if(alChannelLayout == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
+ else if(alChannelLayout == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
+
+ if(format != AL_NONE && !alExt.alIsBufferFormatSupportedSOFT(format))
+ format = AL_NONE;
+ }
+
+ return format;
+ }
+
+ /* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
+ * and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
+ * AL_EXT_DOUBLE for 64-bit float samples. */
+ if(alSampleType == AL_UNSIGNED_BYTE_SOFT)
+ {
+ if(alChannelLayout == AL_MONO_SOFT)
+ format = AL_FORMAT_MONO8;
+ else if(alChannelLayout == AL_STEREO_SOFT)
+ format = AL_FORMAT_STEREO8;
+ else if(al.alIsExtensionPresent("AL_EXT_MCFORMATS"))
+ {
+ if(alChannelLayout == AL_QUAD_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_QUAD8");
+ else if(alChannelLayout == AL_5POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_51CHN8");
+ else if(alChannelLayout == AL_6POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_61CHN8");
+ else if(alChannelLayout == AL_7POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_71CHN8");
+ }
+ }
+ else if(alSampleType == AL_SHORT_SOFT)
+ {
+ if(alChannelLayout == AL_MONO_SOFT)
+ format = AL_FORMAT_MONO16;
+ else if(alChannelLayout == AL_STEREO_SOFT)
+ format = AL_FORMAT_STEREO16;
+ else if(al.alIsExtensionPresent("AL_EXT_MCFORMATS"))
+ {
+ if(alChannelLayout == AL_QUAD_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_QUAD16");
+ else if(alChannelLayout == AL_5POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_51CHN16");
+ else if(alChannelLayout == AL_6POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_61CHN16");
+ else if(alChannelLayout == AL_7POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_71CHN16");
+ }
+ }
+ else if(alSampleType == AL_FLOAT_SOFT && al.alIsExtensionPresent("AL_EXT_FLOAT32"))
+ {
+ if(alChannelLayout == AL_MONO_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
+ else if(alChannelLayout == AL_STEREO_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
+ else if(al.alIsExtensionPresent("AL_EXT_MCFORMATS"))
+ {
+ if(alChannelLayout == AL_QUAD_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_QUAD32");
+ else if(alChannelLayout == AL_5POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_51CHN32");
+ else if(alChannelLayout == AL_6POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_61CHN32");
+ else if(alChannelLayout == AL_7POINT1_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_71CHN32");
+ }
+ }
+ else if(alSampleType == AL_DOUBLE_SOFT && al.alIsExtensionPresent("AL_EXT_DOUBLE"))
+ {
+ if(alChannelLayout == AL_MONO_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
+ else if(alChannelLayout == AL_STEREO_SOFT)
+ format = al.alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
+ }
+
+ /* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as
+ * opposed to 0. Correct it. */
+ if(format == -1) {
+ format = AL_NONE;
+ }
+
+ return format;
+ }
+
+ /**
+ * Returns the default AL channel layout matching the given channel count, or {@link ALConstants#AL_NONE}.
+ * @param channelCount number of channels
+ * @param signed true if signed number, false for unsigned
+ * @param fixedP true for fixed point value, false for floating point value with a sampleSize of 32 (float) or 64 (double)
+ */
+ public static final int getDefaultALChannelLayout(final int channelCount) {
+ switch(channelCount) {
+ case 1: return AL_MONO_SOFT;
+ case 2: return AL_STEREO_SOFT;
+ // case 2: return AL_REAR_SOFT;
+ case 4: return AL_QUAD_SOFT;
+ case 6: return AL_5POINT1_SOFT;
+ case 7: return AL_6POINT1_SOFT;
+ case 8: return AL_7POINT1_SOFT;
+ }
+ return AL_NONE;
+ }
+
+ /**
+ * Returns the readable name of the given AL channel layout
+ */
+ public static final String alChannelLayoutName(final int alChannelLayout) {
+ switch(alChannelLayout) {
+ case AL_MONO_SOFT: return "Mono";
+ case AL_STEREO_SOFT: return "Stereo";
+ case AL_REAR_SOFT: return "Rear";
+ case AL_QUAD_SOFT: return "Quadraphonic";
+ case AL_5POINT1_SOFT: return "5.1 Surround";
+ case AL_6POINT1_SOFT: return "6.1 Surround";
+ case AL_7POINT1_SOFT: return "7.1 Surround";
+ }
+ return "Unknown AL-Channel-Layout 0x"+Integer.toHexString(alChannelLayout);
+ }
+
+ /**
+ * Returns the AL sample type matching the given audio type attributes, or {@link ALConstants#AL_NONE}.
+ * @param sampleSize sample size in bits
+ * @param signed true if signed number, false for unsigned
+ * @param fixedP true for fixed point value, false for floating point value with a sampleSize of 32 (float) or 64 (double)
+ */
+ public static final int getALSampleType(final int sampleSize, boolean signed, boolean fixedP) {
+ if( fixedP ) {
+ if( signed ) {
+ switch( sampleSize ) {
+ case 8: return AL_BYTE_SOFT;
+ case 16: return AL_SHORT_SOFT;
+ case 32: return AL_INT_SOFT;
+ }
+ } else {
+ switch( sampleSize ) {
+ case 8: return AL_UNSIGNED_BYTE_SOFT;
+ case 16: return AL_UNSIGNED_SHORT_SOFT;
+ case 32: return AL_UNSIGNED_INT_SOFT;
+ }
+ }
+ } else {
+ if( signed ) {
+ switch( sampleSize ) {
+ case 32: return AL_FLOAT_SOFT;
+ case 64: return AL_DOUBLE_SOFT;
+ }
+ }
+ }
+ return AL_NONE;
+ }
+
+ /**
+ * Returns the readable name of the given AL sample type
+ */
+ public static final String alSampleTypeName(final int alSampleType) {
+ switch(alSampleType) {
+ case AL_BYTE_SOFT: return "S8";
+ case AL_UNSIGNED_BYTE_SOFT: return "U8";
+ case AL_SHORT_SOFT: return "S16";
+ case AL_UNSIGNED_SHORT_SOFT: return "U16";
+ case AL_INT_SOFT: return "S32";
+ case AL_UNSIGNED_INT_SOFT: return "U32";
+ case AL_FLOAT_SOFT: return "F32";
+ case AL_DOUBLE_SOFT: return "F64";
+ }
+ return "Unknown AL-Type 0x"+Integer.toHexString(alSampleType);
+ }
+
+ /**
+ * Returns the byte size of the given AL sample type
+ * @throws IllegalArgumentException for unknown <code>alChannelLayout</code> or <code>alSampleType</code> values.
+ */
+ public static final int sizeOfALSampleType(final int alSampleType) throws IllegalArgumentException {
+ switch(alSampleType) {
+ case AL_BYTE_SOFT:
+ case AL_UNSIGNED_BYTE_SOFT:
+ return 1;
+ case AL_SHORT_SOFT:
+ case AL_UNSIGNED_SHORT_SOFT:
+ return 2;
+ case AL_INT_SOFT:
+ case AL_UNSIGNED_INT_SOFT:
+ case AL_FLOAT_SOFT:
+ return 4;
+ case AL_DOUBLE_SOFT:
+ return 8;
+ default:
+ throw new IllegalArgumentException("Unknown al-type 0x"+Integer.toHexString(alSampleType));
+ }
+ }
+
+ /**
+ * @param sampleCount number of samples per channel
+ * @param alChannelLayout AL channel layout
+ * @param alSampleType AL sample type
+ * @return bytes count required
+ * @throws IllegalArgumentException for unknown <code>alChannelLayout</code> or <code>alSampleType</code> values.
+ */
+ public static final int samplesToByteCount(int sampleCount, final int alChannelLayout, final int alSampleType)
+ throws IllegalArgumentException
+ {
+ switch(alChannelLayout) {
+ case AL_MONO_SOFT: sampleCount *= 1; break;
+ case AL_STEREO_SOFT: sampleCount *= 2; break;
+ case AL_REAR_SOFT: sampleCount *= 2; break;
+ case AL_QUAD_SOFT: sampleCount *= 4; break;
+ case AL_5POINT1_SOFT: sampleCount *= 6; break;
+ case AL_6POINT1_SOFT: sampleCount *= 7; break;
+ case AL_7POINT1_SOFT: sampleCount *= 8; break;
+ default: throw new IllegalArgumentException("Unknown al-channel-layout 0x"+Integer.toHexString(alChannelLayout));
+ }
+
+ switch(alSampleType) {
+ case AL_BYTE_SOFT:
+ case AL_UNSIGNED_BYTE_SOFT:
+ break;
+ case AL_SHORT_SOFT:
+ case AL_UNSIGNED_SHORT_SOFT:
+ sampleCount *= 2;
+ break;
+ case AL_INT_SOFT:
+ case AL_UNSIGNED_INT_SOFT:
+ case AL_FLOAT_SOFT:
+ sampleCount *= 4;
+ break;
+ case AL_DOUBLE_SOFT:
+ sampleCount *= 8;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown al-type 0x"+Integer.toHexString(alSampleType));
+ }
+
+ return sampleCount;
+ }
+
+ public static final int bytesToSampleCount(final int byteCount, final int alChannelLayout, final int alSampleType) {
+ return byteCount / samplesToByteCount(1, alChannelLayout, alSampleType);
+ }
+}