m3, ui/ux, and more

This commit is contained in:
Boof2015
2026-06-17 16:12:51 -04:00
parent 0afbb37c08
commit 9f2ce3bb75
533 changed files with 5933 additions and 147 deletions
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.13)
project(astrascope)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Pure portable DSP + a plain-JNI bridge. No prefab / ReactAndroid / fbjni:
# <jni.h> comes from the NDK sysroot and we only link liblog.
add_library(astrascope SHARED
../cpp/dsp_utils.cpp
../cpp/spectrum.cpp
../cpp/oscilloscope.cpp
../cpp/vectorscope.cpp
../cpp/scope_jni.cpp)
target_include_directories(astrascope PRIVATE ../cpp)
find_library(log-lib log)
target_link_libraries(astrascope ${log-lib})
+35
View File
@@ -0,0 +1,35 @@
plugins {
id 'com.android.library'
id 'expo-module-gradle-plugin'
}
group = 'expo.modules.astrascope'
version = '0.1.0'
def reactNativeArchitectures() {
def value = project.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : ["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]
}
android {
namespace "expo.modules.astrascope"
defaultConfig {
versionCode 1
versionName "0.1.0"
externalNativeBuild {
cmake {
cppFlags "-O3 -std=c++17 -fexceptions -frtti"
abiFilters(*reactNativeArchitectures())
arguments "-DANDROID_STL=c++_shared"
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
lintOptions {
abortOnError false
}
}
@@ -0,0 +1,2 @@
<manifest>
</manifest>
@@ -0,0 +1,28 @@
package expo.modules.astrascope
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
import expo.modules.kotlin.typedarray.Float32Array
/**
* JS surface for the realtime scope. Both functions are synchronous (JSI):
* [getSpectrumFrame] is pulled once per render frame from the JS thread and
* fills a JS-preallocated Float32Array in place (no per-frame allocation, no
* event-emitter traffic). The PCM that feeds it arrives on the audio thread via
* the vendored kotlin-audio tap -> [ScopeBridge].
*/
class AstraScopeModule : Module() {
override fun definition() = ModuleDefinition {
Name("AstraScope")
// Gate the audio-thread tap (off when backgrounded/paused/reduced-motion).
Function("setActive") { active: Boolean ->
ScopeBridge.active = active
}
// Fill `out` with the latest dB spectrum; returns the number of bins written.
Function("getSpectrumFrame") { out: Float32Array ->
ScopeBridge.nativeFillSpectrum(out.toDirectBuffer(), out.length)
}
}
}
@@ -0,0 +1,36 @@
package expo.modules.astrascope
/**
* Process-wide bridge to the native scope driver (libastrascope.so).
*
* Loaded once here; the vendored kotlin-audio PCM tap (ScopeTapAudioProcessor)
* calls [nativePushFrames]/[nativeConfigure] from the ExoPlayer audio thread,
* while [AstraScopeModule] calls [nativeFillSpectrum] from the JS thread. The
* native side is single-producer/single-consumer and lock-free on the audio
* path; see scope_ring.h.
*
* [active] gates the tap so a backgrounded/paused app pays ~zero in the audio
* callback. The lifecycle owner (RN side) flips it via AstraScope.setActive().
*/
object ScopeBridge {
init {
System.loadLibrary("astrascope")
}
/** Set by the lifecycle owner; checked cheaply in the audio callback. */
@Volatile
var active: Boolean = false
/** Audio thread. Tell the analyzer the stream's sample rate / channels. */
external fun nativeConfigure(sampleRate: Int, channelCount: Int)
/** Audio thread. Push interleaved float PCM (frameCount * channelCount). */
external fun nativePushFrames(frames: FloatArray, frameCount: Int, channelCount: Int)
/**
* Render thread. Fill `buffer` (a direct ByteBuffer over the JS Float32Array's
* memory) with the latest dB spectrum, up to `capacityFloats` floats.
* Returns the number of bins written. Zero-copy: writes straight into JS memory.
*/
external fun nativeFillSpectrum(buffer: java.nio.ByteBuffer, capacityFloats: Int): Int
}