From ce302e8f03dc59b2f63e40557ea135894568701e Mon Sep 17 00:00:00 2001 From: pavl_g Date: Fri, 17 Feb 2023 23:26:05 +0200 Subject: [PATCH 1/7] android-native-vorbis: fix double asset file descriptor closure --- .../com_jme3_audio_plugins_NativeVorbisFile.c | 33 +++++++++++-------- .../jme3/audio/plugins/NativeVorbisFile.java | 23 +++++++++---- .../audio/plugins/NativeVorbisLoader.java | 6 ++-- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c index ceebbd81ba..cccc48dbc0 100644 --- a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c +++ b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c @@ -110,13 +110,18 @@ static int FileDesc_seek(void *datasource, ogg_int64_t offset, int whence) wrapper->current = actual_offset; } -static int FileDesc_close(void *datasource) +static int FileDesc_clear(void *datasource) { FileDescWrapper* wrapper = (FileDescWrapper*)datasource; - LOGI("FD close"); - - return close(wrapper->fd); + LOGI("Clear resources -- delegating closure to the Android ParcelFileDescriptor"); + + /* release the file descriptor wrapper buffer */ + free(wrapper); + + wrapper = NULL; + + return 0; } static long FileDesc_tell(void *datasource) @@ -139,7 +144,7 @@ static long FileDesc_tell(void *datasource) static ov_callbacks FileDescCallbacks = { FileDesc_read, FileDesc_seek, - FileDesc_close, + FileDesc_clear, FileDesc_tell }; @@ -157,10 +162,10 @@ static jfieldID nvf_field_bitRate; static jfieldID nvf_field_totalBytes; static jfieldID nvf_field_duration; -JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_nativeInit +JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_preInit (JNIEnv *env, jclass clazz) { - LOGI("nativeInit"); + LOGI("preInit"); nvf_field_ovf = (*env)->GetFieldID(env, clazz, "ovf", "Ljava/nio/ByteBuffer;");; nvf_field_seekable = (*env)->GetFieldID(env, clazz, "seekable", "Z"); @@ -171,7 +176,7 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_nativeInit nvf_field_duration = (*env)->GetFieldID(env, clazz, "duration", "F"); } -JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_open +JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_init (JNIEnv *env, jobject nvf, jint fd, jlong off, jlong len) { LOGI("open: fd = %d, off = %lld, len = %lld", fd, off, len); @@ -330,19 +335,19 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_readFully } } -JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_close +JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_clearResources (JNIEnv *env, jobject nvf) { - LOGI("close"); + LOGI("clearResources"); jobject ovfBuf = (*env)->GetObjectField(env, nvf, nvf_field_ovf); OggVorbis_File* ovf = (OggVorbis_File*) (*env)->GetDirectBufferAddress(env, ovfBuf); - FileDescWrapper* wrapper = (FileDescWrapper*) ovf->datasource; - wrapper->env = env; + /* release the ovf resources */ ov_clear(ovf); - - free(wrapper); + /* release the ovf buffer */ free(ovf); + ovf = NULL; + /* destroy the java reference object */ (*env)->SetObjectField(env, nvf, nvf_field_ovf, NULL); } diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java index bd6ecc6273..db81da0008 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java @@ -16,14 +16,22 @@ public class NativeVorbisFile { static { System.loadLibrary("decodejme"); - nativeInit(); + preInit(); } - public NativeVorbisFile(int fd, long off, long len) throws IOException { - open(fd, off, len); + /** + * Initializes an ogg vorbis native file from a file descriptor [fd]. + * + * @param fd an integer representing the file descriptor + * @param offset an integer representing the start of the + * @param length an integer representing the length of the + * @throws IOException + */ + public NativeVorbisFile(int fd, long offset, long length) throws IOException { + init(fd, offset, length); } - private native void open(int fd, long off, long len) throws IOException; + private native void init(int fd, long offset, long length) throws IOException; public native void seekTime(double time) throws IOException; @@ -31,7 +39,10 @@ public NativeVorbisFile(int fd, long off, long len) throws IOException { public native void readFully(ByteBuffer out) throws IOException; - public native void close(); + /** + * Clears the native resources by calling free() destroying the structure defining this buffer. + */ + public native void clearResources(); - public static native void nativeInit(); + public static native void preInit(); } diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java index 3093b0d4b2..cdbde1a273 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java @@ -57,7 +57,7 @@ public void setTime(float time) { @Override public void close() throws IOException { - file.close(); + file.clearResources(); afd.close(); } } @@ -78,7 +78,7 @@ private static AudioBuffer loadBuffer(AssetInfo assetInfo) throws IOException { return ab; } finally { if (file != null) { - file.close(); + file.clearResources(); } if (afd != null) { afd.close(); @@ -107,7 +107,7 @@ private static AudioStream loadStream(AssetInfo assetInfo) throws IOException { } finally { if (!success) { if (file != null) { - file.close(); + file.clearResources(); } if (afd != null) { afd.close(); From 7411098983a959c912ba49974ddc63d44c730a19 Mon Sep 17 00:00:00 2001 From: pavl_g Date: Sat, 18 Feb 2023 17:22:52 +0200 Subject: [PATCH 2/7] NativeVorbis: better names and javadocs --- .../com_jme3_audio_plugins_NativeVorbisFile.c | 4 +- .../jme3/audio/plugins/NativeVorbisFile.java | 96 +++++++++++++++++-- .../audio/plugins/NativeVorbisLoader.java | 6 +- 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c index cccc48dbc0..936bde46be 100644 --- a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c +++ b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c @@ -251,7 +251,7 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_seekTime } } -JNIEXPORT jint JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_read +JNIEXPORT jint JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_readIntoArray (JNIEnv *env, jobject nvf, jbyteArray buf, jint off, jint len) { int bitstream = -1; @@ -293,7 +293,7 @@ JNIEXPORT jint JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_read return result; } -JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_readFully +JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_readIntoBuffer (JNIEnv *env, jobject nvf, jobject buf) { int bitstream = -1; diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java index db81da0008..e91cbae541 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java @@ -1,8 +1,49 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.audio.plugins; import java.io.IOException; import java.nio.ByteBuffer; +/** + * Represents the android implementation for the native vorbis file decoder. + * This decoder initializes an OggVorbis_File from an already opened file designated by the {@link NativeVorbisFile#fd}. + *
+ * + * Code by Kirill Vainer. + *
+ * + * Modified by pavl_g. + */ public class NativeVorbisFile { public int fd; @@ -20,29 +61,64 @@ public class NativeVorbisFile { } /** - * Initializes an ogg vorbis native file from a file descriptor [fd]. + * Initializes an ogg vorbis native file from a file descriptor [fd] of an already opened file. * * @param fd an integer representing the file descriptor - * @param offset an integer representing the start of the - * @param length an integer representing the length of the - * @throws IOException + * @param offset an integer indicating the start of the buffer + * @param length an integer indicating the end of the buffer + * @throws IOException in cases of a failure to initialize the vorbis file */ public NativeVorbisFile(int fd, long offset, long length) throws IOException { init(fd, offset, length); } - private native void init(int fd, long offset, long length) throws IOException; - + /** + * Seeks to a playback time relative to the decompressed pcm (Pulse-code modulation) stream. + * + * @param time the playback seek time + * @throws IOException if the seek is not successful + */ public native void seekTime(double time) throws IOException; - public native int read(byte[] buf, int off, int len) throws IOException; + /** + * Reads the vorbis file into a primitive byte buffer [buf]. + * + * @param buffer a primitive byte buffer to read the data into it + * @param offset an integer representing the offset or the start of the data read + * @param length an integer representing the end of the data read + * @return the number of the read bytes, (-1) if the reading has failed indicating an EOF, + * returns (0) if the reading has failed or the primitive [buffer] passed is null + * @throws IOException if the library has failed to read the file into the [out] buffer + * or if the java primitive byte array [buffer] is inaccessible + */ + public native int readIntoArray(byte[] buffer, int offset, int length) throws IOException; - public native void readFully(ByteBuffer out) throws IOException; + /** + * Reads the vorbis file into a direct {@link java.nio.ByteBuffer}. + * + * @param out a reference to the output direct buffer + * @throws IOException if a premature EOF is encountered before reaching the end of the buffer + * or if the library has failed to read the file into the [out] buffer + */ + public native void readIntoBuffer(ByteBuffer out) throws IOException; /** - * Clears the native resources by calling free() destroying the structure defining this buffer. + * Clears the native resources and destroys the buffer {@link NativeVorbisFile#ovf} reference. */ public native void clearResources(); - public static native void preInit(); + /** + * Prepares the java fields for the native environment. + */ + private static native void preInit(); + + /** + * Initializes an ogg vorbis native file from a file descriptor [fd] of an already opened file. + * + * @param fd an integer representing the file descriptor + * @param offset an integer representing the start of the buffer + * @param length an integer representing the length of the buffer + * @throws IOException in cases of a failure to initialize the vorbis file + */ + private native void init(int fd, long offset, long length) throws IOException; } diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java index cdbde1a273..e10afaf493 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java @@ -33,12 +33,12 @@ public int read() throws IOException { @Override public int read(byte[] buf) throws IOException { - return file.read(buf, 0, buf.length); + return file.readIntoArray(buf, 0, buf.length); } @Override public int read(byte[] buf, int off, int len) throws IOException { - return file.read(buf, off, len); + return file.readIntoArray(buf, off, len); } @Override @@ -71,7 +71,7 @@ private static AudioBuffer loadBuffer(AssetInfo assetInfo) throws IOException { int fd = afd.getParcelFileDescriptor().getFd(); file = new NativeVorbisFile(fd, afd.getStartOffset(), afd.getLength()); ByteBuffer data = BufferUtils.createByteBuffer(file.totalBytes); - file.readFully(data); + file.readIntoBuffer(data); AudioBuffer ab = new AudioBuffer(); ab.setupFormat(file.channels, 16, file.sampleRate); ab.updateData(data); From 041cbc79a23d8089f25ca416fa174130e947b92b Mon Sep 17 00:00:00 2001 From: pavl_g Date: Sat, 18 Feb 2023 17:28:41 +0200 Subject: [PATCH 3/7] NativeVorbisFile#readIntoBuffer: specifies the start and the end of the read --- .../src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java index e91cbae541..85f29c14fb 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java @@ -94,7 +94,7 @@ public NativeVorbisFile(int fd, long offset, long length) throws IOException { public native int readIntoArray(byte[] buffer, int offset, int length) throws IOException; /** - * Reads the vorbis file into a direct {@link java.nio.ByteBuffer}. + * Reads the vorbis file into a direct {@link java.nio.ByteBuffer}, starting from offset [0] till the buffer capacity. * * @param out a reference to the output direct buffer * @throws IOException if a premature EOF is encountered before reaching the end of the buffer From 4ae26c1216a5dbe66f5515b3b749be5816e57831 Mon Sep 17 00:00:00 2001 From: pavl_g Date: Sat, 18 Feb 2023 17:52:11 +0200 Subject: [PATCH 4/7] NativeVorbisFile: better explanation for the output buffer on read functions --- .../main/java/com/jme3/audio/plugins/NativeVorbisFile.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java index 85f29c14fb..e46a772543 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java @@ -81,7 +81,8 @@ public NativeVorbisFile(int fd, long offset, long length) throws IOException { public native void seekTime(double time) throws IOException; /** - * Reads the vorbis file into a primitive byte buffer [buf]. + * Reads the vorbis file into a primitive byte buffer [buf] with an [offset] indicating the read start and a [length] indicating the read end on the output buffer. + * This is used for reading a particular chunk of data into a primitive array. * * @param buffer a primitive byte buffer to read the data into it * @param offset an integer representing the offset or the start of the data read @@ -94,7 +95,7 @@ public NativeVorbisFile(int fd, long offset, long length) throws IOException { public native int readIntoArray(byte[] buffer, int offset, int length) throws IOException; /** - * Reads the vorbis file into a direct {@link java.nio.ByteBuffer}, starting from offset [0] till the buffer capacity. + * Reads the vorbis file into a direct {@link java.nio.ByteBuffer}, starting from offset [0] till the buffer end on the output buffer. * * @param out a reference to the output direct buffer * @throws IOException if a premature EOF is encountered before reaching the end of the buffer From f63597fa1f629f5d2de8caaf73014ac7395a453a Mon Sep 17 00:00:00 2001 From: pavl_g Date: Sat, 18 Feb 2023 20:53:22 +0200 Subject: [PATCH 5/7] com_jme3_audio_plugins_NativeVorbisFile.c: refactored logs --- .../jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c index 936bde46be..25a15f5b8a 100644 --- a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c +++ b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c @@ -179,7 +179,7 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_preInit JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_init (JNIEnv *env, jobject nvf, jint fd, jlong off, jlong len) { - LOGI("open: fd = %d, off = %lld, len = %lld", fd, off, len); + LOGI("init: fd = %d, off = %lld, len = %lld", fd, off, len); OggVorbis_File* ovf = (OggVorbis_File*) malloc(sizeof(OggVorbis_File)); @@ -194,19 +194,19 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_init if (result != 0) { - LOGI("ov_open fail"); + LOGI("init fail"); free(ovf); free(wrapper); char err[512]; - sprintf(err, "ov_open failed: %d", result); + sprintf(err, "init failed: %d", result); throwIOException(env, err); return; } - LOGI("ov_open OK"); + LOGI("init OK"); jobject ovfBuf = (*env)->NewDirectByteBuffer(env, ovf, sizeof(OggVorbis_File)); vorbis_info* info = ov_info(ovf, -1); From 156251818581077d47d0a9f2e64e4b162a896f4e Mon Sep 17 00:00:00 2001 From: pavl_g Date: Sat, 18 Feb 2023 20:58:17 +0200 Subject: [PATCH 6/7] NativeVorbisFile: some docs enhances --- .../main/java/com/jme3/audio/plugins/NativeVorbisFile.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java index e46a772543..9af1e62cbe 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisFile.java @@ -81,12 +81,11 @@ public NativeVorbisFile(int fd, long offset, long length) throws IOException { public native void seekTime(double time) throws IOException; /** - * Reads the vorbis file into a primitive byte buffer [buf] with an [offset] indicating the read start and a [length] indicating the read end on the output buffer. - * This is used for reading a particular chunk of data into a primitive array. + * Reads the vorbis file into a primitive byte buffer [buf] with an [offset] indicating the start byte and a [length] indicating the end byte on the output buffer. * * @param buffer a primitive byte buffer to read the data into it - * @param offset an integer representing the offset or the start of the data read - * @param length an integer representing the end of the data read + * @param offset an integer representing the offset or the start byte on the output buffer + * @param length an integer representing the end byte on the output buffer * @return the number of the read bytes, (-1) if the reading has failed indicating an EOF, * returns (0) if the reading has failed or the primitive [buffer] passed is null * @throws IOException if the library has failed to read the file into the [out] buffer From fa4072f3fc3c2d8043f922cd8f98124428efcbb2 Mon Sep 17 00:00:00 2001 From: pavl_g Date: Sat, 18 Feb 2023 21:09:58 +0200 Subject: [PATCH 7/7] NativeVorbisLoader: added updated jme3-copyright --- .../audio/plugins/NativeVorbisLoader.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java index e10afaf493..63517cd3d8 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.audio.plugins; import android.content.res.AssetFileDescriptor;