mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-19 04:06:43 +02:00
m3, ui/ux, and more
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user