A lightweight, dependency-free Python implementation of the standard DTMF (Dual-Tone Multi-Frequency) keypad used in telephony systems.
This library provides safe mappings between keypad keys and their canonical low/high frequencies, together with practical runtime helpers for resolving noisy frequency estimates produced by FFT-based audio pipelines.
The API is intentionally small, predictable, and suitable for both batch analysis and real-time signal processing.
Features
-
Canonical forward and reverse mappings between DTMF keys and frequencies
-
Closed key representation Invalid keys cannot be constructed; all validation happens at creation time
-
Zero external dependencies
-
Runtime helpers:
- Tolerance-based reverse lookup (e.g. from FFT peak estimates)
- Nearest snapping for noisy frequency measurements
- Iteration over all keys and tones
Installation
pip install dtmf-table
Quick Example
from dtmf_table import DtmfTable, DtmfKey
# Construct a table instance
table = DtmfTable()
# Forward lookup from key to canonical frequencies
key = DtmfKey.from_char('8')
low, high = key.freqs()
assert (low, high) == (852, 1336)
# Reverse lookup with tolerance (e.g. from FFT bin centres)
key = table.from_pair_tol_f64(770.2, 1335.6, 6.0)
assert key.to_char() == '5'
# Nearest snapping for noisy estimates
key, snapped_low, snapped_high = table.nearest_u32(768, 1342)
assert key.to_char() == '5'
assert (snapped_low, snapped_high) == (770, 1336)
Design Rationale
DTMF tone mappings are fixed, tiny (a 4×4 keypad), and stable. Rather than exposing a mutable lookup table or relying on dynamic configuration, the mapping is encoded directly in the library and validated eagerly.
This yields:
- Deterministic behaviour with no hidden state
- Early detection of invalid keys and invalid frequency pairs
- Predictable performance characteristics for tight audio loops
While Python cannot provide compile-time guarantees, the API enforces the same invariants at runtime.
API Overview
Core Types
DtmfKey
Represents a valid DTMF keypad key.
-
DtmfKey.from_char(char) -> DtmfKeyCreate a key from a character. Raises if invalid. -
key.to_char() -> strConvert a key back to its character representation. -
key.freqs() -> (int, int)Return the canonical(low_freq, high_freq)pair.
DtmfTable
Provides lookup and matching utilities.
-
DtmfTable.lookup_key(key) -> (int, int)Forward lookup: key → frequencies. -
DtmfTable.from_pair_exact(low, high) -> Optional[DtmfKey]Reverse lookup requiring an exact frequency match. -
DtmfTable.from_pair_normalised(f1, f2) -> Optional[DtmfKey]Reverse lookup ignoring frequency order. -
DtmfTable.from_pair_tol_f64(f1, f2, tol) -> Optional[DtmfKey]Reverse lookup allowing tolerance in Hz. -
DtmfTable.nearest_u32(f1, f2) -> (DtmfKey, int, int)Snap noisy integer frequency estimates to the nearest canonical pair. -
DtmfTable.nearest_f64(f1, f2) -> (DtmfKey, float, float)Float variant of nearest snapping. -
DtmfTable.all_keys() -> list[DtmfKey]Return all valid keys. -
DtmfTable.all_tones() -> list[(DtmfKey, int, int)]Return all keys with their canonical frequencies.
Integration Example
A typical audio workflow looks like:
- Extract an audio segment
- Compute an FFT magnitude spectrum
- Identify two dominant frequency peaks
- Resolve the DTMF key using tolerance or snapping
# freq1 and freq2 are the peak frequencies extracted from your FFT
key = table.from_pair_tol_f64(freq1, freq2, 5.0)
if key is not None:
print(f"Detected key: {key.to_char()}")
This keeps the signal-processing logic decoupled from keypad semantics while remaining simple to integrate.
Documentation
- Python API: https://jmg049.github.io/dtmf_table/
License
This project is licensed under the MIT License.
Metadata
Release files for dtmf-table 1.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dtmf_table-1.1.4.tar.gz | 21.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dtmf_table-1.1.4-cp39-cp39-manylinux_2_34_x86_64.whl | CPython 3.9 | CPython 3.9 | Linux glibc 2.34+ x86-64 | Details |
Total release size: 270.9 kB
Release files / dtmf_table-1.1.4.tar.gz
| Download URL | dtmf_table-1.1.4.tar.gz |
|---|---|
| Size | 21.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a257653c0c5cbf01467d115b170d30bc6709f0af3338fe01b560d8c72d999851
|
|
BLAKE2b-256 checksum How to use checksums |
6835e94c9d3a4d00c1e6a15cc054b59eb3fbf9ae2aa4e4e27abdcc5b1b2238af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.11.5
|
Release files / dtmf_table-1.1.4-cp39-cp39-manylinux_2_34_x86_64.whl
| Download URL | dtmf_table-1.1.4-cp39-cp39-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 249.2 kB |
| Tags | CPython 3.9 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
07713fc6c0a67e0b84e6abd0f794bafdf8f0c2f4822748804a62acb2b9a04d7b
|
|
BLAKE2b-256 checksum How to use checksums |
485b2c0344ee234c43cc390c865a7d0edd83e027f4fa5347b1aaec931015b927
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.11.5
|
Security for dtmf-table 1.1.4
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.