flac

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2026 License: MIT Imports: 1 Imported by: 0

README

go-flac

CI Go Reference

Native, pure-Go FLAC encoder and decoder. No CGO, no external binaries, zero runtime dependencies, with a simple high-level PCM streaming API. SIMD acceleration (via github.com/tphakala/simd behind a pure-Go fallback) is planned for the v0.2.0 track; v0.1.0 is pure-Go.

Install

go get github.com/tphakala/go-flac

Status

Both decoder and encoder are implemented. pcm.NewDecoder reads real FLAC streams and exposes the audio as interleaved little-endian PCM through io.Reader and io.WriterTo. It is validated bit-exactly against the IETF FLAC test corpus (every subset file's decoded-audio MD5 matches its STREAMINFO signature), byte-for-byte against the reference libFLAC flac -d, and fuzzed for panic-freedom.

pcm.NewEncoder encodes interleaved little-endian PCM to FLAC. It supports bit depths 4-32, constant/verbatim/fixed and LPC predictors, full four-way stereo decorrelation (independent, left-side, right-side, mid-side), and the 0-8 compression-level API. Levels 0-2 use fixed predictors; levels 3-8 add quantized LPC with deeper residual-partition search and exhaustive fixed-order selection. Depths up to 24 bps run an int32 path; depths 25-32 bps run a dedicated int64 path (encoder and decoder), and the int32 output for <= 24 bps is byte-identical to before the wide-depth work. The encoder is allocation-light: a per-encoder reusable scratch buffer keeps steady-state per-block heap allocations near zero.

  • M1 Groundwork: skeleton, tooling, CI. (done)
  • M2 Decoder: bitstream, metadata, frame decode, Rice + predictor restore, inter-channel decorrelation, public pcm.Decoder, MD5 + corpus validation. (done)
  • M3 Encoder: constant/verbatim/fixed predictors, four-way stereo decorrelation, 0-8 compression-level API, bit-exact round-trip, libFLAC cross-validation. (done)
  • M3b LPC: quantized linear-predictive coding, bringing levels 3-8 to their full potential. (done)
  • M3c Wide bit-depth: 25-32 bps support end to end via an int64 encode path and the completed int64 decoder dispatch, validated by round-trip and libFLAC cross-validation. (done)
  • M4 Streaming hardening: sample-accurate SeekToSample (requires an io.Seeker), internal frame resync for seek landing, truncated-stream detection (ErrTruncatedStream), and opt-in SEEKTABLE emission (Config.SeekTableInterval, requires an io.WriteSeeker). A present SEEKTABLE accelerates seeks; binary search is the fallback. (done)
  • M5a Encoder performance: a per-encoder reusable scratch Workspace plus the libFLAC merge-upward Rice partition search. The workspace removes the per-frame and per-subframe heap allocations; the merge-upward search computes the partition sums once at the finest order and merges upward instead of rescanning the residuals per partition order. Output is byte-identical to before; steady- state per-block allocations drop to about zero and level-5 16-bit stereo encode throughput improves roughly 65% (about 25.5 ms/op to 15.3 ms/op on the reference benchmark). A follow-up hardening pass clamps the Rice partition order to 15 and defers the STREAMINFO MD5 ingest until after each frame is durably written, both preserving the byte-identical output. (done)
  • M6 completeness and v0.1.0: public-API and godoc review, provenance and license audit, and the full pre-release validation gate. This is the first tagged release: a feature-complete, pure-Go codec. (done)
  • v0.2.0 (next): SIMD integration. Wire the github.com/tphakala/simd integer and float primitives behind runtime dispatch with pure-Go fallbacks, gated on a measured end-to-end speedup.

SeekToSample is sample-accurate and requires an io.Seeker; it returns ErrSeekUnsupported when the source is not seekable and ErrInvalidSeek on a negative sample index. Mid-stream resync from a non-fLaC start position remains future work.

Usage

Decode a FLAC file to raw interleaved little-endian PCM:

package main

import (
	"io"
	"log"
	"os"

	"github.com/tphakala/go-flac/pcm"
)

func main() {
	f, err := os.Open("input.flac")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	dec, err := pcm.NewDecoder(f)
	if err != nil {
		log.Fatal(err)
	}

	info := dec.Info()
	log.Printf("%d Hz, %d channel(s), %d-bit", info.SampleRate, info.Channels, info.BitDepth)

	// dec is an io.Reader and io.WriterTo of interleaved little-endian PCM.
	out, err := os.Create("output.pcm")
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()
	if _, err := io.Copy(out, dec); err != nil {
		log.Fatal(err)
	}
}

Encode interleaved little-endian PCM to a FLAC file:

package main

import (
	"io"
	"log"
	"os"

	"github.com/tphakala/go-flac/pcm"
)

func main() {
	// pcmReader is any io.Reader of interleaved little-endian PCM matching the
	// Config below; here it is a raw PCM file.
	pcmReader, err := os.Open("input.pcm")
	if err != nil {
		log.Fatal(err)
	}
	defer pcmReader.Close()

	// out is an *os.File (an io.WriteSeeker) so Close can finalize the STREAMINFO
	// MD5, total-sample count, and frame sizes.
	out, err := os.Create("output.flac")
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()

	enc, err := pcm.NewEncoder(out, pcm.Config{SampleRate: 44100, BitDepth: 16, Channels: 2, CompressionLevel: 5})
	if err != nil {
		log.Fatal(err)
	}
	if _, err := io.Copy(enc, pcmReader); err != nil {
		log.Fatal(err)
	}
	if err := enc.Close(); err != nil {
		log.Fatal(err)
	}
}

Pass an io.WriteSeeker (for example an *os.File) as the destination so the encoder can finalize the STREAMINFO MD5, total-sample count, and frame sizes when Close is called. A non-seekable writer still produces a valid FLAC stream, but those fields are left as "unknown".

API notes:

import "github.com/tphakala/go-flac/pcm"

// Decoder: implemented.
dec, err := pcm.NewDecoder(r)
// dec implements io.Reader and io.WriterTo, yielding interleaved little-endian
// PCM. dec.Info() returns the stream's STREAMINFO properties.
// SeekToSample requires an io.Seeker: it returns ErrSeekUnsupported for
// non-seekable sources and ErrInvalidSeek on a negative index.

// Encoder: implemented.
enc, err := pcm.NewEncoder(w, pcm.Config{SampleRate: 44100, BitDepth: 16, Channels: 2})
// enc implements io.WriteCloser; write interleaved little-endian PCM and call
// Close to flush the final frame and finalize STREAMINFO. Pass an io.WriteSeeker
// so STREAMINFO totals and MD5 can be written back after encoding.

License

MIT. See LICENSE and THIRD_PARTY.md. go-flac is an independent reimplementation; no third-party source is copied.

Documentation

Overview

Package flac provides a native, pure-Go FLAC encoder and decoder.

The high-level PCM streaming API lives in the pcm subpackage (github.com/tphakala/go-flac/pcm). Use pcm.NewDecoder to decode a FLAC stream to interleaved little-endian PCM, and pcm.NewEncoder to encode interleaved little-endian PCM to a FLAC stream. This root package exposes only shared types used across the public API. Codec internals live under internal/.

Index

Constants

View Source
const Version = "0.1.0"

Version is the current library version. go-flac follows semantic versioning.

Variables

View Source
var (
	// ErrSeekUnsupported is returned by SeekToSample when the source is not seekable.
	ErrSeekUnsupported = errors.New("go-flac: seek unsupported (source is not an io.Seeker)")
	// ErrMissingStreamInfo means the stream had no STREAMINFO metadata block, or it did
	// not appear first.
	ErrMissingStreamInfo = errors.New("go-flac: missing or misplaced STREAMINFO block")
	// ErrCRCMismatch means a frame header CRC-8 or frame CRC-16 did not match.
	ErrCRCMismatch = errors.New("go-flac: CRC mismatch")
	// ErrMD5Mismatch means the decoded-audio MD5 did not match the STREAMINFO MD5.
	ErrMD5Mismatch = errors.New("go-flac: MD5 mismatch")
	// ErrUnsupported marks a reserved or illegal coded value, or an unsupported layout.
	ErrUnsupported = errors.New("go-flac: unsupported or reserved bitstream value")
	// ErrEncoderClosed is returned by Encoder.Write after Close has been called.
	ErrEncoderClosed = errors.New("go-flac: encoder is closed")
	// ErrTruncatedStream means the stream ended before delivering the sample count
	// STREAMINFO declares (an inter-frame cut on a zero-MD5 stream), or a frame body
	// was cut short. Mid-frame truncation wraps io.ErrUnexpectedEOF.
	ErrTruncatedStream = errors.New("go-flac: truncated stream")
	// ErrInvalidSeek means SeekToSample was called with a negative sample index.
	ErrInvalidSeek = errors.New("go-flac: invalid seek (negative sample index)")
)

Sentinel errors returned by the decoder and the pcm streaming layer. Callers can test for them with errors.Is.

Functions

This section is empty.

Types

type StreamInfo

type StreamInfo struct {
	SampleRate   int      // samples per second, e.g. 44100
	Channels     int      // number of channels, 1..8
	BitDepth     int      // bits per sample, e.g. 16 or 24
	TotalSamples uint64   // inter-channel sample count; 0 if unknown
	MD5          [16]byte // MD5 of the unencoded audio; all-zero if absent
}

StreamInfo describes a FLAC stream's global properties, mirroring the STREAMINFO metadata block.

Directories

Path Synopsis
internal
bitio
Package bitio implements MSB-first bit-level reading and writing in the bit order used by the FLAC bitstream.
Package bitio implements MSB-first bit-level reading and writing in the bit order used by the FLAC bitstream.
crc
Package crc provides the checksums FLAC requires: CRC-8 over each frame header, CRC-16 over each complete frame, and the MD5 of the unencoded audio stored in STREAMINFO.
Package crc provides the checksums FLAC requires: CRC-8 over each frame header, CRC-16 over each complete frame, and the MD5 of the unencoded audio stored in STREAMINFO.
frame
Package frame implements FLAC frame and subframe coding: the frame header (with CRC-8 sync validation and frame-sync scanning used for seek and resync), the four subframe types (constant, verbatim, fixed, LPC), and inter-channel decorrelation (left/side, right/side, mid/side).
Package frame implements FLAC frame and subframe coding: the frame header (with CRC-8 sync validation and frame-sync scanning used for seek and resync), the four subframe types (constant, verbatim, fixed, LPC), and inter-channel decorrelation (left/side, right/side, mid/side).
lpc
Package lpc, analysis side: windowing, autocorrelation, Levinson-Durbin, coefficient quantization, and order estimation for the encoder.
Package lpc, analysis side: windowing, autocorrelation, Levinson-Durbin, coefficient quantization, and order estimation for the encoder.
meta
Package meta implements FLAC metadata blocks: STREAMINFO, VORBIS_COMMENT, SEEKTABLE, PICTURE, CUESHEET, PADDING, and APPLICATION.
Package meta implements FLAC metadata blocks: STREAMINFO, VORBIS_COMMENT, SEEKTABLE, PICTURE, CUESHEET, PADDING, and APPLICATION.
rice
Package rice implements FLAC's Rice/Golomb residual coding: encoding and decoding of partitioned residuals and the parameter search that picks the cheapest Rice parameter per partition.
Package rice implements FLAC's Rice/Golomb residual coding: encoding and decoding of partitioned residuals and the parameter search that picks the cheapest Rice parameter per partition.
Package pcm is the high-level, clean-room PCM streaming API for go-flac.
Package pcm is the high-level, clean-room PCM streaming API for go-flac.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL