android: keep radio VAD blocked until AudioTrack plays the receive tail
This commit is contained in:
1 parent
06c35839ef
commit
a1e8bfe80a
3 files changed
+27
-8
No files matched your search
@@ -210,7 +210,7 @@ object NativeLib {
|
||||
fun radioSubscribers(groupId: Long): Int = nativeRadioSubscribers(groupId)
|
||||
fun radioAudioStart(groupId: Long, channels: Int): Boolean = nativeRadioAudioStart(groupId, channels)
|
||||
fun radioAudioFeed(groupId: Long, samples: ShortArray): Boolean = nativeRadioAudioFeed(groupId, samples)
|
||||
fun radioAudioPull(groupId: Long, out: ShortArray): Int = nativeRadioAudioPull(groupId, out)
|
||||
fun radioAudioPull(groupId: Long, out: ShortArray, playedFrames: Long): Int = nativeRadioAudioPull(groupId, out, playedFrames)
|
||||
fun radioAudioStop() { nativeRadioAudioStop() }
|
||||
fun radioCaptureStart(groupId: Long, channels: Int, vad: Boolean): Boolean = nativeRadioCaptureStart(groupId, channels, vad)
|
||||
fun radioCaptureStop() { nativeRadioCaptureStop() }
|
||||
@@ -334,7 +334,7 @@ object NativeLib {
|
||||
private external fun nativeRadioSubscribers(groupId: Long): Int
|
||||
private external fun nativeRadioAudioStart(groupId: Long, channels: Int): Boolean
|
||||
private external fun nativeRadioAudioFeed(groupId: Long, samples: ShortArray): Boolean
|
||||
private external fun nativeRadioAudioPull(groupId: Long, out: ShortArray): Int
|
||||
private external fun nativeRadioAudioPull(groupId: Long, out: ShortArray, playedFrames: Long): Int
|
||||
private external fun nativeRadioAudioStop()
|
||||
private external fun nativeRadioCaptureStart(groupId: Long, channels: Int, vad: Boolean): Boolean
|
||||
private external fun nativeRadioCaptureStop()
|
||||
|
||||
@@ -692,14 +692,32 @@ class RadioAudioEngine {
|
||||
private fun playLoop() {
|
||||
val frame = FRAME_SAMPLES * PLAY_CHANNELS
|
||||
val buf = ShortArray(frame)
|
||||
val silence = ShortArray(frame)
|
||||
val frameNs = FRAME_MS * 1_000_000L /* 20мс в наносекундах */
|
||||
var nextNs = System.nanoTime()
|
||||
var previousHead = 0L
|
||||
var playedFrames = 0L
|
||||
val group = audioGroup
|
||||
val track = audioTrack ?: return
|
||||
LogManager.addLog("DEBUG", "radio", "playback progress tracking group=$group guard=200ms")
|
||||
while (playbackRunning) {
|
||||
val track = audioTrack ?: return
|
||||
val n = NativeLib.radioAudioPull(audioGroup, buf)
|
||||
if (n > 0) track.write(buf, 0, n)
|
||||
if (n < frame) track.write(silence, 0, frame - n)
|
||||
/* AudioTrack возвращает unsigned 32-bit позицию; разворачиваем wrap (~25 часов @48k). */
|
||||
val head = track.playbackHeadPosition.toLong() and 0xffffffffL
|
||||
playedFrames += (head - previousHead) and 0xffffffffL
|
||||
previousHead = head
|
||||
val n = NativeLib.radioAudioPull(group, buf, playedFrames)
|
||||
if (n < frame) buf.fill(0, n.coerceAtLeast(0), frame)
|
||||
var written = 0
|
||||
while (written < frame && playbackRunning) {
|
||||
val count = track.write(buf, written, frame - written)
|
||||
if (count <= 0) {
|
||||
if (playbackRunning) {
|
||||
LogManager.addLog("ERROR", "radio", "playback write failed group=$group rc=$count written=$written/$frame")
|
||||
mainHandler.post { if (audioTrack === track) stop() }
|
||||
}
|
||||
return
|
||||
}
|
||||
written += count
|
||||
}
|
||||
|
||||
/* абсолютный deadline: не даём Thread.sleep накопить систематический дрейф */
|
||||
nextNs += frameNs
|
||||
|
||||
Reference in new issue
Block a user