Metadata-Version: 2.4
Name: audio-samples-qoe
Version: 0.1.3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Rust
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
Classifier: Typing :: Typed
Requires-Dist: numpy>=1.23
Requires-Dist: audio-samples>=0.2.3
License-File: LICENSE
Summary: Perceptual audio quality metrics (ViSQOL MOS-LQO and SCOREQ) — pure-Rust implementation with Python bindings
Keywords: audio,quality,visqol,scoreq,mos,speech,dsp
Home-Page: https://github.com/jmg049/audio_samples_qoe
Author-email: Jack Geraghty <jgeraghty049@gmail.com>
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://github.com/jmg049/audio_samples_qoe
Project-URL: Homepage, https://github.com/jmg049/audio_samples_qoe
Project-URL: Repository, https://github.com/jmg049/audio_samples_qoe

<div align="center">

# AudioSamples QoE

## Quality of Experience Metrics on AudioSamples


<img src="https://raw.githubusercontent.com/jmg049/audio_samples_qoe/main/logo.png" title="AudioSamples Logo -- Ferrous' Mustachioed Cousin From East Berlin, Eisenhaltig" width="200"/>

[![PyPI][pypi-img]][pypi] [![Python Docs][pydocs-img]][pydocs] [![License: MIT][license-img]][license]
</div>

Perceptual audio quality metrics in pure Rust, with Python bindings.

**ViSQOL** (Virtual Speech Quality Objective Listener) is a full-reference
metric that compares a degraded signal against a clean reference and predicts
a MOS-LQO in the range 1.0 to 5.0. Audio and speech modes, conformance-tested
against the reference implementation.

**SCOREQ** (Speech Contrastive Regression for Quality Assessment) is a neural,
wav2vec2-based speech-quality metric. It predicts a MOS from a single signal
(no-reference mode), or an embedding distance between a test and reference
signal (reference mode).

Built on the [`audio_samples`](https://pypi.org/project/audio-samples/)
ecosystem.

## Install

```sh
pip install audio-samples-qoe
```

The wheel is self-contained, so no Rust toolchain is needed. To build from
source instead, install [maturin](https://maturin.rs) and run `maturin develop
--release` from the repository root.

## Usage

```python
from audio_samples import AudioSamples
from audio_samples_qoe import visqol, Scoreq

# Files or audio_samples.AudioSamples, in any combination.
score = visqol("reference.wav", "degraded.wav")

# Speech mode is a keyword away.
score = visqol("reference.wav", "degraded.wav", mode="speech")

# SCOREQ: no-reference MOS, or reference-based embedding distance.
model = Scoreq(domain="natural", mode="nr")
mos = model.predict("degraded.wav")

model = Scoreq(domain="natural", mode="ref")
distance = model.predict_ref("degraded.wav", "reference.wav")
```

Each signal may be an `AudioSamples` object or a path to a WAV/FLAC file
(decoded with `audio_samples.read()`), in any combination. Raw arrays are
deliberately not accepted: wrap them with `AudioSamples.new_mono(arr,
sample_rate)` / `new_multi`, which is where the sample rate is attached.
Multi-channel signals are mixed down to mono, and any input sample rate is
handled internally. Both metrics release the GIL while computing, so scoring
parallelises across Python threads.

Loading a `Scoreq` model is expensive (the first use of a given
`(domain, mode)` pair downloads ~378 MB of weights from Zenodo into
`~/.cache/scoreq/`), so construct one per `(domain, mode)` pair and reuse it
across calls.

## Modes

| Mode       | Operating rate            | Bands            | MOS mapping              | Patch selection      |
|------------|---------------------------|------------------|--------------------------|----------------------|
| `"audio"`  | 48 kHz (resampled)        | 32, up to Nyquist| Support vector regression| All patches          |
| `"speech"` | Reference's native rate   | 21, ≤ 8 kHz      | Exponential NSIM fit     | Voice-activity gated |

In speech mode the reference is never resampled (16 kHz input is recommended),
silence in the reference is excluded by a voice-activity detector, and
identical signals score 5.0.

## Errors

- `TypeError`: an argument is neither an `AudioSamples` nor a path.
- `ValueError`: invalid `mode`/`domain` string.
- `OSError`: a file could not be read or decoded.
- `audio_samples_qoe.VisqolError`: the ViSQOL pipeline failed (most
  commonly a signal too short to extract a single analysis patch).
- `audio_samples_qoe.ScoreqError`: the SCOREQ pipeline failed, or
  `predict`/`predict_ref` was called on a model loaded for the other mode.

The package ships full type stubs and a `py.typed` marker, so `mypy`,
`pyright`, and IDE completion work out of the box.

## Changelog

See [CHANGELOG.md](https://github.com/jmg049/audio_samples_qoe/blob/main/CHANGELOG.md).

## Contributing

See [CONTRIBUTING.md](https://github.com/jmg049/audio_samples_qoe/blob/main/CONTRIBUTING.md).

## License

MIT

[pypi]: https://pypi.org/project/audio-samples-qoe/
[pypi-img]: https://img.shields.io/pypi/v/audio-samples-qoe?style=for-the-badge&color=009E73&label=pypi
[pydocs]: https://jmg049.github.io/audio_samples_qoe/
[pydocs-img]: https://img.shields.io/badge/python%20docs-online-009E73?style=for-the-badge&labelColor=gray
[license-img]: https://img.shields.io/crates/l/audio_samples_qoe?style=for-the-badge&label=license&labelColor=gray
[license]: https://github.com/jmg049/audio_samples_qoe/blob/main/LICENSE

