Skip to main content

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

Project description

icad_tone_detection

PyPI version License: MIT

A Python library for extracting scanner radio tones from scanner audio. This includes Two-Tone (Quick Call), Long Tones, Hi-Low “warble” tones, MDC1200/FleetSync, and DTMF signals. The library uses STFT-based frequency extraction as well as an included external decoder binary (icad_decode) to process advanced signals like MDC1200 and DTMF.


Features

  • Easy-to-use main function tone_detect for detecting:
    • Two-Tone / Quick Call tones
    • Long tones
    • Hi-Low / warble tones
    • MDC1200 / FleetSync
    • DTMF
  • Flexible audio input: Local file paths, URLs, raw byte data, io.BytesIO, or existing pydub.AudioSegment.
  • Automatic resampling to PCM 16bit @16 kHz mono for consistent detection.
  • Cross-platform included binaries for MDC/DTMF decoding:
    • Windows (x86_64)
    • Linux (x86_64, ARM64)
    • macOS (ARM64)
  • Configurable detection thresholds and parameters.

Installation

pip install icad_tone_detection

Requirements

  • Python 3.10 or later.
  • ffmpeg (must be installed and available on the system PATH).
  • The following Python packages (automatically installed if not present):
    • numpy>=1.26.4
    • requests>=2.31.0
    • pydub>=0.25.1
    • scipy>=1.12.0

Getting Started

Here is a quick example on how to use the tone_detect function:

from icad_tone_detection import tone_detect

# Point to an audio file (can be local .wav, .mp3, URL, or BytesIO, etc.)
audio_path = "my_scanner_recording.wav"

# Detect various tones
result = tone_detect(
audio_path=audio_path,
matching_threshold=2.5,   # % difference threshold for grouping frequencies
time_resolution_ms=50,    # STFT window hop in ms
tone_a_min_length=0.85,   # Minimum A-tone length for Quick Call
tone_b_min_length=2.6,    # Minimum B-tone length for Quick Call
hi_low_interval=0.2,      # Maximum gap between warble tones
hi_low_min_alternations=6,# Minimum alternations for hi-low
long_tone_min_length=3.8, # Minimum length for long tone
detect_mdc=True,          # Enable MDC1200/FleetSync detection
mdc_high_pass=200,        # High-pass frequency for MDC decoding
mdc_low_pass=4000,        # Low-pass frequency for MDC decoding
detect_dtmf=True,         # Enable DTMF detection
debug=False               # Print debug info
)

# Results are available in the ToneDetectionResult object:
print("Two-Tone/QuickCall:", result.two_tone_result)
print("Long Tones:", result.long_result)
print("Hi-Low/Warble Tones:", result.hi_low_result)
print("MDC1200/FleetSync:", result.mdc_result)
print("DTMF:", result.dtmf_result)

Inputs Supported

The tone_detect function can handle:

  1. String pointing to:
    • A local file path (e.g., "audio.wav")
    • A URL (e.g., "https://example.com/audio.wav")
  2. Bytes or bytearray objects (raw audio data).
  3. File-like objects (io.BytesIO, open file handle, etc.).
  4. pydub.AudioSegment objects.

If you pass a local file path or a URL, the library will attempt to read the audio file and then convert it to a standard 16 kHz mono WAV internally using ffmpeg. For raw byte data or file-like objects, it similarly uses ffmpeg to resample on the fly.


Function Reference

tone_detect(...)

def tone_detect(audio_path, matching_threshold=2.5, time_resolution_ms=50,
tone_a_min_length=0.85, tone_b_min_length=2.6,
hi_low_interval=0.2, hi_low_min_alternations=6,
long_tone_min_length=3.8, detect_mdc=True, mdc_high_pass=200,
mdc_low_pass=4000, detect_dtmf=True, debug=False):
"""
Loads audio from various sources including local path, URL, BytesIO object, or a PyDub AudioSegment.

    Parameters:
        audio_path: string or other supported input types
        matching_threshold (float): ...
        time_resolution_ms (int): ...
        tone_a_min_length (float): ...
        tone_b_min_length (float): ...
        hi_low_interval (float): ...
        hi_low_min_alternations (int): ...
        long_tone_min_length (float): ...
        detect_mdc (bool): ...
        mdc_high_pass (int): ...
        mdc_low_pass (int): ...
        detect_dtmf (bool): ...
        debug (bool): ...
    
    Returns:
        ToneDetectionResult with:
          - two_tone_result
          - long_result
          - hi_low_result
          - mdc_result
          - dtmf_result
    """
    pass

Parameters

  • audio_path (various types):
    The source of audio. Can be a string (path or URL), bytes, BytesIO, or AudioSegment.
  • matching_threshold (float):
    The percentage threshold for grouping frequencies, e.g. 2.5 means frequencies within ±2.5% are considered matching.
    Default: 2.5
  • time_resolution_ms (int):
    The time window hop (in ms) used by STFT. Smaller = finer resolution but heavier computation.
    Default: 50
  • tone_a_min_length (float):
    Minimum length (seconds) of Tone A for Two-Tone detection.
    Default: 0.85
  • tone_b_min_length (float):
    Minimum length (seconds) of Tone B for Two-Tone detection.
    Default: 2.6
  • hi_low_interval (float):
    Maximum allowed gap (seconds) between consecutive alternating hi-low warble tones.
    Default: 0.2
  • hi_low_min_alternations (int):
    Minimum number of alternations for a hi-low warble sequence.
    Default: 6
  • long_tone_min_length (float):
    Minimum length (seconds) for a long tone detection.
    Default: 3.8
  • detect_mdc (bool):
    Whether to attempt detecting MDC1200/FleetSync frames.
    Default: True
  • mdc_high_pass (int):
    Frequency (Hz) of the high-pass filter for MDC detection.
    Default: 200
  • mdc_low_pass (int):
    Frequency (Hz) of the low-pass filter for MDC detection.
    Default: 4000
  • detect_dtmf (bool):
    Whether to attempt detecting DTMF signals.
    Default: True
  • debug (bool):
    Enable debug info (prints STFT matches, config details, etc.).
    Default: False

Returns
A ToneDetectionResult object with the fields:

  • two_tone_result
  • long_result
  • hi_low_result
  • mdc_result
  • dtmf_result

Each field holds a list of detected tones or an empty list if none found.

Result Caveats

The result includes timestamps in the file where the tones were detected as start and end. These may not align with the original audio due to internal conversions from your input to PCM 16bit @16kHz Mono. If those timestamps are important make sure the input matches those requirements.


Command-Line Example

There is an example script called detect_test.py under the examples/ folder. Usage:

python examples/detect_test.py -p my_scanner_recording.wav \
--matching_threshold 2.5 \
--time_resolution_ms 25 \
--tone_a_min_length 0.7 \
--tone_b_min_length 2.7 \
--long_tone_min_length 3.8 \
--debug

This script prints out the detected tone data in JSON to stdout.


Example Audio Files

Under examples/example_audio, you can find sample WAV files demonstrating:

  • dtmf_example.wav
  • hi_low_example.wav
  • long_tone_example.wav
  • mdc_example.wav
  • two_tone_example.wav

Use them to experiment with the library.


Platform Binaries

The icad_decode binary is automatically chosen depending on your OS/architecture:

  • linux_x86_64
  • linux_arm64
  • macos_arm64
  • windows_x86_64

On non-Windows systems, the library will automatically chmod +x the binary when needed.

If your platform is not supported, you will see a RuntimeError. Currently, only the above architectures and operating systems are supported.


License

This project is licensed under the MIT License.


Contributing / Issues

Contributions, bug reports, and feature requests are welcome. Please open issues or submit pull requests on GitHub.


Links


Author: TheGreatCodeholio
Version: 2.5
Python versions: 3.10+
License: MIT

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.5.tar.gz (2.4 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.5-py3-none-any.whl (2.3 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: icad_tone_detection-2.5.tar.gz
  • Upload date:
  • Size: 2.4 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.5.tar.gz
Algorithm Hash digest
SHA256 57614f6768730f68e55b4d2c2e524337ba5c64673b589d8b4e9fabc710e36ff2
MD5 dbd1679ad0c3100d9c342579a44b1349
BLAKE2b-256 b555ef037b1cbc60eb8a156cec9abb11a8f2eab72a6baf06794af3942f9dc3b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for icad_tone_detection-2.5.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.5-py3-none-any.whl.

File metadata

File hashes

Hashes for icad_tone_detection-2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 855b6c0d861f16c04cc25ca8a623a81711e431ad5969bb36ffc03fd480011d64
MD5 6f0a166ebde82cfa9eac559a7c8f6162
BLAKE2b-256 a7be6dafc54957316cfff65b919fb63410fff91f8444d166823b5175cb744734

See more details on using hashes here.

Provenance

The following attestation bundles were made for icad_tone_detection-2.5-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