audio-engine-core 0.1.0

Reusable decoder, DSP, loudness, resampling, and streaming pipeline primitives
Documentation
# audio-engine-core

Reusable decoder, DSP, loudness, resampling, and streaming pipeline primitives
extracted from the Lyne audio engine.

This crate is the app-agnostic core layer. It is intended for experiments and
integration work around high-quality local audio processing, not as a stable
1.0 SDK yet. The public API is versioned as `0.1.x` and may change while the
larger player continues to evolve.

## What Is Included

- Streaming decode helpers built on Symphonia.
- SoX VHQ resampling wrappers and streaming resampler utilities.
- DSP processors such as EQ, crossfeed, saturation, FFT convolution, dynamic
  loudness, volume smoothing, noise shaping, and spectrum analysis.
- EBU R128 loudness and true-peak measurement helpers.
- Lock-free DSP parameter snapshots and processor adapters for realtime audio
  callback integration.
- A small streaming pipeline/ring-buffer primitive.

## What Is Not Included

- Audio device ownership or CPAL/WASAPI output stream management.
- HTTP/WebSocket server routes.
- Desktop UI, Tauri integration, media-library scanning, playback queue logic,
  WebDAV, NetEase integration, or application runtime directories.
- A stable compatibility layer for every internal Lyne use case.

Those layers remain in the root Lyne application crate.

## Cargo Features

Both features below are enabled by default. Disable them with
`default-features = false` to drop the corresponding dependency.

- `http` (default): HTTP/HTTPS streaming decode via `reqwest`, including Range
  streaming and full-download fallback. With this off, `StreamingDecoder` only
  opens local files; passing an `http(s)://` path returns a decoder error, and
  the `reqwest` dependency and `NetworkError` type are not compiled.
- `loudness-db` (default): SQLite-backed loudness metadata persistence
  (`LoudnessDatabase`, `TrackLoudness`, `DatabaseStats`) via `rusqlite`. With
  this off, the EBU R128 measurement helpers (`LoudnessMeter`,
  `LoudnessNormalizer`, `TruePeakDetector`) still work; only the on-disk cache
  is removed.

DSP-only consumers can take a much smaller dependency tree:

```toml
[dependencies]
audio-engine-core = { version = "0.1", default-features = false }
```

## Native Dependency: SoXR

The resampler depends on `soxr`, which requires the SoXR native library during
build/link.

On Windows, vcpkg is the recommended path:

```powershell
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install soxr:x64-windows-static-md
```

On MSYS2:

```bash
pacman -S mingw-w64-x86_64-soxr
```

On Unix-like systems, install SoXR through your system package manager and make
sure `pkg-config` can locate it.

## Quick Example

```rust
use audio_engine_core::{LoudnessMeter, StreamingDecoder};

fn analyze_file(path: &str) -> Result<f64, Box<dyn std::error::Error>> {
    let mut decoder = StreamingDecoder::open(path)?;
    let mut meter = LoudnessMeter::new(decoder.info.channels, decoder.info.sample_rate);

    while let Some(samples) = decoder.decode_next()? {
        meter.process(&samples);
    }

    Ok(meter.integrated_loudness())
}
```

## Runnable Examples

The `examples/` directory contains self-contained programs that need no audio
files and no optional features:

- `resample_sine` — streams a synthetic 48 kHz sine through the SoX VHQ
  resampler down to 44.1 kHz, demonstrating the chunked feed-then-flush pattern.
- `equalizer_curve` — runs a stereo buffer through the 10-band `Equalizer`.

```bash
cargo run --example resample_sine
cargo run --example equalizer_curve
```

## Realtime Notes

The crate exposes lock-free parameter containers and processor adapters used by
Lyne's realtime callback path. Keep allocations, locks, file I/O, logging, and
network I/O out of an audio callback. Allocate and configure processors before
entering the realtime path, then update parameters through the provided atomic
snapshot types.

## Performance And Audio Quality

These numbers come from the benchmarks in `benches/`, which run entirely against
this crate's public API. They are evidence for one machine and one configuration,
not a universal claim. Reproduce them with `cargo bench`; the exact values will
differ by CPU, compiler version, and load.

```bash
cargo bench --bench audio_callback_chain_perf -- --quick
cargo bench --bench audio_resampler_streaming_perf -- --quick
cargo bench --bench audio_convolver_perf -- --quick
cargo bench --bench audio_lockfree_params_perf -- --quick
cargo bench --bench audio_fir_eq_perf -- --quick
cargo bench --bench audio_quality_measurements -- --quick
```

Drop `--quick` for the longer multi-trial runs the numbers below were taken from.

### Realtime processing budget

Per-sample/per-buffer cost of the DSP and resampler paths at a 512-frame buffer.
These exclude the decoder and the OS audio device write; they measure only the
in-crate processing.

| Path | Per sample | Per 512-frame buffer | Bench |
| --- | ---: | ---: | --- |
| DSP chain, no convolver (EQ, saturation, crossfeed, convolver slot empty, volume, dynamic loudness, peak limiter) | 18.4 ns | 18.8 us | `audio_callback_chain_perf` |
| DSP chain with convolver | 27.8 ns | 28.5 us | `audio_callback_chain_perf` |
| Streaming resampler, 44.1 kHz to 48 kHz | 7.9 ns/input sample | 8.1 us/input buffer | `audio_resampler_streaming_perf` |
| `FFTConvolver` alone, 256-tap IR, stereo | ~10 ns | n/a | `audio_convolver_perf` |
| FIR EQ apply, 511-tap IR via `FFTConvolver`, stereo | 9.6 ns | 9.8 us | `audio_fir_eq_perf` |

For a 512-frame buffer at 48 kHz (about 10.7 ms of audio), even the heaviest
chain measured here uses well under one callback period.

### Lock-free parameter reads

The atomic parameter snapshots (`AtomicEqParams`, `AtomicVolumeParams`, and the
rest) are the mechanism for pushing parameter changes into the audio callback
without locks. Reading the full set of cached parameters once per callback costs
about **7 ns** with the generation-based snapshot path, versus ~50 ns for a
naive split-atomic field-by-field read and ~83 ns for an unconditional
`ArcSwap` guard load — an ~86% to ~92% improvement (`audio_lockfree_params_perf`).

### FIR EQ IR generation

`FirEq` designs a linear- or minimum-phase impulse response from 10 band gains;
the IR is then convolved (typically with `FFTConvolver`) to apply the EQ.
Generation is an offline/control-thread cost, not a per-sample one. On this
machine a 511-tap linear-phase design regenerates in ~31 us; minimum-phase
designs cost roughly 3x more because of the extra cepstral phase shaping, and
cost scales with tap count (`audio_fir_eq_perf`).

### Objective audio-quality measurements

`audio_quality_measurements` generates synthetic f64 signals, runs them through
this crate's processor modules, and analyzes the rendered buffers numerically.
This is native-rendered-buffer evidence, not analog output capture: no audio
device, OS mixer, DAC/ADC loopback, or microphone is involved, and it does not
replace listening tests.

| Metric | Result |
| --- | ---: |
| Resampler THD+N, 44.1 kHz to 48 kHz | -187.0 dB |
| Passband max deviation, 20 Hz to 18 kHz | 0.0013 dB |
| 20 kHz resampler gain | -0.0062 dB |
| Worst fitted alias attenuation, 96 kHz to 48 kHz | -294.7 dB |
| Limiter output ceiling from a +5.11 dBFS transient | -1.00 dBFS |
| Limiter below-threshold THD+N | -238.3 dB |
| `LoudnessMeter` integrated parity vs direct `ebur128` | 0.000000 LU |

The noise shapers (`NoiseShaper`) redistribute quantization error spectrally
rather than lowering broadband noise: the shaped curves strongly reduce the
2-6 kHz band while pushing energy into 14-18 kHz, for up to a +34.9 dB
ear-band advantage over flat TPDF dither.

The benchmark also includes an optional EBU Tech 3341/3342 expected-value corpus
check. It is skipped unless the `libebur128/test` reference vectors are present
(they are not bundled with this crate); the deterministic `LoudnessMeter` parity
fixtures above always run.

One known limitation, kept visible: the sample-peak/lookahead limiter is not an
intersample-true-peak guarantee. The full output-chain true-peak probe is
report-only, and on stressed material it can leave the worst true peak close to
the limiter ceiling rather than below a strict -1 dBTP target.

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or
  <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT]LICENSE-MIT or
  <http://opensource.org/licenses/MIT>)

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

### Native dependency licensing

This crate links the SoXR native library (libsoxr), which is distributed under
the LGPL-2.1. The Rust source in this crate is MIT OR Apache-2.0, but binaries
that statically link libsoxr carry LGPL-2.1 relinking obligations. See
[NOTICE](NOTICE) for details.