Project

phonetics

0.0
A long-lived project that still receives updates
Tools for working with the International Phonetic Alphabet. Two-tier distance API — strict acoustic and listener-perception — backed by a Rust core compiled in via Magnus. Calibrated against Mad Gab puzzle data and English speech-perception literature.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

Runtime

~> 0.9
 Project Readme

phonetics

IPA-based phonetic distance metrics. One Rust core, three packages.

Package Registry name Manifest Registry
Rust crate phonetics-rs rust/phonetics crates.io
Ruby gem phonetics ruby/ (Magnus binding at ruby/ext/phonetics_ruby/) RubyGems
Python wheel phonetics-ipa python/phonetics-py/ (PyO3 binding) PyPI

The Rust crate is phonetics-rs and the Python package is phonetics-ipa because the bare phonetics name is taken on both registries by unrelated projects. The Ruby gem keeps the bare name because it's a continuation of the prior 3.x line. In code you still write use phonetics::…, import phonetics, and Phonetics.… respectively.

The metric

Two scores live in this library:

  • Strict phonetic distance — acoustic-distance edit metric. Bark-space vowel distance, 2D consonant place embedding, approximant–vowel bridge, diphthong/affricate handling, Damerau-Levenshtein edit distance with fixed indel cost. The right call for accent clustering, dialect work, ASR error analysis.

  • Listener-confusion distance — Mad-Gab-tuned perceptual metric. Gotoh affine-gap DP on top of the same per-phoneme cost basis, plus a weak-phoneme indel discount (/ə/, /h/, /ʔ/, /ɦ/), a word-boundary discount (re-syllabification is the operation Mad Gab encodes), and an empirical confusion overlay calibrated against West Coast American English. The right call for Mad Gab solving, pun detection, mondegreen analysis.

Both metrics share the same per-phoneme cost. Improvements to the acoustic model propagate to both.

Use it

// Rust
let d = phonetics::confusion("ɪtsdʒʌstəstupɪdgeɪm", "hɪtsdʒʌstɪsduphɪdkeɪm");
# Ruby
Phonetics.confusion("ɪtsdʒʌstəstupɪdgeɪm", "hɪtsdʒʌstɪsduphɪdkeɪm")
# Python
import phonetics
phonetics.confusion("ɪtsdʒʌstəstupɪdgeɪm", "hɪtsdʒʌstɪsduphɪdkeɪm")

Same number out of all three — they share a binary.

Repository layout

phonetics/
├── rust/
│   ├── Cargo.toml          # workspace
│   └── phonetics/          # the core crate, publishable to crates.io
├── ruby/
│   ├── lib/                # thin Ruby facade
│   ├── ext/phonetics/      # Magnus binding crate; built by extconf.rb
│   └── spec/               # rspec
├── python/phonetics-py/
│   ├── src/                # PyO3 binding crate
│   ├── python/phonetics/   # pure-Python facade
│   └── tests/              # pytest
└── .github/workflows/
    ├── test.yml            # cargo + rspec + pytest on every PR
    └── publish.yml         # crates.io + RubyGems + PyPI on git tag

License

MIT.