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

Uploaded Python 3

File details

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

File metadata

  • Download URL: icad_tone_detection-2.4.tar.gz
  • Upload date:
  • Size: 2.3 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.4.tar.gz
Algorithm Hash digest
SHA256 86b043abc41edac9ded7d33e140bbdf052005e21d89e99aafc14b202b8819ba5
MD5 8c3c181a16544b28ec723edf24900998
BLAKE2b-256 f866150cc0c641d41d087f27d67fec02469c3d3f9a366382a996d02c61278fe5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for icad_tone_detection-2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 0b8dac803722daf6f3d0213d6e3258b061d7a7d9ec40270b014f2a4640a41258
MD5 575d059423072fadbefb75346ecaa5a9
BLAKE2b-256 8ab446685d279863bcb2887b6a624b84dfd911c9352819fc307f78ba580c0c2d

See more details on using hashes here.

Provenance

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