MP3 Decoder in pure Java - Enhanced for reliable playback in Minecraft mods
Fork Purpose: Fixed critical ArrayIndexOutOfBoundsException affecting VBR and high-bitrate MP3 files. Built for Rhythm mod but works as drop-in replacement for any JLayer use case.
Index 433 out of bounds for length 433
at javazoom.jl.decoder.Bitstream.getBits()
Root Cause: Original code used fixed buffer size (433) for bounds checking, but MP3 frames have variable sizes (especially VBR).
Solution: Check against actual frameSize for each frame instead of buffer capacity.
Impact:
- ✅ VBR MP3s now work correctly
- ✅ 320kbps files no longer crash
- ✅ LAME-encoded files play reliably
- ✅ Success rate: ~30% → 95%+
// Before: Fixed bounds (WRONG for VBR)
if (wordPointer >= frameBuffer.length) // Always 433
// After: Dynamic bounds (CORRECT)
int maxWords = (frameSize + 3) / 4; // Actual frame size
if (wordPointer >= maxWords)<dependency>
<groupId>io.github.tamkungz</groupId>
<artifactId>jlayer-custom</artifactId>
<version>1.0.2.2</version>
</dependency>repositories {
mavenCentral()
}
dependencies {
implementation 'io.github.tamkungz:jlayer-custom:1.0.2.2'
}repositories {
mavenCentral()
}
dependencies {
implementation("io.github.tamkungz:jlayer-custom:1.0.2.2")
}<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.tamkungz</groupId>
<artifactId>jlayer-custom</artifactId>
<version>1.0.2.2</version>
</dependency>repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.tamkungz:jlayer-custom:1.0.2.2'
}However, for the best user experience, we recommend using the latest version.
1.0.2.x
The 1.0.2.* line focuses solely on fixing issues from the original JLayer implementation. There are no new features or behavioral changes. If your project previously used JLayer (2010–2024), this version is recommended for maximum compatibility.
1.0.5+
Version 1.0.5 includes several internal improvements aimed at better performance. While execution efficiency is enhanced, some legacy code that depends on the original JLayer behavior may require minor adjustments.
- Input parameter validation (
number_of_bits <= 0) - Dynamic frame size calculation for VBR support
- Safe handling of partial frames at buffer boundaries
- Prevents pointer overflow in multi-word reads
- Returns safe values instead of crashing
- Allows decoder to skip corrupted frames
- Maintains valid internal state after errors
- BitstreamException(Throwable): Better error chaining
- Bitstream.isClosed() / isEOF(): State management
- Player.isClosed(): Check player state
- jlp.stop(): Controlled playback shutdown
- jlp.getPlayer(): Access underlying Player instance
- jlp.isPlaying(): Check active playback status
- Enhanced VBR header parsing
- Improved thread safety and resource cleanup
- 100% compatible with original JLayer
- Drop-in replacement - just change dependency
- All existing code works without modification
Tested with 254+ diverse MP3 files:
- ✅ CBR: 128kbps, 192kbps, 320kbps
- ✅ VBR: LAME v3.98+, modern encoders
- ✅ Various sample rates: 44.1kHz, 48kHz, 32kHz
- ✅ Stereo and mono files
- ✅ Files with ID3v1/v2 tags and no tags
Comprehensive Test Suite (JUnit 5):
- BitstreamTest: Header parsing, frame reading, state management
- BitstreamEdgeCaseTest: Edge cases, concurrent access, large reads
- JavaSoundAudioDeviceTest: Audio device creation and registry
- jlpTest: Playback, volume control, thread safety
Before fix: ~30% success rate (crashes on VBR/320kbps)
After fix: 95%+ success rate
LGPL (same as original JLayer)
- Original: JavaZOOM (1999-2008)
- Parent Fork: umjammer/jlayer - Java 17 modernization
- This Fork: @tamkungz - ArrayIndexOutOfBoundsException fixes
JLayer is a library that decodes/plays/converts MPEG 1/2/2.5 Layer 1/2/3 (i.e. MP3) in real time for the JAVA(tm) platform. This is a non-commercial project and anyone can add his contribution. JLayer is licensed under LGPL (see LICENSE).
No, JMF is not required. You need a Java 17+ runtime with JavaSound 1.0 compliance.
java javazoom.jl.converter.jlc -v -p output.wav yourfile.mp3java javazoom.jl.player.jlp localfile.mp3or
java javazoom.jl.player.jlp -url http://www.aserver.com/remotefile.mp3java javazoom.jl.player.advanced.jlap localfile.mp3Yes, use the following command to play music from stream:
java javazoom.jl.player.jlp -url http://www.shoutcastserver.com:8000Yes, it works fine for all files generated with LAME.
Yes, It supports VBRI and XING VBR header too.
The API provides a getRawID3v2() method to get an InputStream on ID3v2 frames.
<<<<<<< HEAD
See javazoom.jl.player.advanced.jlap source to learn how to skip frames.
