opus1 0.3.0

Pure-Rust implementation of the Opus audio codec (RFC 6716), following libopus 1.x
Documentation
[package]
edition = "2024"
# The aarch64 DotProd intrinsics of the neural network code are stable from
# Rust 1.98 on.
rust-version = "1.98"
authors = ["jinti <shenjindi@fourz.cn>", "gaojiangjie <gaojiangjie@live.com>"]
name = "opus1"
version = "0.3.0"
description = "Pure-Rust implementation of the Opus audio codec (RFC 6716), following libopus 1.x"
keywords = ["opus", "audio", "codec", "no_std"]
categories = ["multimedia::audio", "multimedia::encoding", "no-std", "embedded"]
readme = "README.md"
license = "BSD-3-Clause"
repository = "https://github.com/RealEffect/opus1"
homepage = "https://github.com/RealEffect/opus1"
documentation = "https://docs.rs/opus1"
# Left out of the published crate: repository-only files. The tests compare
# with a linked libopus and read corpora that are not packaged, and the scripts
# build libopus and run the phone and x86 checks. `docs/` and `README.md` stay:
# src/lib.rs includes them for the documentation tests, except
# `docs/opus-explained/`, a web page with its own audio data that the crate
# does not use. `dnn-weights/` stays: the neural network features embed it
# with `include_bytes!`.
exclude = [
    "opus-1.6.1/",
    "fuzz/",
    "fixtures/",
    "corpus/",
    "/tests/",
    "/scripts/",
    "/bench_quick.sh",
    "/docs/opus-explained/",
    "/.github/",
]

[features]
default = ["std", "heap", "analysis"]
# `std` enables OS-backed runtime x86 SIMD detection (CPUID); without it, x86
# SIMD falls back to compile-time `target_feature` detection. It turns on
# `alloc`.
std = ["alloc"]
# `alloc` needs a global allocator but no operating system. It adds the
# `multistream` module, whose encoder and decoder allocate their streams
# when they are built (`Vec`). Each stream is built in place in that
# memory, so building them needs little stack, also without `heap`. It also
# lets the packet functions keep more than 32 extensions and copy more than
# 1275 bytes of old padding. A `no_std` build with an allocator enables it
# (or `heap`, which turns it on):
#   opus1 = { version = "...", default-features = false, features = ["alloc", "libm"] }
alloc = []
# With `heap` (default), the large codec state (`OpusEncoder`/`OpusDecoder`
# working buffers) lives on the heap behind `Box`, so the public structs are
# small (a few KB) and constructing them uses almost no stack. It needs a
# global allocator but not `std`, so it turns on `alloc`. A `no_std` build
# with an allocator can enable it:
#   opus1 = { version = "...", default-features = false, features = ["heap", "libm"] }
#
# Without `heap` (i.e. `default-features = false`), every working buffer is an
# inline fixed-size array, so `OpusEncoder`/`OpusDecoder`
# are large (on aarch64 about 154 KB with `analysis` and 52 KB) and must be
# placed in a `static` or on a large stack by the caller (`init` builds them
# in place). Without `std` and `alloc` as well, the crate is `#![no_std]`
# with **no `alloc`** (fully heap-free — no global allocator required).
heap = ["alloc"]
# Required for `#![no_std]` builds: provides `sin`/`cos`/`sqrt`/`exp2`/... via a
# pure-Rust port of musl libm (`core` does not provide transcendentals). Not
# needed when `std` is enabled. Enable with:
#   opus1 = { version = "...", default-features = false, features = ["libm"] }
libm = ["dep:libm"]
# For targets without atomic compare-and-swap (CAS) instructions, such as
# `thumbv6m-none-eabi` (Cortex-M0/M0+) and `riscv32imc-unknown-none-elf`
# (ESP32-C3): the lazily built shared tables (the CELT mode, the built-in
# neural network models) then use the atomics of the `portable-atomic`
# crate. On those targets portable-atomic needs one more setting from the
# application: its `critical-section` feature (with a `critical-section`
# implementation) or, on a single-core chip,
# `RUSTFLAGS="--cfg portable_atomic_unsafe_assume_single_core"`. Targets
# with CAS do not need this feature. The same idea as upstream opus-rs PR
# #64 by Alix ANNERAUD.
portable-atomic = ["dep:portable-atomic"]
# The speech and music analysis of the encoder (libopus `src/analysis.c` and
# `src/mlp.c`), which libopus runs from complexity 7 on. It adds about 28 KB
# of code, 24 KB of tables (mostly the network weights) and 26 KB of state
# per encoder. Without it, the encoder behaves as libopus below complexity
# 7: no speech or music probability, no detected bandwidth.
analysis = []

# Neural network features of libopus 1.5 and later. All are off by default,
# as in libopus. They work with and without `std` (a `no_std` build needs
# `libm`, as above).
#
# `dnn`: the shared inference layer (layer kernels, weight blob parser).
# It is a building block of the features below, which turn it on. Alone it
# adds no public API: `DnnBlob`, `DnnModels`, `set_dnn_blob` and
# `dnn_models` come with `deep-plc`, the smallest feature with a model.
dnn = []
# `deep-plc`: deep packet loss concealment (PitchDNN, the PLC model and
# FARGAN), like libopus's `--enable-deep-plc`. It conceals lost SILK
# wideband and CELT-only frames at decoder complexity 5 and above. As in
# libopus, compiling it also changes SILK at every complexity: the fade-in
# of the first 16 kHz frame after a loss is skipped.
deep-plc = ["dnn"]
# `osce`: the LACE and NoLACE speech enhancers of SILK, which run at
# decoder complexity 6 and at 7 and above on 20 ms SILK frames at 16 kHz.
# It turns on `deep-plc`, as libopus's `--enable-osce` does. As in
# libopus, compiling it also changes SILK at every complexity: -32768
# becomes -32767 in those frames.
osce = ["deep-plc"]
# `osce-bwe`: the bandwidth extension of SILK wideband to 48 kHz
# (BBWENet), at decoder complexity 4 and above when it is switched on
# with `OpusDecoder::set_osce_bwe`. It turns on `osce`.
osce-bwe = ["osce"]
# `dred`: deep redundancy (DRED), like libopus's `--enable-dred`. The
# encoder adds a compressed history of the speech to each packet, in a
# packet extension (`OpusEncoder::set_dred_duration`). The decoder rebuilds
# lost frames from it (`OpusDredDecoder`, `OpusDred`, and
# `OpusDecoder::dred_decode`, `dred_decode_i16` and `dred_decode24`). It
# embeds the two DRED models (the RDOVAE encoder and decoder) and their
# weights. It turns on `deep-plc`, as libopus's `--enable-dred` does.
dred = ["deep-plc"]
#
# `test-libopus-dnn`: TEST-ONLY. It adds nothing to the library. It only
# compiles the test files that begin with
# `#![cfg(feature = "test-libopus-dnn")]`. Those tests call the neural
# network functions of a libopus built with them (for example
# `scripts/android/build-libopus.sh --dnn`), linked through
# `LIBOPUS_LIB_DIR`, `LIBOPUS_NO_PKG=1` and `LIBOPUS_STATIC=1`, in their own
# `CARGO_TARGET_DIR`. Against a libopus without that code (such as the
# Homebrew build) they fail to link, so `cargo test --all-features` fails
# there. Applications never enable it.
test-libopus-dnn = []
#
# `__internals`: TEST-ONLY, not part of the API and outside semantic
# versioning. It adds the hidden module `opus1::internals`, which exposes
# internal parts of the codec to the tests, benchmarks, examples and fuzz
# targets of this repository. They get it through the dev-dependency on
# opus1 itself below and through `fuzz/Cargo.toml`. Any release may change
# or remove what it holds. Applications never enable it.
__internals = []

# docs.rs builds the documentation with the neural network features, so
# that their types and methods are documented too (`dred` and `osce-bwe`
# turn on all the others). It does not use `--all-features`, which would add
# the test-only features. `--cfg docsrs` turns on `doc_cfg` at the crate
# root, which labels each item that needs a feature with that feature. A
# normal build does not set `docsrs` and ignores it.
[package.metadata.docs.rs]
features = ["dred", "osce-bwe"]
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
# 0.2.6 is the first version of libm with `rint` and `rintf`.
libm = { version = "0.2.6", optional = true, default-features = false }
portable-atomic = { version = "1", optional = true, default-features = false }

[dev-dependencies]
# opus1 itself with the test-only feature `__internals`, so that the tests,
# benchmarks and examples reach `opus1::internals`. It adds no other
# feature (`default-features = false`), so that
# `cargo test --no-default-features` still tests a `no_std` build. A
# dev-dependency with only a `path` is removed from the published crate.
opus1 = { path = ".", default-features = false, features = ["__internals"] }
criterion = { version = "0.8.2", features = ["html_reports"] }
proptest = "1"
opus = { version = "0.3", default-features = false }
# Raw C API of the same libopus (opus_encoder_ctl, opus_decode_float with the
# FEC flag, the repacketizer, the multistream functions). The `opus` crate
# above already links it; examples/perf_harness.rs and the k24_* tests need
# controls that crate does not expose, such as forcing the coding mode.
audiopus_sys = "0.2"
# The fixed-point build of libopus 1.6.1, compiled from its source by
# tools/libopus-fixed, with every symbol renamed so that it links next to
# the float build above. opus1's SILK encoder is a port of the fixed-point
# one, so the tests compare its packets and functions with this build.
# The source comes from `LIBOPUS_SRC_1_6_1` or `opus-1.6.1/` (see
# tools/libopus-fixed/src/lib.rs). Test-only, like the other
# dev-dependencies.
libopus-fixed = { path = "tools/libopus-fixed" }
# The benchmarks and these examples use `opus1::internals`, so they need
# `__internals`. In this repository the dev-dependency on opus1 itself turns
# it on. In the published crate, which has no such dev-dependency, cargo
# skips them unless `--features __internals` is given.
[[bench]]
name = "opus_bench"
harness = false
required-features = ["__internals"]
[[bench]]
name = "dnn_bench"
harness = false
required-features = ["dnn", "__internals"]
[[bench]]
name = "deep_plc_bench"
harness = false
required-features = ["deep-plc", "__internals"]
[[example]]
name = "eval"
required-features = ["__internals"]
[[example]]
name = "opus_demo_data"
required-features = ["__internals"]
[[example]]
name = "opus_compare"
required-features = ["__internals"]
[[example]]
name = "perf_harness"
required-features = ["__internals"]
[[example]]
name = "wav_test"
required-features = ["__internals"]