revert: use ShortArray audio path (DirectByteBuffer causes null ptr crash)
DirectByteBuffer.clear() crashes with null pointer in ART's JIT OSR compiled code on Android 16. Revert AudioPipeline to use the original ShortArray writeAudio/readAudio path. The DirectByteBuffer JNI functions remain in WzpEngine.kt and jni_bridge.rs for future use once the OSR issue is resolved. The original SIGBUS from ART GC is rare (~1 crash per 8 min call) and doesn't warrant the DirectByteBuffer approach until we can allocate the buffer as a class field outside the hot loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -205,8 +205,6 @@ class AudioPipeline(private val context: Context) {
|
||||
Log.i(TAG, "capture started: ${SAMPLE_RATE}Hz mono, buf=$bufSize, aec=${aec?.enabled}, ns=${ns?.enabled}")
|
||||
|
||||
val pcm = ShortArray(FRAME_SAMPLES)
|
||||
// DirectByteBuffer for zero-copy JNI (avoids ART GC SIGBUS on Android 16)
|
||||
val directBuf = ByteBuffer.allocateDirect(FRAME_SAMPLES * 2).order(ByteOrder.LITTLE_ENDIAN)
|
||||
// Debug: PCM file + RMS CSV
|
||||
var pcmOut: BufferedOutputStream? = null
|
||||
var rmsCsv: OutputStreamWriter? = null
|
||||
@@ -226,10 +224,7 @@ class AudioPipeline(private val context: Context) {
|
||||
val read = recorder.read(pcm, 0, FRAME_SAMPLES)
|
||||
if (read > 0) {
|
||||
applyGain(pcm, read, captureGainDb)
|
||||
// Zero-copy write via DirectByteBuffer (no GC array interaction)
|
||||
directBuf.clear()
|
||||
directBuf.asShortBuffer().put(pcm, 0, read)
|
||||
engine.writeAudioDirect(directBuf, read)
|
||||
engine.writeAudio(pcm)
|
||||
|
||||
// Debug: write raw PCM + RMS
|
||||
if (pcmOut != null) {
|
||||
@@ -292,8 +287,6 @@ class AudioPipeline(private val context: Context) {
|
||||
|
||||
val pcm = ShortArray(FRAME_SAMPLES)
|
||||
val silence = ShortArray(FRAME_SAMPLES)
|
||||
// DirectByteBuffer for zero-copy JNI (avoids ART GC SIGBUS on Android 16)
|
||||
val directBuf = ByteBuffer.allocateDirect(FRAME_SAMPLES * 2).order(ByteOrder.LITTLE_ENDIAN)
|
||||
// Debug: PCM file + RMS CSV for playout
|
||||
var pcmOut: BufferedOutputStream? = null
|
||||
var rmsCsv: OutputStreamWriter? = null
|
||||
@@ -310,13 +303,7 @@ class AudioPipeline(private val context: Context) {
|
||||
}
|
||||
try {
|
||||
while (running) {
|
||||
// Zero-copy read via DirectByteBuffer
|
||||
directBuf.clear()
|
||||
val read = engine.readAudioDirect(directBuf, FRAME_SAMPLES)
|
||||
if (read > 0) {
|
||||
directBuf.rewind()
|
||||
directBuf.asShortBuffer().get(pcm, 0, read)
|
||||
}
|
||||
val read = engine.readAudio(pcm)
|
||||
if (read >= FRAME_SAMPLES) {
|
||||
applyGain(pcm, read, playoutGainDb)
|
||||
track.write(pcm, 0, read)
|
||||
|
||||
Reference in New Issue
Block a user