dart_flac 0.0.6
dart_flac: ^0.0.6 copied to clipboard
Pure-Dart FLAC decoder. Reads metadata, decodes LPC/FIXED subframes, verifies MD5, streams PCM to any audio sink. No native deps.
Changelog #
0.0.6 — 2026-05-17 #
- Narrow the public API.
package:dart_flac/dart_flac.dartpreviously did wholesaleexport 'src/frame/frame.dart'andexport 'src/frame/subframe.dart', which leaked every public-by-default symbol in those files into the package surface. The frame export is nowshow-filtered to exactly the four types that have a documented place in the public API:BlockingStrategy,ChannelAssignment,FlacFrame, andFrameHeader. Thesubframe.dartre-export is dropped entirely. - As a result,
FrameParser(the bit-stream parser, which takes a non-publicBitReader),SubframeType, andSubframeDecoderare no longer re-exported frompackage:dart_flac/dart_flac.dart. These were never documented as public API — they are internal helpers used only by the decoder itself. This is breaking only for code that imported those symbols by accident; the package is pre-1.0, so this is the right time to tighten the surface to the "deliberately thin API" goal.
0.0.5 — 2026-04-25 #
- Add
Md5Verifier(lib/src/md5_verifier.dart), a streaming MD5 verifier seeded from STREAMINFO. Feed it native-bit-depth interleaved PCM bytes viaaddPcm, then callfinalize()to get aMd5VerificationResult. Lets callers verify file integrity in the same pass they decode for some other purpose. flac2wav --verifynow does one decode pass instead of two on a full-stream conversion: the WAV write loop tees oneframeToInterleavedPcmper frame into the streaming verifier, and the post-write step just callsfinalize(). For partial decodes (--start-sample/--duration-samples) the CLI still falls back toreader.verifyMd5()so a sliced extract is verified against the original file's MD5, not the slice's own digest.flac2wavnow validates--bits,--start-sample, and--duration-samplesbefore opening the input file. Previously a bad argument could be masked by a downstream file/parse error, reporting the wrong problem to the user.Md5VerificationResultis now defined inmd5_verifier.dart(re-exported frompackage:dart_flac/dart_flac.dartat the same name; the public-API import path is unchanged). Direct imports ofpackage:dart_flac/src/flac_reader.dartwill need updating, butsrc/paths are not part of the public API.
0.0.4 — 2026-04-25 #
- Published archive shrunk from 60 KB to 38 KB by excluding
test/(including the binary.flacfixtures) andtool/(coverage and issue-management scripts) via.pubignore. No library behaviour change; consumers simply get a smaller download. - CI now pins the Dart SDK to
3.11.5, explicitly installs Chrome for the browser smoke test, and uploadscoverage/lcov.infoas a workflow artefact on every run. No consumer-visible change; tightens the development feedback loop.
0.0.3 — 2026-04-25 #
- Add GitHub Actions CI for formatting, analysis, VM tests, browser smoke
tests, and
dart pub publish --dry-run. - Add streaming WAV header/chunk helpers (
writeWavHeaderBytes,frameToWavPcmBytes) and makeflac2wavwrite PCM incrementally for streams with known total samples. - Add CLI flags for output bit depth, start sample, duration, and explicit MD5 verification control.
flac2wavnow halts immediately on invalid arguments instead of falling through to decode, so a bad--bitsvalue can no longer silently overwrite a valid output file with a partial decode.flac2wavwrites atomically: output goes to a sibling temp file that is renamed over the destination on success. On a mid-decode failure the temp is deleted and any pre-existing file at the destination is left untouched. The streaming path also patches the RIFF/data chunk sizes at close, so the header is honest about the bytes actually written (truncated inputs, short tail frames, etc.).- Add coverage tooling and benchmark JSON/baseline comparison support.
- Add malformed-input and WAV helper tests, plus CLI subprocess tests covering streaming/bytes equivalence, validation halting, and pre-existing output survival across decode errors.
0.0.2 — 2026-04-24 #
- Add
FlacReader.frontCoverPicture,backCoverPicture, andpictureByType(int)convenience accessors for the common picture lookups.pictureByTypetakes aPictureTypeint code and returns the first matching block, ornull. - Add a browser smoke test (
test/web_smoke_test.dart,@TestOn('browser')) that exercisesdecodeFlacBytesToPcmunderdart2js. Run withdart test -p chrome. - README: new "Community device results" section with an empty
submission table and a recipe for contributing real-device benchmark
numbers.
benchmark/format_community_row.dartprovides a canonical row formatter that submitters can copy into a Flutter integration test.
0.0.1 #
Initial release.
Metadata #
- Full parsing of STREAMINFO, PADDING, APPLICATION, SEEKTABLE, VORBIS_COMMENT, CUESHEET, and PICTURE blocks.
- Graceful preservation of unknown block types as
UnknownMetadataBlock. - Tolerates a leading ID3v2 tag (with or without the footer flag).
Audio decoding #
- CONSTANT, VERBATIM, FIXED (orders 0–4), and LPC (orders 1–32) subframes.
- PARTITIONED_RICE and PARTITIONED_RICE2 residual coding, including the escape partition.
- Left/side, right/side, and mid/side joint-stereo decorrelation.
- CRC-8 (frame header) and CRC-16 (frame footer) validation.
- Wasted-bits-per-sample handling.
Multi-valued metadata accessors #
FlacReader.picturesAll(alias ofpictures) — every PICTURE block in the stream. FLAC legally permits multiple pictures (front/back cover, booklet, artist).FlacReader.cueSheetsAll— every CUESHEET block. The spec limits this to at most one, but real-world files occasionally contain more; the singularcueSheetstill returns the first match.FlacReader.vorbisCommentsAll— every VORBIS_COMMENT block, with the singularvorbisCommentkept for the common case.
Reader APIs #
FlacReader.fromFile()/fromFileSync()/fromBytes().decodeFrames()— batch decode.decodeFrames(recoverFromCorruption: true, onCorruption: …)— resync on corrupt frames.decodeInterleavedSamples()— all samples as anInt32List.framesLazy()—Iterable<FlacFrame>decoding one frame per pull.pcmChunks({outputBitsPerSample})— lazyIterable<Uint8List>of interleaved little-endian signed PCM, ready to feed to a PCM-accepting audio sink.byteOffsetForSample()/decodeFramesFromSample()— random access using SEEKTABLE with a frame-header walk fallback.verifyMd5()— compares decoded PCM against STREAMINFO.md5, returningmatch/mismatch/notComputed.
Streaming decoder #
StreamingFlacDecoderaccepts bytes viaaddBytes()/close()and emitsStream<MetadataBlock>,Stream<FlacFrame>, andStream<Uint8List>(pcmStream()).onStreamInforesolves as soon as STREAMINFO has been parsed.
Conversion helpers #
frameToInterleavedPcm(frame, outputBitsPerSample)— standalone helper used by both the pull and push APIs.writeWavBytes(…)— produces a RIFF/WAVE byte buffer at 8/16/24/ 32-bit (8-bit output applies the unsigned WAV bias).decodeFlacFileToPcm(path, {outputBitsPerSample = 16})/decodeFlacBytesToPcm(bytes, {outputBitsPerSample = 16})— top-level, isolate-safe one-shot decoders. Take only a path / bytes, return onlyUint8List, intended forIsolate.runcall sites.bin/flac2wav.dart— command-line entry point installed viadart run dart_flac:flac2wav, with--verifyoption.
Platform support #
- Compiles and runs on the Dart VM, AOT, Flutter, and the web.
- 64-bit FLAC fields (SEEKTABLE sample numbers / stream offsets,
CUESHEET offsets and lead-in samples) are exposed as
Int64frompackage:fixnumso they keep full precision underdart compile jsand Flutter web, where nativeintis limited to 2^53.
Benchmarks #
benchmark/decode_benchmark.dart— subprocess-per-operation harness that reports decode throughput and peak RSS for the three decode shapes. Desktop baseline numbers documented in README: ~230× realtime AOT on a 2024 laptop, with streaming (pcmChunks) using ~7× less memory than the full-buffer path on a 3-minute track.