Metadata-Version: 2.4
Name: soniclab
Version: 2026.1.0
Summary: A modular Python DSP engine for audio synthesis, effects, sequencing, and MIDI
Project-URL: Homepage, https://github.com/rasigle/soniclab
Project-URL: Repository, https://github.com/rasigle/soniclab
Project-URL: Issues, https://github.com/rasigle/soniclab/issues
Project-URL: Changelog, https://github.com/rasigle/soniclab/blob/main/CHANGELOG.md
Author-email: Rainer Sigle <rainer.sigle@live.de>
License: MIT
License-File: LICENSE
Keywords: audio,dsp,music,sound-design,synthesis,synthesizer
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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: Topic :: Multimedia :: Sound/Audio :: Sound Synthesis
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: numpy>=1.26
Requires-Dist: scipy>=1.11
Provides-Extra: audio-io
Requires-Dist: numba>=0.66.0; extra == 'audio-io'
Requires-Dist: sounddevice>=0.5.5; extra == 'audio-io'
Provides-Extra: examples
Requires-Dist: ipykernel>=7.3.0; extra == 'examples'
Requires-Dist: ipython>=9.15.0; extra == 'examples'
Requires-Dist: librosa>=0.11.0; extra == 'examples'
Requires-Dist: matplotlib>=3.11.0; extra == 'examples'
Requires-Dist: notebook>=7.4.7; extra == 'examples'
Provides-Extra: full
Requires-Dist: ipykernel>=7.3.0; extra == 'full'
Requires-Dist: ipython>=9.15.0; extra == 'full'
Requires-Dist: librosa>=0.11.0; extra == 'full'
Requires-Dist: matplotlib>=3.11.0; extra == 'full'
Requires-Dist: mido>=1.3.0; extra == 'full'
Requires-Dist: notebook>=7.4.7; extra == 'full'
Requires-Dist: numba>=0.66.0; extra == 'full'
Requires-Dist: python-rtmidi>=1.5.8; extra == 'full'
Requires-Dist: sounddevice>=0.5.5; extra == 'full'
Provides-Extra: midi
Requires-Dist: mido>=1.3.0; extra == 'midi'
Requires-Dist: python-rtmidi>=1.5.8; extra == 'midi'
Provides-Extra: speed
Requires-Dist: numba>=0.66.0; extra == 'speed'
Description-Content-Type: text/markdown

# SonicLab

[![CI](https://github.com/rasigle/soniclab/actions/workflows/engine-package.yml/badge.svg)](https://github.com/rasigle/soniclab/actions/workflows/engine-package.yml)
[![PyPI version](https://img.shields.io/pypi/v/soniclab.svg)](https://pypi.org/project/soniclab/)
[![Python versions](https://img.shields.io/pypi/pyversions/soniclab.svg)](https://pypi.org/project/soniclab/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

SonicLab is a modular **Python DSP / audio synthesis engine**: vectorized oscillators,
envelopes, filters, effects, sequencing, optional realtime audio I/O, and MIDI adapters.

> **Status:** Beta. Public APIs may still evolve; see [docs/stability.md](docs/stability.md)
> and [CHANGELOG.md](CHANGELOG.md).

## Features

- **Oscillators:** sine, square, sawtooth, triangle, PolyBLEP bandlimited variants
- **Modulation:** ADSR / decay envelopes, modulated oscillators & frequency helpers
- **Modifiers:** volume, panning, clipping, frequency processors
- **Composition:** `Chain` (serial), `WaveAdder` (parallel mix)
- **Noise:** white, pink, brownian, blue, grey, velvet, sample-and-hold, Perlin
- **Filters:** Butterworth utilities, biquad resonant, acid/303-style filter
- **Effects:** distortion, delay, reverb, compressor
- **Sequencing:** step sequencers, clock, accent/slide, TB-303 helpers
- **Presets:** `PresetBuilder` / `PresetLibrary`
- **I/O (optional):** `AudioOutput` via the `audio-io` extra
- **MIDI (optional):** adapters and synth helpers via the `midi` extra

## Install

From PyPI:

```bash
pip install soniclab
```

Optional extras:

```bash
pip install "soniclab[audio-io]"   # sounddevice + numba speed path
pip install "soniclab[midi]"       # mido + python-rtmidi
pip install "soniclab[speed]"      # numba only
pip install "soniclab[examples]"   # notebooks / plotting
pip install "soniclab[full]"       # audio-io + midi + examples
```

From a checkout (recommended while developing):

```powershell
uv sync
# or:
python -m pip install -e ".[dev]"
```

Notes:

- Base install is the core NumPy/SciPy engine only.
- Realtime device playback needs working system audio drivers plus `audio-io`.
- MIDI needs local MIDI ports/backends plus the `midi` extra.

## Minimal example

```python
from soniclab import SineOscillator, __version__

print(__version__)
osc = SineOscillator(frequency=440, amplitude=0.3)
samples = osc.get_samples(44100)  # 1 second @ 44.1 kHz, float32
print(samples.shape, samples.dtype)
```

Chain + stereo pan:

```python
from soniclab import SineOscillator, Chain, Volume, Panner

chain = Chain(
    SineOscillator(frequency=440, amplitude=0.4),
    Volume(0.8),
    Panner(0.25),
)
stereo = chain.get_samples(2048, mode="vectorized")  # shape (2048, 2)
```

PolyBLEP oscillator:

```python
from soniclab import PolyBLEPOscillator, WaveShape

osc = PolyBLEPOscillator(
    frequency=110,
    amplitude=0.5,
    wave_shape=WaveShape.SAWTOOTH_UP,
)
samples = osc.get_samples(1024, mode="vectorized")
```

Optional audio output:

```python
from soniclab.audio_io import AudioOutput
# See examples/ and soniclab/audio_io for callback-based playback.
```

## Sample generation modes

Most generators support:

| Mode           | Behavior                                                                                                                                                            |
|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `"vectorized"` | NumPy block rendering (preferred for production)                                                                                                                    |
| `"iterator"`   | Python sample loop (flexible, slower)                                                                                                                               |
| `"auto"`       | oscillators: vectorized when `n >= 512`, else iterator; **composers (`Chain` / `WaveAdder`) always use vectorized** so small realtime buffers stay on the fast path |

For realtime or offline renderers, prefer `"vectorized"` (or `"auto"` with buffer sizes ≥ 512).

## Documentation

- [docs/](docs/) — getting started, API overview, recipes, stability policy
- Local preview: `uv run --with mkdocs mkdocs serve`
- [CHANGELOG.md](CHANGELOG.md)
- [CONTRIBUTING.md](CONTRIBUTING.md)
- [SECURITY.md](SECURITY.md)

## Testing

```powershell
uv run pytest tests -q
uv run ruff check soniclab tests
uv run mypy soniclab
```

Suggested slices (mirrors `soniclab/` layout):

```powershell
uv run pytest tests/core -q
uv run pytest tests/dsp -q
uv run pytest tests/generators -q
uv run pytest tests/audio_io -q
uv run pytest tests/midi_io -q
uv run pytest tests/utils -q
uv run pytest tests/presets -q
uv run pytest tests/sequencing -q
uv run pytest tests/voices -q
```

## Project layout

```text
soniclab/          # installable package
tests/             # pytest suite (mirrors soniclab/ packages)
examples/          # demos & notebooks (not in sdist)
docs/              # user documentation (MkDocs)
scripts/           # benchmarks & local tooling
```

## Public API

Import the stable surface from the top-level package:

```python
from soniclab import (
    SineOscillator,
    SquareOscillator,
    TriangleOscillator,
    SawtoothOscillator,
    PolyBLEPOscillator,
    ADSREnvelope,
    Chain,
    WaveAdder,
    Volume,
    Panner,
    Delay,
    Reverb,
)
```

Optional subsystems stay in subpackages so the core install stays light:

```python
from soniclab.audio_io import AudioOutput
from soniclab.midi_io import MIDIInput  # requires midi extra
```

## Contributing

1. Prefer `uv` for environments (`uv sync --group dev`).
2. Keep changes covered by tests under `tests/`.
3. Run `pytest`, `ruff`, and `mypy` before opening a PR.
4. Follow existing module patterns (component descriptor + registry registration).
5. See [CONTRIBUTING.md](CONTRIBUTING.md) for details.

## Changelog

See [CHANGELOG.md](CHANGELOG.md).

## License

See [LICENSE](LICENSE).
