Skip to content

Commit 13ca92c

Browse files
Agent Session 2025-10-07: Fix overlapping frame iterator
1 parent ddf5197 commit 13ca92c

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

audio/src/main/kotlin/com/siya/epistemophile/audio/dsp/NormalizedFrameIterator.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class NormalizedFrameIterator(
1616
init {
1717
require(frameSize > 0) { "Frame size must be larger than zero." }
1818
require(shiftAmount > 0) { "Shift size must be larger than zero." }
19+
require(shiftAmount <= frameSize) { "Shift size cannot exceed frame size." }
1920
}
2021

2122
override fun hasNext(): Boolean {
@@ -51,7 +52,11 @@ class NormalizedFrameIterator(
5152
DoubleVector(data)
5253
} else {
5354
val previous = currentFrame!!.data.clone()
54-
System.arraycopy(data, 0, previous, previous.size - shiftAmount, shiftAmount)
55+
val preserved = previous.size - shiftAmount
56+
if (preserved > 0) {
57+
System.arraycopy(previous, shiftAmount, previous, 0, preserved)
58+
}
59+
System.arraycopy(data, 0, previous, preserved, data.size)
5560
DoubleVector(previous)
5661
}
5762
frameCounter++

audio/src/test/kotlin/com/siya/epistemophile/audio/dsp/NormalizedFrameIteratorTest.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class NormalizedFrameIteratorTest {
2626
assertEquals(2, frames.size)
2727
val normalization = 0x7fff.toDouble()
2828
val expectedFirst = doubleArrayOf(0.0, 1000 / normalization, 2000 / normalization, 3000 / normalization)
29-
val expectedSecond = doubleArrayOf(0.0, 1000 / normalization, 4000 / normalization, 5000 / normalization)
29+
val expectedSecond = doubleArrayOf(2000 / normalization, 3000 / normalization, 4000 / normalization, 5000 / normalization)
3030
frames[0].forEachIndexed { index, value ->
3131
assertEquals(expectedFirst[index], value, 1e-3)
3232
}
@@ -51,4 +51,12 @@ class NormalizedFrameIteratorTest {
5151
assertEquals(3000 / 0x7fff.toDouble(), first[2], 1e-3)
5252
assertEquals(0.0, first[3], 1e-6)
5353
}
54+
55+
@Test(expected = IllegalArgumentException::class)
56+
fun `iterator rejects shift larger than frame size`() {
57+
val format = PcmAudioFormat.mono16BitSignedLittleEndian(8000)
58+
val stream = PcmMonoInputStream(format, ByteArrayInputStream(ByteArray(0)))
59+
60+
NormalizedFrameIterator(stream, frameSize = 2, shiftAmount = 3, applyPadding = false)
61+
}
5462
}

0 commit comments

Comments
 (0)