Metadata-Version: 2.4
Name: muslib
Version: 0.2.0
License-File: LICENSE
Summary: Rust library for music synthesis and processing, inspired by Essentia.
Keywords: music
Author: Wiktor W. <wykwit@disroot.org>
Author-email: Wiktor W. <wykwit@disroot.org>
License: AGPL-3.0-or-later
Requires-Python: >=3.11
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Source Code, https://gitlab.com/wykwit/muslib/

# muslib

Rust library for music synthesis and processing, inspired by [Essentia](https://essentia.upf.edu/),
with Python bindings and a command line tool.

- **HPCP** (harmonic pitch class profile) and **Chromagram** (HPCP over time)
- **FFT** and **IFFT**
- **mixer**: load audio files as mono tracks, write 16-bit WAV
- **convert**: resampling and peak normalization
- **encode**: Ogg Opus in pure Rust
- **synth**: simple waveforms

## Installation

```
$ cargo add muslib                      # Rust crate
$ pip install muslib                    # Python package
$ cargo install muslib --features cli   # command line tool
```

Pre-built binaries are on [the releases page](https://gitlab.com/wykwit/muslib/-/releases).

## Usage

Load, resample, normalize and encode:

```rust,no_run
use muslib::convert::{normalize_peak, resample};
use muslib::encode::OggOpusWriter;
use muslib::mixer::Loader;

let loaded = Loader::<f32>::new().files(["a.wav", "b.wav"]).load()?;
let mut data = resample(loaded.data(), loaded.sample_rate(), 48000)?;
normalize_peak(&mut data, -1.0)?;
OggOpusWriter::new().file("voice.ogg").bitrate(48000).write(&data)?;
# Ok::<(), muslib::MuslibError>(())
```

The same from the command line:

```
$ muslib convert --rate 48000 --normalize -1 --bitrate 48000 --output voice.ogg a.wav b.wav
```

Notes:

- Loading reads WAV, FLAC, Ogg Vorbis and Matroska/WebM, and averages channels
  into mono unless `.channel(index)` picks one. Concatenated files must share a sample rate.
- Opus input must be 8, 12, 16, 24 or 48 kHz, at 6–512 kbit/s (64 by default).
- Errors are `muslib::MuslibError` in Rust and `muslib.MuslibError`
  (a `ValueError`) in Python; file errors include the path.

See the [API docs](https://docs.rs/muslib/latest/muslib/) for all parameters and
input requirements, and the `examples` directory for Rust and Python examples,
including comparisons with Essentia.

## Development

Requires Rust 1.87 or newer; Python wheels target Python 3.11 and newer.

```
$ cargo build --release --features cli
$ cargo test --all-features
$ cargo clippy --all-targets -- -D warnings
$ cargo fmt --check
$ cargo bench --bench core          # Criterion, reports in target/criterion/
$ maturin build                     # Python wheel
```

Comparisons against live Essentia are opt-in:

```sh
python3.12 -m venv .venv-essentia
.venv-essentia/bin/python -m pip install essentia==2.1b6.dev1389
ESSENTIA_PYTHON="$PWD/.venv-essentia/bin/python" \
  cargo test --features essentia-oracle --test essentia_oracle
```

The [GitLab pipeline](https://gitlab.com/wykwit/muslib/-/pipelines) runs these checks,
builds wheels for release tags, and publishes them manually.

## Alternatives

- [dasp](https://github.com/RustAudio/dasp)
- [fundsp](https://github.com/SamiPerttu/fundsp)

## License

[AGPL-3.0-or-later](https://www.gnu.org/licenses/agpl-3.0.en.html), in the same spirit as Essentia.
Copyright (C) 2023 wykwit.

