Add support for URA, or Unified Renderer Architecture for audio

* Unified all renderers into common class 'ALAudioRenderer'
 * LWJGL and Android now implement the AL / ALC / EFX interfaces to provide a common OpenAL backend for jME
 * Added support for OpenAL Soft "Pause Device" extension, which allows the engine to pause the context while running in the background (currently requires OpenAL soft 1.16 and thus is Android only feature)
experimental
shadowislord 10 years ago
parent e3c0b0ae38
commit 91715c4a48
  1. 21
      jme3-android-native/openalsoft.gradle
  2. 4
      jme3-android-native/src/native/jme_openalsoft/Android.mk
  3. 134
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.c
  4. 173
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.h
  5. 174
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.c
  6. 77
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.h
  7. 75
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.c
  8. 101
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.h
  9. 483
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp
  10. 15
      jme3-android-native/src/native/jme_openalsoft/util.h
  11. 20
      jme3-android/src/main/java/com/jme3/app/AndroidHarness.java
  12. 53
      jme3-android/src/main/java/com/jme3/audio/android/AndroidAL.java
  13. 30
      jme3-android/src/main/java/com/jme3/audio/android/AndroidALC.java
  14. 24
      jme3-android/src/main/java/com/jme3/audio/android/AndroidAudioRenderer.java
  15. 32
      jme3-android/src/main/java/com/jme3/audio/android/AndroidEFX.java
  16. 2
      jme3-android/src/main/java/com/jme3/audio/android/AndroidMediaPlayerAudioRenderer.java
  17. 1423
      jme3-android/src/main/java/com/jme3/audio/android/AndroidOpenALSoftAudioRenderer.java
  18. 18
      jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java
  19. 12
      jme3-core/src/main/java/com/jme3/audio/AudioRenderer.java
  20. 296
      jme3-core/src/main/java/com/jme3/audio/openal/AL.java
  21. 295
      jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java
  22. 73
      jme3-core/src/main/java/com/jme3/audio/openal/ALC.java
  23. 43
      jme3-core/src/main/java/com/jme3/audio/openal/ALUtil.java
  24. 405
      jme3-core/src/main/java/com/jme3/audio/openal/EFX.java
  25. 29
      jme3-desktop/src/main/java/com/jme3/system/JmeDesktopSystem.java
  26. 20
      jme3-jogl/src/main/java/com/jme3/audio/joal/JoalAudioRenderer.java
  27. 107
      jme3-lwjgl/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java
  28. 50
      jme3-lwjgl/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
  29. 65
      jme3-lwjgl/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java

@ -72,20 +72,13 @@ task copyJmeOpenALSoft(type: Copy, dependsOn:copyOpenALSoft) {
into outputDir into outputDir
} }
task generateOpenAlSoftHeaders(dependsOn: copyJmeOpenALSoft) << { task generateOpenAlSoftHeaders(type:Exec, dependsOn: copyJmeOpenALSoft) {
String destDirPath = openalsoftBuildJniDir executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
String classes = "" args '-d', openalsoftJmeAndroidPath
.concat("com.jme3.audio.android.AndroidOpenALSoftAudioRenderer, ") args '-classpath', project.projectClassPath
// println "openalsoft classes = " + classes args "com.jme3.audio.android.AndroidAL"
// println "openalsoft destDir = " + destDirPath args "com.jme3.audio.android.AndroidALC"
// println "openalsoft classpath = " + project.projectClassPath args "com.jme3.audio.android.AndroidEFX"
exec {
executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
args '-d', destDirPath
args '-classpath', project.projectClassPath
args "com.jme3.audio.android.AndroidOpenALSoftAudioRenderer"
}
} }
task buildOpenAlSoftNativeLib(type: Exec, dependsOn: generateOpenAlSoftHeaders) { task buildOpenAlSoftNativeLib(type: Exec, dependsOn: generateOpenAlSoftHeaders) {

@ -62,7 +62,9 @@ LOCAL_SRC_FILES := Alc/backends/opensl.c \
OpenAL32/alSource.c \ OpenAL32/alSource.c \
OpenAL32/alState.c \ OpenAL32/alState.c \
OpenAL32/sample_cvt.c \ OpenAL32/sample_cvt.c \
com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp com_jme3_audio_android_AndroidAL.c \
com_jme3_audio_android_AndroidALC.c \
com_jme3_audio_android_AndroidEFX.c
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

@ -0,0 +1,134 @@
#include "com_jme3_audio_android_AndroidAL.h"
#include "AL/al.h"
#include "AL/alext.h"
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidAL_alGetString
(JNIEnv* env, jobject obj, jint param)
{
return (*env)->NewStringUTF(env, alGetString(param));
}
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGenSources
(JNIEnv *env, jobject obj)
{
ALuint source;
alGenSources(1, &source);
return source;
}
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetError
(JNIEnv *env, jobject obj)
{
return alGetError();
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteSources
(JNIEnv* env, jobject obj, jint numSources, jobject intbufSources)
{
ALuint* pIntBufSources = (ALuint*) (*env)->GetDirectBufferAddress(env, intbufSources);
alDeleteSources((ALsizei)numSources, pIntBufSources);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alGenBuffers
(JNIEnv* env, jobject obj, jint numBuffers, jobject intbufBuffers)
{
ALuint* pIntBufBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, intbufBuffers);
alGenBuffers((ALsizei)numBuffers, pIntBufBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteBuffers
(JNIEnv* env, jobject obj, jint numBuffers, jobject intbufBuffers)
{
ALuint* pIntBufBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, intbufBuffers);
alDeleteBuffers((ALsizei)numBuffers, pIntBufBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceStop
(JNIEnv *env, jobject obj, jint source)
{
alSourceStop((ALuint)source);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcei
(JNIEnv *env, jobject obj, jint source, jint param, jint value)
{
alSourcei((ALuint)source, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alBufferData
(JNIEnv* env, jobject obj, jint buffer, jint format, jobject bufferData, jint bufferSize, jint frequency)
{
ALuint* pBufferData = (ALuint*) (*env)->GetDirectBufferAddress(env, bufferData);
alBufferData((ALuint)buffer, (ALenum)format, pBufferData, (ALsizei)bufferSize, (ALsizei)frequency);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePlay
(JNIEnv *env, jobject obj, jint source)
{
alSourcePlay((ALuint)source);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePause
(JNIEnv *env, jobject obj, jint source)
{
alSourcePause((ALuint)source);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcef
(JNIEnv *env, jobject obj, jint source, jint param, jfloat value)
{
alSourcef((ALuint)source, (ALenum)param, (ALfloat)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3f
(JNIEnv *env, jobject obj, jint source, jint param, jfloat value1, jfloat value2, jfloat value3)
{
alSource3f((ALuint)source, (ALenum)param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
}
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetSourcei
(JNIEnv *env, jobject obj, jint source, jint param)
{
ALint result;
alGetSourcei((ALuint)source, (ALenum)param, &result);
return (jint)result;
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceUnqueueBuffers
(JNIEnv* env, jobject obj, jint source, jint numBuffers, jobject buffers)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffers);
alSourceUnqueueBuffers((ALuint)source, (ALsizei)numBuffers, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceQueueBuffers
(JNIEnv* env, jobject obj, jint source, jint numBuffers, jobject buffers)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffers);
alSourceQueueBuffers((ALuint)source, (ALsizei)numBuffers, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener
(JNIEnv* env, jobject obj, jint param, jobject bufferData)
{
ALfloat* pBufferData = (ALfloat*) (*env)->GetDirectBufferAddress(env, bufferData);
alListenerfv((ALenum)param, pBufferData);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListenerf
(JNIEnv *env, jobject obj, jint param, jfloat value)
{
alListenerf((ALenum)param, (ALfloat)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener3f
(JNIEnv *env, jobject obj, jint param, jfloat value1, jfloat value2, jfloat value3)
{
alListener3f((ALenum)param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3i
(JNIEnv *env, jobject obj, jint source, jint param, jint value1, jint value2, jint value3)
{
alSource3i((ALuint)source, (ALenum)param, (ALint)value1, (ALint)value2, (ALint)value3);
}

@ -0,0 +1,173 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jme3_audio_android_AndroidAL */
#ifndef _Included_com_jme3_audio_android_AndroidAL
#define _Included_com_jme3_audio_android_AndroidAL
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGetString
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidAL_alGetString
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGenSources
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGenSources
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGetError
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetError
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alDeleteSources
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteSources
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGenBuffers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alGenBuffers
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alDeleteBuffers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteBuffers
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourceStop
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceStop
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcei
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcei
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alBufferData
* Signature: (IILjava/nio/ByteBuffer;II)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alBufferData
(JNIEnv *, jobject, jint, jint, jobject, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcePlay
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePlay
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcePause
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePause
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcef
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcef
(JNIEnv *, jobject, jint, jint, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSource3f
* Signature: (IIFFF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3f
(JNIEnv *, jobject, jint, jint, jfloat, jfloat, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGetSourcei
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetSourcei
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourceUnqueueBuffers
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceUnqueueBuffers
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourceQueueBuffers
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceQueueBuffers
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alListener
* Signature: (ILjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alListenerf
* Signature: (IF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListenerf
(JNIEnv *, jobject, jint, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alListener3f
* Signature: (IFFF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener3f
(JNIEnv *, jobject, jint, jfloat, jfloat, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSource3i
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3i
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,174 @@
#include "util.h"
#include "com_jme3_audio_android_AndroidALC.h"
#include "AL/alc.h"
#include "AL/alext.h"
static jboolean created = JNI_FALSE;
/* InitAL opens the default device and sets up a context using default
* attributes, making the program ready to call OpenAL functions. */
static int InitAL()
{
ALCdevice *device = NULL;
ALCcontext *ctx = NULL;
/* Open and initialize a device with default settings */
device = alcOpenDevice(NULL);
if(device == NULL)
{
fprintf(stderr, "Could not open a device!\n");
goto cleanup;
}
ctx = alcCreateContext(device, NULL);
if (ctx == NULL)
{
fprintf(stderr, "Could not create context!\n");
goto cleanup;
}
if (!alcMakeContextCurrent(ctx))
{
fprintf(stderr, "Could not make context current!\n");
goto cleanup;
}
return 0;
cleanup:
if (ctx != NULL) alcDestroyContext(ctx);
if (device != NULL) alcCloseDevice(device);
return 1;
}
/* CloseAL closes the device belonging to the current context, and destroys the
* context. */
static void CloseAL()
{
ALCdevice *device;
ALCcontext *ctx;
ctx = alcGetCurrentContext();
if (ctx == NULL)
{
return;
}
device = alcGetContextsDevice(ctx);
if (device == NULL)
{
return;
}
if(!alcMakeContextCurrent(NULL)) {
return;
}
alcDestroyContext(ctx);
alcCloseDevice(device);
}
static ALCdevice* GetALCDevice()
{
ALCdevice *device;
ALCcontext *ctx;
ctx = alcGetCurrentContext();
if (ctx != NULL)
{
device = alcGetContextsDevice(ctx);
if (device != NULL)
{
return device;
}
}
return NULL;
}
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_isCreated
(JNIEnv* env, jobject obj)
{
return created;
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_createALC
(JNIEnv* env, jobject obj)
{
created = (InitAL() == 0);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_destroyALC
(JNIEnv* env, jobject obj)
{
CloseAL();
created = JNI_FALSE;
}
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetString
(JNIEnv* env, jobject obj, jint param)
{
ALCdevice* device = GetALCDevice();
if (device == NULL) return NULL;
return (*env)->NewStringUTF(env, alcGetString(device, param));
}
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_alcIsExtensionPresent
(JNIEnv* env, jobject obj, jstring extension)
{
ALCdevice* device = GetALCDevice();
if (device == NULL) return JNI_FALSE;
const char* strExtension = (*env)->GetStringUTFChars(env, extension, NULL);
if (strExtension == NULL)
{
return JNI_FALSE;
}
jboolean result = alcIsExtensionPresent(device, strExtension);
(*env)->ReleaseStringUTFChars(env, extension, strExtension);
return result;
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetInteger
(JNIEnv* env, jobject obj, jint param, jobject buffer, jint bufferSize)
{
ALCdevice* device = GetALCDevice();
if (device == NULL) return;
ALCint* pBuffers = (ALCint*) (*env)->GetDirectBufferAddress(env, buffer);
alcGetIntegerv(device, (ALCenum)param, (ALCsizei)bufferSize, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDevicePauseSOFT
(JNIEnv* env, jobject obj)
{
ALCdevice* device = GetALCDevice();
if (device == NULL) return;
alcDevicePauseSOFT(device);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDeviceResumeSOFT
(JNIEnv* env, jobject obj)
{
ALCdevice* device = GetALCDevice();
if (device == NULL) return;
alcDeviceResumeSOFT(device);
}

@ -0,0 +1,77 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jme3_audio_android_AndroidALC */
#ifndef _Included_com_jme3_audio_android_AndroidALC
#define _Included_com_jme3_audio_android_AndroidALC
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: createALC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_createALC
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: destroyALC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_destroyALC
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: isCreated
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_isCreated
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcGetString
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetString
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcIsExtensionPresent
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_alcIsExtensionPresent
(JNIEnv *, jobject, jstring);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcGetInteger
* Signature: (ILjava/nio/IntBuffer;I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetInteger
(JNIEnv *, jobject, jint, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcDevicePauseSOFT
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDevicePauseSOFT
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcDeviceResumeSOFT
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDeviceResumeSOFT
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,75 @@
#include "util.h"
#include "com_jme3_audio_android_AndroidEFX.h"
#include "AL/alext.h"
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenAuxiliaryEffectSlots
(JNIEnv* env, jobject obj, jint numSlots, jobject buffer)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffer);
alGenAuxiliaryEffectSlots((ALsizei)numSlots, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenEffects
(JNIEnv* env, jobject obj, jint numEffects, jobject buffer)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffer);
alGenEffects((ALsizei)numEffects, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffecti
(JNIEnv* env, jobject obj, jint effect, jint param, jint value)
{
alEffecti((ALuint)effect, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alAuxiliaryEffectSloti
(JNIEnv* env, jobject obj, jint effectSlot, jint param, jint value)
{
alAuxiliaryEffectSloti((ALuint)effectSlot, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteEffects
(JNIEnv* env, jobject obj, jint numEffects, jobject buffer)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffer);
alDeleteEffects((ALsizei)numEffects, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteAuxiliaryEffectSlots
(JNIEnv* env, jobject obj, jint numEffectSlots, jobject buffer)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffer);
alDeleteAuxiliaryEffectSlots((ALsizei)numEffectSlots, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenFilters
(JNIEnv* env, jobject obj, jint numFilters, jobject buffer)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffer);
alGenFilters((ALsizei)numFilters, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilteri
(JNIEnv* env, jobject obj, jint filter, jint param, jint value)
{
alFilteri((ALuint)filter, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilterf
(JNIEnv* env, jobject obj, jint filter, jint param, jfloat value)
{
alFilterf((ALuint)filter, (ALenum)param, (ALfloat)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteFilters
(JNIEnv* env, jobject obj, jint numFilters, jobject buffer)
{
ALuint* pBuffers = (ALuint*) (*env)->GetDirectBufferAddress(env, buffer);
alDeleteFilters((ALsizei)numFilters, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffectf
(JNIEnv* env, jobject obj, jint effect, jint param, jfloat value)
{
alEffectf((ALuint)effect, (ALenum)param, (ALfloat)value);
}

@ -0,0 +1,101 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jme3_audio_android_AndroidEFX */
#ifndef _Included_com_jme3_audio_android_AndroidEFX
#define _Included_com_jme3_audio_android_AndroidEFX
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alGenAuxiliaryEffectSlots
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenAuxiliaryEffectSlots
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alGenEffects
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenEffects
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alEffecti
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffecti
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alAuxiliaryEffectSloti
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alAuxiliaryEffectSloti
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alDeleteEffects
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteEffects
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alDeleteAuxiliaryEffectSlots
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteAuxiliaryEffectSlots
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alGenFilters
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenFilters
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alFilteri
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilteri
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alFilterf
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilterf
(JNIEnv *, jobject, jint, jint, jfloat);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alDeleteFilters
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteFilters
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alEffectf
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffectf
(JNIEnv *, jobject, jint, jint, jfloat);
#ifdef __cplusplus
}
#endif
#endif

@ -1,483 +0,0 @@
#include "com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.h"
#include "AL/alc.h"
#include "AL/al.h"
#include "AL/alext.h"
// for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message");
#include <android/log.h>
#include <jni.h>
#include <stddef.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
static jboolean created = JNI_FALSE;
#define BUFFER_COUNT 1
ALuint* buffers[BUFFER_COUNT] = { 0 };
ALuint* source = 0;
int getError() {
int errorcode = alGetError();
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "getError: %d", errorcode);
return errorcode;
}
/* InitAL opens the default device and sets up a context using default
* attributes, making the program ready to call OpenAL functions. */
int InitAL()
{
ALCdevice *device;
ALCcontext *ctx;
/* Open and initialize a device with default settings */
device = alcOpenDevice(NULL);
if(!device)
{
fprintf(stderr, "Could not open a device!\n");
return 1;
}
ctx = alcCreateContext(device, NULL);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "NULL: %d", NULL);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Created context: %d", ctx);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Created context addr: %d", &ctx);
if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
{
if(ctx != NULL)
alcDestroyContext(ctx);
alcCloseDevice(device);
fprintf(stderr, "Could not set a context!\n");
return 1;
}
printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Opened %s", alcGetString(device, ALC_DEVICE_SPECIFIER));
return 0;
}
/* CloseAL closes the device belonging to the current context, and destroys the
* context. */
void CloseAL()
{
ALCdevice *device;
ALCcontext *ctx;
ALCboolean result;
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Getting current context");
ctx = alcGetCurrentContext();
// getError();
if(ctx == NULL){
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "No context found");
return;
}
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Getting current context device");
device = alcGetContextsDevice(ctx);
if(device == NULL) {
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "No device found");
return;
} else {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetContextsDevice device: %d", device);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetContextsDevice device addr: %d", &device);
}
// getError();
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Setting context to NULL");
result = alcMakeContextCurrent(NULL);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcMakeContextCurrent returned");
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcMakeContextCurrent returned with result: %d", result);
if(!result) {
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcMakeContextCurrent failed");
return;
}
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Destroying context: %d", ctx);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Destroying context addr: %d", &ctx);
alcDestroyContext(ctx);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Closing device");
result = alcCloseDevice(device);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcCloseDevice result: %d", result);
}
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alIsCreated
(JNIEnv* env, jclass)
{
return created;
}
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alCreate
(JNIEnv* env, jclass)
{
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Starting Audio Engine");
InitAL();
created = JNI_TRUE;
return created;
}
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDestroy
(JNIEnv* env, jclass)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDestroy");
CloseAL();
created = JNI_FALSE;
return created;
}
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alcGetString
(JNIEnv* env, jclass, jint param)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetString for param: %d", param);
ALCdevice *device;
ALCcontext *ctx;
ctx = alcGetCurrentContext();
if(ctx != NULL) {
device = alcGetContextsDevice(ctx);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetString param value: %s", alcGetString(device, param));
return env->NewStringUTF(alcGetString(device, param));
}
}
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetString
(JNIEnv* env, jclass, jint param)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGetString for param: %d", param);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGetString param value: %s", alGetString(param));
return env->NewStringUTF(alGetString(param));
}
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenSources
(JNIEnv *, jclass)
{
ALuint source;
alGenSources(1, &source);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenSources: %d", source);
return source;
}
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetError
(JNIEnv *, jclass)
{
return getError();
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteSources
(JNIEnv* env, jclass, jint numSources, jobject intbufSources)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteSources numSources: %d", numSources);
ALuint* pIntBufSources = (ALuint*) env->GetDirectBufferAddress(intbufSources);
alDeleteSources((ALsizei)numSources, pIntBufSources);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenBuffers
(JNIEnv* env, jclass, jint numBuffers, jobject intbufBuffers)
{
ALuint* pIntBufBuffers = (ALuint*) env->GetDirectBufferAddress(intbufBuffers);
alGenBuffers((ALsizei)numBuffers, pIntBufBuffers);
// for (int i=0; i<numBuffers; i++) {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenBuffers[%d]: %d", i, *(pIntBufBuffers+i));
// }
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteBuffers
(JNIEnv* env, jclass, jint numBuffers, jobject intbufBuffers)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers numBuffers: %d", numBuffers);
ALuint* pIntBufBuffers = (ALuint*) env->GetDirectBufferAddress(intbufBuffers);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers Buffers: %d", *pIntBufBuffers);
// for (int i=0; i<numBuffers; i++) {
// if(alIsBuffer(*(pIntBufBuffers+i)) == AL_TRUE) {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers[%d]: %d", i, *(pIntBufBuffers+i));
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers buffer is a known buffer");
// }
// }
alDeleteBuffers((ALsizei)numBuffers, pIntBufBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceStop
(JNIEnv *, jclass, jint source)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceStop for source: %d", source);
alSourceStop((ALuint)source);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcei
(JNIEnv *, jclass, jint source, jint param, jint value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcei for source: %d, param: %d, value: %d", source, param, value);
alSourcei((ALuint)source, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alBufferData
(JNIEnv* env, jclass, jint buffer, jint format, jobject bufferData, jint bufferSize, jint frequency)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alBufferData for source: %d, format: %d, size: %d, frequency: %d", buffer, format, bufferSize, frequency);
ALuint* pBufferData = (ALuint*) env->GetDirectBufferAddress(bufferData);
alBufferData((ALuint)buffer, (ALenum)format, pBufferData, (ALsizei)bufferSize, (ALsizei)frequency);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcePlay
(JNIEnv *, jclass, jint source)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcePlay for source: %d", source);
alSourcePlay((ALuint)source);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcePause
(JNIEnv *, jclass, jint source)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcePause for source: %d", source);
alSourcePause((ALuint)source);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcef
(JNIEnv *, jclass, jint source, jint param, jfloat value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcef for source: %d, param: %d, value: %f", source, param, value);
alSourcef((ALuint)source, (ALenum)param, (ALfloat)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSource3f
(JNIEnv *, jclass, jint source, jint param, jfloat value1, jfloat value2, jfloat value3)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSource3f for source: %d, param: %d, value1: %f, value2: %f, value3: %f", source, param, value1, value2, value3);
alSource3f((ALuint)source, (ALenum)param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
}
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetSourcei
(JNIEnv *, jclass, jint source, jint param)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGetSourcei for source: %d, param: %d", source, param);
ALint result;
alGetSourcei((ALuint)source, (ALenum)param, &result);
return (jint)result;
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceUnqueueBuffers
(JNIEnv* env, jclass, jint source, jint numBuffers, jobject buffers)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceUnqueueBuffers for source: %d, numBuffers: %d", source, numBuffers);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffers);
// for (ALuint i=0; i<numBuffers; i++) {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceUnqueueBuffers, checking buffer[%d]: %d", i, *(pBuffers+i));
// ALboolean isBuffer = alIsBuffer(*(pBuffers+i));
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "buffer check result: %d", isBuffer);
// }
alSourceUnqueueBuffers((ALuint)source, (ALsizei)numBuffers, pBuffers);
// for (ALuint i=0; i<numBuffers; i++) {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceUnqueueBuffers[%d]: %d", i, *(pBuffers+i));
// }
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceQueueBuffers
(JNIEnv* env, jclass, jint source, jint numBuffers, jobject buffers)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceQueueBuffers for source: %d, numBuffers: %d", source, numBuffers);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffers);
alSourceQueueBuffers((ALuint)source, (ALsizei)numBuffers, pBuffers);
// for (ALuint i=0; i<numBuffers; i++) {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceQueueBuffers[%d]: %d", i, *(pBuffers+i));
// }
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListener
(JNIEnv* env, jclass, jint param, jobject bufferData)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListener for param: %d", param);
ALfloat* pBufferData = (ALfloat*) env->GetDirectBufferAddress(bufferData);
alListenerfv((ALenum)param, pBufferData);
// getError();
// for (int i=0; i<4; i++) {
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListener[%d]: %f", i, *(pBufferData+(i*sizeof(ALfloat))));
// }
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListenerf
(JNIEnv *, jclass, jint param, jfloat value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListenerf for param: %d, value: %f", param, value);
alListenerf((ALenum)param, (ALfloat)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListener3f
(JNIEnv *, jclass, jint param, jfloat value1, jfloat value2, jfloat value3)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListener3f for param: %d, value1: %f, value2: %f, value3: %f", param, value1, value2, value3);
alListener3f((ALenum)param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
}
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alcIsExtensionPresent
(JNIEnv* env, jclass, jstring extension)
{
ALCdevice *device;
ALCcontext *ctx;
ALboolean result;
// char buf[128];
const char* strExtension;
jsize strLength = env->GetStringUTFLength(extension);
ctx = alcGetCurrentContext();
if(ctx != NULL) {
device = alcGetContextsDevice(ctx);
if (device != NULL) {
strExtension = env->GetStringUTFChars(extension, NULL);
if (strExtension == NULL) {
return JNI_FALSE; /* OutOfMemoryError already thrown */
}
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcIsExtensionPresent for param: %s with size: %d", strExtension, strLength);
result = alcIsExtensionPresent(device, strExtension);
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcIsExtensionPresent found: %d", result);
env->ReleaseStringUTFChars(extension, strExtension);
return (jboolean)result;
} else {
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "device is null in alcIsExtensionPresent");
}
} else {
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "current context is null in alcIsExtensionPresent");
}
return JNI_FALSE;
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alcGetInteger
(JNIEnv* env, jclass, jint param, jobject buffer, jint bufferSize)
{
ALCdevice *device;
ALCcontext *ctx;
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetInteger for param: %d", param);
ALCint* pBuffers = (ALCint*) env->GetDirectBufferAddress(buffer);
ctx = alcGetCurrentContext();
if(ctx != NULL) {
device = alcGetContextsDevice(ctx);
if (device != NULL) {
alcGetIntegerv(device, (ALCenum)param, (ALCsizei)bufferSize, pBuffers);
} else {
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "device is null in alcGetInteger");
}
} else {
__android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "current context is null in alcGetInteger");
}
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenAuxiliaryEffectSlots
(JNIEnv* env, jclass, jint numSlots, jobject buffer)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenAuxiliaryEffectSlots for numSlots: %d", numSlots);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffer);
alGenAuxiliaryEffectSlots((ALsizei)numSlots, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenEffects
(JNIEnv* env, jclass, jint numEffects, jobject buffer)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenEffects for numEffects: %d", numEffects);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffer);
alGenEffects((ALsizei)numEffects, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alEffecti
(JNIEnv *, jclass, jint effect, jint param, jint value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alEffecti for effect: %d, param: %d, value: %d", effect, param, value);
alEffecti((ALuint)effect, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alAuxiliaryEffectSloti
(JNIEnv *, jclass, jint effectSlot, jint param, jint value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alAuxiliaryEffectSloti for effect: %d, param: %d, value: %d", effectSlot, param, value);
alAuxiliaryEffectSloti((ALuint)effectSlot, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteEffects
(JNIEnv* env, jclass, jint numEffects, jobject buffer)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteEffects for numEffects: %d", numEffects);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffer);
alDeleteEffects((ALsizei)numEffects, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteAuxiliaryEffectSlots
(JNIEnv* env, jclass, jint numEffectSlots, jobject buffer)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteAuxiliaryEffectSlots for numEffectSlots: %d", numEffectSlots);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffer);
alDeleteAuxiliaryEffectSlots((ALsizei)numEffectSlots, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenFilters
(JNIEnv* env, jclass, jint numFilters, jobject buffer)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenFilters for numFilters: %d", numFilters);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffer);
alGenFilters((ALsizei)numFilters, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alFilteri
(JNIEnv *, jclass, jint filter, jint param, jint value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alFilteri for filter: %d, param: %d, value: %d", filter, param, value);
alFilteri((ALuint)filter, (ALenum)param, (ALint)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alFilterf
(JNIEnv *, jclass, jint filter, jint param, jfloat value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alFilterf for filter: %d, param: %d, value: %f", filter, param, value);
alFilterf((ALuint)filter, (ALenum)param, (ALfloat)value);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSource3i
(JNIEnv *, jclass, jint source, jint param, jint value1, jint value2, jint value3)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSource3i for source: %d, param: %d, value1: %d, value2: %d, value3: %d", source, param, value1, value2, value3);
alSource3i((ALuint)source, (ALenum)param, (ALint)value1, (ALint)value2, (ALint)value3);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteFilters
(JNIEnv* env, jclass, jint numFilters, jobject buffer)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteFilters for numFilters: %d", numFilters);
ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffer);
alDeleteFilters((ALsizei)numFilters, pBuffers);
}
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alEffectf
(JNIEnv *, jclass, jint effect, jint param, jfloat value)
{
// __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alEffectf for effect: %d, param: %d, value: %d", effect, param, value);
alEffectf((ALuint)effect, (ALenum)param, (ALfloat)value);
}
#ifdef __cplusplus
}
#endif

@ -0,0 +1,15 @@
#ifndef JME_UTIL_H
#define JME_UTIL_H
#include <stddef.h>
#include <stdio.h>
#ifndef NDEBUG
#include <android/log.h>
#define LOGI(fmt, ...) __android_log_print(ANDROID_LOG_INFO, \
"OpenALSoft", fmt, ##__VA_ARGS__);
#else
#define LOGI(fmt, ...)
#endif
#endif

@ -15,7 +15,6 @@ import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.jme3.audio.AudioRenderer; import com.jme3.audio.AudioRenderer;
import com.jme3.audio.android.AndroidAudioRenderer;
import com.jme3.input.JoyInput; import com.jme3.input.JoyInput;
import com.jme3.input.TouchInput; import com.jme3.input.TouchInput;
import com.jme3.input.android.AndroidSensorJoyInput; import com.jme3.input.android.AndroidSensorJoyInput;
@ -522,12 +521,9 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
if (app != null) { if (app != null) {
//resume the audio //resume the audio
AudioRenderer result = app.getAudioRenderer(); AudioRenderer audioRenderer = app.getAudioRenderer();
if (result != null) { if (audioRenderer != null) {
if (result instanceof AndroidAudioRenderer) { audioRenderer.resumeAll();
AndroidAudioRenderer renderer = (AndroidAudioRenderer) result;
renderer.resumeAll();
}
} }
//resume the sensors (aka joysticks) //resume the sensors (aka joysticks)
if (app.getContext() != null) { if (app.getContext() != null) {
@ -560,13 +556,9 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
if (app != null) { if (app != null) {
//pause the audio //pause the audio
AudioRenderer result = app.getAudioRenderer(); AudioRenderer audioRenderer = app.getAudioRenderer();
if (result != null) { if (audioRenderer != null) {
logger.log(Level.FINE, "pause: {0}", result.getClass().getSimpleName()); audioRenderer.pauseAll();
if (result instanceof AndroidAudioRenderer) {
AndroidAudioRenderer renderer = (AndroidAudioRenderer) result;
renderer.pauseAll();
}
} }
//pause the sensors (aka joysticks) //pause the sensors (aka joysticks)
if (app.getContext() != null) { if (app.getContext() != null) {

@ -0,0 +1,53 @@
package com.jme3.audio.android;
import com.jme3.audio.openal.AL;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public final class AndroidAL implements AL {
public AndroidAL() {
}
public native String alGetString(int parameter);
public native int alGenSources();
public native int alGetError();
public native void alDeleteSources(int numSources, IntBuffer sources);
public native void alGenBuffers(int numBuffers, IntBuffer buffers);
public native void alDeleteBuffers(int numBuffers, IntBuffer buffers);
public native void alSourceStop(int source);
public native void alSourcei(int source, int param, int value);
public native void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency);
public native void alSourcePlay(int source);
public native void alSourcePause(int source);
public native void alSourcef(int source, int param, float value);
public native void alSource3f(int source, int param, float value1, float value2, float value3);
public native int alGetSourcei(int source, int param);
public native void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers);
public native void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers);
public native void alListener(int param, FloatBuffer data);
public native void alListenerf(int param, float value);
public native void alListener3f(int param, float value1, float value2, float value3);
public native void alSource3i(int source, int param, int value1, int value2, int value3);
}

@ -0,0 +1,30 @@
package com.jme3.audio.android;
import com.jme3.audio.openal.ALC;
import java.nio.IntBuffer;
public final class AndroidALC implements ALC {
static {
System.loadLibrary("openalsoftjme");
}
public AndroidALC() {
}
public native void createALC();
public native void destroyALC();
public native boolean isCreated();
public native String alcGetString(int parameter);
public native boolean alcIsExtensionPresent(String extension);
public native void alcGetInteger(int param, IntBuffer buffer, int size);
public native void alcDevicePauseSOFT();
public native void alcDeviceResumeSOFT();
}

@ -1,24 +0,0 @@
package com.jme3.audio.android;
import com.jme3.audio.AudioRenderer;
/**
* Android specific AudioRenderer interface that supports pausing and resuming
* audio files when the app is minimized or placed in the background
*
* @author iwgeric
*/
public interface AndroidAudioRenderer extends AudioRenderer {
/**
* Pauses all Playing audio. To be used when the app is placed in the
* background.
*/
public void pauseAll();
/**
* Resumes all Paused audio. To be used when the app is brought back to
* the foreground.
*/
public void resumeAll();
}

@ -0,0 +1,32 @@
package com.jme3.audio.android;
import com.jme3.audio.openal.EFX;
import java.nio.IntBuffer;
public class AndroidEFX implements EFX {
public AndroidEFX() {
}
public native void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers);
public native void alGenEffects(int numEffects, IntBuffer buffers);
public native void alEffecti(int effect, int param, int value);
public native void alAuxiliaryEffectSloti(int effectSlot, int param, int value);
public native void alDeleteEffects(int numEffects, IntBuffer buffers);
public native void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers);
public native void alGenFilters(int numFilters, IntBuffer buffers);
public native void alFilteri(int filter, int param, int value);
public native void alFilterf(int filter, int param, float value);
public native void alDeleteFilters(int numFilters, IntBuffer buffers);
public native void alEffectf(int effect, int param, float value);
}

@ -54,7 +54,7 @@ import java.util.logging.Logger;
* @author larynx * @author larynx
* @author plan_rich * @author plan_rich
*/ */
public class AndroidMediaPlayerAudioRenderer implements AndroidAudioRenderer, public class AndroidMediaPlayerAudioRenderer implements AudioRenderer,
SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener { SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
private static final Logger logger = Logger.getLogger(AndroidMediaPlayerAudioRenderer.class.getName()); private static final Logger logger = Logger.getLogger(AndroidMediaPlayerAudioRenderer.class.getName());

@ -9,8 +9,13 @@ import com.jme3.asset.AndroidAssetManager;
import com.jme3.asset.AndroidImageInfo; import com.jme3.asset.AndroidImageInfo;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer; import com.jme3.audio.AudioRenderer;
import com.jme3.audio.android.AndroidMediaPlayerAudioRenderer; import com.jme3.audio.android.AndroidAL;
import com.jme3.audio.android.AndroidOpenALSoftAudioRenderer; import com.jme3.audio.android.AndroidALC;
import com.jme3.audio.android.AndroidEFX;
import com.jme3.audio.openal.AL;
import com.jme3.audio.openal.ALAudioRenderer;
import com.jme3.audio.openal.ALC;
import com.jme3.audio.openal.EFX;
import com.jme3.system.*; import com.jme3.system.*;
import com.jme3.system.JmeContext.Type; import com.jme3.system.JmeContext.Type;
import com.jme3.texture.Image; import com.jme3.texture.Image;
@ -112,7 +117,11 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
@Override @Override
public AudioRenderer newAudioRenderer(AppSettings settings) { public AudioRenderer newAudioRenderer(AppSettings settings) {
ALC alc = new AndroidALC();
AL al = new AndroidAL();
EFX efx = new AndroidEFX();
return new ALAudioRenderer(al, alc, efx);
/*
if (settings.getAudioRenderer().equals(AppSettings.ANDROID_MEDIAPLAYER)) { if (settings.getAudioRenderer().equals(AppSettings.ANDROID_MEDIAPLAYER)) {
logger.log(Level.INFO, "newAudioRenderer settings set to Android MediaPlayer / SoundPool"); logger.log(Level.INFO, "newAudioRenderer settings set to Android MediaPlayer / SoundPool");
audioRendererType = AppSettings.ANDROID_MEDIAPLAYER; audioRendererType = AppSettings.ANDROID_MEDIAPLAYER;
@ -120,12 +129,13 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
} else if (settings.getAudioRenderer().equals(AppSettings.ANDROID_OPENAL_SOFT)) { } else if (settings.getAudioRenderer().equals(AppSettings.ANDROID_OPENAL_SOFT)) {
logger.log(Level.INFO, "newAudioRenderer settings set to Android OpenAL Soft"); logger.log(Level.INFO, "newAudioRenderer settings set to Android OpenAL Soft");
audioRendererType = AppSettings.ANDROID_OPENAL_SOFT; audioRendererType = AppSettings.ANDROID_OPENAL_SOFT;
return new AndroidOpenALSoftAudioRenderer(); return new AndroidMediaPlayerAudioRenderer(activity);
} else { } else {
logger.log(Level.INFO, "AudioRenderer not set. Defaulting to Android MediaPlayer / SoundPool"); logger.log(Level.INFO, "AudioRenderer not set. Defaulting to Android MediaPlayer / SoundPool");
audioRendererType = AppSettings.ANDROID_MEDIAPLAYER; audioRendererType = AppSettings.ANDROID_MEDIAPLAYER;
return new AndroidMediaPlayerAudioRenderer(activity); return new AndroidMediaPlayerAudioRenderer(activity);
} }
*/
} }
@Override @Override

@ -75,6 +75,18 @@ public interface AudioRenderer {
*/ */
public void update(float tpf); public void update(float tpf);
/**
* Pauses all Playing audio.
* To be used when the app is placed in the background.
*/
public void pauseAll();
/**
* Resumes all audio paused by {@link #pauseAll()}.
* To be used when the app is brought back to the foreground.
*/
public void resumeAll();
/** /**
* Cleanup/destroy the audio system. Call this when app closes. * Cleanup/destroy the audio system. Call this when app closes.
*/ */

@ -0,0 +1,296 @@
package com.jme3.audio.openal;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
/**
* @author iwgeric
*/
public interface AL {
/**
* Boolean False.
*/
static final int AL_FALSE = 0;
/**
* Boolean True.
*/
static final int AL_TRUE = 1;
/* "no distance model" or "no buffer" */
static final int AL_NONE = 0;
/**
* Indicate Source has relative coordinates.
*/
static final int AL_SOURCE_RELATIVE = 0x202;
/**
* Directional source, inner cone angle, in degrees. Range: [0-360] Default:
* 360
*/
static final int AL_CONE_INNER_ANGLE = 0x1001;
/**
* Directional source, outer cone angle, in degrees. Range: [0-360] Default:
* 360
*/
static final int AL_CONE_OUTER_ANGLE = 0x1002;
/**
* Specify the pitch to be applied at source. Range: [0.5-2.0] Default: 1.0
*/
static final int AL_PITCH = 0x1003;
/**
* Specify the current location in three dimensional space. OpenAL, like
* OpenGL, uses a right handed coordinate system, where in a frontal default
* view X (thumb) points right, Y points up (index finger), and Z points
* towards the viewer/camera (middle finger). To switch from a left handed
* coordinate system, flip the sign on the Z coordinate. Listener position
* is always in the world coordinate system.
*/
static final int AL_POSITION = 0x1004;
/**
* Specify the current direction.
*/
static final int AL_DIRECTION = 0x1005;
/**
* Specify the current velocity in three dimensional space.
*/
static final int AL_VELOCITY = 0x1006;
/**
* Indicate whether source is looping. Type: ALboolean? Range: [AL_TRUE,
* AL_FALSE] Default: FALSE.
*/
static final int AL_LOOPING = 0x1007;
/**
* Indicate the buffer to provide sound samples. Type: ALuint. Range: any
* valid Buffer id.
*/
static final int AL_BUFFER = 0x1009;
/**
* Indicate the gain (volume amplification) applied. Type: ALfloat. Range:
* ]0.0- ] A value of 1.0 means un-attenuated/unchanged. Each division by 2
* equals an attenuation of -6dB. Each multiplicaton with 2 equals an
* amplification of +6dB. A value of 0.0 is meaningless with respect to a
* logarithmic scale; it is interpreted as zero volume - the channel is
* effectively disabled.
*/
static final int AL_GAIN = 0x100A;
/*
* Indicate minimum source attenuation
* Type: ALfloat
* Range: [0.0 - 1.0]
*
* Logarthmic
*/
static final int AL_MIN_GAIN = 0x100D;
/**
* Indicate maximum source attenuation Type: ALfloat Range: [0.0 - 1.0]
*
* Logarthmic
*/
static final int AL_MAX_GAIN = 0x100E;
/**
* Indicate listener orientation.
*
* at/up
*/
static final int AL_ORIENTATION = 0x100F;
/**
* Source state information.
*/
static final int AL_SOURCE_STATE = 0x1010;
static final int AL_INITIAL = 0x1011;
static final int AL_PLAYING = 0x1012;
static final int AL_PAUSED = 0x1013;
static final int AL_STOPPED = 0x1014;
/**
* Buffer Queue params
*/
static final int AL_BUFFERS_QUEUED = 0x1015;
static final int AL_BUFFERS_PROCESSED = 0x1016;
/**
* Source buffer position information
*/
static final int AL_SEC_OFFSET = 0x1024;
static final int AL_SAMPLE_OFFSET = 0x1025;
static final int AL_BYTE_OFFSET = 0x1026;
/*
* Source type (Static, Streaming or undetermined)
* Source is Static if a Buffer has been attached using AL_BUFFER
* Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers
* Source is undetermined when it has the NULL buffer attached
*/
static final int AL_SOURCE_TYPE = 0x1027;
static final int AL_STATIC = 0x1028;
static final int AL_STREAMING = 0x1029;
static final int AL_UNDETERMINED = 0x1030;
/**
* Sound samples: format specifier.
*/
static final int AL_FORMAT_MONO8 = 0x1100;
static final int AL_FORMAT_MONO16 = 0x1101;
static final int AL_FORMAT_STEREO8 = 0x1102;
static final int AL_FORMAT_STEREO16 = 0x1103;
/**
* source specific reference distance Type: ALfloat Range: 0.0 - +inf
*
* At 0.0, no distance attenuation occurs. Default is 1.0.
*/
static final int AL_REFERENCE_DISTANCE = 0x1020;
/**
* source specific rolloff factor Type: ALfloat Range: 0.0 - +inf
*
*/
static final int AL_ROLLOFF_FACTOR = 0x1021;
/**
* Directional source, outer cone gain.
*
* Default: 0.0 Range: [0.0 - 1.0] Logarithmic
*/
static final int AL_CONE_OUTER_GAIN = 0x1022;
/**
* Indicate distance above which sources are not attenuated using the
* inverse clamped distance model.
*
* Default: +inf Type: ALfloat Range: 0.0 - +inf
*/
static final int AL_MAX_DISTANCE = 0x1023;
/**
* Sound samples: frequency, in units of Hertz [Hz]. This is the number of
* samples per second. Half of the sample frequency marks the maximum
* significant frequency component.
*/
static final int AL_FREQUENCY = 0x2001;
static final int AL_BITS = 0x2002;
static final int AL_CHANNELS = 0x2003;
static final int AL_SIZE = 0x2004;
/**
* Buffer state.
*
* Not supported for public use (yet).
*/
static final int AL_UNUSED = 0x2010;
static final int AL_PENDING = 0x2011;
static final int AL_PROCESSED = 0x2012;
/**
* Errors: No Error.
*/
static final int AL_NO_ERROR = 0;
/**
* Invalid Name paramater passed to AL call.
*/
static final int AL_INVALID_NAME = 0xA001;
/**
* Invalid parameter passed to AL call.
*/
static final int AL_INVALID_ENUM = 0xA002;
/**
* Invalid enum parameter value.
*/
static final int AL_INVALID_VALUE = 0xA003;
/**
* Illegal call.
*/
static final int AL_INVALID_OPERATION = 0xA004;
/**
* No mojo.
*/
static final int AL_OUT_OF_MEMORY = 0xA005;
/**
* Context strings: Vendor Name.
*/
static final int AL_VENDOR = 0xB001;
static final int AL_VERSION = 0xB002;
static final int AL_RENDERER = 0xB003;
static final int AL_EXTENSIONS = 0xB004;
/**
* Global tweakage.
*/
/**
* Doppler scale. Default 1.0
*/
static final int AL_DOPPLER_FACTOR = 0xC000;
/**
* Tweaks speed of propagation.
*/
static final int AL_DOPPLER_VELOCITY = 0xC001;
/**
* Speed of Sound in units per second
*/
static final int AL_SPEED_OF_SOUND = 0xC003;
/**
* Distance models
*
* used in conjunction with DistanceModel
*
* implicit: NONE, which disances distance attenuation.
*/
static final int AL_DISTANCE_MODEL = 0xD000;
static final int AL_INVERSE_DISTANCE = 0xD001;
static final int AL_INVERSE_DISTANCE_CLAMPED = 0xD002;
static final int AL_LINEAR_DISTANCE = 0xD003;
static final int AL_LINEAR_DISTANCE_CLAMPED = 0xD004;
static final int AL_EXPONENT_DISTANCE = 0xD005;
static final int AL_EXPONENT_DISTANCE_CLAMPED = 0xD006;
//
///* Listener parameter value ranges and defaults. */
//#define AL_MIN_METERS_PER_UNIT FLT_MIN
//#define AL_MAX_METERS_PER_UNIT FLT_MAX
//#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
public String alGetString(int parameter);
public int alGenSources();
public int alGetError();
public void alDeleteSources(int numSources, IntBuffer sources);
public void alGenBuffers(int numBuffers, IntBuffer buffers);
public void alDeleteBuffers(int numBuffers, IntBuffer buffers);
public void alSourceStop(int source);
public void alSourcei(int source, int param, int value);
public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency);
public void alSourcePlay(int source);
public void alSourcePause(int source);
public void alSourcef(int source, int param, float value);
public void alSource3f(int source, int param, float value1, float value2, float value3);
public int alGetSourcei(int source, int param);
public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers);
public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers);
public void alListener(int param, FloatBuffer data);
public void alListenerf(int param, float value);
public void alListener3f(int param, float value1, float value2, float value3);
public void alSource3i(int source, int param, int value1, int value2, int value3);
}

@ -29,7 +29,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.audio.lwjgl; package com.jme3.audio.openal;
import com.jme3.audio.AudioSource.Status; import com.jme3.audio.AudioSource.Status;
import com.jme3.audio.*; import com.jme3.audio.*;
@ -43,13 +43,14 @@ import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import static org.lwjgl.openal.AL10.*;
import org.lwjgl.openal.*;
public class LwjglAudioRenderer implements AudioRenderer, Runnable { import static com.jme3.audio.openal.AL.*;
import static com.jme3.audio.openal.ALC.*;
import static com.jme3.audio.openal.EFX.*;
private static final Logger logger = Logger.getLogger(LwjglAudioRenderer.class.getName()); public class ALAudioRenderer implements AudioRenderer, Runnable {
private static final Logger logger = Logger.getLogger(ALAudioRenderer.class.getName());
private final NativeObjectManager objManager = new NativeObjectManager(); private final NativeObjectManager objManager = new NativeObjectManager();
// When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2 // When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2
// which is exactly 1 second of audio. // which is exactly 1 second of audio.
@ -63,10 +64,11 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
private int[] channels; private int[] channels;
private AudioSource[] chanSrcs; private AudioSource[] chanSrcs;
private int nextChan = 0; private int nextChan = 0;
private ArrayList<Integer> freeChans = new ArrayList<Integer>(); private final ArrayList<Integer> freeChans = new ArrayList<Integer>();
private Listener listener; private Listener listener;
private boolean audioDisabled = false; private boolean audioDisabled = false;
private boolean supportEfx = false; private boolean supportEfx = false;
private boolean supportPauseDevice = false;
private int auxSends = 0; private int auxSends = 0;
private int reverbFx = -1; private int reverbFx = -1;
private int reverbFxSlot = -1; private int reverbFxSlot = -1;
@ -75,7 +77,14 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
private final Thread audioThread = new Thread(this, "jME3 Audio Thread"); private final Thread audioThread = new Thread(this, "jME3 Audio Thread");
private final AtomicBoolean threadLock = new AtomicBoolean(false); private final AtomicBoolean threadLock = new AtomicBoolean(false);
public LwjglAudioRenderer() { private final AL al;
private final ALC alc;
private final EFX efx;
public ALAudioRenderer(AL al, ALC alc, EFX efx) {
this.al = al;
this.alc = alc;
this.efx = efx;
} }
public void initialize() { public void initialize() {
@ -136,36 +145,30 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
public void initInThread() { public void initInThread() {
try { try {
if (!AL.isCreated()) { if (!alc.isCreated()) {
AL.create(); alc.createALC();
} }
} catch (OpenALException ex) {
logger.log(Level.SEVERE, "Failed to load audio library", ex);
audioDisabled = true;
return;
} catch (LWJGLException ex) {
logger.log(Level.SEVERE, "Failed to load audio library", ex);
audioDisabled = true;
return;
} catch (UnsatisfiedLinkError ex) { } catch (UnsatisfiedLinkError ex) {
logger.log(Level.SEVERE, "Failed to load audio library", ex); logger.log(Level.SEVERE, "Failed to load audio library", ex);
audioDisabled = true; audioDisabled = true;
return; return;
} }
ALCdevice device = AL.getDevice(); String deviceName = alc.alcGetString(ALC.ALC_DEVICE_SPECIFIER);
String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER);
logger.log(Level.INFO, "Audio Device: {0}", deviceName); logger.log(Level.INFO, "Audio Device: {0}", deviceName);
logger.log(Level.INFO, "Audio Vendor: {0}", alGetString(AL_VENDOR)); logger.log(Level.INFO, "Audio Vendor: {0}", al.alGetString(AL_VENDOR));
logger.log(Level.INFO, "Audio Renderer: {0}", alGetString(AL_RENDERER)); logger.log(Level.INFO, "Audio Renderer: {0}", al.alGetString(AL_RENDERER));
logger.log(Level.INFO, "Audio Version: {0}", alGetString(AL_VERSION)); logger.log(Level.INFO, "Audio Version: {0}", al.alGetString(AL_VERSION));
logger.log(Level.INFO, "ALC extensions: {0}", alc.alcGetString(ALC.ALC_EXTENSIONS));
logger.log(Level.INFO, "AL extensions: {0}", al.alGetString(AL_EXTENSIONS));
// Find maximum # of sources supported by this implementation // Find maximum # of sources supported by this implementation
ArrayList<Integer> channelList = new ArrayList<Integer>(); ArrayList<Integer> channelList = new ArrayList<Integer>();
for (int i = 0; i < MAX_NUM_CHANNELS; i++) { for (int i = 0; i < MAX_NUM_CHANNELS; i++) {
int chan = alGenSources(); int chan = al.alGenSources();
if (alGetError() != 0) { if (al.alGetError() != 0) {
break; break;
} else { } else {
channelList.add(chan); channelList.add(chan);
@ -182,33 +185,41 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length); logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length);
supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX"); // Pause device is a feature used specifically on Android
// where the application could be closed but still running,
// thus the audio context remains open but no audio should be playing.
supportPauseDevice = alc.alcIsExtensionPresent("ALC_SOFT_pause_device");
if (!supportPauseDevice) {
logger.log(Level.WARNING, "Pausing audio device not supported.");
}
supportEfx = alc.alcIsExtensionPresent("ALC_EXT_EFX");
if (supportEfx) { if (supportEfx) {
ib.position(0).limit(1); ib.position(0).limit(1);
ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, ib); alc.alcGetInteger(EFX.ALC_EFX_MAJOR_VERSION, ib, 1);
int major = ib.get(0); int major = ib.get(0);
ib.position(0).limit(1); ib.position(0).limit(1);
ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib); alc.alcGetInteger(EFX.ALC_EFX_MINOR_VERSION, ib, 1);
int minor = ib.get(0); int minor = ib.get(0);
logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor}); logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor});
ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib); alc.alcGetInteger(EFX.ALC_MAX_AUXILIARY_SENDS, ib, 1);
auxSends = ib.get(0); auxSends = ib.get(0);
logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends); logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends);
// create slot // create slot
ib.position(0).limit(1); ib.position(0).limit(1);
EFX10.alGenAuxiliaryEffectSlots(ib); efx.alGenAuxiliaryEffectSlots(1, ib);
reverbFxSlot = ib.get(0); reverbFxSlot = ib.get(0);
// create effect // create effect
ib.position(0).limit(1); ib.position(0).limit(1);
EFX10.alGenEffects(ib); efx.alGenEffects(1, ib);
reverbFx = ib.get(0); reverbFx = ib.get(0);
EFX10.alEffecti(reverbFx, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_REVERB); efx.alEffecti(reverbFx, EFX.AL_EFFECT_TYPE, EFX.AL_EFFECT_REVERB);
// attach reverb effect to effect slot // attach reverb effect to effect slot
EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); efx.alAuxiliaryEffectSloti(reverbFxSlot, EFX.AL_EFFECTSLOT_EFFECT, reverbFx);
} else { } else {
logger.log(Level.WARNING, "OpenAL EFX not available! Audio effects won't work."); logger.log(Level.WARNING, "OpenAL EFX not available! Audio effects won't work.");
} }
@ -216,7 +227,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
public void cleanupInThread() { public void cleanupInThread() {
if (audioDisabled) { if (audioDisabled) {
AL.destroy(); alc.destroyALC();
return; return;
} }
@ -231,7 +242,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
ib.clear(); ib.clear();
ib.put(channels); ib.put(channels);
ib.flip(); ib.flip();
alDeleteSources(ib); al.alDeleteSources(channels.length, ib);
// delete audio buffers and filters // delete audio buffers and filters
objManager.deleteAllObjects(this); objManager.deleteAllObjects(this);
@ -239,16 +250,16 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (supportEfx) { if (supportEfx) {
ib.position(0).limit(1); ib.position(0).limit(1);
ib.put(0, reverbFx); ib.put(0, reverbFx);
EFX10.alDeleteEffects(ib); efx.alDeleteEffects(1, ib);
// If this is not allocated, why is it deleted? // If this is not allocated, why is it deleted?
// Commented out to fix native crash in OpenAL. // Commented out to fix native crash in OpenAL.
ib.position(0).limit(1); ib.position(0).limit(1);
ib.put(0, reverbFxSlot); ib.put(0, reverbFxSlot);
EFX10.alDeleteAuxiliaryEffectSlots(ib); efx.alDeleteAuxiliaryEffectSlots(1, ib);
} }
AL.destroy(); alc.destroyALC();
} }
public void cleanup() { public void cleanup() {
@ -266,7 +277,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
int id = f.getId(); int id = f.getId();
if (id == -1) { if (id == -1) {
ib.position(0).limit(1); ib.position(0).limit(1);
EFX10.alGenFilters(ib); efx.alGenFilters(1, ib);
id = ib.get(0); id = ib.get(0);
f.setId(id); f.setId(id);
@ -275,9 +286,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (f instanceof LowPassFilter) { if (f instanceof LowPassFilter) {
LowPassFilter lpf = (LowPassFilter) f; LowPassFilter lpf = (LowPassFilter) f;
EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); efx.alFilteri(id, EFX.AL_FILTER_TYPE, EFX.AL_FILTER_LOWPASS);
EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume()); efx.alFilterf(id, EFX.AL_LOWPASS_GAIN, lpf.getVolume());
EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume()); efx.alFilterf(id, EFX.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume());
} else { } else {
throw new UnsupportedOperationException("Filter type unsupported: " throw new UnsupportedOperationException("Filter type unsupported: "
+ f.getClass().getName()); + f.getClass().getName());
@ -322,7 +333,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
Vector3f pos = src.getPosition(); Vector3f pos = src.getPosition();
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); al.alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
break; break;
case Velocity: case Velocity:
if (!src.isPositional()) { if (!src.isPositional()) {
@ -330,28 +341,28 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
Vector3f vel = src.getVelocity(); Vector3f vel = src.getVelocity();
alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); al.alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);
break; break;
case MaxDistance: case MaxDistance:
if (!src.isPositional()) { if (!src.isPositional()) {
return; return;
} }
alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); al.alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance());
break; break;
case RefDistance: case RefDistance:
if (!src.isPositional()) { if (!src.isPositional()) {
return; return;
} }
alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); al.alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance());
break; break;
case ReverbFilter: case ReverbFilter:
if (!supportEfx || !src.isPositional() || !src.isReverbEnabled()) { if (!supportEfx || !src.isPositional() || !src.isReverbEnabled()) {
return; return;
} }
int filter = EFX10.AL_FILTER_NULL; int filter = EFX.AL_FILTER_NULL;
if (src.getReverbFilter() != null) { if (src.getReverbFilter() != null) {
Filter f = src.getReverbFilter(); Filter f = src.getReverbFilter();
if (f.isUpdateNeeded()) { if (f.isUpdateNeeded()) {
@ -359,7 +370,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
filter = f.getId(); filter = f.getId();
} }
AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); al.alSource3i(id, EFX.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter);
break; break;
case ReverbEnabled: case ReverbEnabled:
if (!supportEfx || !src.isPositional()) { if (!supportEfx || !src.isPositional()) {
@ -369,20 +380,20 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (src.isReverbEnabled()) { if (src.isReverbEnabled()) {
updateSourceParam(src, AudioParam.ReverbFilter); updateSourceParam(src, AudioParam.ReverbFilter);
} else { } else {
AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); al.alSource3i(id, EFX.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX.AL_FILTER_NULL);
} }
break; break;
case IsPositional: case IsPositional:
if (!src.isPositional()) { if (!src.isPositional()) {
// Play in headspace // Play in headspace
alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); al.alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(id, AL_POSITION, 0, 0, 0); al.alSource3f(id, AL_POSITION, 0, 0, 0);
alSource3f(id, AL_VELOCITY, 0, 0, 0); al.alSource3f(id, AL_VELOCITY, 0, 0, 0);
// Disable reverb // Disable reverb
AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); al.alSource3i(id, EFX.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX.AL_FILTER_NULL);
} else { } else {
alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); al.alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE);
updateSourceParam(src, AudioParam.Position); updateSourceParam(src, AudioParam.Position);
updateSourceParam(src, AudioParam.Velocity); updateSourceParam(src, AudioParam.Velocity);
updateSourceParam(src, AudioParam.MaxDistance); updateSourceParam(src, AudioParam.MaxDistance);
@ -396,32 +407,32 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
Vector3f dir = src.getDirection(); Vector3f dir = src.getDirection();
alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); al.alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z);
break; break;
case InnerAngle: case InnerAngle:
if (!src.isDirectional()) { if (!src.isDirectional()) {
return; return;
} }
alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); al.alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle());
break; break;
case OuterAngle: case OuterAngle:
if (!src.isDirectional()) { if (!src.isDirectional()) {
return; return;
} }
alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); al.alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle());
break; break;
case IsDirectional: case IsDirectional:
if (src.isDirectional()) { if (src.isDirectional()) {
updateSourceParam(src, AudioParam.Direction); updateSourceParam(src, AudioParam.Direction);
updateSourceParam(src, AudioParam.InnerAngle); updateSourceParam(src, AudioParam.InnerAngle);
updateSourceParam(src, AudioParam.OuterAngle); updateSourceParam(src, AudioParam.OuterAngle);
alSourcef(id, AL_CONE_OUTER_GAIN, 0); al.alSourcef(id, AL_CONE_OUTER_GAIN, 0);
} else { } else {
alSourcef(id, AL_CONE_INNER_ANGLE, 360); al.alSourcef(id, AL_CONE_INNER_ANGLE, 360);
alSourcef(id, AL_CONE_OUTER_ANGLE, 360); al.alSourcef(id, AL_CONE_OUTER_ANGLE, 360);
alSourcef(id, AL_CONE_OUTER_GAIN, 1f); al.alSourcef(id, AL_CONE_OUTER_GAIN, 1f);
} }
break; break;
case DryFilter: case DryFilter:
@ -435,26 +446,26 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
updateFilter(f); updateFilter(f);
// NOTE: must re-attach filter for changes to apply. // NOTE: must re-attach filter for changes to apply.
alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); al.alSourcei(id, EFX.AL_DIRECT_FILTER, f.getId());
} }
} else { } else {
alSourcei(id, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); al.alSourcei(id, EFX.AL_DIRECT_FILTER, EFX.AL_FILTER_NULL);
} }
break; break;
case Looping: case Looping:
if (src.isLooping()) { if (src.isLooping()) {
if (!(src.getAudioData() instanceof AudioStream)) { if (!(src.getAudioData() instanceof AudioStream)) {
alSourcei(id, AL_LOOPING, AL_TRUE); al.alSourcei(id, AL_LOOPING, AL_TRUE);
} }
} else { } else {
alSourcei(id, AL_LOOPING, AL_FALSE); al.alSourcei(id, AL_LOOPING, AL_FALSE);
} }
break; break;
case Volume: case Volume:
alSourcef(id, AL_GAIN, src.getVolume()); al.alSourcef(id, AL_GAIN, src.getVolume());
break; break;
case Pitch: case Pitch:
alSourcef(id, AL_PITCH, src.getPitch()); al.alSourcef(id, AL_PITCH, src.getPitch());
break; break;
} }
} }
@ -464,14 +475,14 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (src.isPositional()) { if (src.isPositional()) {
Vector3f pos = src.getPosition(); Vector3f pos = src.getPosition();
Vector3f vel = src.getVelocity(); Vector3f vel = src.getVelocity();
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); al.alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); al.alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);
alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); al.alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance());
alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); al.alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance());
alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); al.alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE);
if (src.isReverbEnabled() && supportEfx) { if (src.isReverbEnabled() && supportEfx) {
int filter = EFX10.AL_FILTER_NULL; int filter = EFX.AL_FILTER_NULL;
if (src.getReverbFilter() != null) { if (src.getReverbFilter() != null) {
Filter f = src.getReverbFilter(); Filter f = src.getReverbFilter();
if (f.isUpdateNeeded()) { if (f.isUpdateNeeded()) {
@ -479,13 +490,13 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
filter = f.getId(); filter = f.getId();
} }
AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); al.alSource3i(id, EFX.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter);
} }
} else { } else {
// play in headspace // play in headspace
alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); al.alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(id, AL_POSITION, 0, 0, 0); al.alSource3f(id, AL_POSITION, 0, 0, 0);
alSource3f(id, AL_VELOCITY, 0, 0, 0); al.alSource3f(id, AL_VELOCITY, 0, 0, 0);
} }
if (src.getDryFilter() != null && supportEfx) { if (src.getDryFilter() != null && supportEfx) {
@ -494,29 +505,29 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
updateFilter(f); updateFilter(f);
// NOTE: must re-attach filter for changes to apply. // NOTE: must re-attach filter for changes to apply.
alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); al.alSourcei(id, EFX.AL_DIRECT_FILTER, f.getId());
} }
} }
if (forceNonLoop) { if (forceNonLoop) {
alSourcei(id, AL_LOOPING, AL_FALSE); al.alSourcei(id, AL_LOOPING, AL_FALSE);
} else { } else {
alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE); al.alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE);
} }
alSourcef(id, AL_GAIN, src.getVolume()); al.alSourcef(id, AL_GAIN, src.getVolume());
alSourcef(id, AL_PITCH, src.getPitch()); al.alSourcef(id, AL_PITCH, src.getPitch());
alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset()); al.alSourcef(id, AL_SEC_OFFSET, src.getTimeOffset());
if (src.isDirectional()) { if (src.isDirectional()) {
Vector3f dir = src.getDirection(); Vector3f dir = src.getDirection();
alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); al.alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z);
alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); al.alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle());
alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); al.alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle());
alSourcef(id, AL_CONE_OUTER_GAIN, 0); al.alSourcef(id, AL_CONE_OUTER_GAIN, 0);
} else { } else {
alSourcef(id, AL_CONE_INNER_ANGLE, 360); al.alSourcef(id, AL_CONE_INNER_ANGLE, 360);
alSourcef(id, AL_CONE_OUTER_ANGLE, 360); al.alSourcef(id, AL_CONE_OUTER_ANGLE, 360);
alSourcef(id, AL_CONE_OUTER_GAIN, 1f); al.alSourcef(id, AL_CONE_OUTER_GAIN, 1f);
} }
} }
@ -536,7 +547,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
switch (param) { switch (param) {
case Position: case Position:
Vector3f pos = listener.getLocation(); Vector3f pos = listener.getLocation();
alListener3f(AL_POSITION, pos.x, pos.y, pos.z); al.alListener3f(AL_POSITION, pos.x, pos.y, pos.z);
break; break;
case Rotation: case Rotation:
Vector3f dir = listener.getDirection(); Vector3f dir = listener.getDirection();
@ -545,14 +556,14 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
fb.put(dir.x).put(dir.y).put(dir.z); fb.put(dir.x).put(dir.y).put(dir.z);
fb.put(up.x).put(up.y).put(up.z); fb.put(up.x).put(up.y).put(up.z);
fb.flip(); fb.flip();
alListener(AL_ORIENTATION, fb); al.alListener(AL_ORIENTATION, fb);
break; break;
case Velocity: case Velocity:
Vector3f vel = listener.getVelocity(); Vector3f vel = listener.getVelocity();
alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); al.alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z);
break; break;
case Volume: case Volume:
alListenerf(AL_GAIN, listener.getVolume()); al.alListenerf(AL_GAIN, listener.getVolume());
break; break;
} }
} }
@ -564,14 +575,14 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
Vector3f dir = listener.getDirection(); Vector3f dir = listener.getDirection();
Vector3f up = listener.getUp(); Vector3f up = listener.getUp();
alListener3f(AL_POSITION, pos.x, pos.y, pos.z); al.alListener3f(AL_POSITION, pos.x, pos.y, pos.z);
alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); al.alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z);
fb.rewind(); fb.rewind();
fb.put(dir.x).put(dir.y).put(dir.z); fb.put(dir.x).put(dir.y).put(dir.z);
fb.put(up.x).put(up.y).put(up.z); fb.put(up.x).put(up.y).put(up.z);
fb.flip(); fb.flip();
alListener(AL_ORIENTATION, fb); al.alListener(AL_ORIENTATION, fb);
alListenerf(AL_GAIN, listener.getVolume()); al.alListenerf(AL_GAIN, listener.getVolume());
} }
private int newChannel() { private int newChannel() {
@ -605,21 +616,21 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
return; return;
} }
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity()); efx.alEffectf(reverbFx, EFX.AL_REVERB_DENSITY, env.getDensity());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion()); efx.alEffectf(reverbFx, EFX.AL_REVERB_DIFFUSION, env.getDiffusion());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain()); efx.alEffectf(reverbFx, EFX.AL_REVERB_GAIN, env.getGain());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf()); efx.alEffectf(reverbFx, EFX.AL_REVERB_GAINHF, env.getGainHf());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime()); efx.alEffectf(reverbFx, EFX.AL_REVERB_DECAY_TIME, env.getDecayTime());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio()); efx.alEffectf(reverbFx, EFX.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain()); efx.alEffectf(reverbFx, EFX.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay()); efx.alEffectf(reverbFx, EFX.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain()); efx.alEffectf(reverbFx, EFX.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay()); efx.alEffectf(reverbFx, EFX.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf()); efx.alEffectf(reverbFx, EFX.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor()); efx.alEffectf(reverbFx, EFX.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor());
// attach effect to slot // attach effect to slot
EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); efx.alAuxiliaryEffectSloti(reverbFxSlot, EFX.AL_EFFECTSLOT_EFFECT, reverbFx);
} }
} }
@ -645,7 +656,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
nativeBuf.put(arrayBuf, 0, size); nativeBuf.put(arrayBuf, 0, size);
nativeBuf.flip(); nativeBuf.flip();
alBufferData(id, convertFormat(stream), nativeBuf, stream.getSampleRate()); al.alBufferData(id, convertFormat(stream), nativeBuf, size, stream.getSampleRate());
return true; return true;
} }
@ -656,21 +667,21 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
boolean active = true; boolean active = true;
int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED); int processed = al.alGetSourcei(sourceId, AL_BUFFERS_PROCESSED);
// while((processed--) != 0){ // while((processed--) != 0){
if (processed > 0) { if (processed > 0) {
int buffer; int buffer;
ib.position(0).limit(1); ib.position(0).limit(1);
alSourceUnqueueBuffers(sourceId, ib); al.alSourceUnqueueBuffers(sourceId, 1, ib);
buffer = ib.get(0); buffer = ib.get(0);
active = fillBuffer(stream, buffer); active = fillBuffer(stream, buffer);
ib.position(0).limit(1); ib.position(0).limit(1);
ib.put(0, buffer); ib.put(0, buffer);
alSourceQueueBuffers(sourceId, ib); al.alSourceQueueBuffers(sourceId, 1, ib);
} }
if (!active && stream.isOpen()) { if (!active && stream.isOpen()) {
@ -686,13 +697,13 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
active = fillBuffer(stream, id); active = fillBuffer(stream, id);
ib.position(0).limit(1); ib.position(0).limit(1);
ib.put(id).flip(); ib.put(id).flip();
alSourceQueueBuffers(sourceId, ib); al.alSourceQueueBuffers(sourceId, 1, ib);
} }
return active; return active;
} }
private boolean attachBufferToSource(int sourceId, AudioBuffer buffer) { private boolean attachBufferToSource(int sourceId, AudioBuffer buffer) {
alSourcei(sourceId, AL_BUFFER, buffer.getId()); al.alSourcei(sourceId, AL_BUFFER, buffer.getId());
return true; return true;
} }
@ -711,25 +722,25 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
AudioSource src = chanSrcs[index]; AudioSource src = chanSrcs[index];
int sourceId = channels[index]; int sourceId = channels[index];
alSourceStop(sourceId); al.alSourceStop(sourceId);
if (src.getAudioData() instanceof AudioStream) { if (src.getAudioData() instanceof AudioStream) {
AudioStream str = (AudioStream) src.getAudioData(); AudioStream str = (AudioStream) src.getAudioData();
ib.position(0).limit(STREAMING_BUFFER_COUNT); ib.position(0).limit(STREAMING_BUFFER_COUNT);
ib.put(str.getIds()).flip(); ib.put(str.getIds()).flip();
alSourceUnqueueBuffers(sourceId, ib); al.alSourceUnqueueBuffers(sourceId, STREAMING_BUFFER_COUNT, ib);
} else if (src.getAudioData() instanceof AudioBuffer) { } else if (src.getAudioData() instanceof AudioBuffer) {
alSourcei(sourceId, AL_BUFFER, 0); al.alSourcei(sourceId, AL_BUFFER, 0);
} }
if (src.getDryFilter() != null && supportEfx) { if (src.getDryFilter() != null && supportEfx) {
// detach filter // detach filter
alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); al.alSourcei(sourceId, EFX.AL_DIRECT_FILTER, EFX.AL_FILTER_NULL);
} }
if (src.isPositional()) { if (src.isPositional()) {
AudioSource pas = (AudioSource) src; AudioSource pas = (AudioSource) src;
if (pas.isReverbEnabled() && supportEfx) { if (pas.isReverbEnabled() && supportEfx) {
AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); al.alSource3i(sourceId, EFX.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX.AL_FILTER_NULL);
} }
} }
@ -764,7 +775,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
// only buffered sources can be bound // only buffered sources can be bound
assert (boundSource && streaming) || (!streaming); assert (boundSource && streaming) || (!streaming);
int state = alGetSourcei(sourceId, AL_SOURCE_STATE); int state = al.alGetSourcei(sourceId, AL_SOURCE_STATE);
boolean wantPlaying = src.getStatus() == Status.Playing; boolean wantPlaying = src.getStatus() == Status.Playing;
boolean stopped = state == AL_STOPPED; boolean stopped = state == AL_STOPPED;
@ -773,7 +784,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (stream.isOpen()) { if (stream.isOpen()) {
fillStreamingSource(sourceId, stream); fillStreamingSource(sourceId, stream);
if (stopped) { if (stopped) {
alSourcePlay(sourceId); al.alSourcePlay(sourceId);
} }
} else { } else {
if (stopped) { if (stopped) {
@ -834,6 +845,22 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
} }
public void pauseAll() {
if (!supportPauseDevice) {
throw new UnsupportedOperationException("Pause device is NOT supported!");
}
alc.alcDevicePauseSOFT();
}
public void resumeAll() {
if (!supportPauseDevice) {
throw new UnsupportedOperationException("Pause device is NOT supported!");
}
alc.alcDeviceResumeSOFT();
}
public void playSourceInstance(AudioSource src) { public void playSourceInstance(AudioSource src) {
checkDead(); checkDead();
synchronized (threadLock) { synchronized (threadLock) {
@ -873,7 +900,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
chanSrcs[index] = src; chanSrcs[index] = src;
// play the channel // play the channel
alSourcePlay(sourceId); al.alSourcePlay(sourceId);
} }
} }
@ -915,7 +942,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
attachAudioToSource(channels[index], data); attachAudioToSource(channels[index], data);
} }
alSourcePlay(channels[src.getChannel()]); al.alSourcePlay(channels[src.getChannel()]);
src.setStatus(Status.Playing); src.setStatus(Status.Playing);
} }
} }
@ -936,7 +963,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (src.getStatus() == Status.Playing) { if (src.getStatus() == Status.Playing) {
assert src.getChannel() != -1; assert src.getChannel() != -1;
alSourcePause(channels[src.getChannel()]); al.alSourcePause(channels[src.getChannel()]);
src.setStatus(Status.Paused); src.setStatus(Status.Paused);
} }
} }
@ -1002,7 +1029,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
int id = ab.getId(); int id = ab.getId();
if (ab.getId() == -1) { if (ab.getId() == -1) {
ib.position(0).limit(1); ib.position(0).limit(1);
alGenBuffers(ib); al.alGenBuffers(1, ib);
id = ib.get(0); id = ib.get(0);
ab.setId(id); ab.setId(id);
@ -1010,7 +1037,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} }
ab.getData().clear(); ab.getData().clear();
alBufferData(id, convertFormat(ab), ab.getData(), ab.getSampleRate()); al.alBufferData(id, convertFormat(ab), ab.getData(), ab.getData().capacity(), ab.getSampleRate());
ab.clearUpdateNeeded(); ab.clearUpdateNeeded();
} }
@ -1021,7 +1048,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
int[] ids = new int[STREAMING_BUFFER_COUNT]; int[] ids = new int[STREAMING_BUFFER_COUNT];
ib.position(0).limit(STREAMING_BUFFER_COUNT); ib.position(0).limit(STREAMING_BUFFER_COUNT);
alGenBuffers(ib); al.alGenBuffers(STREAMING_BUFFER_COUNT, ib);
ib.position(0).limit(STREAMING_BUFFER_COUNT); ib.position(0).limit(STREAMING_BUFFER_COUNT);
ib.get(ids); ib.get(ids);
@ -1044,7 +1071,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
public void deleteFilter(Filter filter) { public void deleteFilter(Filter filter) {
int id = filter.getId(); int id = filter.getId();
if (id != -1) { if (id != -1) {
EFX10.alDeleteFilters(id); ib.position(0).limit(1);
ib.put(id).flip();
efx.alDeleteFilters(1, ib);
} }
} }
@ -1066,7 +1095,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (id != -1) { if (id != -1) {
ib.put(0, id); ib.put(0, id);
ib.position(0).limit(1); ib.position(0).limit(1);
alDeleteBuffers(ib); al.alDeleteBuffers(1, ib);
ab.resetObject(); ab.resetObject();
} }
} else if (ad instanceof AudioStream) { } else if (ad instanceof AudioStream) {
@ -1075,7 +1104,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
if (ids != null) { if (ids != null) {
ib.clear(); ib.clear();
ib.put(ids).flip(); ib.put(ids).flip();
alDeleteBuffers(ib); al.alDeleteBuffers(ids.length, ib);
as.resetObject(); as.resetObject();
} }
} }

@ -0,0 +1,73 @@
package com.jme3.audio.openal;
import java.nio.IntBuffer;
public interface ALC {
/**
* No error
*/
static final int ALC_NO_ERROR = 0;
/**
* No device
*/
static final int ALC_INVALID_DEVICE = 0xA001;
/**
* invalid context ID
*/
static final int ALC_INVALID_CONTEXT = 0xA002;
/**
* bad enum
*/
static final int ALC_INVALID_ENUM = 0xA003;
/**
* bad value
*/
static final int ALC_INVALID_VALUE = 0xA004;
/**
* Out of memory.
*/
static final int ALC_OUT_OF_MEMORY = 0xA005;
/**
* The Specifier string for default device
*/
static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004;
static final int ALC_DEVICE_SPECIFIER = 0x1005;
static final int ALC_EXTENSIONS = 0x1006;
static final int ALC_MAJOR_VERSION = 0x1000;
static final int ALC_MINOR_VERSION = 0x1001;
static final int ALC_ATTRIBUTES_SIZE = 0x1002;
static final int ALC_ALL_ATTRIBUTES = 0x1003;
/**
* Capture extension
*/
static final int ALC_EXT_CAPTURE = 1;
static final int ALC_CAPTURE_DEVICE_SPECIFIER = 0x310;
static final int ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311;
static final int ALC_CAPTURE_SAMPLES = 0x312;
/**
* ALC_ENUMERATE_ALL_EXT enums
*/
static final int ALC_ENUMERATE_ALL_EXT = 1;
static final int ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012;
static final int ALC_ALL_DEVICES_SPECIFIER = 0x1013;
public void createALC();
public void destroyALC();
public boolean isCreated();
public String alcGetString(int parameter);
public boolean alcIsExtensionPresent(String extension);
public void alcGetInteger(int param, IntBuffer buffer, int size);
public void alcDevicePauseSOFT();
public void alcDeviceResumeSOFT();
}

@ -0,0 +1,43 @@
package com.jme3.audio.openal;
import static com.jme3.audio.openal.AL.*;
public final class ALUtil {
private ALUtil() {
}
public static String getALErrorMessage(int errorCode) {
String errorText;
switch (errorCode) {
case AL_NO_ERROR:
errorText = "No Error";
break;
case AL_INVALID_NAME:
errorText = "Invalid Name";
break;
case AL_INVALID_ENUM:
errorText = "Invalid Enum";
break;
case AL_INVALID_VALUE:
errorText = "Invalid Value";
break;
case AL_INVALID_OPERATION:
errorText = "Invalid Operation";
break;
case AL_OUT_OF_MEMORY:
errorText = "Out of Memory";
break;
default:
errorText = "Unknown Error Code: " + String.valueOf(errorCode);
}
return errorText;
}
public static void checkALError(AL al) {
int err = al.alGetError();
if (err != AL_NO_ERROR) {
throw new RuntimeException("OpenAL Error: " + getALErrorMessage(err));
}
}
}

@ -1,368 +1,14 @@
package com.jme3.audio.android; package com.jme3.audio.openal;
/** import java.nio.IntBuffer;
*
* @author iwgeric
*/
public class AL {
public interface EFX {
/* ********** */
/* FROM ALC.h */
/* ********** */
// typedef struct ALCdevice_struct ALCdevice;
// typedef struct ALCcontext_struct ALCcontext;
/**
* No error
*/
static final int ALC_NO_ERROR = 0;
/**
* No device
*/
static final int ALC_INVALID_DEVICE = 0xA001;
/**
* invalid context ID
*/
static final int ALC_INVALID_CONTEXT = 0xA002;
/**
* bad enum
*/
static final int ALC_INVALID_ENUM = 0xA003;
/**
* bad value
*/
static final int ALC_INVALID_VALUE = 0xA004;
/**
* Out of memory.
*/
static final int ALC_OUT_OF_MEMORY = 0xA005;
/**
* The Specifier string for default device
*/
static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004;
static final int ALC_DEVICE_SPECIFIER = 0x1005;
static final int ALC_EXTENSIONS = 0x1006;
static final int ALC_MAJOR_VERSION = 0x1000;
static final int ALC_MINOR_VERSION = 0x1001;
static final int ALC_ATTRIBUTES_SIZE = 0x1002;
static final int ALC_ALL_ATTRIBUTES = 0x1003;
/**
* Capture extension
*/
static final int ALC_EXT_CAPTURE = 1;
static final int ALC_CAPTURE_DEVICE_SPECIFIER = 0x310;
static final int ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311;
static final int ALC_CAPTURE_SAMPLES = 0x312;
/**
* ALC_ENUMERATE_ALL_EXT enums
*/
static final int ALC_ENUMERATE_ALL_EXT = 1;
static final int ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012;
static final int ALC_ALL_DEVICES_SPECIFIER = 0x1013;
/* ********** */
/* FROM AL.h */
/* ********** */
/** Boolean False. */
static final int AL_FALSE = 0;
/** Boolean True. */
static final int AL_TRUE = 1;
/* "no distance model" or "no buffer" */
static final int AL_NONE = 0;
/** Indicate Source has relative coordinates. */
static final int AL_SOURCE_RELATIVE = 0x202;
/**
* Directional source, inner cone angle, in degrees.
* Range: [0-360]
* Default: 360
*/
static final int AL_CONE_INNER_ANGLE = 0x1001;
/**
* Directional source, outer cone angle, in degrees.
* Range: [0-360]
* Default: 360
*/
static final int AL_CONE_OUTER_ANGLE = 0x1002;
/**
* Specify the pitch to be applied at source.
* Range: [0.5-2.0]
* Default: 1.0
*/
static final int AL_PITCH = 0x1003;
/**
* Specify the current location in three dimensional space.
* OpenAL, like OpenGL, uses a right handed coordinate system,
* where in a frontal default view X (thumb) points right,
* Y points up (index finger), and Z points towards the
* viewer/camera (middle finger).
* To switch from a left handed coordinate system, flip the
* sign on the Z coordinate.
* Listener position is always in the world coordinate system.
*/
static final int AL_POSITION = 0x1004;
/** Specify the current direction. */
static final int AL_DIRECTION = 0x1005;
/** Specify the current velocity in three dimensional space. */
static final int AL_VELOCITY = 0x1006;
/**
* Indicate whether source is looping.
* Type: ALboolean?
* Range: [AL_TRUE, AL_FALSE]
* Default: FALSE.
*/
static final int AL_LOOPING = 0x1007;
/**
* Indicate the buffer to provide sound samples.
* Type: ALuint.
* Range: any valid Buffer id.
*/
static final int AL_BUFFER = 0x1009;
/**
* Indicate the gain (volume amplification) applied.
* Type: ALfloat.
* Range: ]0.0- ]
* A value of 1.0 means un-attenuated/unchanged.
* Each division by 2 equals an attenuation of -6dB.
* Each multiplicaton with 2 equals an amplification of +6dB.
* A value of 0.0 is meaningless with respect to a logarithmic
* scale; it is interpreted as zero volume - the channel
* is effectively disabled.
*/
static final int AL_GAIN = 0x100A;
/*
* Indicate minimum source attenuation
* Type: ALfloat
* Range: [0.0 - 1.0]
*
* Logarthmic
*/
static final int AL_MIN_GAIN = 0x100D;
/**
* Indicate maximum source attenuation
* Type: ALfloat
* Range: [0.0 - 1.0]
*
* Logarthmic
*/
static final int AL_MAX_GAIN = 0x100E;
/**
* Indicate listener orientation.
*
* at/up
*/
static final int AL_ORIENTATION = 0x100F;
/**
* Source state information.
*/
static final int AL_SOURCE_STATE = 0x1010;
static final int AL_INITIAL = 0x1011;
static final int AL_PLAYING = 0x1012;
static final int AL_PAUSED = 0x1013;
static final int AL_STOPPED = 0x1014;
/**
* Buffer Queue params
*/
static final int AL_BUFFERS_QUEUED = 0x1015;
static final int AL_BUFFERS_PROCESSED = 0x1016;
/**
* Source buffer position information
*/
static final int AL_SEC_OFFSET = 0x1024;
static final int AL_SAMPLE_OFFSET = 0x1025;
static final int AL_BYTE_OFFSET = 0x1026;
/*
* Source type (Static, Streaming or undetermined)
* Source is Static if a Buffer has been attached using AL_BUFFER
* Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers
* Source is undetermined when it has the NULL buffer attached
*/
static final int AL_SOURCE_TYPE = 0x1027;
static final int AL_STATIC = 0x1028;
static final int AL_STREAMING = 0x1029;
static final int AL_UNDETERMINED = 0x1030;
/** Sound samples: format specifier. */
static final int AL_FORMAT_MONO8 = 0x1100;
static final int AL_FORMAT_MONO16 = 0x1101;
static final int AL_FORMAT_STEREO8 = 0x1102;
static final int AL_FORMAT_STEREO16 = 0x1103;
/**
* source specific reference distance
* Type: ALfloat
* Range: 0.0 - +inf
*
* At 0.0, no distance attenuation occurs. Default is
* 1.0.
*/
static final int AL_REFERENCE_DISTANCE = 0x1020;
/**
* source specific rolloff factor
* Type: ALfloat
* Range: 0.0 - +inf
*
*/
static final int AL_ROLLOFF_FACTOR = 0x1021;
/**
* Directional source, outer cone gain.
*
* Default: 0.0
* Range: [0.0 - 1.0]
* Logarithmic
*/
static final int AL_CONE_OUTER_GAIN = 0x1022;
/**
* Indicate distance above which sources are not
* attenuated using the inverse clamped distance model.
*
* Default: +inf
* Type: ALfloat
* Range: 0.0 - +inf
*/
static final int AL_MAX_DISTANCE = 0x1023;
/**
* Sound samples: frequency, in units of Hertz [Hz].
* This is the number of samples per second. Half of the
* sample frequency marks the maximum significant
* frequency component.
*/
static final int AL_FREQUENCY = 0x2001;
static final int AL_BITS = 0x2002;
static final int AL_CHANNELS = 0x2003;
static final int AL_SIZE = 0x2004;
/**
* Buffer state.
*
* Not supported for public use (yet).
*/
static final int AL_UNUSED = 0x2010;
static final int AL_PENDING = 0x2011;
static final int AL_PROCESSED = 0x2012;
/** Errors: No Error. */
static final int AL_NO_ERROR = 0;
/**
* Invalid Name paramater passed to AL call.
*/
static final int AL_INVALID_NAME = 0xA001;
/**
* Invalid parameter passed to AL call.
*/
static final int AL_INVALID_ENUM = 0xA002;
/**
* Invalid enum parameter value.
*/
static final int AL_INVALID_VALUE = 0xA003;
/**
* Illegal call.
*/
static final int AL_INVALID_OPERATION = 0xA004;
/**
* No mojo.
*/
static final int AL_OUT_OF_MEMORY = 0xA005;
/** Context strings: Vendor Name. */
static final int AL_VENDOR = 0xB001;
static final int AL_VERSION = 0xB002;
static final int AL_RENDERER = 0xB003;
static final int AL_EXTENSIONS = 0xB004;
/** Global tweakage. */
/**
* Doppler scale. Default 1.0
*/
static final int AL_DOPPLER_FACTOR = 0xC000;
/**
* Tweaks speed of propagation.
*/
static final int AL_DOPPLER_VELOCITY = 0xC001;
/**
* Speed of Sound in units per second
*/
static final int AL_SPEED_OF_SOUND = 0xC003;
/**
* Distance models
*
* used in conjunction with DistanceModel
*
* implicit: NONE, which disances distance attenuation.
*/
static final int AL_DISTANCE_MODEL = 0xD000;
static final int AL_INVERSE_DISTANCE = 0xD001;
static final int AL_INVERSE_DISTANCE_CLAMPED = 0xD002;
static final int AL_LINEAR_DISTANCE = 0xD003;
static final int AL_LINEAR_DISTANCE_CLAMPED = 0xD004;
static final int AL_EXPONENT_DISTANCE = 0xD005;
static final int AL_EXPONENT_DISTANCE_CLAMPED = 0xD006;
/* ********** */
/* FROM efx.h */
/* ********** */
static final String ALC_EXT_EFX_NAME = "ALC_EXT_EFX"; static final String ALC_EXT_EFX_NAME = "ALC_EXT_EFX";
static final int ALC_EFX_MAJOR_VERSION = 0x20001; static final int ALC_EFX_MAJOR_VERSION = 0x20001;
static final int ALC_EFX_MINOR_VERSION = 0x20002; static final int ALC_EFX_MINOR_VERSION = 0x20002;
static final int ALC_MAX_AUXILIARY_SENDS = 0x20003; static final int ALC_MAX_AUXILIARY_SENDS = 0x20003;
///* Listener properties. */ ///* Listener properties. */
//#define AL_METERS_PER_UNIT 0x20004 //#define AL_METERS_PER_UNIT 0x20004
@ -1017,38 +663,17 @@ public class AL {
//#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE //#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
//#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE //#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
// //
//
///* Listener parameter value ranges and defaults. */
//#define AL_MIN_METERS_PER_UNIT FLT_MIN
//#define AL_MAX_METERS_PER_UNIT FLT_MAX
//#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
public void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers);
public void alGenEffects(int numEffects, IntBuffer buffers);
public void alEffecti(int effect, int param, int value);
public void alAuxiliaryEffectSloti(int effectSlot, int param, int value);
public void alDeleteEffects(int numEffects, IntBuffer buffers);
public void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers);
public void alGenFilters(int numFilters, IntBuffer buffers);
public void alFilteri(int filter, int param, int value);
public void alFilterf(int filter, int param, float value);
public void alDeleteFilters(int numFilters, IntBuffer buffers);
public void alEffectf(int effect, int param, float value);
public static String GetALErrorMsg(int errorCode) {
String errorText;
switch (errorCode) {
case AL_NO_ERROR:
errorText = "No Error";
break;
case AL_INVALID_NAME:
errorText = "Invalid Name";
break;
case AL_INVALID_ENUM:
errorText = "Invalid Enum";
break;
case AL_INVALID_VALUE:
errorText = "Invalid Value";
break;
case AL_INVALID_OPERATION:
errorText = "Invalid Operation";
break;
case AL_OUT_OF_MEMORY:
errorText = "Out of Memory";
break;
default:
errorText = "Unknown Error Code: " + String.valueOf(errorCode);
}
return errorText;
}
} }

@ -37,6 +37,10 @@ import com.jme3.asset.AssetManager;
import com.jme3.asset.AssetNotFoundException; import com.jme3.asset.AssetNotFoundException;
import com.jme3.asset.DesktopAssetManager; import com.jme3.asset.DesktopAssetManager;
import com.jme3.audio.AudioRenderer; import com.jme3.audio.AudioRenderer;
import com.jme3.audio.openal.AL;
import com.jme3.audio.openal.ALAudioRenderer;
import com.jme3.audio.openal.ALC;
import com.jme3.audio.openal.EFX;
import com.jme3.system.JmeContext.Type; import com.jme3.system.JmeContext.Type;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.image.DefaultImageRaster; import com.jme3.texture.image.DefaultImageRaster;
@ -253,13 +257,36 @@ public class JmeDesktopSystem extends JmeSystemDelegate {
return ctx; return ctx;
} }
private <T> T newObject(String className) {
try {
Class<T> clazz = (Class<T>) Class.forName(className);
return clazz.newInstance();
} catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, "CRITICAL ERROR: Audio implementation class is missing!\n"
+ "Make sure jme3_lwjgl-oal or jm3_joal is on the classpath.", ex);
} catch (IllegalAccessException ex) {
logger.log(Level.SEVERE, "Failed to create context", ex);
} catch (InstantiationException ex) {
logger.log(Level.SEVERE, "Failed to create context", ex);
}
return null;
}
private AudioRenderer newAudioRendererLwjgl() {
AL al = newObject("com.jme3.audio.lwjgl.LwjglAL");
ALC alc = newObject("com.jme3.audio.lwjgl.LwjglALC");
EFX efx = newObject("com.jme3.audio.lwjgl.LwjglEFX");
return new ALAudioRenderer(al, alc, efx);
}
@Override @Override
public AudioRenderer newAudioRenderer(AppSettings settings) { public AudioRenderer newAudioRenderer(AppSettings settings) {
initialize(settings); initialize(settings);
Class<? extends AudioRenderer> clazz = null; Class<? extends AudioRenderer> clazz = null;
try { try {
if (settings.getAudioRenderer().startsWith("LWJGL")) { if (settings.getAudioRenderer().startsWith("LWJGL")) {
clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.lwjgl.LwjglAudioRenderer"); return newAudioRendererLwjgl();
} else if (settings.getAudioRenderer().startsWith("JOAL")) { } else if (settings.getAudioRenderer().startsWith("JOAL")) {
clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.joal.JoalAudioRenderer"); clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.joal.JoalAudioRenderer");
} else { } else {

@ -37,8 +37,18 @@ import com.jme3.math.Vector3f;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.NativeObjectManager; import com.jme3.util.NativeObjectManager;
import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.Buffers;
import com.jogamp.openal.*; import com.jogamp.openal.AL;
import com.jogamp.openal.ALC;
import com.jogamp.openal.ALCcontext;
import com.jogamp.openal.ALCdevice;
import com.jogamp.openal.ALConstants;
import com.jogamp.openal.ALException;
import com.jogamp.openal.ALExt;
import com.jogamp.openal.ALExtConstants;
import com.jogamp.openal.ALFactory;
import com.jogamp.openal.util.ALut; import com.jogamp.openal.util.ALut;
//import com.jogamp.openal.*;
//import com.jogamp.openal.util.ALut;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
@ -861,6 +871,14 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
} }
} }
public void pauseAll() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public void resumeAll() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public void playSourceInstance(AudioSource src) { public void playSourceInstance(AudioSource src) {
checkDead(); checkDead();
synchronized (threadLock) { synchronized (threadLock) {

@ -0,0 +1,107 @@
package com.jme3.audio.lwjgl;
import com.jme3.audio.openal.AL;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.AL11;
public final class LwjglAL implements AL {
public LwjglAL() {
}
public String alGetString(int parameter) {
return AL10.alGetString(parameter);
}
public int alGenSources() {
return AL10.alGenSources();
}
public int alGetError() {
return AL10.alGetError();
}
public void alDeleteSources(int numSources, IntBuffer sources) {
if (sources.position() != 0) throw new AssertionError();
if (sources.limit() != numSources) throw new AssertionError();
AL10.alDeleteSources(sources);
}
public void alGenBuffers(int numBuffers, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numBuffers) throw new AssertionError();
AL10.alGenBuffers(buffers);
}
public void alDeleteBuffers(int numBuffers, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numBuffers) throw new AssertionError();
AL10.alDeleteBuffers(buffers);
}
public void alSourceStop(int source) {
AL10.alSourceStop(source);
}
public void alSourcei(int source, int param, int value) {
AL10.alSourcei(source, param, value);
}
public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency) {
if (data.position() != 0) throw new AssertionError();
if (data.limit() != size) throw new AssertionError();
AL10.alBufferData(buffer, format, data, frequency);
}
public void alSourcePlay(int source) {
AL10.alSourcePlay(source);
}
public void alSourcePause(int source) {
AL10.alSourcePause(source);
}
public void alSourcef(int source, int param, float value) {
AL10.alSourcef(source, param, value);
}
public void alSource3f(int source, int param, float value1, float value2, float value3) {
AL10.alSource3f(source, param, value1, value2, value3);
}
public int alGetSourcei(int source, int param) {
return AL10.alGetSourcei(source, param);
}
public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numBuffers) throw new AssertionError();
AL10.alSourceUnqueueBuffers(source, buffers);
}
public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numBuffers) throw new AssertionError();
AL10.alSourceQueueBuffers(source, buffers);
}
public void alListener(int param, FloatBuffer data) {
AL10.alListener(param, data);
}
public void alListenerf(int param, float value) {
AL10.alListenerf(param, value);
}
public void alListener3f(int param, float value1, float value2, float value3) {
AL10.alListener3f(param, value1, value2, value3);
}
public void alSource3i(int source, int param, int value1, int value2, int value3) {
AL11.alSource3i(source, param, value1, value2, value3);
}
}

@ -0,0 +1,50 @@
package com.jme3.audio.lwjgl;
import com.jme3.audio.openal.ALC;
import java.nio.IntBuffer;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.ALCcontext;
import org.lwjgl.openal.ALCdevice;
public class LwjglALC implements ALC {
public void createALC() {
try {
AL.create();
} catch (LWJGLException ex) {
throw new RuntimeException(ex);
}
}
public void destroyALC() {
AL.destroy();
}
public boolean isCreated() {
return AL.isCreated();
}
public String alcGetString(int parameter) {
ALCcontext context = ALC10.alcGetCurrentContext();
ALCdevice device = ALC10.alcGetContextsDevice(context);
return ALC10.alcGetString(device, parameter);
}
public boolean alcIsExtensionPresent(String extension) {
ALCcontext context = ALC10.alcGetCurrentContext();
ALCdevice device = ALC10.alcGetContextsDevice(context);
return ALC10.alcIsExtensionPresent(device, extension);
}
public void alcGetInteger(int param, IntBuffer buffer, int size) {
if (buffer.position() != 0) throw new AssertionError();
if (buffer.limit() != size) throw new AssertionError();
ALCcontext context = ALC10.alcGetCurrentContext();
ALCdevice device = ALC10.alcGetContextsDevice(context);
ALC10.alcGetInteger(device, param, buffer);
}
}

@ -0,0 +1,65 @@
package com.jme3.audio.lwjgl;
import com.jme3.audio.openal.EFX;
import java.nio.IntBuffer;
import org.lwjgl.openal.EFX10;
public class LwjglEFX implements EFX {
public void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numSlots) throw new AssertionError();
EFX10.alGenAuxiliaryEffectSlots(buffers);
}
public void alGenEffects(int numEffects, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numEffects) throw new AssertionError();
EFX10.alGenEffects(buffers);
}
public void alEffecti(int effect, int param, int value) {
EFX10.alEffecti(effect, param, value);
}
public void alAuxiliaryEffectSloti(int effectSlot, int param, int value) {
EFX10.alAuxiliaryEffectSloti(effectSlot, param, value);
}
public void alDeleteEffects(int numEffects, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numEffects) throw new AssertionError();
EFX10.alDeleteEffects(buffers);
}
public void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numEffectSlots) throw new AssertionError();
EFX10.alDeleteAuxiliaryEffectSlots(buffers);
}
public void alGenFilters(int numFilters, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numFilters) throw new AssertionError();
EFX10.alGenFilters(buffers);
}
public void alFilteri(int filter, int param, int value) {
EFX10.alFilteri(filter, param, value);
}
public void alFilterf(int filter, int param, float value) {
EFX10.alFilterf(filter, param, value);
}
public void alDeleteFilters(int numFilters, IntBuffer buffers) {
if (buffers.position() != 0) throw new AssertionError();
if (buffers.limit() != numFilters) throw new AssertionError();
EFX10.alDeleteFilters(buffers);
}
public void alEffectf(int effect, int param, float value) {
EFX10.alEffectf(effect, param, value);
}
}
Loading…
Cancel
Save