kopia lustrzana https://github.com/sh123/codec2_talkie
122 wiersze
3.9 KiB
C++
122 wiersze
3.9 KiB
C++
#include <jni.h>
|
|
#include <cstdlib>
|
|
#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, numChannels, 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, numChannels, &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)I", (void *) decode },
|
|
{"encode", "(J[SI[B)I", (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<void **>(&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;
|
|
}
|
|
}
|
|
}
|