praatfan-gpl
Praat-compatible acoustic analysis in Python, powered by Rust.
This package provides exact reimplementations of Praat's acoustic analysis algorithms, designed to produce bit-accurate output matching Praat/parselmouth.
Installation
pip install praatfan-gpl
Building from source
Requires Rust and maturin:
cd python
pip install maturin
maturin develop --release
Quick Start
import praatfan_gpl as pc
# Load an audio file
sound = pc.Sound.from_file("speech.wav")
# Or create from numpy array
import numpy as np
samples = np.sin(2 * np.pi * 440 * np.arange(44100) / 44100)
sound = pc.Sound(samples, 44100.0)
# Compute pitch (F0)
pitch = sound.to_pitch(0.01, 75.0, 600.0)
print(f"Pitch at 0.5s: {pitch.get_value_at_time(0.5, 'hertz', 'linear')}")
# Get all pitch values as numpy array
f0_values = pitch.values() # NaN for unvoiced frames
times = pitch.times()
# Compute formants
formant = sound.to_formant_burg(
time_step=0.01,
max_num_formants=5,
max_formant_hz=5500.0, # Use 5000 for female speakers
window_length=0.025,
pre_emphasis_from=50.0
)
# Get F1, F2 at specific time
f1 = formant.get_value_at_time(1, 0.5, "hertz", "linear")
f2 = formant.get_value_at_time(2, 0.5, "hertz", "linear")
# Get all F1 values
f1_values = formant.formant_values(1) # numpy array
# Compute intensity
intensity = sound.to_intensity(100.0, 0.01)
db_values = intensity.values()
# Compute spectrum (single-frame FFT)
spectrum = sound.to_spectrum(fast=True)
cog = spectrum.get_center_of_gravity(2.0)
std = spectrum.get_standard_deviation(2.0)
# Compute spectrogram
spectrogram = sound.to_spectrogram(
effective_analysis_width=0.005,
max_frequency=5000.0,
time_step=0.002,
frequency_step=20.0,
window_shape="gaussian"
)
spec_data = spectrogram.values() # 2D numpy array [freq, time]
# Compute harmonicity (HNR)
hnr = sound.to_harmonicity_ac(0.01, 75.0, 0.1, 1.0)
# Or cross-correlation method:
hnr_cc = sound.to_harmonicity_cc(0.01, 75.0, 0.1, 1.0)
API Reference
Sound
# Loading
Sound.from_file(path) # Load from WAV, MP3, FLAC, OGG
Sound(samples, sample_rate) # From numpy array
# Properties
sound.sample_rate # Sample rate in Hz
sound.duration # Duration in seconds
sound.num_samples # Number of samples
sound.start_time, sound.end_time # Time bounds
# Methods
sound.samples() # Get samples as numpy array
sound.get_value_at_time(time) # Linear interpolation
sound.extract_part(start, end, ...) # Extract segment
sound.pre_emphasis(from_freq) # High-pass filter
sound.rms(), sound.peak() # Amplitude measures
# Analysis
sound.to_pitch(dt, floor, ceil) # Pitch extraction
sound.to_formant_burg(...) # Formant analysis
sound.to_intensity(min_pitch, dt) # Intensity contour
sound.to_spectrum(fast) # Single-frame FFT
sound.to_spectrogram(...) # Time-frequency analysis
sound.to_harmonicity_ac/cc(...) # HNR analysis
# Speech-referenced variants (robust on long recordings — see below)
sound.to_pitch_ac_referenced(dt, floor, ceil, *, reference_peak=None)
sound.to_pitch_cc_referenced(dt, floor, ceil, *, reference_peak=None)
sound.to_harmonicity_ac_referenced(dt, min_pitch, silence, ppw, *, reference_peak=None)
sound.to_harmonicity_cc_referenced(dt, min_pitch, silence, ppw, *, reference_peak=None)
Speech-referenced normalization (long recordings)
Praat references each frame's amplitude against the whole-file peak. On utterance-length audio that peak is the speech peak, which is correct. On long conversational recordings (e.g. 10-minute Buckeye files) the peak is set by whatever is loudest anywhere — a click, laugh, or interviewer burst — so every quiet voiced frame's relative intensity drops and gets misclassified as silent, which then NaN-gates downstream formants and HNR.
The *_referenced methods substitute a robust amplitude reference for the
whole-file peak. The plain to_pitch / to_harmonicity_* methods are
unchanged and remain bit-exact with Praat.
import praatfan_gpl as pg
# Estimate one reference per recording, then share it across pitch and HNR.
# Standards are frame-level robust statistics over speech-active frames, so a
# short loud burst cannot dominate them:
ref = pg.estimate_speech_reference(samples, sample_rate)
ref.reference_peak # 75th-pct of per-frame peak |x| — a typical-speech peak
ref.std # median per-frame RMS (z-norm scale)
ref.mean # median per-frame mean (DC reference)
ref.speech_mask # per-frame bool, hop_s=0.01 grid
ref.frame_times # frame centers (s)
ref.speech_fraction # fraction of frames in the speech mask
pitch = sound.to_pitch_ac_referenced(0.01, 75.0, 600.0,
reference_peak=ref.reference_peak)
hnr = sound.to_harmonicity_cc_referenced(0.01, 75.0, 0.1, 1.0,
reference_peak=ref.reference_peak)
# Or pass reference_peak=None (the default) to have each call estimate the
# reference internally.
The estimator definition and constants are shared across the praatfan package
family (praatfan, praatfan-rust, praatfan-gpl), so a reference_peak
computed by one package is interchangeable with the others.
Pitch
pitch.get_value_at_time(time, unit, interp) # Query pitch
pitch.values() # All values (NaN=unvoiced)
pitch.times() # Frame times
pitch.num_frames, pitch.time_step # Frame info
pitch.pitch_floor, pitch.pitch_ceiling # Analysis parameters
Formant
formant.get_value_at_time(n, time, unit, interp) # Fn frequency
formant.get_bandwidth_at_time(n, time, unit, interp) # Fn bandwidth
formant.formant_values(n) # All Fn values
formant.bandwidth_values(n) # All Bn values
formant.times() # Frame times
Intensity
intensity.get_value_at_time(time, interp) # Query dB
intensity.values() # All values
intensity.times() # Frame times
intensity.min(), intensity.max(), intensity.mean()
Spectrum
spectrum.get_band_energy(f_min, f_max) # Energy in band (Pa² s)
spectrum.get_center_of_gravity(power) # Spectral centroid
spectrum.get_standard_deviation(power) # Spectral spread
spectrum.get_skewness(power) # Spectral skewness
spectrum.get_kurtosis(power) # Spectral kurtosis
spectrum.num_bins, spectrum.df # Frequency info
Spectrogram
spectrogram.values() # 2D array [freq, time]
spectrogram.get_time_from_frame(i) # Frame time
spectrogram.get_frequency_from_bin(i) # Bin frequency
spectrogram.num_frames, spectrogram.num_freq_bins
spectrogram.time_step, spectrogram.freq_step
Harmonicity
harmonicity.get_value_at_time(time, interp) # Query HNR (dB)
harmonicity.values() # All values
harmonicity.times() # Frame times
harmonicity.min(), harmonicity.max(), harmonicity.mean()
Unit Options
- Pitch units:
"hertz","mel","semitones","erb" - Frequency units:
"hertz","bark","mel","erb" - Interpolation:
"nearest","linear","cubic" - Window shapes:
"gaussian","hanning","hamming","rectangular"
Threading
Pitch, harmonicity, intensity, formant (including FormantPath), spectrogram and resampling spread their frames across all CPU cores. Results are bit-identical to a single-threaded run, whatever the thread count. Every analysis releases the GIL while it runs, so other Python threads keep going.
- Thread count: each call uses every core unless you set
RAYON_NUM_THREADS(e.g.RAYON_NUM_THREADS=1) before importing the package. If you already run files in parallel across processes (multiprocessing, joblib, a job array), set it to avoid oversubscribing: N processes × all cores each is slower than either alone. - fork(): safe. A child forked after the parent has run an analysis
(Python
multiprocessing's default on Linux) builds a fresh thread pool on its first call instead of deadlocking on the parent's.
Comparison with parselmouth
praatfan-gpl aims for bit-accurate compatibility with Praat/parselmouth:
import parselmouth
import praatfan_gpl as pc
import numpy as np
sound_pm = parselmouth.Sound("speech.wav")
sound_pc = pc.Sound.from_file("speech.wav")
# Formant comparison
formant_pm = sound_pm.to_formant_burg(0.01, 5, 5500, 0.025, 50)
formant_pc = sound_pc.to_formant_burg(0.01, 5, 5500.0, 0.025, 50.0)
for t in np.arange(0, sound_pm.duration, 0.01):
f1_pm = formant_pm.get_value_at_time(1, t)
f1_pc = formant_pc.get_value_at_time(1, t, "hertz", "linear")
if f1_pm is not None and f1_pc is not None:
assert abs(f1_pm - f1_pc) < 1.0 # Within 1 Hz
License
GPL-3.0 (same as Praat).
Citing
If you use praatfan-gpl in published work, please cite Praat, Parselmouth,
and — if you use FormantPath — Weenink (2015):
- Boersma, P. & Weenink, D. (2024). Praat: doing phonetics by computer. https://www.fon.hum.uva.nl/praat/
- Jadoul, Y., Thompson, B., & de Boer, B. (2018). "Introducing Parselmouth: A Python interface to Praat." Journal of Phonetics, 71, 1–15.
- Weenink, D. (2015). "Improved formant frequency measurements of short segments." Proceedings of ICPhS 2015, Glasgow.
Metadata
Release files for praatfan-gpl 0.1.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 10.5 MB
Release files / praatfan_gpl-0.1.14-cp39-abi3-win_arm64.whl
| Download URL | praatfan_gpl-0.1.14-cp39-abi3-win_arm64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.9 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
f053229b7728fe6c3b74d99c6b504785f4b66bd21e91c8712c23236b9a2cd274
|
|
BLAKE2b-256 checksum How to use checksums |
99701ad8b81b05572878b3aae11a9120448b6d8871396801515782d9cd234580
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / praatfan_gpl-0.1.14-cp39-abi3-win_amd64.whl
| Download URL | praatfan_gpl-0.1.14-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
f7419e382848300fb6e718b40e157637cba446f7537040598772fa282a3b9ac4
|
|
BLAKE2b-256 checksum How to use checksums |
06e1eeacf8966b629ab4ee862f79c278eec0ebabcf169cb1928be0a6910781dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / praatfan_gpl-0.1.14-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | praatfan_gpl-0.1.14-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
0dd5b7dccefe03087b9e0a3f5ab03790ee95f902eaeca8a355f15cb8a6cefe4e
|
|
BLAKE2b-256 checksum How to use checksums |
7461ae7249585aa78c13e7a390197efa649f28f20562658629fe5d458b7f3a74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / praatfan_gpl-0.1.14-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | praatfan_gpl-0.1.14-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
a274e7931580074eec0e8661e76f990d53d413435b58d2881be729515d0951be
|
|
BLAKE2b-256 checksum How to use checksums |
e454f4100dcc5b5e35fb0cb7abf26ac28582e695cd972af04720091392cb4a36
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / praatfan_gpl-0.1.14-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | praatfan_gpl-0.1.14-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9d2e4618a7809ea46578b762637782788f544abf544d009f88756051d123ad34
|
|
BLAKE2b-256 checksum How to use checksums |
bec2cbb5424136bd2eed5447e7ceb866034d62f2ca423dbc4b9e6b06b648bafc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / praatfan_gpl-0.1.14-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | praatfan_gpl-0.1.14-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.9 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
6b779bed2a8d5d5f6bc239bcbb2e5704d8bdd7a7d72638fff34ec65e319e62a4
|
|
BLAKE2b-256 checksum How to use checksums |
d1dd9f4129284d2260a111a0ce906302c0e256ab2acac0e5b8851a74c20e6ece
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Security for praatfan-gpl 0.1.14
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.