Skip to content
darui3018823Public

About

βœ¨πŸ‘πŸ˜ŽπŸ‘Pure-Go Opus audio codecβœ¨πŸ‘πŸ˜ŽπŸ‘

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

Β 

History

877 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Pure Go Opus Codec

Go Reference Test Race Fuzz License

ζ—₯本θͺž | English

github.com/darui3018823/opus is a stateful, Pure Go Opus codec library with no runtime CGO dependency. It provides single-stream, multistream, surround, projection/Ambisonics, packet transformation, and Ogg Opus APIs.

The decoder's PCM is sample-exact against libopus 1.6.1's plain-C float decoder on all 12 official RFC 8251 vectors, including packet loss concealment. The encoder produces standards-compatible CELT, SILK-only, and hybrid packets. Since v1.5.0 its automatic decisions follow libopus 1.6.1's encoder (ModePolicyLibopus, the default), and its packets (2.5 to 120 ms) are byte-identical to libopus's plain-C float build in the tested configurations (automatic mode, mode transitions, 8–48 kHz input, CBR and VBR, in-band FEC, and DTX). SetModePolicy(ModePolicyLegacy) restores the decisions of earlier releases. The residual differences found by the libopus parity audit (for example long noise concealment and rare encoder float-rounding cases) are listed in the implementation snapshot. The authoritative implementation snapshot is docs/CURRENT_IMPLEMENTATION.md.

The compatibility target is standard Opus and core libopus behavior. DRED, QEXT, OSCE/DNN processing, Opus Custom, and the libopus C ABI are outside that claim, as is bit-exact encoder output beyond ModePolicyLibopus's tested configurations; see docs/LIBOPUS_SCOPE.md.

Install

go get github.com/darui3018823/opus

The module currently declares Go 1.24.11 in go.mod.

Minimal encode/decode

package main

import (
	"fmt"
	"log"

	"github.com/darui3018823/opus"
)

func main() {
	const channels = 2
	encoder, err := opus.NewEncoder(
		opus.SampleRate48kHz,
		channels,
		opus.ApplicationAudio,
	)
	if err != nil {
		log.Fatal(err)
	}

	// frameSize is samples per channel; PCM is interleaved.
	pcm := make([]int16, opus.FrameSize20ms*channels)
	packet, err := encoder.Encode(pcm, opus.FrameSize20ms)
	if err != nil {
		log.Fatal(err)
	}

	decoder, err := opus.NewDecoder(opus.SampleRate48kHz, channels)
	if err != nil {
		log.Fatal(err)
	}
	decoded := make([]int16, opus.MaxFrameSize*channels)
	samplesPerChannel, err := decoder.Decode(packet, decoded)
	if err != nil {
		log.Fatal(err)
	}
	decoded = decoded[:samplesPerChannel*channels]
	fmt.Println(samplesPerChannel, len(decoded)) // 960 1920
}

Executable examples are included in the root package documentation and Ogg Opus package documentation.

Support matrix

Area Support
Sample rates 8, 12, 16, 24, and 48 kHz
Single-stream channels Mono and stereo
PCM APIs Interleaved int16, signed 24-bit-in-int32, float32, and float64
Encoder packet durations CELT 2.5/5/10 ms; exact 20 ms multiples through 120 ms
Decoder packet durations Valid Opus packets up to 120 ms
Coding modes CELT encode/decode; voice-oriented SILK-only and hybrid encode; SILK/hybrid decode
Loss handling Explicit-duration CELT/SILK/hybrid PLC and SILK LBRR in-band FEC in int16, signed 24-bit-in-int32, float32, and float64
Multistream/surround RFC self-delimited framing; families 0, 1 (through 7.1), and 255; matching PLC/FEC PCM variants
Projection/Ambisonics RFC 8486 families 2 and 3; predefined first- through fifth-order family-3 matrices
Packet tools Validated inspection, repacketizing, padding, soft clipping, LBRR detection, extensions
Ogg Opus CRC/lacing, headers/tags (mapping families 0-3 and 255), timing trims, chained reading, per-link seek, validated single-link writing
Runtime dependencies Pure Go; CGO/libopus is optional and test-only under opusref

MaxFrameSize is 5760 samples per channel at 48 kHz (120 ms). MaxFrameBytes is the 1275-byte compressed-frame limit. MaxPacketSize is a conservative bound for an unpadded single-stream packet; explicit padding may exceed it.

Loss recovery

DecodePLC, DecodePLC24, DecodePLCFloat32, and DecodePLCFloat conceal an explicit missing duration. The duration may be any positive 2.5 ms multiple (multistream and projection decoders conceal at most 120 ms per call, as in libopus). Before the first successfully decoded packet, and after Reset, PLC returns zero concealment.

For in-band FEC, prefer DecodeFECWithDuration for int16 or the explicit- duration DecodeFEC24, DecodeFECFloat32, and DecodeFECFloat variants. They recover LBRR from the first Opus frame in the carrier and use PLC for an unrecoverable prefix or when FEC is unavailable. The original DecodeFEC remains a compatibility wrapper that infers the missing duration from the carrier and retains its legacy CELT-only error behavior. MultistreamDecoder provides the same PCM variants and duration contract; SurroundDecoder inherits them. A returned FEC error does not commit partial decoder state.

Correct use of state and memory

Encoder, decoder, multistream, surround, projection, repacketizer, and Ogg reader/writer values are stateful and are not safe for concurrent use. Use one instance per logical stream, process packets in order, and serialize every operation on an instance, including getters, controls, child stream access, seeking, and Reset. Distinct instances may run concurrently. Do not copy an instance after first use.

Codec methods borrow per-call PCM, packet, and destination slices only until the call returns. Constructors copy mappings and matrices. Returned packet, PCM, mapping, and matrix slices are caller-owned copies. Ogg readers and writers borrow their io.Reader/io.Writer for the instance lifetime and do not close it.

Where a codec type exposes Reset, it clears codec history and last-packet observations while retaining configuration such as bitrate, application, output gain, and phase-inversion controls. Reuse an instance after Reset only for a new stream with the same configuration, or apply new controls explicitly.

Conformance and reference testing

CI downloads the unmodified RFC 8251 vector archive and runs all 12 decoder vectors. Vector data is not committed, so local vector tests skip when testdata/opus_newvectors/ is absent.

go test -count=1 ./...
go test -count=1 -run TestOfficialVectors .

Optional opusref tests require a C toolchain and libopus. They compare decoder output, interoperability, final ranges, FEC/PLC, multistream, projection, and selected encoder quality behavior against libopus 1.6.1. They are reference checks, not runtime dependencies.

go test -count=1 -tags opusref ./...

The current CELT constrained-VBR and TF-allocation corrections are guarded by a 140-cell opt-in corpus scoreboard; the measured one-second byte totals stayed unchanged while the targeted music/mixed worst cases improved. Surround channel-role masking improved the weighted SNR of the deterministic 5.1 and 7.1 fixtures without changing elementary packet lengths. SILK scratch reuse is guarded by packet/final-range digests and reduced allocations in the recorded Windows amd64 benchmarks. v1.7.0 roughly halves encode and decode time against v1.6.0 and removes about 97% of the bytes allocated, without changing decoded PCM, final ranges or encoded bytes. v1.7.1 fixes four encoder differences from plain-C libopus found on real audio, so encoded bytes change on the frames they affect; decoding is unchanged. These are regression fixtures and local measurements, not universal quality or performance guarantees; see the real-corpus scoreboard and the performance baseline for conditions and values.

Input safety and fuzzing

Public decoder and packet/container parsing paths are designed to reject malformed input with errors instead of panicking. Stateful decoder sequences, PLC/FEC interleaving, encoder controls and extreme PCM (including floating-point edge cases), packet extensions, multistream framing, repacketizing, and Ogg Reader/Writer round trips have dedicated fuzz targets. CI runs the target set nightly on Linux amd64 and arm64.

This is a bounded API guarantee, not a claim that fuzzing proves correctness. Callers must still enforce application-level packet, stream, CPU, and memory budgets; fuzz coverage does not guarantee audio quality, timing availability, or protection against every denial-of-service pattern. Report suspected security issues through SECURITY.md, not a public issue.

Example local runs:

go test -run='^$' -fuzz='^FuzzDecoderSequence$' -fuzztime=60s .
go test -run='^$' -fuzz='^FuzzOggOpusReaderWriter$' -fuzztime=60s ./oggopus

Current limitations

  • ModePolicyLibopus (the default) reproduces libopus for single-stream packets of every duration and for the multistream, surround (mapping families 0, 1 and 255), and projection / Ambisonics (families 2 and 3) encoders. ModePolicyLegacy, the Go encoder's earlier decisions, differs from libopus: below about 40 kbit/s it codes speech at 8 kHz and tonal music down to 4 kHz audio bandwidth.
  • Byte identity is measured against libopus built without SIMD kernels; a libopus linked with SIMD kernels sums floats in a different order, so its CELT output differs.
  • DRED and QEXT packet extensions are transported opaquely; their codecs/DSP are not implemented.
  • Projection family 3 uses predefined libopus 1.6.1 matrices; arbitrary custom encoder matrix generation is not provided.
  • The Ogg Opus reader supports chained logical streams but not multiplexed physical-stream demultiplexing. Each Writer emits one logical stream.
  • Not every libopus single-stream or multistream CTL has a public equivalent.

Development

go generate ./...
git diff --exit-code
go fmt ./...
go vet ./...
go test -count=1 ./...
go test -race -count=1 ./...
go test -run='^$' -bench '^BenchmarkPerf/' -benchmem .

Normal CI runs native tests on Linux, macOS, and Windows for both amd64 and arm64. The Windows arm64 runner is currently a GitHub public-preview image. Generated-file drift, vet, and official vectors are separate Ubuntu jobs, and the opusref workflow stays on Ubuntu with libopus. See the workflow files for the exact current matrix.

Documentation

License

BSD 2-Clause License. See LICENSE.

About

βœ¨πŸ‘πŸ˜ŽπŸ‘Pure-Go Opus audio codecβœ¨πŸ‘πŸ˜ŽπŸ‘

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages