From 50cf61e9cd92be2b388d500483bb7baa348b9693 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 21 Oct 2026 01:11:35 +0200 Subject: [PATCH] Mix partial stream PCM without copying stale buffer tails --- .../src/main/java/com/utun/chat/data/StreamAudioMix.kt | 8 ++++---- .../test/java/com/utun/chat/data/StreamAudioMixTest.kt | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamAudioMix.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamAudioMix.kt index 5c50e494..3e28cafd 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamAudioMix.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamAudioMix.kt @@ -30,14 +30,14 @@ internal class StreamMixBuffer(val frames: Int = 480) { private var gain = 1f fun clear() = sum.fill(0f) - fun add(pcm: ShortArray, fadeFrames: Int = 480): Int { - require(pcm.size <= sum.size && pcm.size % 2 == 0) - for (i in 0 until pcm.size / 2) { + fun add(pcm: ShortArray, fadeFrames: Int = 480, count: Int = pcm.size / 2): Int { + require(pcm.size % 2 == 0 && count in 0..min(frames, pcm.size / 2)) + for (i in 0 until count) { val volume = min(1f, (fadeFrames + i + 1) / 480f) / 32768f sum[2 * i] += pcm[2 * i] * volume sum[2 * i + 1] += pcm[2 * i + 1] * volume } - return min(480, fadeFrames + pcm.size / 2) + return min(480, fadeFrames + count) } fun finish(): ShortArray { diff --git a/tools/chatgui-android/app/src/test/java/com/utun/chat/data/StreamAudioMixTest.kt b/tools/chatgui-android/app/src/test/java/com/utun/chat/data/StreamAudioMixTest.kt index c1590517..443b039d 100644 --- a/tools/chatgui-android/app/src/test/java/com/utun/chat/data/StreamAudioMixTest.kt +++ b/tools/chatgui-android/app/src/test/java/com/utun/chat/data/StreamAudioMixTest.kt @@ -7,6 +7,16 @@ import kotlin.math.abs import kotlin.math.sin class StreamAudioMixTest { + @Test fun reusedPcmOnlyMixesTheNewlyPreparedPrefix() { + val mix = StreamMixBuffer() + val pcm = ShortArray(960) { 12000 } + mix.clear(); assertEquals(480, mix.add(pcm, 480, 120)) + val output = mix.finish() + for (i in output.indices) assertEquals(if (i < 240) 12000 else 0, output[i].toInt()) + mix.clear(); mix.add(pcm, 480, 0) + assertTrue(mix.finish().all { it == 0.toShort() }) + } + @Test fun joiningAndResetUseTheirOwnOutputOrigin() { val first = StreamMixTimeline() first.append(0, 480); first.append(480, 480)