mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-16 00:01:59 +02:00
m4
This commit is contained in:
@@ -29,5 +29,52 @@ class AstraScopeModule : Module() {
|
||||
Function("getOscilloscopeFrame") { out: Float32Array ->
|
||||
ScopeBridge.nativeFillOscilloscope(out.toDirectBuffer(), out.length)
|
||||
}
|
||||
|
||||
// --- M4: post-EQ spectrum (EQ screen overlay) ---
|
||||
// Gate the post-EQ tap (true only while the EQ screen is open).
|
||||
Function("setActivePostEq") { active: Boolean ->
|
||||
ScopeBridge.postEqActive = active
|
||||
}
|
||||
|
||||
Function("getSpectrumFramePostEq") { out: Float32Array ->
|
||||
ScopeBridge.nativeFillSpectrumPostEq(out.toDirectBuffer(), out.length)
|
||||
}
|
||||
|
||||
// --- M4: EQ params + per-track gain (consumed by the kotlin-audio processors) ---
|
||||
Function("setEqEnabled") { enabled: Boolean ->
|
||||
EqBridge.enabled = enabled
|
||||
EqBridge.revision += 1
|
||||
}
|
||||
|
||||
Function("setEqPreamp") { linear: Double ->
|
||||
EqBridge.preampLinear = linear.toFloat()
|
||||
EqBridge.revision += 1
|
||||
}
|
||||
|
||||
// Flat band params: 5 floats per band [typeOrdinal, frequency, gain, Q, enabled?1:0].
|
||||
Function("setEqBands") { params: FloatArray ->
|
||||
EqBridge.bands = params
|
||||
EqBridge.revision += 1
|
||||
}
|
||||
|
||||
Function("setNormalizationGain") { linear: Double ->
|
||||
GainBridge.linearGain = linear.toFloat()
|
||||
}
|
||||
|
||||
// Register a queued track's gain by URL so the player can switch to it natively at
|
||||
// the exact media-item transition (no JS round-trip on track change).
|
||||
Function("setTrackGain") { url: String, linear: Double ->
|
||||
GainBridge.putGain(url, linear.toFloat())
|
||||
}
|
||||
|
||||
// Make the registered gain for this URL active now (used for the current track on
|
||||
// mount / settings change, where no transition fires).
|
||||
Function("activateTrackGain") { url: String ->
|
||||
GainBridge.activateFor(url)
|
||||
}
|
||||
|
||||
Function("clearTrackGains") {
|
||||
GainBridge.clearGains()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package expo.modules.astrascope
|
||||
|
||||
/**
|
||||
* Holds the current parametric-EQ configuration, set from JS (raw band params, NOT
|
||||
* biquad coefficients). The vendored kotlin-audio `EqAudioProcessor` reads these
|
||||
* fields lock-free on the ExoPlayer audio thread and recomputes coefficients at the
|
||||
* real stream sample rate whenever [revision] changes.
|
||||
*
|
||||
* Single writer (JS thread via [AstraScopeModule]); single reader (audio thread).
|
||||
* `bands` is published before `revision` is bumped, so a reader that observes a new
|
||||
* revision also observes the matching band array.
|
||||
*/
|
||||
object EqBridge {
|
||||
/** Master bypass. When false the processor is passthrough. */
|
||||
@Volatile
|
||||
var enabled: Boolean = false
|
||||
|
||||
/** EQ preamp as a linear amplitude (1 = unity). */
|
||||
@Volatile
|
||||
var preampLinear: Float = 1f
|
||||
|
||||
/** 5 floats per band: [typeOrdinal, frequency, gain, Q, enabled?1:0]. */
|
||||
@Volatile
|
||||
var bands: FloatArray = FloatArray(0)
|
||||
|
||||
/** Bumped on every enabled/preamp/bands change so the processor recomputes. */
|
||||
@Volatile
|
||||
var revision: Int = 0
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package expo.modules.astrascope
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* Per-track normalization / ReplayGain gain, read lock-free by the vendored
|
||||
* kotlin-audio `NormalizationGainProcessor` on the audio thread. Applied BEFORE the
|
||||
* scope taps so the scopes see normalized levels.
|
||||
*
|
||||
* JS pre-registers each queued track's gain by URL ([putGain]); the player then swaps
|
||||
* the active gain to the matching one natively at the real media-item transition
|
||||
* ([activateFor], called from BaseAudioPlayer.onMediaItemTransition). That lands the
|
||||
* gain at the actual audio boundary instead of after a JS round-trip on track change.
|
||||
*/
|
||||
object GainBridge {
|
||||
/** Active linear amplitude multiplier (1 = unity). Read on the audio thread. */
|
||||
@Volatile
|
||||
var linearGain: Float = 1f
|
||||
|
||||
// url -> linear gain, seeded from JS ahead of playback.
|
||||
private val gains = ConcurrentHashMap<String, Float>()
|
||||
|
||||
/** Register (or update) the gain for a track URL. */
|
||||
fun putGain(url: String, gain: Float) {
|
||||
gains[url] = gain
|
||||
}
|
||||
|
||||
/** Make the gain registered for [url] active (unity if unknown/null). */
|
||||
fun activateFor(url: String?) {
|
||||
linearGain = if (url != null) gains[url] ?: 1f else 1f
|
||||
}
|
||||
|
||||
/** Drop all registered gains (e.g. on full queue reset). */
|
||||
fun clearGains() {
|
||||
gains.clear()
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,14 @@ object ScopeBridge {
|
||||
@Volatile
|
||||
var active: Boolean = false
|
||||
|
||||
/**
|
||||
* Gates the POST-EQ tap specifically (true only while the EQ screen is open).
|
||||
* The post-EQ tap runs when [active] && [postEqActive], so the second downmix
|
||||
* costs nothing unless the EQ overlay is actually being viewed.
|
||||
*/
|
||||
@Volatile
|
||||
var postEqActive: Boolean = false
|
||||
|
||||
/** Audio thread. Tell the analyzer the stream's sample rate / channels. */
|
||||
external fun nativeConfigure(sampleRate: Int, channelCount: Int)
|
||||
|
||||
@@ -41,4 +49,13 @@ object ScopeBridge {
|
||||
* writes straight into JS memory.
|
||||
*/
|
||||
external fun nativeFillOscilloscope(buffer: java.nio.ByteBuffer, capacityFloats: Int): Int
|
||||
|
||||
/** Audio thread. Push POST-EQ interleaved float PCM (the M4 second tap). */
|
||||
external fun nativePushFramesPostEq(frames: FloatArray, frameCount: Int, channelCount: Int)
|
||||
|
||||
/**
|
||||
* Render thread. Fill `buffer` with the latest POST-EQ dB spectrum (feeds the
|
||||
* EQ screen's response-curve overlay). Returns bins written. Zero-copy.
|
||||
*/
|
||||
external fun nativeFillSpectrumPostEq(buffer: java.nio.ByteBuffer, capacityFloats: Int): Int
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user