Skip to main content

A Python library for extracting scanner radio tones from scanner audio.

Project description

icad_tone_detection

PyPI version License: MIT

Detect Two-Tone (Quick Call), Pulsed Single-Tone (On/Off Beeps), Long Tones, Hi–Low warble tones, MDC1200 / FleetSync, and DTMF in scanner-audio recordings.
The heavy DSP is performed by a bundled native binary (icad_decode), while the Python wrapper handles audio I/O and STFT-based frequency extraction.


Features

  • Single function: tone_detect() or CLI tool icad-tone-detect
  • Tone types:
    • Pulsed single-tone
    • Two-Tone / Quick Call
    • Long tones
    • Hi–Low warble tones
    • MDC1200 / FleetSync
    • DTMF
  • Flexible inputs: File path, URL, bytes, BytesIO, or pydub.AudioSegment
  • Automatic resample to 16 kHz mono PCM via FFmpeg
  • Fully configurable: All thresholds & detection params exposed as keyword args or CLI flags
  • Binaries included for:
    • Linux (x86_64, arm64, armv7)
    • macOS (x86_64, arm64)
    • Windows (x86_64)

Installation

pip install icad_tone_detection

Requires: Python 3.9+ and ffmpeg in PATH.


Quick start — Python

from icad_tone_detection import tone_detect

result = tone_detect("my_scanner_recording.wav")
print(result.pulsed_result)
print(result.two_tone_result)

Quick start — CLI

# Show help
icad-tone-detect --help

# Analyze a file with MDC disabled
icad-tone-detect my.wav --detect_mdc false --debug

Boolean flags accepted: true/false, yes/no, or 1/0.


Full CLI example

icad-tone-detect my_scanner_recording.wav \
--detect_pulsed true \
--pulsed_center_hz 1010 --pulsed_bw_hz 25 \
--pulsed_min_cycles 6 \
--pulsed_min_on_ms 120  --pulsed_max_on_ms 900 \
--pulsed_min_off_ms 25  --pulsed_max_off_ms 350 \
--detect_two_tone true \
--tone_a_min_length 0.85 --tone_b_min_length 2.6 \
--detect_hi_low true --hi_low_interval 0.2 --hi_low_min_alternations 6 \
--detect_long true --long_tone_min_length 3.8 \
--detect_mdc false --detect_dtmf true \
--time_resolution_ms 50 --matching_threshold 2.5 \
--debug

Example output (debug mode)

############################################################
ICAD Tone Detection: DEBUG - v2.8.0
------------------------------------------------------------
Decode binary path:        /…/bin/linux_arm64/icad_decode
Analyzing audio at:        my_scanner_recording.wav
Matching Threshold:        2.5%
Time Resolution (ms):      50
… (trimmed) …
------------------------------------------------------------
DETECTION SUMMARY
------------------------------------------------------------
Two-Tone (Quick Call): 1
Long Tones:            0
Hi-Low Warble:         0
Pulsed Single Tone:    3
MDC1200/FleetSync:     0   (disabled)
DTMF:                  2
------------------------------------------------------------
{
"pulsed": [
{
"tone_id": "pl_1",
"detected": 1010.1,
"start": 2.31, "end": 5.12, "length": 2.81,
"cycles": 8,
"on_ms_median": 180, "off_ms_median": 95
}
],
"two_tone": [
{
"tone_id": "qc_1",
"detected": [473.2, 810.0],
"tone_a_length": 0.90, "tone_b_length": 2.84,
"start": 6.23, "end": 9.07
}
],
"long_tone": [],
"hi_low": [],
"mdc": [],
"dtmf": [
{ "digit": "5", "start": 12.01, "end": 12.08 },
{ "digit": "9", "start": 12.35, "end": 12.42 }
]
}

Python API — tone_detect() signature

result = tone_detect(
audio_path="my.wav",          # path / URL / BytesIO / AudioSegment

    # STFT & grouping
    matching_threshold=2.5,       # % tolerance for grouping freqs
    time_resolution_ms=50,        # STFT hop size in ms

    # Quick Call (two-tone)
    tone_a_min_length=0.85,       # sec – min A-tone
    tone_b_min_length=2.6,        # sec – min B-tone

    # Hi/Low warble
    hi_low_interval=0.2,          # sec – max gap between hi/low groups
    hi_low_min_alternations=6,    # min alternations

    # Long tone
    long_tone_min_length=3.8,     # sec – min duration

    # Pulsed single-tone (~1 kHz)
    pulsed_center_hz=None,        # Hz – None=auto estimate (200–3000 Hz)
    pulsed_bw_hz=25.0,            # Hz ± deviation counted as ON
    pulsed_min_cycles=6,          # min ON→OFF cycles
    pulsed_min_on_ms=120,         # ms – ON min
    pulsed_max_on_ms=900,         # ms – ON max
    pulsed_min_off_ms=25,         # ms – OFF min
    pulsed_max_off_ms=350,        # ms – OFF max

    # Detector toggles
    detect_pulsed=True,
    detect_two_tone=True,
    detect_long=True,
    detect_hi_low=True,

    # External decoders
    detect_mdc=True,              # MDC1200 / FleetSync
    mdc_high_pass=200,            # Hz
    mdc_low_pass=4000,            # Hz
    detect_dtmf=True,

    debug=False
)

Result object

tone_detect() returns a ToneDetectionResult dataclass with:

  • pulsed_result — Pulsed single-tone hits: tone_id, detected, start, end, length, cycles, on_ms_median, off_ms_median
  • two_tone_result — Quick-Call matches: tone_id, detected [A,B], tone_a_length, tone_b_length, start, end
  • long_result — Long tone hits: tone_id, detected, length, start, end
  • hi_low_result — Warble sequences: tone_id, detected [low,high], alternations, length, start, end
  • mdc_result — Decoded frames from external MDC/FleetSync decoder (if enabled)
  • dtmf_result — Decoded DTMF presses (if enabled)

Platforms & binaries

OS Architectures Wheel folder name
Linux x86_64, arm64, armv7 linux_x86_64, linux_arm64, linux_armv7
macOS x86_64, arm64 macos_x86_64, macos_arm64
Windows x86_64 windows_x86_64

Example audio

Sample WAV files are in examples/example_audio/.


Contributing

Issues and pull requests welcome: GitHub repo


License

MIT © TheGreatCodeholio • Version 2.8.2 • Python 3.9+

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

icad_tone_detection-2.8.2.tar.gz (2.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

icad_tone_detection-2.8.2-py3-none-any.whl (2.9 MB view details)

Uploaded Python 3

File details

Details for the file icad_tone_detection-2.8.2.tar.gz.

File metadata

  • Download URL: icad_tone_detection-2.8.2.tar.gz
  • Upload date:
  • Size: 2.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for icad_tone_detection-2.8.2.tar.gz
Algorithm Hash digest
SHA256 7efc7d050be7b13a2cd25a9ee7983bb9f5206d9b0a355e20a16b0b6a2355035c
MD5 ad2177929264ca64365363322bf46ba0
BLAKE2b-256 0ea54c9392bb72277091d53540488b27417e68ad3c768ede38b7d2cd1857c813

See more details on using hashes here.

Provenance

The following attestation bundles were made for icad_tone_detection-2.8.2.tar.gz:

Publisher: python-package.yml on TheGreatCodeholio/icad_tone_detection

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file icad_tone_detection-2.8.2-py3-none-any.whl.

File metadata

File hashes

Hashes for icad_tone_detection-2.8.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c1ac578357b180011b3666b93b30b8f64069dd507f347e723325660e131a7040
MD5 799f38ce4f2ba208fd80916b87f969e5
BLAKE2b-256 9e5fe42884b5563e5e909fe83b2e99f4f8e5693a54cfff3d5b6efdca3825e2ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for icad_tone_detection-2.8.2-py3-none-any.whl:

Publisher: python-package.yml on TheGreatCodeholio/icad_tone_detection

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page