xref: /aosp_15_r20/external/oboe/apps/fxlab/app/src/main/cpp/native-lib.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1 /*
2  * Copyright  2019 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <jni.h>
18 
19 #include <string>
20 #include <functional>
21 #include <utility>
22 #include <vector>
23 
24 #include "DuplexEngine.h"
25 #include "effects/Effects.h"
26 #include "FunctionList.h"
27 
28 
29 // JNI Utility functions and globals
30 static DuplexEngine *enginePtr = nullptr;
31 
32 // Actual JNI interface
33 extern "C" {
34 
35 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_createAudioEngine(JNIEnv,jobject)36 Java_com_mobileer_androidfxlab_NativeInterface_createAudioEngine(
37         JNIEnv,
38         jobject /* this */) {
39     enginePtr = new DuplexEngine();
40 }
41 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_destroyAudioEngine(JNIEnv,jobject)42 Java_com_mobileer_androidfxlab_NativeInterface_destroyAudioEngine(
43         JNIEnv,
44         jobject /* this */) {
45     if (!enginePtr) return;
46     delete enginePtr;
47     enginePtr = nullptr;
48 }
49 
50 JNIEXPORT jobjectArray JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_getEffects(JNIEnv * env,jobject)51 Java_com_mobileer_androidfxlab_NativeInterface_getEffects(JNIEnv *env, jobject) {
52     jclass jcl = env->FindClass("com/mobileer/androidfxlab/datatype/EffectDescription");
53     jclass jparamcl = env->FindClass("com/mobileer/androidfxlab/datatype/ParamDescription");
54     assert (jcl != nullptr && jparamcl != nullptr);
55 
56     auto jparamMethodId = env->GetMethodID(jparamcl, "<init>", "(Ljava/lang/String;FFF)V");
57     auto jMethodId = env->GetMethodID(jcl, "<init>",
58                                       "(Ljava/lang/String;Ljava/lang/String;I[Lcom/mobileer/androidfxlab/datatype/ParamDescription;)V");
59 
60     auto arr = env->NewObjectArray(numEffects, jcl, nullptr);
61     auto lambda = [&](auto &arg, int i) {
62         const auto &paramArr = arg.getParams();
63         auto jparamArr = env->NewObjectArray(paramArr.size(), jparamcl, nullptr);
64         int c = 0;
65         for (auto const &elem: paramArr) {
66             jobject j = env->NewObject(jparamcl, jparamMethodId,
67                                        env->NewStringUTF(std::string(elem.kName).c_str()),
68                                        elem.kMinVal, elem.kMaxVal, elem.kDefVal);
69             assert(j != nullptr);
70             env->SetObjectArrayElement(jparamArr, c++, j);
71         }
72         jobject j = env->NewObject(jcl, jMethodId,
73                                    env->NewStringUTF(std::string(arg.getName()).c_str()),
74                                    env->NewStringUTF(std::string(arg.getCategory()).c_str()),
75                                    i, jparamArr);
76         assert(j != nullptr);
77         env->SetObjectArrayElement(arr, i, j);
78     };
79     int i = 0;
80     std::apply([&i, &lambda](auto &&... args) mutable { ((lambda(args, i++)), ...); },
81                EffectsTuple);
82     return arr;
83 }
84 
85 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_addDefaultEffectNative(JNIEnv *,jobject,jint jid)86 Java_com_mobileer_androidfxlab_NativeInterface_addDefaultEffectNative(JNIEnv *, jobject, jint jid) {
87     if (!enginePtr) return;
88     auto id = static_cast<int>(jid);
89 
90     std::visit([id](auto &&stack) {
91         std::function<void(decltype(stack.getType()), decltype(stack.getType()))> f;
92         int i = 0;
93         std::apply([id, &f, &i](auto &&... args) mutable {
94             ((f = (i++ == id) ?
95                   args.template buildDefaultEffect<decltype(stack.getType())>() : f), ...);
96         }, EffectsTuple);
97         stack.addEffect(std::move(f));
98     }, enginePtr->functionList);
99 }
100 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_removeEffectNative(JNIEnv *,jobject,jint jind)101 Java_com_mobileer_androidfxlab_NativeInterface_removeEffectNative(JNIEnv *, jobject, jint jind) {
102     if (!enginePtr) return;
103     auto ind = static_cast<size_t>(jind);
104     std::visit([ind](auto &&arg) {
105         arg.removeEffectAt(ind);
106     }, enginePtr->functionList);
107 }
108 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_rotateEffectNative(JNIEnv *,jobject,jint jfrom,jint jto)109 Java_com_mobileer_androidfxlab_NativeInterface_rotateEffectNative(JNIEnv *, jobject,
110                                                                 jint jfrom, jint jto) {
111     if (!enginePtr) return;
112     auto from = static_cast<size_t>(jfrom);
113     auto to = static_cast<size_t>(jto);
114 
115     std::visit([from, to](auto &&arg) {
116         arg.rotateEffectAt(from, to);
117     }, enginePtr->functionList);
118 }
119 
120 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_modifyEffectNative(JNIEnv * env,jobject,jint jid,jint jindex,jfloatArray params)121 Java_com_mobileer_androidfxlab_NativeInterface_modifyEffectNative(
122         JNIEnv *env, jobject, jint jid, jint jindex, jfloatArray params) {
123     if (!enginePtr) return;
124     int id = static_cast<int>(jid);
125     int index = static_cast<size_t>(jindex);
126 
127     jfloat *data = env->GetFloatArrayElements(params, nullptr);
128     std::vector<float> arr{data, data + env->GetArrayLength(params)};
129     env->ReleaseFloatArrayElements(params, data, 0);
130     std::visit([&arr, &id, &index](auto &&stack) {
131         std::function<void(decltype(stack.getType()), decltype(stack.getType()))> ef;
132         int i = 0;
133         std::apply([&](auto &&... args) mutable {
134             ((ef = (i++ == id) ?
135                    args.modifyEffectVec(ef, arr) : ef), ...);
136         }, EffectsTuple);
137         stack.modifyEffectAt(index, std::move(ef));
138     }, enginePtr->functionList);
139 }
140 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_enableEffectNative(JNIEnv *,jobject,jint jindex,jboolean jenable)141 Java_com_mobileer_androidfxlab_NativeInterface_enableEffectNative(
142         JNIEnv *, jobject, jint jindex, jboolean jenable) {
143     if (!enginePtr) return;
144     auto ind = static_cast<size_t>(jindex);
145     auto enable = static_cast<bool>(jenable);
146     std::visit([ind, enable](auto &&args) {
147         args.enableEffectAt(ind, enable);
148     }, enginePtr->functionList);
149 }
150 JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_enablePassthroughNative(JNIEnv *,jobject,jboolean jenable)151 Java_com_mobileer_androidfxlab_NativeInterface_enablePassthroughNative(
152         JNIEnv *, jobject, jboolean jenable) {
153     if (!enginePtr) return;
154     std::visit([enable = static_cast<bool>(jenable)](auto &&args) {
155         args.mute(!enable);
156     }, enginePtr->functionList);
157 }
158 } //extern C
159 
160