|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#include <android/log.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sys/sysinfo.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "whisper.h"
|
|
|
|
|
|
|
|
|
|
#define UNUSED(x) (void)(x)
|
|
|
|
@ -17,6 +18,79 @@ static inline int max(int a, int b) {
|
|
|
|
|
return (a > b) ? a : b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct input_stream_context {
|
|
|
|
|
size_t offset;
|
|
|
|
|
JNIEnv * env;
|
|
|
|
|
jobject thiz;
|
|
|
|
|
jobject input_stream;
|
|
|
|
|
|
|
|
|
|
jmethodID mid_available;
|
|
|
|
|
jmethodID mid_read;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
size_t inputStreamRead(void * ctx, void * output, size_t read_size) {
|
|
|
|
|
struct input_stream_context* is = (struct input_stream_context*)ctx;
|
|
|
|
|
|
|
|
|
|
jint avail_size = (*is->env)->CallIntMethod(is->env, is->input_stream, is->mid_available);
|
|
|
|
|
jint size_to_copy = read_size < avail_size ? (jint)read_size : avail_size;
|
|
|
|
|
|
|
|
|
|
jbyteArray byte_array = (*is->env)->NewByteArray(is->env, size_to_copy);
|
|
|
|
|
|
|
|
|
|
jint n_read = (*is->env)->CallIntMethod(is->env, is->input_stream, is->mid_read, byte_array, 0, size_to_copy);
|
|
|
|
|
|
|
|
|
|
if (size_to_copy != read_size || size_to_copy != n_read) {
|
|
|
|
|
LOGI("Insufficient Read: Req=%zu, ToCopy=%d, Available=%d", read_size, size_to_copy, n_read);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jbyte* byte_array_elements = (*is->env)->GetByteArrayElements(is->env, byte_array, NULL);
|
|
|
|
|
memcpy(output, byte_array_elements, size_to_copy);
|
|
|
|
|
(*is->env)->ReleaseByteArrayElements(is->env, byte_array, byte_array_elements, JNI_ABORT);
|
|
|
|
|
|
|
|
|
|
(*is->env)->DeleteLocalRef(is->env, byte_array);
|
|
|
|
|
|
|
|
|
|
is->offset += size_to_copy;
|
|
|
|
|
|
|
|
|
|
return size_to_copy;
|
|
|
|
|
}
|
|
|
|
|
bool inputStreamEof(void * ctx) {
|
|
|
|
|
struct input_stream_context* is = (struct input_stream_context*)ctx;
|
|
|
|
|
|
|
|
|
|
jint result = (*is->env)->CallIntMethod(is->env, is->input_stream, is->mid_available);
|
|
|
|
|
return result <= 0;
|
|
|
|
|
}
|
|
|
|
|
void inputStreamClose(void * ctx) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
|
|
|
Java_com_whispercppdemo_whisper_WhisperLib_00024Companion_initContextFromInputStream(
|
|
|
|
|
JNIEnv *env, jobject thiz, jobject input_stream) {
|
|
|
|
|
UNUSED(thiz);
|
|
|
|
|
|
|
|
|
|
struct whisper_context *context = NULL;
|
|
|
|
|
struct whisper_model_loader loader = {};
|
|
|
|
|
struct input_stream_context inp_ctx = {};
|
|
|
|
|
|
|
|
|
|
inp_ctx.offset = 0;
|
|
|
|
|
inp_ctx.env = env;
|
|
|
|
|
inp_ctx.thiz = thiz;
|
|
|
|
|
inp_ctx.input_stream = input_stream;
|
|
|
|
|
|
|
|
|
|
jclass cls = (*env)->GetObjectClass(env, input_stream);
|
|
|
|
|
inp_ctx.mid_available = (*env)->GetMethodID(env, cls, "available", "()I");
|
|
|
|
|
inp_ctx.mid_read = (*env)->GetMethodID(env, cls, "read", "([BII)I");
|
|
|
|
|
|
|
|
|
|
loader.context = &inp_ctx;
|
|
|
|
|
loader.read = inputStreamRead;
|
|
|
|
|
loader.eof = inputStreamEof;
|
|
|
|
|
loader.close = inputStreamClose;
|
|
|
|
|
|
|
|
|
|
loader.eof(loader.context);
|
|
|
|
|
|
|
|
|
|
context = whisper_init(&loader);
|
|
|
|
|
return (jlong) context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
|
|
|
Java_com_whispercppdemo_whisper_WhisperLib_00024Companion_initContext(
|
|
|
|
|
JNIEnv *env, jobject thiz, jstring model_path_str) {
|
|
|
|
|