|
|
|
@@ -79,13 +79,11 @@ class PcmStreamPlayerModule(reactContext: ReactApplicationContext) : ReactContex
|
|
|
|
|
val minBuf = AudioTrack.getMinBufferSize(sampleRate, channelConfig, encoding)
|
|
|
|
|
val bytesPerSecond = sampleRate * channels * 2 // 16-bit = 2 bytes
|
|
|
|
|
val prerollTarget = (bytesPerSecond * prerollSec).toInt()
|
|
|
|
|
// Buffer entkoppelt von Preroll — fester ~3s-Buffer reicht. Wenn er
|
|
|
|
|
// an Preroll gekoppelt ist (z.B. 7s bei preroll=3.5s) und nur kurz
|
|
|
|
|
// gefuettert wird, stallt AudioTrack auf manchen Geraeten (OnePlus
|
|
|
|
|
// Android 12: pos bleibt 0 obwohl play() lief).
|
|
|
|
|
// 3s damit Padding bis 2s vor play() noch Headroom hat (write() ist
|
|
|
|
|
// blocking — wenn Buffer voll ist, deadlockt es vor play()).
|
|
|
|
|
val bufferSize = (bytesPerSecond * 3).coerceAtLeast(minBuf * 8)
|
|
|
|
|
// Buffer entkoppelt von Preroll — fester ~4s-Buffer. OnePlus A12
|
|
|
|
|
// mit USAGE_ASSISTANT laeuft AudioTrack erst ab ~3s gepufferter
|
|
|
|
|
// Daten an. Wir padden Kurztexte vor play() auf 3s (siehe Block
|
|
|
|
|
// nach mainLoop), Buffer braucht ~1s Headroom weil write() blockt.
|
|
|
|
|
val bufferSize = (bytesPerSecond * 4).coerceAtLeast(minBuf * 8)
|
|
|
|
|
prerollBytes = prerollTarget
|
|
|
|
|
bytesBuffered = 0
|
|
|
|
|
playbackStarted = false
|
|
|
|
@@ -94,7 +92,12 @@ class PcmStreamPlayerModule(reactContext: ReactApplicationContext) : ReactContex
|
|
|
|
|
val newTrack = AudioTrack.Builder()
|
|
|
|
|
.setAudioAttributes(
|
|
|
|
|
AudioAttributes.Builder()
|
|
|
|
|
.setUsage(AudioAttributes.USAGE_ASSISTANT)
|
|
|
|
|
// USAGE_MEDIA statt USAGE_ASSISTANT — auf OnePlus A12 stallt
|
|
|
|
|
// AudioTrack mit USAGE_ASSISTANT wenn play() nach komplettem
|
|
|
|
|
// Buffer-Fuellen called wird (pos bleibt 0). USAGE_MEDIA ist
|
|
|
|
|
// robust. AudioFocus wird eh separat ueber AudioFocusModule
|
|
|
|
|
// gehandhabt, nicht ueber dieses USAGE-Tag.
|
|
|
|
|
.setUsage(AudioAttributes.USAGE_MEDIA)
|
|
|
|
|
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
|
|
|
|
.build(),
|
|
|
|
|
)
|
|
|
|
@@ -229,10 +232,11 @@ class PcmStreamPlayerModule(reactContext: ReactApplicationContext) : ReactContex
|
|
|
|
|
bytesBuffered += silence.size
|
|
|
|
|
}
|
|
|
|
|
// Bei kurzem Text (play() noch nicht gestartet): Buffer auf min.
|
|
|
|
|
// 2s padden + DANN play(). Auf OnePlus A12 startet AudioTrack
|
|
|
|
|
// bei einem zu duennen Buffer nicht — pos bleibt auf 0 stehen.
|
|
|
|
|
// 3s padden + DANN play(). Auf OnePlus A12 startet AudioTrack
|
|
|
|
|
// bei < 3s Buffer-Inhalt nicht — pos bleibt auf 0 stehen.
|
|
|
|
|
// (2s war zu wenig, 8 Worte ~2.5s gingen, 3 Worte ~1s nicht.)
|
|
|
|
|
if (!playbackStarted && !writerShouldStop) {
|
|
|
|
|
val minStartBytes = bytesPerSecond * 2
|
|
|
|
|
val minStartBytes = bytesPerSecond * 3
|
|
|
|
|
if (bytesBuffered < minStartBytes) {
|
|
|
|
|
val padBytes = (minStartBytes - bytesBuffered.toInt()) and 0x7FFFFFFE
|
|
|
|
|
val pad = ByteArray(padBytes)
|
|
|
|
|