Downloads
Pick one file. If unsure which CPU you have, choose Intel or AMD.
| Platform | CPU | File |
|---|---|---|
| Windows | Intel or AMD (almost all PCs) | truehdd-0.5.0-x86_64-pc-windows-msvc.zip
|
| Windows | ARM (Snapdragon, Windows on ARM) | truehdd-0.5.0-aarch64-pc-windows-msvc.zip
|
| macOS | Intel and Apple Silicon (universal) | truehdd-0.5.0-universal-macOS.zip
|
| Linux | Intel or AMD | truehdd-0.5.0-x86_64-unknown-linux-gnu.tar.gz
|
| Linux | Intel or AMD, static build | truehdd-0.5.0-x86_64-unknown-linux-musl.tar.gz
|
| Linux | ARM | truehdd-0.5.0-aarch64-unknown-linux-gnu.tar.gz
|
| Linux | ARM, static build | truehdd-0.5.0-aarch64-unknown-linux-musl.tar.gz
|
The static Linux builds run on distributions with an older or different C library.
Each archive ships a matching .sha256 file for verification.
Changes
Added
--presentationaccepts a list (0,1,3),all, ormaxin addition to a single index; multiple presentations decode in a single pass with shared extraction and parsing, writing one output per presentation with_p{index}filename suffixes- Extraction, parsing and decoding run on separate threads
- Decode now recovers from mid-stream corruption: after a parse or decode failure, both stages reset in lockstep and resume at the next major sync instead of continuing on damaged state
--metadata-onlywrites the Dolby Atmos master header and metadata without the audio file (#10)--jsonprints a result summary on stdout listing the files written per presentation, along with frame, sample, skipped-frame and seamless-branch counts, including branch points that fail the buffer-model checks- Exit codes now identify the failing stage: 3 input, 4 parse, 5 decode, 6 write
--probe-rangesets how many access units are probed for Atmos metadata when--bed-conformis used (default 12000)
Changed
- Minimum supported Rust version for building the CLI is now 1.95.0
- Updated dependencies (clap 4.6, vergen-gitcl 10, darling 0.24 with syn 3 in truehdd-macros)
- Decode pipeline errors now travel in-band with the data: failures report the originating stage (input/parse/decode/write) instead of always "Write error", and output file headers are finalized even when decoding fails, keeping partial output playable
- The default
--presentationis now spelledmax; it requests the same presentation as the previous default of3, including the fallback used when a stream has no presentation 3 - BREAKING:
--formatnow applies to whichever presentation is written, except presentation 3 which always uses CAF; it was previously ignored whenever presentation 3 was requested, so a stream without presentation 3 produced CAF regardless of the option - BREAKING:
--stricttreats frames the extractor had to skip as a failure, so it now exits non-zero on input it previously accepted
Fixed
- The presentation list parser failed to build on Windows, where an extra
FromIteratorimplementation made the element type ambiguous - Errors are reported on stderr even when logging is turned off
- DAMF YAML no longer corrupts file references containing double spaces,
-or single quotes, and keeps quoting for names that need it so the output stays valid YAML (#17, #18) - Fields in
--log-format jsonoutput are escaped, so paths and messages containing quotes no longer break the JSON - Removed a shutdown race that could report success after an unreported pipeline error
The DAMF YAML fix above builds on @nekno's report and first fix in #18.
Library (truehd crate)
Added
Decoder::decode_presentations()decoding several presentations from one access unit in a single pass, andPresentationMapfor resolving which substreams a presentation needsParser::invalid_branches()counting seamless branch points that fail the buffer-model checks; the decoded samples are unaffected, so callers can treat it as a conformance signalParser::reset_for_next_major_sync()andDecoder::reset_for_next_major_sync()to recover from fatal parse/decode failures at the next major syncExtractor::error_count()exposing the number of corrupt-frame eventsParser::substream_state()read-only accessor for per-substream state (DRC gain/time values)- OAMD object distance parsing:
ObjectRenderInfo::distance_factorresolved via the newDISTANCE_FACTORStable PartialEq,Eq,Hashderives onSpeakerLabels
Changed
- BREAKING:
DecoderState::decode_access_unit()is replaced bydecode_access_unit_presentations(); useDecoder::decode_presentation()orDecoder::decode_presentations()instead - Minimum supported Rust version is now 1.88.0 (let chains; was already required, now declared correctly)
- Updated dependency floors (anyhow, bitstream-io 4.10, log, thiserror)
- BREAKING:
ObjectRenderInfofieldsb_object_at_infinityanddistance_factor_idxreplaced bydistance_factor: Option<f64> Extractorinternal buffer reworked (Vec + cursor with amortized compaction) removing per-resync allocations
Fixed
- Correct substream 0 size calculation for substream size history
- Correct
TRIM_LUT[14]value (-16.0 -> -15.0) (#26, fixed by @yuygfgg in #27) - No longer panic on corrupt bitstreams: invalid
restart_sync_word, division by zero in seamless-branch timing, and substream size/length underflows now return typed errors (#15, #16) - Persist heavy DRC gain/time updates in parser substream state; heavy DRC validation previously compared against zeroed values
decode_presentations()no longer copies OAMD payloads into non-object presentation results
The panic-free parsing, recovery API, DRC state, OAMD distance and extractor buffer changes above are based on work by @harletty in the harletty-bridge fork.