Skip to content

Fix Android waveform IndexOutOfBoundsException on long files - #48

Merged
sjoenk merged 3 commits into
mainfrom
bugfix/45-android-waveform-int-overflow
May 29, 2026
Merged

Fix Android waveform IndexOutOfBoundsException on long files#48
sjoenk merged 3 commits into
mainfrom
bugfix/45-android-waveform-int-overflow

Conversation

@sjoenk

@sjoenk sjoenk commented May 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix an IndexOutOfBoundsException (negative index) in getWaveform / getWaveformBytes on Android for medium-to-large audio files (e.g. a 5-minute MP3).
  • Root cause was a 32-bit integer overflow: the per-window offset i * totalSamples exceeds Int.MAX_VALUE once a file decodes to ~millions of samples, wrapping to a negative index.
  • The window-bound math now uses 64-bit arithmetic, and the RMS reduction is extracted into a testable helper with regression coverage.

Closes #45

Changes

  • android/.../AudioDecoderPlugin.kt: extract the RMS/normalization reduction into an internal fun computeWaveform(...) and compute the window start with (i.toLong() * totalSamples / numberOfSamples).toInt() so large files no longer overflow.
  • android/.../AudioDecoderPluginTest.kt: add three tests — a regression test with 15,567,358 samples (the length from the bug report), an empty-input test, and an absolute-normalization test.
  • example/integration_test/: add an on-device regression test that synthesizes a long (3M-frame) WAV at runtime via a new buildPcmWav helper and runs getWaveform over it, catching the overflow end-to-end without bundling a large asset.
  • CHANGELOG.md / pubspec.yaml: release 0.8.1 documenting the fix.
  • example/pubspec.lock: refresh the resolved local package version to 0.8.1.

Test plan

  • Run the native unit tests from example/android/: ./gradlew :audio_decoder:testDebugUnitTest — all 14 tests pass, including computeWaveform_largeSampleCount_doesNotOverflow.
  • On a real Android device (Samsung SM A266B, API 36), run getWaveform over a long file without an IndexOutOfBoundsException — verified via the new integration test using a synthetic 3M-frame WAV that crosses the same 32-bit overflow threshold (not a literal 4–6 min MP3, but exercises the identical code path).
  • Confirm waveforms for short files are unchanged — the short-file getWaveform / getWaveformBytes integration tests pass on device, and the example app renders waveforms correctly.

Time spent

⏱️ Estimated time spent: 3 hours

sjoenk added 2 commits May 29, 2026 13:40
On long files the 32-bit product `i * totalSamples` overflowed to a
negative index, crashing getWaveform/getWaveformBytes with an
IndexOutOfBoundsException. Extract the RMS reduction into a testable
computeWaveform helper and widen the offset math to Long.
Synthesize a multi-million-frame WAV at runtime and run getWaveform over
it, so the 32-bit window-offset overflow is caught end-to-end on Android
without bundling a large audio asset.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a 32-bit integer overflow in the Android waveform reduction that crashed getWaveform/getWaveformBytes on long files (issue #45). The window-offset arithmetic now uses 64-bit math, and the reduction is extracted into a testable helper with new unit and integration coverage. Version bumped to 0.8.1.

Changes:

  • Extract RMS reduction into internal fun computeWaveform(...) and compute window starts via (i.toLong() * totalSamples / numberOfSamples).toInt().
  • Add Android unit tests (large-sample regression, empty input, absolute normalization) and a Dart integration regression test using a new buildPcmWav helper.
  • Release 0.8.1 (CHANGELOG, pubspec, example lockfile).

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
android/src/main/kotlin/nl/silversoft/audio_decoder/AudioDecoderPlugin.kt Extracts computeWaveform helper; uses 64-bit math for window offsets.
android/src/test/kotlin/nl/silversoft/audio_decoder/AudioDecoderPluginTest.kt Adds 3 unit tests covering the helper, including the overflow regression.
example/integration_test/test_helpers.dart Adds buildPcmWav helper to synthesize long PCM WAV files.
example/integration_test/plugin_integration_test.dart Adds on-device regression test using a 3M-frame synthetic WAV.
CHANGELOG.md Documents the 0.8.1 fix.
pubspec.yaml Bumps version to 0.8.1.
example/pubspec.lock Refreshes resolved local package version.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sjoenk
sjoenk merged commit 05f7d06 into main May 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Android] IndexOutOfBoundsException (Negative Index) during waveform extraction on larger files

2 participants