Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -139,7 +144,7 @@ static long FileDesc_tell(void *datasource)
static ov_callbacks FileDescCallbacks = {
FileDesc_read,
FileDesc_seek,
FileDesc_close,
FileDesc_clear,
FileDesc_tell
};

Expand All @@ -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");
Expand All @@ -171,10 +176,10 @@ 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);
LOGI("init: fd = %d, off = %lld, len = %lld", fd, off, len);

OggVorbis_File* ovf = (OggVorbis_File*) malloc(sizeof(OggVorbis_File));

Expand All @@ -189,19 +194,19 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_open

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);
Expand Down Expand Up @@ -246,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;
Expand Down Expand Up @@ -288,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;
Expand Down Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
@@ -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 <a href="https://xiph.org"/> vorbis file decoder.
* This decoder initializes an OggVorbis_File from an already opened file designated by the {@link NativeVorbisFile#fd}.
* <br/>
*
* Code by Kirill Vainer.
* <br/>
*
* Modified by pavl_g.
*/
public class NativeVorbisFile {

public int fd;
Expand All @@ -16,22 +57,68 @@ 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] of an already opened file.
*
* @param fd an integer representing the file descriptor
* @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 open(int fd, long off, long len) 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] 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 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
* or if the java primitive byte array [buffer] is inaccessible
*/
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 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
* or if the library has failed to read the file into the [out] buffer
*/
public native void readIntoBuffer(ByteBuffer out) throws IOException;

public native void readFully(ByteBuffer out) throws IOException;
/**
* Clears the native resources and destroys the buffer {@link NativeVorbisFile#ovf} reference.
*/
public native void clearResources();

public native void close();
/**
* Prepares the java fields for the native environment.
*/
private static native void preInit();

public static native void nativeInit();
/**
* 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;
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -33,12 +64,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
Expand All @@ -57,7 +88,7 @@ public void setTime(float time) {

@Override
public void close() throws IOException {
file.close();
file.clearResources();
afd.close();
}
}
Expand All @@ -71,14 +102,14 @@ 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);
return ab;
} finally {
if (file != null) {
file.close();
file.clearResources();
}
if (afd != null) {
afd.close();
Expand Down Expand Up @@ -107,7 +138,7 @@ private static AudioStream loadStream(AssetInfo assetInfo) throws IOException {
} finally {
if (!success) {
if (file != null) {
file.close();
file.clearResources();
}
if (afd != null) {
afd.close();
Expand Down