1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker * Copyright 2021 The Android Open Source Project
3*b7c941bbSAndroid Build Coastguard Worker *
4*b7c941bbSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*b7c941bbSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*b7c941bbSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*b7c941bbSAndroid Build Coastguard Worker *
8*b7c941bbSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*b7c941bbSAndroid Build Coastguard Worker *
10*b7c941bbSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*b7c941bbSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*b7c941bbSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b7c941bbSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*b7c941bbSAndroid Build Coastguard Worker * limitations under the License.
15*b7c941bbSAndroid Build Coastguard Worker */
16*b7c941bbSAndroid Build Coastguard Worker #include <cstring>
17*b7c941bbSAndroid Build Coastguard Worker
18*b7c941bbSAndroid Build Coastguard Worker #include <android/log.h>
19*b7c941bbSAndroid Build Coastguard Worker #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
20*b7c941bbSAndroid Build Coastguard Worker
21*b7c941bbSAndroid Build Coastguard Worker #include "JavaSourceProxy.h"
22*b7c941bbSAndroid Build Coastguard Worker
23*b7c941bbSAndroid Build Coastguard Worker static const char* TAG = "JavaSourceProxy";
24*b7c941bbSAndroid Build Coastguard Worker static const char* sClassNameAudioSource = "org/hyphonate/megaaudio/player/AudioSource";
25*b7c941bbSAndroid Build Coastguard Worker
26*b7c941bbSAndroid Build Coastguard Worker JavaVM* sJVM;
27*b7c941bbSAndroid Build Coastguard Worker
28*b7c941bbSAndroid Build Coastguard Worker jmethodID JavaSourceProxy::sMidInit;
29*b7c941bbSAndroid Build Coastguard Worker jmethodID JavaSourceProxy::sMidStart;
30*b7c941bbSAndroid Build Coastguard Worker jmethodID JavaSourceProxy::sMidStop;
31*b7c941bbSAndroid Build Coastguard Worker jmethodID JavaSourceProxy::sMidReset;
32*b7c941bbSAndroid Build Coastguard Worker jmethodID JavaSourceProxy::sMidPull;
33*b7c941bbSAndroid Build Coastguard Worker
initJni(JNIEnv * env)34*b7c941bbSAndroid Build Coastguard Worker void JavaSourceProxy::initJni(JNIEnv *env) {
35*b7c941bbSAndroid Build Coastguard Worker env->GetJavaVM(&sJVM);
36*b7c941bbSAndroid Build Coastguard Worker
37*b7c941bbSAndroid Build Coastguard Worker jclass clsAudioSource = env->FindClass(sClassNameAudioSource);
38*b7c941bbSAndroid Build Coastguard Worker
39*b7c941bbSAndroid Build Coastguard Worker sMidInit = env->GetMethodID(clsAudioSource, "init", "(II)V");
40*b7c941bbSAndroid Build Coastguard Worker sMidStart = env->GetMethodID(clsAudioSource, "start", "()V");
41*b7c941bbSAndroid Build Coastguard Worker sMidStop = env->GetMethodID(clsAudioSource, "stop", "()V");
42*b7c941bbSAndroid Build Coastguard Worker sMidReset = env->GetMethodID(clsAudioSource, "reset", "()V");
43*b7c941bbSAndroid Build Coastguard Worker sMidPull = env->GetMethodID(clsAudioSource, "pull", "([FII)I");
44*b7c941bbSAndroid Build Coastguard Worker }
45*b7c941bbSAndroid Build Coastguard Worker
JavaSourceProxy(jobject sourceObj)46*b7c941bbSAndroid Build Coastguard Worker JavaSourceProxy::JavaSourceProxy(jobject sourceObj)
47*b7c941bbSAndroid Build Coastguard Worker : mSourceObj(nullptr),
48*b7c941bbSAndroid Build Coastguard Worker mJavaBuffer(nullptr),
49*b7c941bbSAndroid Build Coastguard Worker mIsJVMAttached(false) {
50*b7c941bbSAndroid Build Coastguard Worker // Get the local JNI env
51*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
52*b7c941bbSAndroid Build Coastguard Worker mSourceObj = env->NewGlobalRef(sourceObj);
53*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
54*b7c941bbSAndroid Build Coastguard Worker }
55*b7c941bbSAndroid Build Coastguard Worker
~JavaSourceProxy()56*b7c941bbSAndroid Build Coastguard Worker JavaSourceProxy::~JavaSourceProxy() {
57*b7c941bbSAndroid Build Coastguard Worker // Get the local JNI env
58*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
59*b7c941bbSAndroid Build Coastguard Worker env->DeleteGlobalRef(mSourceObj);
60*b7c941bbSAndroid Build Coastguard Worker env->DeleteGlobalRef(mJavaBuffer);
61*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
62*b7c941bbSAndroid Build Coastguard Worker }
63*b7c941bbSAndroid Build Coastguard Worker
attachToJVM()64*b7c941bbSAndroid Build Coastguard Worker JNIEnv * JavaSourceProxy::attachToJVM() {
65*b7c941bbSAndroid Build Coastguard Worker // Get the local JNI env
66*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env;
67*b7c941bbSAndroid Build Coastguard Worker int getEnvStat = sJVM->GetEnv((void **)&env, JNI_VERSION_1_6);
68*b7c941bbSAndroid Build Coastguard Worker
69*b7c941bbSAndroid Build Coastguard Worker if (getEnvStat == JNI_EDETACHED) {
70*b7c941bbSAndroid Build Coastguard Worker /*int rs = */sJVM->AttachCurrentThread(&env, NULL);
71*b7c941bbSAndroid Build Coastguard Worker mIsJVMAttached = true;
72*b7c941bbSAndroid Build Coastguard Worker }
73*b7c941bbSAndroid Build Coastguard Worker
74*b7c941bbSAndroid Build Coastguard Worker return env;
75*b7c941bbSAndroid Build Coastguard Worker }
76*b7c941bbSAndroid Build Coastguard Worker
detachFromJVM()77*b7c941bbSAndroid Build Coastguard Worker void JavaSourceProxy::detachFromJVM() {
78*b7c941bbSAndroid Build Coastguard Worker if (mIsJVMAttached) {
79*b7c941bbSAndroid Build Coastguard Worker sJVM->DetachCurrentThread();
80*b7c941bbSAndroid Build Coastguard Worker }
81*b7c941bbSAndroid Build Coastguard Worker }
82*b7c941bbSAndroid Build Coastguard Worker
init(int numFrames,int numChans)83*b7c941bbSAndroid Build Coastguard Worker void JavaSourceProxy::init(int numFrames, int numChans) {
84*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
85*b7c941bbSAndroid Build Coastguard Worker
86*b7c941bbSAndroid Build Coastguard Worker mJavaBuffer = env->NewFloatArray(numFrames * numChans);
87*b7c941bbSAndroid Build Coastguard Worker mJavaBuffer = (jfloatArray)env->NewGlobalRef(mJavaBuffer);
88*b7c941bbSAndroid Build Coastguard Worker
89*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
90*b7c941bbSAndroid Build Coastguard Worker }
91*b7c941bbSAndroid Build Coastguard Worker
start()92*b7c941bbSAndroid Build Coastguard Worker void JavaSourceProxy::start() {
93*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
94*b7c941bbSAndroid Build Coastguard Worker env->CallVoidMethod(mSourceObj, sMidStart);
95*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
96*b7c941bbSAndroid Build Coastguard Worker }
97*b7c941bbSAndroid Build Coastguard Worker
stop()98*b7c941bbSAndroid Build Coastguard Worker void JavaSourceProxy::stop() {
99*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
100*b7c941bbSAndroid Build Coastguard Worker env->CallVoidMethod(mSourceObj, sMidStop);
101*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
102*b7c941bbSAndroid Build Coastguard Worker }
103*b7c941bbSAndroid Build Coastguard Worker
reset()104*b7c941bbSAndroid Build Coastguard Worker void JavaSourceProxy::reset() {
105*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
106*b7c941bbSAndroid Build Coastguard Worker env->CallVoidMethod(mSourceObj, sMidReset);
107*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
108*b7c941bbSAndroid Build Coastguard Worker }
109*b7c941bbSAndroid Build Coastguard Worker
pull(float * buffer,int numFrames,int numChans)110*b7c941bbSAndroid Build Coastguard Worker int JavaSourceProxy::pull(float* buffer, int numFrames, int numChans) {
111*b7c941bbSAndroid Build Coastguard Worker JNIEnv * env = attachToJVM();
112*b7c941bbSAndroid Build Coastguard Worker
113*b7c941bbSAndroid Build Coastguard Worker int numFilledFrames = env->CallIntMethod(mSourceObj, sMidPull, mJavaBuffer, numFrames, numChans);
114*b7c941bbSAndroid Build Coastguard Worker memcpy(buffer,
115*b7c941bbSAndroid Build Coastguard Worker env->GetFloatArrayElements(mJavaBuffer, 0),
116*b7c941bbSAndroid Build Coastguard Worker (numFilledFrames * numChans) * sizeof(float));
117*b7c941bbSAndroid Build Coastguard Worker
118*b7c941bbSAndroid Build Coastguard Worker detachFromJVM();
119*b7c941bbSAndroid Build Coastguard Worker
120*b7c941bbSAndroid Build Coastguard Worker return numFilledFrames;
121*b7c941bbSAndroid Build Coastguard Worker }
122*b7c941bbSAndroid Build Coastguard Worker
123*b7c941bbSAndroid Build Coastguard Worker extern "C" {
124*b7c941bbSAndroid Build Coastguard Worker JNIEXPORT void JNICALL
Java_org_hyphonate_megaaudio_player_JavaSourceProxy_initN(JNIEnv * env,jclass clazz)125*b7c941bbSAndroid Build Coastguard Worker Java_org_hyphonate_megaaudio_player_JavaSourceProxy_initN(JNIEnv *env, jclass clazz) {
126*b7c941bbSAndroid Build Coastguard Worker JavaSourceProxy::initJni(env);
127*b7c941bbSAndroid Build Coastguard Worker }
128*b7c941bbSAndroid Build Coastguard Worker
129*b7c941bbSAndroid Build Coastguard Worker JNIEXPORT jlong JNICALL
Java_org_hyphonate_megaaudio_player_JavaSourceProxy_allocNativeSource(JNIEnv * env,jclass clazz,jobject javaSource)130*b7c941bbSAndroid Build Coastguard Worker Java_org_hyphonate_megaaudio_player_JavaSourceProxy_allocNativeSource(JNIEnv *env, jclass clazz, jobject javaSource) {
131*b7c941bbSAndroid Build Coastguard Worker ALOGI("allocNativeSource(%p)", javaSource);
132*b7c941bbSAndroid Build Coastguard Worker return (jlong)(new JavaSourceProxy(javaSource));
133*b7c941bbSAndroid Build Coastguard Worker }
134*b7c941bbSAndroid Build Coastguard Worker
135*b7c941bbSAndroid Build Coastguard Worker } // extern "C"
136