Metadata-Version: 2.4
Name: sadda
Version: 0.1.1
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
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 :: Rust
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Dist: numpy>=1.24
Requires-Dist: polars>=1.0
License-File: LICENSE-APACHE
License-File: LICENSE-MIT
Summary: Open-source toolkit for phonetics and speech-science research.
Keywords: phonetics,speech,audio,praat,linguistics,dsp,formants,pitch,spectrogram
Author-email: Daniel Brenner <wobaidan@gmail.com>
License-Expression: Apache-2.0 OR MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/sadda-speech/sadda/blob/main/CHANGELOG.md
Project-URL: Documentation, https://sadda-speech.github.io/sadda/
Project-URL: Homepage, https://sadda-speech.github.io/sadda/
Project-URL: Issues, https://github.com/sadda-speech/sadda/issues
Project-URL: Repository, https://github.com/sadda-speech/sadda

# sadda

*Sadda* (Pali: सद्द) — *sound, voice*.

An open-source toolkit for phonetics and speech-science research.

## Install

```bash
pip install sadda
```

Pre-built wheels are available for Linux x86_64, macOS arm64, and
Windows x86_64 on Python 3.10–3.13. Other platforms install from
sdist; you'll need a Rust toolchain locally.

## Quickstart

```python
import sadda
from pathlib import Path

proj = sadda.new_project(Path("vowels"), name="vowel-study")
bundle_id = proj.add_bundle("speaker_01", Path("rec01.wav"))

audio = proj.load_audio(bundle_id)
pitch = sadda.dsp.voiced_pitch(
    audio.samples.astype("float32"),
    audio.sample_rate,
)

proj.import_textgrid(Path("phones.TextGrid"), bundle_id)
df = proj.query(tier_id="phones")
```

Full walk-through at the [quickstart](https://sadda-speech.github.io/sadda/quickstart/).

## What's in the box

- **Corpus model** — projects, bundles, six tier types (interval,
  point, reference, dense numeric / vector / categorical), parent-
  child cardinality, append-only audit log.
- **DSP toolkit** — windowing, STFT, spectrogram, intensity, pitch
  (autocorrelation + voicing), LPC formants, MFCC.
- **Interop** — Praat TextGrid and ELAN `.eaf` import/export with
  documented lossiness and a JSON-sentinel for `extra` payloads.
- **Live recording** — cpal-driven capture with streaming meter /
  pitch / intensity / formants subscribers; atomic commit into the
  project.
- **Recipes** — `with sadda.recipe.record(proj, name="..."):` links
  operations to a named record and emits a runnable `.py` script.

Status by module:

| Tier | Modules |
|---|---|
| **Stable** | `sadda.corpus`, `sadda.dsp`, top-level project loaders |
| **Provisional** | `sadda.live`, `sadda.recipe` |
| **Experimental** | none yet |

## Documentation

- **[sadda-speech.github.io/sadda](https://sadda-speech.github.io/sadda/)** — user docs (quickstart, API ref, round-trip lossiness)
- **[`DEVLOG.md`](DEVLOG.md)** — design decision log; the running record of why things are the way they are
- **[`CHANGELOG.md`](CHANGELOG.md)** — versioned release history

## Repository structure

```
sadda/
├── crates/
│   ├── engine/        Core Rust engine — DSP, corpus, I/O
│   ├── python/        PyO3 bindings; built into the `sadda` Python module via maturin
│   ├── app/           Desktop GUI (egui + wgpu) — planned for Phase 2
│   └── uniffi/        UniFFI bindings for mobile (iOS / Android) — planned for Phase 8
├── python/sadda/      Python wrapper around the Rust extension
├── docs/              mkdocs-material site source
├── DEVLOG.md          Design-decision log
├── CHANGELOG.md       Versioned release history
├── Cargo.toml         Rust workspace root
├── pyproject.toml     Python project metadata + maturin config
└── mkdocs.yml         Docs site config
```

## Development

Requirements:

- Rust stable (managed via `rust-toolchain.toml`)
- Python 3.10+
- [uv](https://docs.astral.sh/uv/) for Python environment management

```bash
# Rust workspace
cargo build
cargo test

# Python extension + tests
uv sync
uv run pytest python/tests/

# Docs site (auto-rebuilds on save)
uv pip install mkdocs-material "mkdocstrings[python]"
mkdocs serve
```

## License

Dual-licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT license ([LICENSE-MIT](LICENSE-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.

