#include #include #include "opus.h" namespace Java_com_radio_opus_Opus { struct Context { OpusEncoder* encoder; OpusDecoder* decoder; }; static Context *getContext(jlong jp) { auto p = (unsigned long) jp; Context *con; con = (Context *) p; return con; } static jlong create(JNIEnv *env, jclass clazz, jint sampleRate, jint numChannels, jint application, jint bitrate, jint complexity) { struct Context *con; con = (struct Context *) malloc(sizeof(struct Context)); int encoderError; OpusEncoder* encoder = opus_encoder_create(sampleRate, 1, application, &encoderError); if (!encoderError) { encoderError = opus_encoder_init(encoder, sampleRate, numChannels, application); opus_encoder_ctl(encoder, OPUS_SET_BITRATE(bitrate)); opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(complexity)); } int decoderError; OpusDecoder* decoder = opus_decoder_create(sampleRate, 1, &decoderError); if (!decoderError) { decoderError = opus_decoder_init(decoder, sampleRate, numChannels); } if (encoderError || decoderError) { free(encoder); free(decoder); free(con); return 0; } con->decoder = decoder; con->encoder = encoder; auto pv = (unsigned long) con; return pv; } static jint destroy(JNIEnv *env, jclass clazz, jlong n) { Context *con = getContext(n); free(con->encoder); free(con->decoder); free(con); return 0; } static jint decode(JNIEnv *env, jclass clazz, jlong n, jbyteArray in, jshortArray out, jint frames) { Context *con = getContext(n); OpusDecoder *decoder = con->decoder; jint inputArraySize = env->GetArrayLength(in); jbyte* encodedData = env->GetByteArrayElements(in, 0); jshort* decodedData = env->GetShortArrayElements(out, 0); int samples = opus_decode(decoder, (const unsigned char *)encodedData, inputArraySize, decodedData, frames, 0); env->ReleaseByteArrayElements(in, encodedData, JNI_ABORT); env->ReleaseShortArrayElements(out, decodedData, 0); return samples; } static jint encode(JNIEnv *env, jclass clazz, jlong n, jshortArray in, jint frames, jbyteArray out) { Context *con = getContext(n); OpusEncoder *encoder = con->encoder; jint outputArraySize = env->GetArrayLength(out); jshort* audioSignal = env->GetShortArrayElements(in, 0); jbyte* encodedSignal = env->GetByteArrayElements(out, 0); int dataArraySize = opus_encode(encoder, audioSignal, frames, (unsigned char *)encodedSignal, outputArraySize); env->ReleaseShortArrayElements(in, audioSignal, JNI_ABORT); env->ReleaseByteArrayElements(out, encodedSignal, 0); return dataArraySize; } static JNINativeMethod method_table[] = { {"create", "(IIIII)J", (void *) create }, {"destroy", "(J)I", (void *) destroy }, {"decode", "(J[B[SI)J", (void *) decode }, {"encode", "(J[SI[B)J", (void *) encode } }; } using namespace Java_com_radio_opus_Opus; extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } else { jclass clazz = env->FindClass("com/radio/opus/Opus"); if (clazz) { jint ret = env->RegisterNatives(clazz, method_table, sizeof(method_table) / sizeof(method_table[0])); env->DeleteLocalRef(clazz); return ret == 0 ? JNI_VERSION_1_6 : JNI_ERR; } else { return JNI_ERR; } } }