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 ¶mArr = 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