All notable changes to this project will be documented in this file. Format follows Keep a Changelog; versioning follows Semantic Versioning.
0.4.0 — 2026-05-21
- Zero-copy
ByteBufferoverloads onOpusEncoderandOpusDecoder:encode(ByteBuffer, int, ByteBuffer),encodeFloat(ByteBuffer, int, ByteBuffer),decode(ByteBuffer, int, ByteBuffer, int),decodeFloat(ByteBuffer, int, ByteBuffer, int),decodeWithFec(ByteBuffer, int, ByteBuffer, int), anddecodeFloatWithFec(ByteBuffer, int, ByteBuffer, int). Both buffers must be direct; data flows straight from the caller's native memory to libopus and back with no intermediate heap copies. Returns the number of samples decoded (decode variants) or bytes written (encode variants). OpusDecoder.MAX_PCM_FRAME_SAMPLESpromoted topublicfor use in buffer-sizing calculations outside the library.OpusDecoder.getMaxPcmFrameBytes()andgetMaxPcmFrameFloatBytes()— return the exact maximum output buffer size in bytes for this decoder's channel count.
OpusEncoder,OpusDecoder, andOpusRepacketizernow useArena.ofShared()for their long-lived native buffers. Create, use, and close may now happen on different threads — the common pattern in real-time streaming pipelines (e.g. init on startup thread, decode on network thread, close on teardown thread). Concurrent calls on the same instance remain unsafe; libopus state is inherently single-threaded.
0.3.2 — 2026-05-21
panopus.libopus.pathJVM system property: set to a full path to load a specificlibopusshared library instead of the OS default. Useful for bundling or testing against a non-system build of libopus without needing OS environment variables. When the library cannot be loaded, a descriptiveIllegalStateExceptionis thrown with installation hints and the underlying OS error, instead of a bareIllegalArgumentException: Cannot open library.
- README "Custom library path" section restructured to document the new JVM system property as the primary (recommended) approach, with OS-level env-var mechanisms moved to a secondary option.
0.3.1 — 2026-05-21
Opus.isAvailable()— returnsfalsewhenlibopuscannot be found or loaded, allowing consumer applications to handle native library absence gracefully without encounteringExceptionInInitializerErrororNoClassDefFoundError.
- Upgraded Gradle wrapper to 9.5.1.
- Corrected GitLab CI pipeline stage ordering.
0.3.0 — 2026-05-20
- Maven Central publishing via
com.vanniktech.maven.publish0.36.0; artifacts are signed with GPG and uploaded directly to the Central Portal. CI publishes automatically on version tags when the signing credentials are configured. - Javadoc hosted on javadoc.io and linked from the README badge.
- Real audio round-trip tests across all Opus-supported sample rates (8 / 16 / 48 kHz) using raw PCM test resources derived from a 3-second stereo reference recording.
- External packet decoder compatibility tests: 151 Opus packets pre-encoded by ffmpeg verify decoder correctness independently of the panopus encoder.
tools/extract_opus_packets.py— extracts raw Opus audio packets from an Ogg container into a simple length-prefixed binary format for use as test resources.
0.2.0 — 2026-05-14
- Pre-allocate native PCM and packet buffers in
OpusEncoder,OpusDecoder, andOpusRepacketizer— eliminates oneArenaallocation per encode/decode call.
- Regression tests asserting that returned
short[]/float[]/byte[]arrays are independent heap copies unaffected by subsequent calls.
0.1.0 — 2026-05-01
- Initial release:
OpusEncoder,OpusDecoder,OpusRepacketizer,OpusPacket,OpusException,ParsedPacket, and supporting enums via the JDK 25 Panama FFM API. - Full static analysis pipeline: Spotless, Error Prone + NullAway, Checkstyle, SpotBugs, PMD.
- GitLab CI/CD pipeline with build, test, and release stages.