more android progress
This commit is contained in:
parent
9e31fb8058
commit
b719737eda
@ -12,6 +12,15 @@ import android.content.pm.PackageManager;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
static {
|
||||
System.loadLibrary("@NAME@");
|
||||
}
|
||||
|
||||
public native boolean nativeAudioStart();
|
||||
public native void nativeAudioStop();
|
||||
public native float nativeGetParameter(int i);
|
||||
public native void nativeSetParameter(int i, float v);
|
||||
|
||||
private WebView webView;
|
||||
|
||||
public class WebAppInterface {
|
||||
@ -21,9 +30,28 @@ public class MainActivity extends Activity {
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public boolean requestAudioPermission() {
|
||||
public void requestAudioPermission() {
|
||||
ActivityCompat.requestPermissions(MainActivity.this, new String[] { android.Manifest.permission.RECORD_AUDIO }, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public boolean audioStart() {
|
||||
return nativeAudioStart();
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void audioStop() {
|
||||
nativeAudioStop();
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public float getParameter(int i) {
|
||||
return nativeGetParameter(i);
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void setParameter(int i, float v) {
|
||||
nativeSetParameter(i, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
COMMON_DIR := ${ROOT_DIR}/../../common/android
|
||||
BUILD_TOOLS_DIR := ${HOME}/Android/Sdk/build-tools/34.0.0
|
||||
ANDROIDX_DIR := ${HOME}/Android/androidx
|
||||
MINIAUDIO_DIR := ${ROOT_DIR}/../../../../miniaudio
|
||||
|
||||
JAR_FILE := ${HOME}/Android/Sdk/platforms/android-34/android.jar
|
||||
ANDROIDX_CORE_FILE := ${ANDROIDX_DIR}/core-1.10.1.jar
|
||||
@ -26,6 +27,7 @@ CXXFLAGS := \
|
||||
-I${ROOT_DIR}/../src \
|
||||
-I${COMMON_DIR} \
|
||||
-I${ROOT_DIR}/../../../include \
|
||||
-I${MINIAUDIO_DIR} \
|
||||
-O3 \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
@ -39,7 +41,7 @@ LDFLAGS := \
|
||||
-landroid
|
||||
|
||||
SOURCES_COMMON := \
|
||||
${COMMON_DIR}/jni.cpp
|
||||
build/gen/jni.cpp
|
||||
|
||||
JARS := \
|
||||
${JAR_FILE} \
|
||||
@ -50,6 +52,8 @@ JARS := \
|
||||
${KOTLINX_COROUTINES_CORE_FILE} \
|
||||
${KOTLINX_COROUTINES_CORE_JVM_FILE}
|
||||
|
||||
JNI_NAME := $(shell echo ${NAME} | sed 's:_:_1:g')
|
||||
|
||||
all: build/${NAME}.apk
|
||||
|
||||
build/${NAME}.apk: build/gen/${NAME}.aligned.apk build/apk/lib/armeabi-v7a/lib${NAME}.so build/gen/keystore.jks
|
||||
@ -61,7 +65,7 @@ build/gen/keystore.jks: | build/gen
|
||||
build/gen/${NAME}.aligned.apk: build/gen/${NAME}.unsigned.apk
|
||||
${ZIPALIGN} -f -p 4 $^ $@
|
||||
|
||||
build/gen/${NAME}.unsigned.apk: build/apk/classes.dex build/gen/AndroidManifest.xml build/assets/index.html build/assets/config.js | build/gen
|
||||
build/gen/${NAME}.unsigned.apk: build/apk/classes.dex build/gen/AndroidManifest.xml build/assets/index.html build/assets/config.js build/apk/lib/armeabi-v7a/lib${NAME}.so| build/gen
|
||||
${AAPT} package -f -M build/gen/AndroidManifest.xml -A build/assets -I ${JAR_FILE} -I ${ANDROIDX_CORE_FILE} -I ${ANDROIDX_LIFECYCLE_COMMON_FILE} -I ${ANDROIDX_VERSIONEDPARCELABLE_FILE} -I ${KOTLIN_STDLIB_FILE} -I ${KOTLINX_COROUTINES_CORE_FILE} -I ${KOTLINX_COROUTINES_CORE_JVM_FILE} -F $@ build/apk
|
||||
|
||||
build/apk/classes.dex: build/apk/my_classes.jar
|
||||
@ -72,6 +76,9 @@ build/apk/my_classes.jar: build/obj/com/orastron/${NAME}/MainActivity.class buil
|
||||
|
||||
build/apk/lib/armeabi-v7a/lib${NAME}.so: ${SOURCES} | build/apk/lib/armeabi-v7a
|
||||
${CXX} $^ ${CXXFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
build/gen/jni.cpp: ${COMMON_DIR}/jni.cpp | build/gen
|
||||
cat $^ | sed s:@JNI_NAME@:${JNI_NAME}:g > $@
|
||||
|
||||
build/obj/com/orastron/${NAME}/MainActivity$$WebAppInterface.class: build/obj/com/orastron/${NAME}/MainActivity.class
|
||||
|
||||
|
@ -2,35 +2,72 @@
|
||||
<head>
|
||||
<script type="text/javascript" src="config.js"></script>
|
||||
<script type="text/javascript">
|
||||
var hasAudioPermission = Android.hasAudioPermission();
|
||||
var hasAudioPermission = true;
|
||||
for (var i = 0; i < buses.length; i++)
|
||||
if (!buses[i].output) {
|
||||
hasAudioPermission = Android.hasAudioPermission();
|
||||
break;
|
||||
}
|
||||
var audioStarted = false;
|
||||
var topButtonElem;
|
||||
var outParamInterval;
|
||||
|
||||
window.onload = function () {
|
||||
topButtonElem = document.getElementById("topButton");
|
||||
var paramsElem = document.getElementById("params");
|
||||
|
||||
topButtonElem.value = hasAudioPermission ? "START" : "INIT";
|
||||
topButtonElem.addEventListener("click", function () {
|
||||
if (hasAudioPermission) {
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
if (audioStarted) {
|
||||
clearInterval(outParamInterval);
|
||||
Android.audioStop();
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.innerText = parameters[i].name;
|
||||
div.appendChild(label);
|
||||
paramsElem.innerHTML = "";
|
||||
|
||||
div.appendChild(document.createElement("br"));
|
||||
topButtonElem.value = "START";
|
||||
audioStarted = false;
|
||||
} else {
|
||||
if (Android.audioStart()) {
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var div = document.createElement("div");
|
||||
paramsElem.appendChild(div);
|
||||
|
||||
var range = document.createElement("input");
|
||||
range.classList.add("range");
|
||||
range.setAttribute("type", "range");
|
||||
range.setAttribute("id", "p" + i);
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", parameters[i].step ? 1 / parameters[i].step : "any");
|
||||
range.value = parameters[i].defaultValue;
|
||||
if (parameters[i].output)
|
||||
range.setAttribute("readonly", true);
|
||||
div.appendChild(range);
|
||||
var label = document.createElement("label");
|
||||
label.innerText = parameters[i].name;
|
||||
div.appendChild(label);
|
||||
|
||||
div.appendChild(document.createElement("br"));
|
||||
|
||||
var range = document.createElement("input");
|
||||
range.classList.add("range");
|
||||
range.setAttribute("type", "range");
|
||||
range.setAttribute("id", "p" + i);
|
||||
range.setAttribute("min", 0);
|
||||
range.setAttribute("max", 1);
|
||||
range.setAttribute("step", parameters[i].step ? 1 / parameters[i].step : "any");
|
||||
range.value = parameters[i].defaultValue;
|
||||
if (parameters[i].output)
|
||||
range.setAttribute("readonly", "readonly");
|
||||
else
|
||||
range.addEventListener("input",
|
||||
function (ev) {
|
||||
Android.setParameter(i, e.target.value);
|
||||
});
|
||||
div.appendChild(range);
|
||||
}
|
||||
|
||||
outParamInterval = setInterval(
|
||||
function () {
|
||||
for (var i = 0; i < parameters.length; i++)
|
||||
if (parameters[i].output)
|
||||
document.getElementById("p" + i).value = Android.getParameter(i);
|
||||
}, 50);
|
||||
|
||||
topButtonElem.value = "STOP";
|
||||
audioStarted = true;
|
||||
} else
|
||||
alert("Could not start audio");
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -59,5 +96,6 @@ function gotAudioPermission() {
|
||||
</head>
|
||||
<body>
|
||||
<input id="topButton" type="button">
|
||||
<div id="params"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,61 @@
|
||||
#include <jni.h>
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include <miniaudio.h>
|
||||
#include "config.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
ma_device device;
|
||||
|
||||
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_orastron_@JNI_NAME@_MainActivity_nativeAudioStart(JNIEnv* env, jobject thiz) {
|
||||
#if NUM_CHANNELS_IN == 0
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
#else
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
||||
#endif
|
||||
deviceConfig.sampleRate = 0;
|
||||
deviceConfig.periodSizeInFrames = 64;
|
||||
deviceConfig.periods = 1;
|
||||
deviceConfig.noPreSilencedOutputBuffer = 1;
|
||||
deviceConfig.noDisableDenormals = 0;
|
||||
deviceConfig.performanceProfile = ma_performance_profile_low_latency;
|
||||
deviceConfig.capture.pDeviceID = NULL;
|
||||
deviceConfig.capture.format = ma_format_f32;
|
||||
deviceConfig.capture.channels = NUM_CHANNELS_IN;
|
||||
deviceConfig.capture.shareMode = ma_share_mode_shared;
|
||||
deviceConfig.playback.pDeviceID = NULL;
|
||||
deviceConfig.playback.format = ma_format_f32;
|
||||
deviceConfig.playback.channels = NUM_CHANNELS_OUT;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
|
||||
return false;
|
||||
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
ma_device_uninit(&device);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_orastron_@JNI_NAME@_MainActivity_nativeAudioStop(JNIEnv* env, jobject thiz) {
|
||||
ma_device_stop(&device);
|
||||
ma_device_uninit(&device);
|
||||
}
|
||||
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_orastron_@JNI_NAME@_MainActivity_nativeGetParameter(JNIEnv* env, jobject thiz, jint i) {
|
||||
return 0.3f;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_orastron_@JNI_NAME@_MainActivity_nativeSetParameter(JNIEnv* env, jobject thiz, jint i, jfloat v) {
|
||||
}
|
||||
|
||||
}
|
6
examples/synth_simple/android/Makefile
Normal file
6
examples/synth_simple/android/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_synth_simple
|
||||
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_synth_simple.c
|
||||
|
||||
include ${ROOT_DIR}/../../common/android/android.mk
|
Loading…
Reference in New Issue
Block a user